Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| 6 | 6 |
| 7 #include "public/fpdf_ppo.h" | 7 #include "public/fpdf_ppo.h" |
| 8 | 8 |
| 9 #include <map> | 9 #include <map> |
| 10 #include <memory> | 10 #include <memory> |
| 11 #include <vector> | 11 #include <vector> |
| 12 | 12 |
| 13 #include "core/fpdfapi/parser/cpdf_array.h" | 13 #include "core/fpdfapi/parser/cpdf_array.h" |
| 14 #include "core/fpdfapi/parser/cpdf_document.h" | 14 #include "core/fpdfapi/parser/cpdf_document.h" |
| 15 #include "core/fpdfapi/parser/cpdf_name.h" | 15 #include "core/fpdfapi/parser/cpdf_name.h" |
| 16 #include "core/fpdfapi/parser/cpdf_number.h" | 16 #include "core/fpdfapi/parser/cpdf_number.h" |
| 17 #include "core/fpdfapi/parser/cpdf_reference.h" | 17 #include "core/fpdfapi/parser/cpdf_reference.h" |
| 18 #include "core/fpdfapi/parser/cpdf_stream.h" | 18 #include "core/fpdfapi/parser/cpdf_stream.h" |
| 19 #include "core/fpdfapi/parser/cpdf_string.h" | 19 #include "core/fpdfapi/parser/cpdf_string.h" |
| 20 #include "fpdfsdk/fsdk_define.h" | 20 #include "fpdfsdk/fsdk_define.h" |
| 21 #include "third_party/base/ptr_util.h" | |
| 21 #include "third_party/base/stl_util.h" | 22 #include "third_party/base/stl_util.h" |
| 22 | 23 |
| 24 namespace { | |
| 25 | |
| 26 CPDF_Object* PageDictGetInheritableTag(CPDF_Dictionary* pDict, | |
| 27 const CFX_ByteString& bsSrcTag) { | |
| 28 if (!pDict || bsSrcTag.IsEmpty()) | |
| 29 return nullptr; | |
| 30 if (!pDict->KeyExist("Parent") || !pDict->KeyExist("Type")) | |
| 31 return nullptr; | |
| 32 | |
| 33 CPDF_Object* pType = pDict->GetObjectFor("Type")->GetDirect(); | |
| 34 if (!ToName(pType)) | |
| 35 return nullptr; | |
| 36 if (pType->GetString().Compare("Page")) | |
| 37 return nullptr; | |
| 38 | |
| 39 CPDF_Dictionary* pp = | |
| 40 ToDictionary(pDict->GetObjectFor("Parent")->GetDirect()); | |
| 41 if (!pp) | |
| 42 return nullptr; | |
| 43 | |
| 44 if (pDict->KeyExist(bsSrcTag)) | |
| 45 return pDict->GetObjectFor(bsSrcTag); | |
| 46 | |
| 47 while (pp) { | |
| 48 if (pp->KeyExist(bsSrcTag)) | |
| 49 return pp->GetObjectFor(bsSrcTag); | |
| 50 if (!pp->KeyExist("Parent")) | |
| 51 break; | |
| 52 pp = ToDictionary(pp->GetObjectFor("Parent")->GetDirect()); | |
| 53 } | |
| 54 return nullptr; | |
| 55 } | |
| 56 | |
| 57 bool CopyInheritable(CPDF_Dictionary* pCurPageDict, | |
| 58 CPDF_Dictionary* pSrcPageDict, | |
| 59 const CFX_ByteString& key) { | |
| 60 if (pCurPageDict->KeyExist(key)) | |
| 61 return true; | |
| 62 | |
| 63 CPDF_Object* pInheritable = PageDictGetInheritableTag(pSrcPageDict, key); | |
| 64 if (!pInheritable) | |
| 65 return false; | |
| 66 | |
| 67 pCurPageDict->SetFor(key, pInheritable->Clone().release()); | |
| 68 return true; | |
| 69 } | |
| 70 | |
| 71 bool ParserPageRangeString(CFX_ByteString rangstring, | |
| 72 std::vector<uint16_t>* pageArray, | |
| 73 int nCount) { | |
| 74 if (rangstring.IsEmpty()) | |
| 75 return true; | |
| 76 | |
| 77 rangstring.Remove(' '); | |
| 78 int nLength = rangstring.GetLength(); | |
| 79 CFX_ByteString cbCompareString("0123456789-,"); | |
| 80 for (int i = 0; i < nLength; ++i) { | |
| 81 if (cbCompareString.Find(rangstring[i]) == -1) | |
| 82 return false; | |
| 83 } | |
| 84 | |
| 85 CFX_ByteString cbMidRange; | |
| 86 int nStringFrom = 0; | |
| 87 int nStringTo = 0; | |
| 88 while (nStringTo < nLength) { | |
| 89 nStringTo = rangstring.Find(',', nStringFrom); | |
| 90 if (nStringTo == -1) | |
| 91 nStringTo = nLength; | |
| 92 cbMidRange = rangstring.Mid(nStringFrom, nStringTo - nStringFrom); | |
| 93 int nMid = cbMidRange.Find('-'); | |
| 94 if (nMid == -1) { | |
| 95 long lPageNum = atol(cbMidRange.c_str()); | |
| 96 if (lPageNum <= 0 || lPageNum > nCount) | |
| 97 return false; | |
| 98 pageArray->push_back((uint16_t)lPageNum); | |
| 99 } else { | |
| 100 int nStartPageNum = atol(cbMidRange.Mid(0, nMid).c_str()); | |
| 101 if (nStartPageNum == 0) | |
| 102 return false; | |
| 103 | |
| 104 ++nMid; | |
| 105 int nEnd = cbMidRange.GetLength() - nMid; | |
| 106 if (nEnd == 0) | |
| 107 return false; | |
| 108 | |
| 109 int nEndPageNum = atol(cbMidRange.Mid(nMid, nEnd).c_str()); | |
| 110 if (nStartPageNum < 0 || nStartPageNum > nEndPageNum || | |
| 111 nEndPageNum > nCount) { | |
| 112 return false; | |
| 113 } | |
| 114 for (int i = nStartPageNum; i <= nEndPageNum; ++i) { | |
| 115 pageArray->push_back(i); | |
| 116 } | |
| 117 } | |
| 118 nStringFrom = nStringTo + 1; | |
| 119 } | |
| 120 return true; | |
| 121 } | |
| 122 | |
| 123 } // namespace | |
| 124 | |
| 23 class CPDF_PageOrganizer { | 125 class CPDF_PageOrganizer { |
| 24 public: | 126 public: |
| 25 using ObjectNumberMap = std::map<uint32_t, uint32_t>; | 127 CPDF_PageOrganizer(CPDF_Document* pDestPDFDoc, CPDF_Document* pSrcPDFDoc); |
| 26 CPDF_PageOrganizer(); | |
| 27 ~CPDF_PageOrganizer(); | 128 ~CPDF_PageOrganizer(); |
| 28 | 129 |
| 29 bool PDFDocInit(CPDF_Document* pDestPDFDoc, CPDF_Document* pSrcPDFDoc); | 130 bool PDFDocInit(); |
| 30 bool ExportPage(CPDF_Document* pSrcPDFDoc, | 131 bool ExportPage(const std::vector<uint16_t>& pageNums, int nIndex); |
| 31 std::vector<uint16_t>* pPageNums, | 132 |
| 32 CPDF_Document* pDestPDFDoc, | 133 private: |
| 33 int nIndex); | 134 using ObjectNumberMap = std::map<uint32_t, uint32_t>; |
| 34 CPDF_Object* PageDictGetInheritableTag(CPDF_Dictionary* pDict, | 135 |
| 35 const CFX_ByteString& bsSrctag); | 136 bool UpdateReference(CPDF_Object* pObj, ObjectNumberMap* pObjNumberMap); |
| 36 bool UpdateReference(CPDF_Object* pObj, | 137 uint32_t GetNewObjId(ObjectNumberMap* pObjNumberMap, CPDF_Reference* pRef); |
| 37 CPDF_Document* pDoc, | 138 |
| 38 ObjectNumberMap* pObjNumberMap); | 139 CPDF_Document* m_pDestPDFDoc; |
| 39 uint32_t GetNewObjId(CPDF_Document* pDoc, | 140 CPDF_Document* m_pSrcPDFDoc; |
| 40 ObjectNumberMap* pObjNumberMap, | |
| 41 CPDF_Reference* pRef); | |
| 42 }; | 141 }; |
| 43 | 142 |
| 44 CPDF_PageOrganizer::CPDF_PageOrganizer() {} | 143 CPDF_PageOrganizer::CPDF_PageOrganizer(CPDF_Document* pDestPDFDoc, |
| 144 CPDF_Document* pSrcPDFDoc) | |
| 145 : m_pDestPDFDoc(pDestPDFDoc), m_pSrcPDFDoc(pSrcPDFDoc) {} | |
| 45 | 146 |
| 46 CPDF_PageOrganizer::~CPDF_PageOrganizer() {} | 147 CPDF_PageOrganizer::~CPDF_PageOrganizer() {} |
| 47 | 148 |
| 48 bool CPDF_PageOrganizer::PDFDocInit(CPDF_Document* pDestPDFDoc, | 149 bool CPDF_PageOrganizer::PDFDocInit() { |
| 49 CPDF_Document* pSrcPDFDoc) { | 150 ASSERT(m_pDestPDFDoc); |
| 50 if (!pDestPDFDoc || !pSrcPDFDoc) | 151 ASSERT(m_pSrcPDFDoc); |
| 51 return false; | |
| 52 | 152 |
| 53 CPDF_Dictionary* pNewRoot = pDestPDFDoc->GetRoot(); | 153 CPDF_Dictionary* pNewRoot = m_pDestPDFDoc->GetRoot(); |
| 54 if (!pNewRoot) | 154 if (!pNewRoot) |
| 55 return false; | 155 return false; |
| 56 | 156 |
| 57 CPDF_Dictionary* DInfoDict = pDestPDFDoc->GetInfo(); | 157 CPDF_Dictionary* pDocInfoDict = m_pDestPDFDoc->GetInfo(); |
| 58 if (!DInfoDict) | 158 if (!pDocInfoDict) |
| 59 return false; | 159 return false; |
| 60 | 160 |
| 61 CFX_ByteString producerstr; | 161 CFX_ByteString producerstr; |
| 62 producerstr.Format("PDFium"); | 162 producerstr.Format("PDFium"); |
| 63 DInfoDict->SetFor("Producer", new CPDF_String(producerstr, false)); | 163 pDocInfoDict->SetFor("Producer", new CPDF_String(producerstr, false)); |
| 64 | 164 |
| 65 CFX_ByteString cbRootType = pNewRoot->GetStringFor("Type", ""); | 165 CFX_ByteString cbRootType = pNewRoot->GetStringFor("Type", ""); |
| 66 if (cbRootType.IsEmpty()) | 166 if (cbRootType.IsEmpty()) |
| 67 pNewRoot->SetFor("Type", new CPDF_Name("Catalog")); | 167 pNewRoot->SetFor("Type", new CPDF_Name("Catalog")); |
| 68 | 168 |
| 69 CPDF_Object* pElement = pNewRoot->GetObjectFor("Pages"); | 169 CPDF_Object* pElement = pNewRoot->GetObjectFor("Pages"); |
| 70 CPDF_Dictionary* pNewPages = | 170 CPDF_Dictionary* pNewPages = |
| 71 pElement ? ToDictionary(pElement->GetDirect()) : nullptr; | 171 pElement ? ToDictionary(pElement->GetDirect()) : nullptr; |
| 72 if (!pNewPages) { | 172 if (!pNewPages) { |
| 73 pNewPages = new CPDF_Dictionary(pDestPDFDoc->GetByteStringPool()); | 173 pNewPages = new CPDF_Dictionary(m_pDestPDFDoc->GetByteStringPool()); |
| 74 pNewRoot->SetReferenceFor("Pages", pDestPDFDoc, | 174 pNewRoot->SetReferenceFor("Pages", m_pDestPDFDoc, |
| 75 pDestPDFDoc->AddIndirectObject(pNewPages)); | 175 m_pDestPDFDoc->AddIndirectObject(pNewPages)); |
| 76 } | 176 } |
| 77 | 177 |
| 78 CFX_ByteString cbPageType = pNewPages->GetStringFor("Type", ""); | 178 CFX_ByteString cbPageType = pNewPages->GetStringFor("Type", ""); |
| 79 if (cbPageType == "") { | 179 if (cbPageType.IsEmpty()) |
| 80 pNewPages->SetFor("Type", new CPDF_Name("Pages")); | 180 pNewPages->SetFor("Type", new CPDF_Name("Pages")); |
| 81 } | |
| 82 | 181 |
| 83 if (!pNewPages->GetArrayFor("Kids")) { | 182 if (!pNewPages->GetArrayFor("Kids")) { |
| 84 pNewPages->SetIntegerFor("Count", 0); | 183 pNewPages->SetIntegerFor("Count", 0); |
| 85 pNewPages->SetReferenceFor("Kids", pDestPDFDoc, | 184 pNewPages->SetReferenceFor( |
| 86 pDestPDFDoc->AddIndirectObject(new CPDF_Array)); | 185 "Kids", m_pDestPDFDoc, |
| 186 m_pDestPDFDoc->AddIndirectObject(new CPDF_Array)); | |
| 87 } | 187 } |
| 88 | 188 |
| 89 return true; | 189 return true; |
| 90 } | 190 } |
| 91 | 191 |
| 92 bool CPDF_PageOrganizer::ExportPage(CPDF_Document* pSrcPDFDoc, | 192 bool CPDF_PageOrganizer::ExportPage(const std::vector<uint16_t>& pageNums, |
| 93 std::vector<uint16_t>* pPageNums, | |
| 94 CPDF_Document* pDestPDFDoc, | |
| 95 int nIndex) { | 193 int nIndex) { |
| 96 int curpage = nIndex; | 194 int curpage = nIndex; |
| 97 std::unique_ptr<ObjectNumberMap> pObjNumberMap(new ObjectNumberMap); | 195 auto pObjNumberMap = pdfium::MakeUnique<ObjectNumberMap>(); |
| 98 int nSize = pdfium::CollectionSize<int>(*pPageNums); | 196 int nSize = pdfium::CollectionSize<int>(pageNums); |
| 99 for (int i = 0; i < nSize; ++i) { | 197 for (int i = 0; i < nSize; ++i) { |
| 100 CPDF_Dictionary* pCurPageDict = pDestPDFDoc->CreateNewPage(curpage); | 198 CPDF_Dictionary* pCurPageDict = m_pDestPDFDoc->CreateNewPage(curpage); |
| 101 CPDF_Dictionary* pSrcPageDict = pSrcPDFDoc->GetPage(pPageNums->at(i) - 1); | 199 CPDF_Dictionary* pSrcPageDict = m_pSrcPDFDoc->GetPage(pageNums[i] - 1); |
| 102 if (!pSrcPageDict || !pCurPageDict) | 200 if (!pSrcPageDict || !pCurPageDict) |
| 103 return false; | 201 return false; |
| 104 | 202 |
| 105 // Clone the page dictionary | 203 // Clone the page dictionary |
| 106 for (const auto& it : *pSrcPageDict) { | 204 for (const auto& it : *pSrcPageDict) { |
| 107 const CFX_ByteString& cbSrcKeyStr = it.first; | 205 const CFX_ByteString& cbSrcKeyStr = it.first; |
| 108 CPDF_Object* pObj = it.second; | 206 CPDF_Object* pObj = it.second; |
| 109 if (cbSrcKeyStr.Compare(("Type")) && cbSrcKeyStr.Compare(("Parent"))) { | 207 if (cbSrcKeyStr == "Type" || cbSrcKeyStr == "Parent") |
| 110 if (pCurPageDict->KeyExist(cbSrcKeyStr)) | 208 continue; |
| 111 pCurPageDict->RemoveFor(cbSrcKeyStr); | 209 |
| 112 pCurPageDict->SetFor(cbSrcKeyStr, pObj->Clone().release()); | 210 pCurPageDict->SetFor(cbSrcKeyStr, pObj->Clone().release()); |
| 211 } | |
| 212 | |
| 213 // inheritable item | |
| 214 // 1 MediaBox - required | |
| 215 if (!CopyInheritable(pCurPageDict, pSrcPageDict, "MediaBox")) { | |
| 216 // Search for "CropBox" in the source page dictionary, | |
| 217 // if it does not exists, use the default letter size. | |
| 218 CPDF_Object* pInheritable = | |
| 219 PageDictGetInheritableTag(pSrcPageDict, "CropBox"); | |
| 220 if (pInheritable) { | |
| 221 pCurPageDict->SetFor("MediaBox", pInheritable->Clone().release()); | |
| 222 } else { | |
| 223 // Make the default size to be letter size (8.5'x11') | |
| 224 CPDF_Array* pArray = new CPDF_Array; | |
| 225 pArray->AddNumber(0); | |
| 226 pArray->AddNumber(0); | |
| 227 pArray->AddNumber(612); | |
| 228 pArray->AddNumber(792); | |
| 229 pCurPageDict->SetFor("MediaBox", pArray); | |
| 113 } | 230 } |
| 114 } | 231 } |
| 115 | 232 |
| 116 // inheritable item | 233 // 2 Resources - required |
| 117 CPDF_Object* pInheritable = nullptr; | 234 if (!CopyInheritable(pCurPageDict, pSrcPageDict, "Resources")) |
| 118 // 1 MediaBox //required | 235 return false; |
| 119 if (!pCurPageDict->KeyExist("MediaBox")) { | 236 |
| 120 pInheritable = PageDictGetInheritableTag(pSrcPageDict, "MediaBox"); | 237 // 3 CropBox - optional |
| 121 if (!pInheritable) { | 238 CopyInheritable(pCurPageDict, pSrcPageDict, "CropBox"); |
| 122 // Search the "CropBox" from source page dictionary, | 239 // 4 Rotate - optional |
| 123 // if not exists,we take the letter size. | 240 CopyInheritable(pCurPageDict, pSrcPageDict, "Rotate"); |
| 124 pInheritable = PageDictGetInheritableTag(pSrcPageDict, "CropBox"); | |
| 125 if (pInheritable) { | |
| 126 pCurPageDict->SetFor("MediaBox", pInheritable->Clone().release()); | |
| 127 } else { | |
| 128 // Make the default size to be letter size (8.5'x11') | |
| 129 CPDF_Array* pArray = new CPDF_Array; | |
| 130 pArray->AddNumber(0); | |
| 131 pArray->AddNumber(0); | |
| 132 pArray->AddNumber(612); | |
| 133 pArray->AddNumber(792); | |
| 134 pCurPageDict->SetFor("MediaBox", pArray); | |
| 135 } | |
| 136 } else { | |
| 137 pCurPageDict->SetFor("MediaBox", pInheritable->Clone().release()); | |
| 138 } | |
| 139 } | |
| 140 // 2 Resources //required | |
| 141 if (!pCurPageDict->KeyExist("Resources")) { | |
| 142 pInheritable = PageDictGetInheritableTag(pSrcPageDict, "Resources"); | |
| 143 if (!pInheritable) | |
| 144 return false; | |
| 145 pCurPageDict->SetFor("Resources", pInheritable->Clone().release()); | |
| 146 } | |
| 147 // 3 CropBox //Optional | |
| 148 if (!pCurPageDict->KeyExist("CropBox")) { | |
| 149 pInheritable = PageDictGetInheritableTag(pSrcPageDict, "CropBox"); | |
| 150 if (pInheritable) | |
| 151 pCurPageDict->SetFor("CropBox", pInheritable->Clone().release()); | |
| 152 } | |
| 153 // 4 Rotate //Optional | |
| 154 if (!pCurPageDict->KeyExist("Rotate")) { | |
| 155 pInheritable = PageDictGetInheritableTag(pSrcPageDict, "Rotate"); | |
| 156 if (pInheritable) | |
| 157 pCurPageDict->SetFor("Rotate", pInheritable->Clone().release()); | |
| 158 } | |
| 159 | 241 |
| 160 // Update the reference | 242 // Update the reference |
| 161 uint32_t dwOldPageObj = pSrcPageDict->GetObjNum(); | 243 uint32_t dwOldPageObj = pSrcPageDict->GetObjNum(); |
| 162 uint32_t dwNewPageObj = pCurPageDict->GetObjNum(); | 244 uint32_t dwNewPageObj = pCurPageDict->GetObjNum(); |
| 163 (*pObjNumberMap)[dwOldPageObj] = dwNewPageObj; | 245 (*pObjNumberMap)[dwOldPageObj] = dwNewPageObj; |
| 164 UpdateReference(pCurPageDict, pDestPDFDoc, pObjNumberMap.get()); | 246 UpdateReference(pCurPageDict, pObjNumberMap.get()); |
| 165 ++curpage; | 247 ++curpage; |
| 166 } | 248 } |
| 167 | 249 |
| 168 return true; | 250 return true; |
| 169 } | 251 } |
| 170 | 252 |
| 171 CPDF_Object* CPDF_PageOrganizer::PageDictGetInheritableTag( | |
| 172 CPDF_Dictionary* pDict, | |
| 173 const CFX_ByteString& bsSrcTag) { | |
| 174 if (!pDict || bsSrcTag.IsEmpty()) | |
| 175 return nullptr; | |
| 176 if (!pDict->KeyExist("Parent") || !pDict->KeyExist("Type")) | |
| 177 return nullptr; | |
| 178 | |
| 179 CPDF_Object* pType = pDict->GetObjectFor("Type")->GetDirect(); | |
| 180 if (!ToName(pType)) | |
| 181 return nullptr; | |
| 182 if (pType->GetString().Compare("Page")) | |
| 183 return nullptr; | |
| 184 | |
| 185 CPDF_Dictionary* pp = | |
| 186 ToDictionary(pDict->GetObjectFor("Parent")->GetDirect()); | |
| 187 if (!pp) | |
| 188 return nullptr; | |
| 189 | |
| 190 if (pDict->KeyExist(bsSrcTag)) | |
| 191 return pDict->GetObjectFor(bsSrcTag); | |
| 192 | |
| 193 while (pp) { | |
| 194 if (pp->KeyExist(bsSrcTag)) | |
| 195 return pp->GetObjectFor(bsSrcTag); | |
| 196 if (!pp->KeyExist("Parent")) | |
| 197 break; | |
| 198 pp = ToDictionary(pp->GetObjectFor("Parent")->GetDirect()); | |
| 199 } | |
| 200 return nullptr; | |
| 201 } | |
| 202 | |
| 203 bool CPDF_PageOrganizer::UpdateReference(CPDF_Object* pObj, | 253 bool CPDF_PageOrganizer::UpdateReference(CPDF_Object* pObj, |
| 204 CPDF_Document* pDoc, | |
| 205 ObjectNumberMap* pObjNumberMap) { | 254 ObjectNumberMap* pObjNumberMap) { |
| 206 switch (pObj->GetType()) { | 255 switch (pObj->GetType()) { |
| 207 case CPDF_Object::REFERENCE: { | 256 case CPDF_Object::REFERENCE: { |
| 208 CPDF_Reference* pReference = pObj->AsReference(); | 257 CPDF_Reference* pReference = pObj->AsReference(); |
| 209 uint32_t newobjnum = GetNewObjId(pDoc, pObjNumberMap, pReference); | 258 uint32_t newobjnum = GetNewObjId(pObjNumberMap, pReference); |
| 210 if (newobjnum == 0) | 259 if (newobjnum == 0) |
| 211 return false; | 260 return false; |
| 212 pReference->SetRef(pDoc, newobjnum); | 261 pReference->SetRef(m_pDestPDFDoc, newobjnum); |
| 213 break; | 262 break; |
| 214 } | 263 } |
| 215 case CPDF_Object::DICTIONARY: { | 264 case CPDF_Object::DICTIONARY: { |
| 216 CPDF_Dictionary* pDict = pObj->AsDictionary(); | 265 CPDF_Dictionary* pDict = pObj->AsDictionary(); |
| 217 auto it = pDict->begin(); | 266 auto it = pDict->begin(); |
| 218 while (it != pDict->end()) { | 267 while (it != pDict->end()) { |
| 219 const CFX_ByteString& key = it->first; | 268 const CFX_ByteString& key = it->first; |
| 220 CPDF_Object* pNextObj = it->second; | 269 CPDF_Object* pNextObj = it->second; |
| 221 ++it; | 270 ++it; |
| 222 if (key == "Parent" || key == "Prev" || key == "First") | 271 if (key == "Parent" || key == "Prev" || key == "First") |
| 223 continue; | 272 continue; |
| 224 if (!pNextObj) | 273 if (!pNextObj) |
| 225 return false; | 274 return false; |
| 226 if (!UpdateReference(pNextObj, pDoc, pObjNumberMap)) | 275 if (!UpdateReference(pNextObj, pObjNumberMap)) |
| 227 pDict->RemoveFor(key); | 276 pDict->RemoveFor(key); |
| 228 } | 277 } |
| 229 break; | 278 break; |
| 230 } | 279 } |
| 231 case CPDF_Object::ARRAY: { | 280 case CPDF_Object::ARRAY: { |
| 232 CPDF_Array* pArray = pObj->AsArray(); | 281 CPDF_Array* pArray = pObj->AsArray(); |
| 233 for (size_t i = 0; i < pArray->GetCount(); ++i) { | 282 for (size_t i = 0; i < pArray->GetCount(); ++i) { |
| 234 CPDF_Object* pNextObj = pArray->GetObjectAt(i); | 283 CPDF_Object* pNextObj = pArray->GetObjectAt(i); |
| 235 if (!pNextObj) | 284 if (!pNextObj) |
| 236 return false; | 285 return false; |
| 237 if (!UpdateReference(pNextObj, pDoc, pObjNumberMap)) | 286 if (!UpdateReference(pNextObj, pObjNumberMap)) |
| 238 return false; | 287 return false; |
| 239 } | 288 } |
| 240 break; | 289 break; |
| 241 } | 290 } |
| 242 case CPDF_Object::STREAM: { | 291 case CPDF_Object::STREAM: { |
| 243 CPDF_Stream* pStream = pObj->AsStream(); | 292 CPDF_Stream* pStream = pObj->AsStream(); |
| 244 CPDF_Dictionary* pDict = pStream->GetDict(); | 293 CPDF_Dictionary* pDict = pStream->GetDict(); |
| 245 if (pDict) { | 294 if (!pDict) |
| 246 if (!UpdateReference(pDict, pDoc, pObjNumberMap)) | |
| 247 return false; | |
| 248 } else { | |
| 249 return false; | 295 return false; |
| 250 } | 296 if (!UpdateReference(pDict, pObjNumberMap)) |
| 297 return false; | |
| 251 break; | 298 break; |
| 252 } | 299 } |
| 253 default: | 300 default: |
| 254 break; | 301 break; |
| 255 } | 302 } |
| 256 | 303 |
| 257 return true; | 304 return true; |
| 258 } | 305 } |
| 259 | 306 |
| 260 uint32_t CPDF_PageOrganizer::GetNewObjId(CPDF_Document* pDoc, | 307 uint32_t CPDF_PageOrganizer::GetNewObjId(ObjectNumberMap* pObjNumberMap, |
| 261 ObjectNumberMap* pObjNumberMap, | |
| 262 CPDF_Reference* pRef) { | 308 CPDF_Reference* pRef) { |
| 263 if (!pRef) | 309 if (!pRef) |
| 264 return 0; | 310 return 0; |
| 265 | 311 |
| 266 uint32_t dwObjnum = pRef->GetRefObjNum(); | 312 uint32_t dwObjnum = pRef->GetRefObjNum(); |
| 267 uint32_t dwNewObjNum = 0; | 313 uint32_t dwNewObjNum = 0; |
| 268 const auto it = pObjNumberMap->find(dwObjnum); | 314 const auto it = pObjNumberMap->find(dwObjnum); |
| 269 if (it != pObjNumberMap->end()) | 315 if (it != pObjNumberMap->end()) |
| 270 dwNewObjNum = it->second; | 316 dwNewObjNum = it->second; |
| 271 if (dwNewObjNum) | 317 if (dwNewObjNum) |
| 272 return dwNewObjNum; | 318 return dwNewObjNum; |
| 273 | 319 |
| 274 CPDF_Object* pDirect = pRef->GetDirect(); | 320 CPDF_Object* pDirect = pRef->GetDirect(); |
| 275 if (!pDirect) | 321 if (!pDirect) |
| 276 return 0; | 322 return 0; |
| 277 | 323 |
| 278 std::unique_ptr<CPDF_Object> pClone = pDirect->Clone(); | 324 std::unique_ptr<CPDF_Object> pClone = pDirect->Clone(); |
| 279 if (CPDF_Dictionary* pDictClone = pClone->AsDictionary()) { | 325 if (CPDF_Dictionary* pDictClone = pClone->AsDictionary()) { |
| 280 if (pDictClone->KeyExist("Type")) { | 326 if (pDictClone->KeyExist("Type")) { |
| 281 CFX_ByteString strType = pDictClone->GetStringFor("Type"); | 327 CFX_ByteString strType = pDictClone->GetStringFor("Type"); |
| 282 if (!FXSYS_stricmp(strType.c_str(), "Pages")) | 328 if (!FXSYS_stricmp(strType.c_str(), "Pages")) |
| 283 return 4; | 329 return 4; |
| 284 if (!FXSYS_stricmp(strType.c_str(), "Page")) | 330 if (!FXSYS_stricmp(strType.c_str(), "Page")) |
| 285 return 0; | 331 return 0; |
| 286 } | 332 } |
| 287 } | 333 } |
| 288 CPDF_Object* pUnownedClone = pClone.get(); | 334 CPDF_Object* pUnownedClone = pClone.get(); |
| 289 dwNewObjNum = pDoc->AddIndirectObject(pClone.release()); | 335 dwNewObjNum = m_pDestPDFDoc->AddIndirectObject(pClone.release()); |
| 290 (*pObjNumberMap)[dwObjnum] = dwNewObjNum; | 336 (*pObjNumberMap)[dwObjnum] = dwNewObjNum; |
| 291 if (!UpdateReference(pUnownedClone, pDoc, pObjNumberMap)) | 337 if (!UpdateReference(pUnownedClone, pObjNumberMap)) |
| 292 return 0; | 338 return 0; |
| 293 | 339 |
| 294 return dwNewObjNum; | 340 return dwNewObjNum; |
| 295 } | 341 } |
| 296 | 342 |
| 297 FPDF_BOOL ParserPageRangeString(CFX_ByteString rangstring, | |
| 298 std::vector<uint16_t>* pageArray, | |
| 299 int nCount) { | |
| 300 if (rangstring.GetLength() != 0) { | |
| 301 rangstring.Remove(' '); | |
| 302 int nLength = rangstring.GetLength(); | |
| 303 CFX_ByteString cbCompareString("0123456789-,"); | |
| 304 for (int i = 0; i < nLength; ++i) { | |
| 305 if (cbCompareString.Find(rangstring[i]) == -1) | |
| 306 return false; | |
| 307 } | |
| 308 CFX_ByteString cbMidRange; | |
| 309 int nStringFrom = 0; | |
| 310 int nStringTo = 0; | |
| 311 while (nStringTo < nLength) { | |
| 312 nStringTo = rangstring.Find(',', nStringFrom); | |
| 313 if (nStringTo == -1) | |
| 314 nStringTo = nLength; | |
| 315 cbMidRange = rangstring.Mid(nStringFrom, nStringTo - nStringFrom); | |
| 316 int nMid = cbMidRange.Find('-'); | |
| 317 if (nMid == -1) { | |
| 318 long lPageNum = atol(cbMidRange.c_str()); | |
| 319 if (lPageNum <= 0 || lPageNum > nCount) | |
| 320 return false; | |
| 321 pageArray->push_back((uint16_t)lPageNum); | |
| 322 } else { | |
| 323 int nStartPageNum = atol(cbMidRange.Mid(0, nMid).c_str()); | |
| 324 if (nStartPageNum == 0) | |
| 325 return false; | |
| 326 | |
| 327 ++nMid; | |
| 328 int nEnd = cbMidRange.GetLength() - nMid; | |
| 329 if (nEnd == 0) | |
| 330 return false; | |
| 331 | |
| 332 int nEndPageNum = atol(cbMidRange.Mid(nMid, nEnd).c_str()); | |
| 333 if (nStartPageNum < 0 || nStartPageNum > nEndPageNum || | |
| 334 nEndPageNum > nCount) { | |
| 335 return false; | |
| 336 } | |
| 337 for (int i = nStartPageNum; i <= nEndPageNum; ++i) { | |
| 338 pageArray->push_back(i); | |
| 339 } | |
| 340 } | |
| 341 nStringFrom = nStringTo + 1; | |
| 342 } | |
| 343 } | |
| 344 return true; | |
| 345 } | |
| 346 | |
| 347 DLLEXPORT FPDF_BOOL STDCALL FPDF_ImportPages(FPDF_DOCUMENT dest_doc, | 343 DLLEXPORT FPDF_BOOL STDCALL FPDF_ImportPages(FPDF_DOCUMENT dest_doc, |
| 348 FPDF_DOCUMENT src_doc, | 344 FPDF_DOCUMENT src_doc, |
| 349 FPDF_BYTESTRING pagerange, | 345 FPDF_BYTESTRING pagerange, |
| 350 int index) { | 346 int index) { |
| 351 CPDF_Document* pDestDoc = CPDFDocumentFromFPDFDocument(dest_doc); | 347 CPDF_Document* pDestDoc = CPDFDocumentFromFPDFDocument(dest_doc); |
| 352 if (!dest_doc) | 348 if (!dest_doc) |
| 353 return false; | 349 return false; |
| 354 | 350 |
| 355 CPDF_Document* pSrcDoc = CPDFDocumentFromFPDFDocument(src_doc); | 351 CPDF_Document* pSrcDoc = CPDFDocumentFromFPDFDocument(src_doc); |
| 356 if (!pSrcDoc) | 352 if (!pSrcDoc) |
| 357 return false; | 353 return false; |
| 358 | 354 |
| 359 std::vector<uint16_t> pageArray; | 355 std::vector<uint16_t> pageArray; |
| 360 int nCount = pSrcDoc->GetPageCount(); | 356 int nCount = pSrcDoc->GetPageCount(); |
| 361 if (pagerange) { | 357 if (pagerange) { |
| 362 if (!ParserPageRangeString(pagerange, &pageArray, nCount)) | 358 if (!ParserPageRangeString(pagerange, &pageArray, nCount)) |
| 363 return false; | 359 return false; |
| 364 } else { | 360 } else { |
| 365 for (int i = 1; i <= nCount; ++i) { | 361 for (int i = 1; i <= nCount; ++i) { |
| 366 pageArray.push_back(i); | 362 pageArray.push_back(i); |
| 367 } | 363 } |
| 368 } | 364 } |
| 369 | 365 |
| 370 CPDF_PageOrganizer pageOrg; | 366 CPDF_PageOrganizer pageOrg(pDestDoc, pSrcDoc); |
| 371 pageOrg.PDFDocInit(pDestDoc, pSrcDoc); | 367 if (!pageOrg.PDFDocInit()) |
| 372 return pageOrg.ExportPage(pSrcDoc, &pageArray, pDestDoc, index); | 368 return false; |
|
Tom Sepez
2016/11/14 21:27:36
nit: or just return pageOrg.PDFDocInit() && pageOr
Lei Zhang
2016/11/14 21:37:14
Done.
| |
| 369 return pageOrg.ExportPage(pageArray, index); | |
| 373 } | 370 } |
| 374 | 371 |
| 375 DLLEXPORT FPDF_BOOL STDCALL FPDF_CopyViewerPreferences(FPDF_DOCUMENT dest_doc, | 372 DLLEXPORT FPDF_BOOL STDCALL FPDF_CopyViewerPreferences(FPDF_DOCUMENT dest_doc, |
| 376 FPDF_DOCUMENT src_doc) { | 373 FPDF_DOCUMENT src_doc) { |
| 377 CPDF_Document* pDstDoc = CPDFDocumentFromFPDFDocument(dest_doc); | 374 CPDF_Document* pDstDoc = CPDFDocumentFromFPDFDocument(dest_doc); |
| 378 if (!pDstDoc) | 375 if (!pDstDoc) |
| 379 return false; | 376 return false; |
| 380 | 377 |
| 381 CPDF_Document* pSrcDoc = CPDFDocumentFromFPDFDocument(src_doc); | 378 CPDF_Document* pSrcDoc = CPDFDocumentFromFPDFDocument(src_doc); |
| 382 if (!pSrcDoc) | 379 if (!pSrcDoc) |
| 383 return false; | 380 return false; |
| 384 | 381 |
| 385 CPDF_Dictionary* pSrcDict = pSrcDoc->GetRoot(); | 382 CPDF_Dictionary* pSrcDict = pSrcDoc->GetRoot(); |
| 386 pSrcDict = pSrcDict->GetDictFor("ViewerPreferences"); | 383 pSrcDict = pSrcDict->GetDictFor("ViewerPreferences"); |
| 387 if (!pSrcDict) | 384 if (!pSrcDict) |
| 388 return false; | 385 return false; |
| 389 | 386 |
| 390 CPDF_Dictionary* pDstDict = pDstDoc->GetRoot(); | 387 CPDF_Dictionary* pDstDict = pDstDoc->GetRoot(); |
| 391 if (!pDstDict) | 388 if (!pDstDict) |
| 392 return false; | 389 return false; |
| 393 | 390 |
| 394 pDstDict->SetFor("ViewerPreferences", | 391 pDstDict->SetFor("ViewerPreferences", |
| 395 pSrcDict->CloneDirectObject().release()); | 392 pSrcDict->CloneDirectObject().release()); |
| 396 return true; | 393 return true; |
| 397 } | 394 } |
| OLD | NEW |