| 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 #include "../../third_party/base/nonstd_unique_ptr.h" | 8 #include "../../third_party/base/nonstd_unique_ptr.h" |
| 9 #include "../include/fsdk_define.h" | 9 #include "../include/fsdk_define.h" |
| 10 | 10 |
| 11 class CPDF_PageOrganizer | 11 class CPDF_PageOrganizer { |
| 12 { | 12 public: |
| 13 public: | 13 using ObjectNumberMap = std::map<FX_DWORD, FX_DWORD>; |
| 14 using ObjectNumberMap = std::map<FX_DWORD, FX_DWORD>; | 14 CPDF_PageOrganizer(); |
| 15 CPDF_PageOrganizer(); | 15 ~CPDF_PageOrganizer(); |
| 16 ~CPDF_PageOrganizer(); | 16 |
| 17 | 17 FX_BOOL PDFDocInit(CPDF_Document* pDestPDFDoc, CPDF_Document* pSrcPDFDoc); |
| 18 FX_BOOL PDFDocInit(CPDF_Document* pDestPDFDoc, CPDF_Document* pSrcPDFDoc); | 18 FX_BOOL ExportPage(CPDF_Document* pSrcPDFDoc, |
| 19 FX_BOOL ExportPage(CPDF_Document* pSrcPDFDoc, | 19 CFX_WordArray* nPageNum, |
| 20 CFX_WordArray* nPageNum, | 20 CPDF_Document* pDestPDFDoc, |
| 21 CPDF_Document* pDestPDFDoc, | 21 int nIndex); |
| 22 int nIndex); | 22 CPDF_Object* PageDictGetInheritableTag(CPDF_Dictionary* pDict, |
| 23 CPDF_Object* PageDictGetInheritableTag(CPDF_Dictionary* pDict, | 23 CFX_ByteString nSrctag); |
| 24 CFX_ByteString nSrctag); | 24 FX_BOOL UpdateReference(CPDF_Object* pObj, |
| 25 FX_BOOL UpdateReference(CPDF_Object* pObj, | 25 CPDF_Document* pDoc, |
| 26 CPDF_Document* pDoc, | 26 ObjectNumberMap* pObjNumberMap); |
| 27 ObjectNumberMap* pObjNumberMap); | 27 FX_DWORD GetNewObjId(CPDF_Document* pDoc, |
| 28 FX_DWORD GetNewObjId(CPDF_Document* pDoc, | 28 ObjectNumberMap* pObjNumberMap, |
| 29 ObjectNumberMap* pObjNumberMap, | 29 CPDF_Reference* pRef); |
| 30 CPDF_Reference* pRef); | |
| 31 }; | 30 }; |
| 32 | 31 |
| 33 | 32 CPDF_PageOrganizer::CPDF_PageOrganizer() {} |
| 34 CPDF_PageOrganizer::CPDF_PageOrganizer() | 33 |
| 35 { | 34 CPDF_PageOrganizer::~CPDF_PageOrganizer() {} |
| 36 } | |
| 37 | |
| 38 CPDF_PageOrganizer::~CPDF_PageOrganizer() | |
| 39 { | |
| 40 } | |
| 41 | 35 |
| 42 FX_BOOL CPDF_PageOrganizer::PDFDocInit(CPDF_Document* pDestPDFDoc, | 36 FX_BOOL CPDF_PageOrganizer::PDFDocInit(CPDF_Document* pDestPDFDoc, |
| 43 CPDF_Document* pSrcPDFDoc) | 37 CPDF_Document* pSrcPDFDoc) { |
| 44 { | 38 if (!pDestPDFDoc || !pSrcPDFDoc) |
| 45 if (!pDestPDFDoc || !pSrcPDFDoc) | 39 return FALSE; |
| 46 return FALSE; | 40 |
| 47 | 41 CPDF_Dictionary* pNewRoot = pDestPDFDoc->GetRoot(); |
| 48 CPDF_Dictionary* pNewRoot = pDestPDFDoc->GetRoot(); | 42 if (!pNewRoot) |
| 49 if (!pNewRoot) | 43 return FALSE; |
| 50 return FALSE; | 44 |
| 51 | 45 // Set the document information//////////////////////////////////////////// |
| 52 //Set the document information//////////////////////////////////////////// | 46 |
| 53 | 47 CPDF_Dictionary* DInfoDict = pDestPDFDoc->GetInfo(); |
| 54 CPDF_Dictionary* DInfoDict = pDestPDFDoc->GetInfo(); | 48 if (!DInfoDict) |
| 55 if (!DInfoDict) | 49 return FALSE; |
| 56 return FALSE; | 50 |
| 57 | 51 CFX_ByteString producerstr; |
| 58 CFX_ByteString producerstr; | 52 producerstr.Format("PDFium"); |
| 59 producerstr.Format("PDFium"); | 53 DInfoDict->SetAt("Producer", new CPDF_String(producerstr)); |
| 60 DInfoDict->SetAt("Producer", new CPDF_String(producerstr)); | 54 |
| 61 | 55 // Set type//////////////////////////////////////////////////////////////// |
| 62 //Set type//////////////////////////////////////////////////////////////// | 56 CFX_ByteString cbRootType = pNewRoot->GetString("Type", ""); |
| 63 CFX_ByteString cbRootType = pNewRoot->GetString("Type", ""); | 57 if (cbRootType.Equal("")) { |
| 64 if (cbRootType.Equal("") ) { | 58 pNewRoot->SetAt("Type", new CPDF_Name("Catalog")); |
| 65 pNewRoot->SetAt("Type", new CPDF_Name("Catalog")); | 59 } |
| 66 } | 60 |
| 67 | 61 CPDF_Object* pElement = pNewRoot->GetElement("Pages"); |
| 68 CPDF_Object* pElement = pNewRoot->GetElement("Pages"); | 62 CPDF_Dictionary* pNewPages = |
| 69 CPDF_Dictionary* pNewPages = pElement ? | 63 pElement ? (CPDF_Dictionary*)pElement->GetDirect() : nullptr; |
| 70 (CPDF_Dictionary*)pElement->GetDirect() : nullptr; | 64 if (!pNewPages) { |
| 71 if (!pNewPages) { | 65 pNewPages = new CPDF_Dictionary; |
| 72 pNewPages = new CPDF_Dictionary; | 66 FX_DWORD NewPagesON = pDestPDFDoc->AddIndirectObject(pNewPages); |
| 73 FX_DWORD NewPagesON = pDestPDFDoc->AddIndirectObject(pNewPages); | 67 pNewRoot->SetAt("Pages", new CPDF_Reference(pDestPDFDoc, NewPagesON)); |
| 74 pNewRoot->SetAt("Pages", new CPDF_Reference(pDestPDFDoc, NewPagesON)); | 68 } |
| 75 } | 69 |
| 76 | 70 CFX_ByteString cbPageType = pNewPages->GetString("Type", ""); |
| 77 CFX_ByteString cbPageType = pNewPages->GetString("Type", ""); | 71 if (cbPageType.Equal("")) { |
| 78 if (cbPageType.Equal("")) { | 72 pNewPages->SetAt("Type", new CPDF_Name("Pages")); |
| 79 pNewPages->SetAt("Type", new CPDF_Name("Pages")); | 73 } |
| 80 } | 74 |
| 81 | 75 CPDF_Array* pKeysArray = pNewPages->GetArray("Kids"); |
| 82 CPDF_Array* pKeysArray = pNewPages->GetArray("Kids"); | 76 if (!pKeysArray) { |
| 83 if (!pKeysArray) { | 77 CPDF_Array* pNewKids = new CPDF_Array; |
| 84 CPDF_Array* pNewKids = new CPDF_Array; | 78 FX_DWORD Kidsobjnum = -1; |
| 85 FX_DWORD Kidsobjnum = -1; | 79 Kidsobjnum = pDestPDFDoc->AddIndirectObject(pNewKids); |
| 86 Kidsobjnum = pDestPDFDoc->AddIndirectObject(pNewKids); | 80 |
| 87 | 81 pNewPages->SetAt("Kids", new CPDF_Reference(pDestPDFDoc, Kidsobjnum)); |
| 88 pNewPages->SetAt("Kids", new CPDF_Reference(pDestPDFDoc, Kidsobjnum)); | 82 pNewPages->SetAt("Count", new CPDF_Number(0)); |
| 89 pNewPages->SetAt("Count", new CPDF_Number(0)); | 83 } |
| 90 } | 84 |
| 91 | 85 return TRUE; |
| 92 return TRUE; | |
| 93 } | 86 } |
| 94 | 87 |
| 95 FX_BOOL CPDF_PageOrganizer::ExportPage(CPDF_Document* pSrcPDFDoc, | 88 FX_BOOL CPDF_PageOrganizer::ExportPage(CPDF_Document* pSrcPDFDoc, |
| 96 CFX_WordArray* nPageNum, | 89 CFX_WordArray* nPageNum, |
| 97 CPDF_Document* pDestPDFDoc, | 90 CPDF_Document* pDestPDFDoc, |
| 98 int nIndex) | 91 int nIndex) { |
| 99 { | 92 int curpage = nIndex; |
| 100 int curpage = nIndex; | 93 |
| 101 | 94 nonstd::unique_ptr<ObjectNumberMap> pObjNumberMap(new ObjectNumberMap); |
| 102 nonstd::unique_ptr<ObjectNumberMap> pObjNumberMap(new ObjectNumberMap); | 95 |
| 103 | 96 for (int i = 0; i < nPageNum->GetSize(); ++i) { |
| 104 for (int i = 0; i < nPageNum->GetSize(); ++i) { | 97 CPDF_Dictionary* pCurPageDict = pDestPDFDoc->CreateNewPage(curpage); |
| 105 CPDF_Dictionary* pCurPageDict = pDestPDFDoc->CreateNewPage(curpage); | 98 CPDF_Dictionary* pSrcPageDict = pSrcPDFDoc->GetPage(nPageNum->GetAt(i) - 1); |
| 106 CPDF_Dictionary* pSrcPageDict = | 99 if (!pSrcPageDict || !pCurPageDict) |
| 107 pSrcPDFDoc->GetPage(nPageNum->GetAt(i) - 1); | 100 return FALSE; |
| 108 if (!pSrcPageDict || !pCurPageDict) | 101 |
| 109 return FALSE; | 102 // Clone the page dictionary/////////// |
| 110 | 103 FX_POSITION SrcPos = pSrcPageDict->GetStartPos(); |
| 111 // Clone the page dictionary/////////// | 104 while (SrcPos) { |
| 112 FX_POSITION SrcPos = pSrcPageDict->GetStartPos(); | 105 CFX_ByteString cbSrcKeyStr; |
| 113 while (SrcPos) { | 106 CPDF_Object* pObj = pSrcPageDict->GetNextElement(SrcPos, cbSrcKeyStr); |
| 114 CFX_ByteString cbSrcKeyStr; | 107 if (cbSrcKeyStr.Compare(("Type")) && cbSrcKeyStr.Compare(("Parent"))) { |
| 115 CPDF_Object* pObj = pSrcPageDict->GetNextElement(SrcPos, | 108 if (pCurPageDict->KeyExist(cbSrcKeyStr)) |
| 116 cbSrcKeyStr); | 109 pCurPageDict->RemoveAt(cbSrcKeyStr); |
| 117 if (cbSrcKeyStr.Compare(("Type")) && | 110 pCurPageDict->SetAt(cbSrcKeyStr, pObj->Clone()); |
| 118 cbSrcKeyStr.Compare(("Parent"))) { | 111 } |
| 119 if (pCurPageDict->KeyExist(cbSrcKeyStr)) | 112 } |
| 120 pCurPageDict->RemoveAt(cbSrcKeyStr); | 113 |
| 121 pCurPageDict->SetAt(cbSrcKeyStr, pObj->Clone()); | 114 // inheritable item/////////////////////// |
| 122 } | 115 CPDF_Object* pInheritable = nullptr; |
| 116 // 1 MediaBox //required |
| 117 if (!pCurPageDict->KeyExist("MediaBox")) { |
| 118 pInheritable = PageDictGetInheritableTag(pSrcPageDict, "MediaBox"); |
| 119 if (!pInheritable) { |
| 120 // Search the "CropBox" from source page dictionary, |
| 121 // if not exists,we take the letter size. |
| 122 pInheritable = PageDictGetInheritableTag(pSrcPageDict, "CropBox"); |
| 123 if (pInheritable) { |
| 124 pCurPageDict->SetAt("MediaBox", pInheritable->Clone()); |
| 125 } else { |
| 126 // Make the default size to be letter size (8.5'x11') |
| 127 CPDF_Array* pArray = new CPDF_Array; |
| 128 pArray->AddNumber(0); |
| 129 pArray->AddNumber(0); |
| 130 pArray->AddNumber(612); |
| 131 pArray->AddNumber(792); |
| 132 pCurPageDict->SetAt("MediaBox", pArray); |
| 123 } | 133 } |
| 124 | 134 } else { |
| 125 //inheritable item/////////////////////// | 135 pCurPageDict->SetAt("MediaBox", pInheritable->Clone()); |
| 126 CPDF_Object* pInheritable = nullptr; | 136 } |
| 127 //1 MediaBox //required | 137 } |
| 128 if (!pCurPageDict->KeyExist("MediaBox")) { | 138 // 2 Resources //required |
| 129 pInheritable = PageDictGetInheritableTag(pSrcPageDict, "MediaBox"); | 139 if (!pCurPageDict->KeyExist("Resources")) { |
| 130 if (!pInheritable) { | 140 pInheritable = PageDictGetInheritableTag(pSrcPageDict, "Resources"); |
| 131 // Search the "CropBox" from source page dictionary, | 141 if (!pInheritable) |
| 132 // if not exists,we take the letter size. | 142 return FALSE; |
| 133 pInheritable = PageDictGetInheritableTag(pSrcPageDict, | 143 pCurPageDict->SetAt("Resources", pInheritable->Clone()); |
| 134 "CropBox"); | 144 } |
| 135 if (pInheritable) { | 145 // 3 CropBox //Optional |
| 136 pCurPageDict->SetAt("MediaBox", pInheritable->Clone()); | 146 if (!pCurPageDict->KeyExist("CropBox")) { |
| 137 } else { | 147 pInheritable = PageDictGetInheritableTag(pSrcPageDict, "CropBox"); |
| 138 // Make the default size to be letter size (8.5'x11') | 148 if (pInheritable) |
| 139 CPDF_Array* pArray = new CPDF_Array; | 149 pCurPageDict->SetAt("CropBox", pInheritable->Clone()); |
| 140 pArray->AddNumber(0); | 150 } |
| 141 pArray->AddNumber(0); | 151 // 4 Rotate //Optional |
| 142 pArray->AddNumber(612); | 152 if (!pCurPageDict->KeyExist("Rotate")) { |
| 143 pArray->AddNumber(792); | 153 pInheritable = PageDictGetInheritableTag(pSrcPageDict, "Rotate"); |
| 144 pCurPageDict->SetAt("MediaBox", pArray); | 154 if (pInheritable) |
| 145 } | 155 pCurPageDict->SetAt("Rotate", pInheritable->Clone()); |
| 146 } else { | 156 } |
| 147 pCurPageDict->SetAt("MediaBox", pInheritable->Clone()); | 157 |
| 148 } | 158 ///////////////////////////////////////////// |
| 149 } | 159 // Update the reference |
| 150 //2 Resources //required | 160 FX_DWORD dwOldPageObj = pSrcPageDict->GetObjNum(); |
| 151 if (!pCurPageDict->KeyExist("Resources")) { | 161 FX_DWORD dwNewPageObj = pCurPageDict->GetObjNum(); |
| 152 pInheritable = PageDictGetInheritableTag(pSrcPageDict, "Resources"); | 162 |
| 153 if (!pInheritable) | 163 (*pObjNumberMap)[dwOldPageObj] = dwNewPageObj; |
| 154 return FALSE; | 164 |
| 155 pCurPageDict->SetAt("Resources", pInheritable->Clone()); | 165 UpdateReference(pCurPageDict, pDestPDFDoc, pObjNumberMap.get()); |
| 156 } | 166 ++curpage; |
| 157 //3 CropBox //Optional | 167 } |
| 158 if (!pCurPageDict->KeyExist("CropBox")) { | 168 |
| 159 pInheritable = PageDictGetInheritableTag(pSrcPageDict, "CropBox"); | 169 return TRUE; |
| 160 if (pInheritable) | |
| 161 pCurPageDict->SetAt("CropBox", pInheritable->Clone()); | |
| 162 } | |
| 163 //4 Rotate //Optional | |
| 164 if (!pCurPageDict->KeyExist("Rotate")) { | |
| 165 pInheritable = PageDictGetInheritableTag(pSrcPageDict, "Rotate"); | |
| 166 if (pInheritable) | |
| 167 pCurPageDict->SetAt("Rotate", pInheritable->Clone()); | |
| 168 } | |
| 169 | |
| 170 ///////////////////////////////////////////// | |
| 171 //Update the reference | |
| 172 FX_DWORD dwOldPageObj = pSrcPageDict->GetObjNum(); | |
| 173 FX_DWORD dwNewPageObj = pCurPageDict->GetObjNum(); | |
| 174 | |
| 175 (*pObjNumberMap)[dwOldPageObj] = dwNewPageObj; | |
| 176 | |
| 177 UpdateReference(pCurPageDict, pDestPDFDoc, pObjNumberMap.get()); | |
| 178 ++curpage; | |
| 179 } | |
| 180 | |
| 181 return TRUE; | |
| 182 } | 170 } |
| 183 | 171 |
| 184 CPDF_Object* CPDF_PageOrganizer::PageDictGetInheritableTag( | 172 CPDF_Object* CPDF_PageOrganizer::PageDictGetInheritableTag( |
| 185 CPDF_Dictionary* pDict, | 173 CPDF_Dictionary* pDict, |
| 186 CFX_ByteString nSrctag) | 174 CFX_ByteString nSrctag) { |
| 187 { | 175 if (!pDict || nSrctag.IsEmpty()) |
| 188 if (!pDict || nSrctag.IsEmpty()) | |
| 189 return nullptr; | |
| 190 if (!pDict->KeyExist("Parent") || !pDict->KeyExist("Type")) | |
| 191 return nullptr; | |
| 192 | |
| 193 CPDF_Object* pType = pDict->GetElement("Type")->GetDirect(); | |
| 194 if (!pType || pType->GetType() != PDFOBJ_NAME) | |
| 195 return nullptr; | |
| 196 if (pType->GetString().Compare("Page")) | |
| 197 return nullptr; | |
| 198 | |
| 199 CPDF_Object* pParent = pDict->GetElement("Parent")->GetDirect(); | |
| 200 if (!pParent || pParent->GetType() != PDFOBJ_DICTIONARY) | |
| 201 return nullptr; | |
| 202 | |
| 203 if (pDict->KeyExist((const char*)nSrctag)) | |
| 204 return pDict->GetElement((const char*)nSrctag); | |
| 205 | |
| 206 CPDF_Dictionary* pp = (CPDF_Dictionary*)pParent; | |
| 207 while (pp) { | |
| 208 if (pp->KeyExist((const char*)nSrctag)) { | |
| 209 return pp->GetElement((const char*)nSrctag); | |
| 210 } | |
| 211 if (!pp->KeyExist("Parent")) { | |
| 212 break; | |
| 213 } | |
| 214 pp = (CPDF_Dictionary*)pp->GetElement("Parent")->GetDirect(); | |
| 215 if (pp->GetType() == PDFOBJ_NULL) { | |
| 216 break; | |
| 217 } | |
| 218 } | |
| 219 | |
| 220 return nullptr; | 176 return nullptr; |
| 177 if (!pDict->KeyExist("Parent") || !pDict->KeyExist("Type")) |
| 178 return nullptr; |
| 179 |
| 180 CPDF_Object* pType = pDict->GetElement("Type")->GetDirect(); |
| 181 if (!pType || pType->GetType() != PDFOBJ_NAME) |
| 182 return nullptr; |
| 183 if (pType->GetString().Compare("Page")) |
| 184 return nullptr; |
| 185 |
| 186 CPDF_Object* pParent = pDict->GetElement("Parent")->GetDirect(); |
| 187 if (!pParent || pParent->GetType() != PDFOBJ_DICTIONARY) |
| 188 return nullptr; |
| 189 |
| 190 if (pDict->KeyExist((const char*)nSrctag)) |
| 191 return pDict->GetElement((const char*)nSrctag); |
| 192 |
| 193 CPDF_Dictionary* pp = (CPDF_Dictionary*)pParent; |
| 194 while (pp) { |
| 195 if (pp->KeyExist((const char*)nSrctag)) { |
| 196 return pp->GetElement((const char*)nSrctag); |
| 197 } |
| 198 if (!pp->KeyExist("Parent")) { |
| 199 break; |
| 200 } |
| 201 pp = (CPDF_Dictionary*)pp->GetElement("Parent")->GetDirect(); |
| 202 if (pp->GetType() == PDFOBJ_NULL) { |
| 203 break; |
| 204 } |
| 205 } |
| 206 |
| 207 return nullptr; |
| 221 } | 208 } |
| 222 | 209 |
| 223 FX_BOOL CPDF_PageOrganizer::UpdateReference(CPDF_Object* pObj, | 210 FX_BOOL CPDF_PageOrganizer::UpdateReference(CPDF_Object* pObj, |
| 224 CPDF_Document* pDoc, | 211 CPDF_Document* pDoc, |
| 225 ObjectNumberMap* pObjNumberMap) | 212 ObjectNumberMap* pObjNumberMap) { |
| 226 { | 213 switch (pObj->GetType()) { |
| 227 switch (pObj->GetType()) { | 214 case PDFOBJ_REFERENCE: { |
| 228 case PDFOBJ_REFERENCE: { | 215 CPDF_Reference* pReference = (CPDF_Reference*)pObj; |
| 229 CPDF_Reference* pReference = (CPDF_Reference*)pObj; | 216 FX_DWORD newobjnum = GetNewObjId(pDoc, pObjNumberMap, pReference); |
| 230 FX_DWORD newobjnum = GetNewObjId(pDoc, pObjNumberMap, pReference); | 217 if (newobjnum == 0) |
| 231 if (newobjnum == 0) | 218 return FALSE; |
| 232 return FALSE; | 219 pReference->SetRef(pDoc, newobjnum); |
| 233 pReference->SetRef(pDoc, newobjnum); | 220 break; |
| 234 break; | 221 } |
| 222 case PDFOBJ_DICTIONARY: { |
| 223 CPDF_Dictionary* pDict = (CPDF_Dictionary*)pObj; |
| 224 |
| 225 FX_POSITION pos = pDict->GetStartPos(); |
| 226 while (pos) { |
| 227 CFX_ByteString key(""); |
| 228 CPDF_Object* pNextObj = pDict->GetNextElement(pos, key); |
| 229 if (!FXSYS_strcmp(key, "Parent") || !FXSYS_strcmp(key, "Prev") || |
| 230 !FXSYS_strcmp(key, "First")) { |
| 231 continue; |
| 235 } | 232 } |
| 236 case PDFOBJ_DICTIONARY: { | 233 if (pNextObj) { |
| 237 CPDF_Dictionary* pDict = (CPDF_Dictionary*)pObj; | 234 if (!UpdateReference(pNextObj, pDoc, pObjNumberMap)) |
| 238 | 235 pDict->RemoveAt(key); |
| 239 FX_POSITION pos = pDict->GetStartPos(); | 236 } else { |
| 240 while (pos) { | 237 return FALSE; |
| 241 CFX_ByteString key(""); | |
| 242 CPDF_Object* pNextObj = pDict->GetNextElement(pos, key); | |
| 243 if (!FXSYS_strcmp(key, "Parent") || | |
| 244 !FXSYS_strcmp(key, "Prev") || | |
| 245 !FXSYS_strcmp(key, "First")) { | |
| 246 continue; | |
| 247 } | |
| 248 if (pNextObj) { | |
| 249 if (!UpdateReference(pNextObj, pDoc, pObjNumberMap)) | |
| 250 pDict->RemoveAt(key); | |
| 251 } else { | |
| 252 return FALSE; | |
| 253 } | |
| 254 } | |
| 255 break; | |
| 256 } | 238 } |
| 257 case PDFOBJ_ARRAY: { | 239 } |
| 258 CPDF_Array* pArray = (CPDF_Array*)pObj; | 240 break; |
| 259 FX_DWORD count = pArray->GetCount(); | 241 } |
| 260 for (FX_DWORD i = 0; i < count; ++i) { | 242 case PDFOBJ_ARRAY: { |
| 261 CPDF_Object* pNextObj = pArray->GetElement(i); | 243 CPDF_Array* pArray = (CPDF_Array*)pObj; |
| 262 if (!pNextObj) | 244 FX_DWORD count = pArray->GetCount(); |
| 263 return FALSE; | 245 for (FX_DWORD i = 0; i < count; ++i) { |
| 264 if (!UpdateReference(pNextObj, pDoc, pObjNumberMap)) | 246 CPDF_Object* pNextObj = pArray->GetElement(i); |
| 265 return FALSE; | 247 if (!pNextObj) |
| 266 } | 248 return FALSE; |
| 267 break; | 249 if (!UpdateReference(pNextObj, pDoc, pObjNumberMap)) |
| 268 } | 250 return FALSE; |
| 269 case PDFOBJ_STREAM: { | 251 } |
| 270 CPDF_Stream* pStream = (CPDF_Stream*)pObj; | 252 break; |
| 271 CPDF_Dictionary* pDict = pStream->GetDict(); | 253 } |
| 272 if (pDict) { | 254 case PDFOBJ_STREAM: { |
| 273 if (!UpdateReference(pDict, pDoc, pObjNumberMap)) | 255 CPDF_Stream* pStream = (CPDF_Stream*)pObj; |
| 274 return FALSE; | 256 CPDF_Dictionary* pDict = pStream->GetDict(); |
| 275 } else { | 257 if (pDict) { |
| 276 return FALSE; | 258 if (!UpdateReference(pDict, pDoc, pObjNumberMap)) |
| 277 } | 259 return FALSE; |
| 278 break; | 260 } else { |
| 279 } | 261 return FALSE; |
| 280 default: | 262 } |
| 281 break; | 263 break; |
| 282 } | 264 } |
| 283 | 265 default: |
| 284 return TRUE; | 266 break; |
| 267 } |
| 268 |
| 269 return TRUE; |
| 285 } | 270 } |
| 286 | 271 |
| 287 FX_DWORD CPDF_PageOrganizer::GetNewObjId(CPDF_Document* pDoc, | 272 FX_DWORD CPDF_PageOrganizer::GetNewObjId(CPDF_Document* pDoc, |
| 288 ObjectNumberMap* pObjNumberMap, | 273 ObjectNumberMap* pObjNumberMap, |
| 289 CPDF_Reference* pRef) | 274 CPDF_Reference* pRef) { |
| 290 { | 275 if (!pRef) |
| 291 if (!pRef) | 276 return 0; |
| 277 |
| 278 FX_DWORD dwObjnum = pRef->GetRefObjNum(); |
| 279 FX_DWORD dwNewObjNum = 0; |
| 280 const auto it = pObjNumberMap->find(dwObjnum); |
| 281 if (it != pObjNumberMap->end()) |
| 282 dwNewObjNum = it->second; |
| 283 if (dwNewObjNum) |
| 284 return dwNewObjNum; |
| 285 |
| 286 CPDF_Object* pDirect = pRef->GetDirect(); |
| 287 if (!pDirect) |
| 288 return 0; |
| 289 |
| 290 CPDF_Object* pClone = pDirect->Clone(); |
| 291 if (!pClone) |
| 292 return 0; |
| 293 |
| 294 if (pClone->GetType() == PDFOBJ_DICTIONARY) { |
| 295 CPDF_Dictionary* pDictClone = (CPDF_Dictionary*)pClone; |
| 296 if (pDictClone->KeyExist("Type")) { |
| 297 CFX_ByteString strType = pDictClone->GetString("Type"); |
| 298 if (!FXSYS_stricmp(strType, "Pages")) { |
| 299 pDictClone->Release(); |
| 300 return 4; |
| 301 } |
| 302 if (!FXSYS_stricmp(strType, "Page")) { |
| 303 pDictClone->Release(); |
| 292 return 0; | 304 return 0; |
| 293 | 305 } |
| 294 FX_DWORD dwObjnum = pRef->GetRefObjNum(); | 306 } |
| 295 FX_DWORD dwNewObjNum = 0; | 307 } |
| 296 const auto it = pObjNumberMap->find(dwObjnum); | 308 dwNewObjNum = pDoc->AddIndirectObject(pClone); |
| 297 if (it != pObjNumberMap->end()) | 309 (*pObjNumberMap)[dwObjnum] = dwNewObjNum; |
| 298 dwNewObjNum = it->second; | 310 |
| 299 if (dwNewObjNum) | 311 if (!UpdateReference(pClone, pDoc, pObjNumberMap)) { |
| 300 return dwNewObjNum; | 312 pClone->Release(); |
| 301 | 313 return 0; |
| 302 CPDF_Object* pDirect = pRef->GetDirect(); | 314 } |
| 303 if (!pDirect) | 315 return dwNewObjNum; |
| 304 return 0; | |
| 305 | |
| 306 CPDF_Object* pClone = pDirect->Clone(); | |
| 307 if (!pClone) | |
| 308 return 0; | |
| 309 | |
| 310 if (pClone->GetType() == PDFOBJ_DICTIONARY) { | |
| 311 CPDF_Dictionary* pDictClone = (CPDF_Dictionary*)pClone; | |
| 312 if (pDictClone->KeyExist("Type")) { | |
| 313 CFX_ByteString strType = pDictClone->GetString("Type"); | |
| 314 if (!FXSYS_stricmp(strType, "Pages")) { | |
| 315 pDictClone->Release(); | |
| 316 return 4; | |
| 317 } | |
| 318 if (!FXSYS_stricmp(strType, "Page")) { | |
| 319 pDictClone->Release(); | |
| 320 return 0; | |
| 321 } | |
| 322 } | |
| 323 } | |
| 324 dwNewObjNum = pDoc->AddIndirectObject(pClone); | |
| 325 (*pObjNumberMap)[dwObjnum] = dwNewObjNum; | |
| 326 | |
| 327 if (!UpdateReference(pClone, pDoc, pObjNumberMap)) { | |
| 328 pClone->Release(); | |
| 329 return 0; | |
| 330 } | |
| 331 return dwNewObjNum; | |
| 332 } | 316 } |
| 333 | 317 |
| 334 FPDF_BOOL ParserPageRangeString(CFX_ByteString rangstring, | 318 FPDF_BOOL ParserPageRangeString(CFX_ByteString rangstring, |
| 335 CFX_WordArray* pageArray, | 319 CFX_WordArray* pageArray, |
| 336 int nCount) | 320 int nCount) { |
| 337 { | 321 if (rangstring.GetLength() != 0) { |
| 338 if (rangstring.GetLength() != 0) { | 322 rangstring.Remove(' '); |
| 339 rangstring.Remove(' '); | 323 int nLength = rangstring.GetLength(); |
| 340 int nLength = rangstring.GetLength(); | 324 CFX_ByteString cbCompareString("0123456789-,"); |
| 341 CFX_ByteString cbCompareString("0123456789-,"); | 325 for (int i = 0; i < nLength; ++i) { |
| 342 for (int i = 0; i < nLength; ++i) { | 326 if (cbCompareString.Find(rangstring[i]) == -1) |
| 343 if (cbCompareString.Find(rangstring[i]) == -1) | 327 return FALSE; |
| 344 return FALSE; | 328 } |
| 329 CFX_ByteString cbMidRange; |
| 330 int nStringFrom = 0; |
| 331 int nStringTo = 0; |
| 332 while (nStringTo < nLength) { |
| 333 nStringTo = rangstring.Find(',', nStringFrom); |
| 334 if (nStringTo == -1) |
| 335 nStringTo = nLength; |
| 336 cbMidRange = rangstring.Mid(nStringFrom, nStringTo - nStringFrom); |
| 337 int nMid = cbMidRange.Find('-'); |
| 338 if (nMid == -1) { |
| 339 long lPageNum = atol(cbMidRange); |
| 340 if (lPageNum <= 0 || lPageNum > nCount) |
| 341 return FALSE; |
| 342 pageArray->Add((FX_WORD)lPageNum); |
| 343 } else { |
| 344 int nStartPageNum = atol(cbMidRange.Mid(0, nMid)); |
| 345 if (nStartPageNum == 0) |
| 346 return FALSE; |
| 347 |
| 348 ++nMid; |
| 349 int nEnd = cbMidRange.GetLength() - nMid; |
| 350 if (nEnd == 0) |
| 351 return FALSE; |
| 352 |
| 353 int nEndPageNum = atol(cbMidRange.Mid(nMid, nEnd)); |
| 354 if (nStartPageNum < 0 || nStartPageNum > nEndPageNum || |
| 355 nEndPageNum > nCount) { |
| 356 return FALSE; |
| 345 } | 357 } |
| 346 CFX_ByteString cbMidRange; | 358 for (int i = nStartPageNum; i <= nEndPageNum; ++i) { |
| 347 int nStringFrom = 0; | 359 pageArray->Add(i); |
| 348 int nStringTo = 0; | |
| 349 while (nStringTo < nLength) { | |
| 350 nStringTo = rangstring.Find(',', nStringFrom); | |
| 351 if (nStringTo == -1) | |
| 352 nStringTo = nLength; | |
| 353 cbMidRange = rangstring.Mid(nStringFrom, nStringTo - nStringFrom); | |
| 354 int nMid = cbMidRange.Find('-'); | |
| 355 if (nMid == -1) { | |
| 356 long lPageNum = atol(cbMidRange); | |
| 357 if (lPageNum <= 0 || lPageNum > nCount) | |
| 358 return FALSE; | |
| 359 pageArray->Add((FX_WORD)lPageNum); | |
| 360 } else { | |
| 361 int nStartPageNum = atol(cbMidRange.Mid(0, nMid)); | |
| 362 if (nStartPageNum == 0) | |
| 363 return FALSE; | |
| 364 | |
| 365 ++nMid; | |
| 366 int nEnd = cbMidRange.GetLength() - nMid; | |
| 367 if (nEnd == 0) | |
| 368 return FALSE; | |
| 369 | |
| 370 int nEndPageNum = atol(cbMidRange.Mid(nMid, nEnd)); | |
| 371 if (nStartPageNum < 0 || | |
| 372 nStartPageNum >nEndPageNum || | |
| 373 nEndPageNum > nCount) { | |
| 374 return FALSE; | |
| 375 } | |
| 376 for (int i = nStartPageNum; i <= nEndPageNum; ++i) { | |
| 377 pageArray->Add(i); | |
| 378 } | |
| 379 } | |
| 380 nStringFrom = nStringTo + 1; | |
| 381 } | 360 } |
| 382 } | 361 } |
| 383 return TRUE; | 362 nStringFrom = nStringTo + 1; |
| 363 } |
| 364 } |
| 365 return TRUE; |
| 384 } | 366 } |
| 385 | 367 |
| 386 DLLEXPORT FPDF_BOOL STDCALL FPDF_ImportPages(FPDF_DOCUMENT dest_doc, | 368 DLLEXPORT FPDF_BOOL STDCALL FPDF_ImportPages(FPDF_DOCUMENT dest_doc, |
| 387 FPDF_DOCUMENT src_doc, | 369 FPDF_DOCUMENT src_doc, |
| 388 FPDF_BYTESTRING pagerange, | 370 FPDF_BYTESTRING pagerange, |
| 389 int index) | 371 int index) { |
| 390 { | 372 if (!dest_doc || !src_doc) |
| 391 if (!dest_doc || !src_doc) | 373 return FALSE; |
| 392 return FALSE; | 374 |
| 393 | 375 CFX_WordArray pageArray; |
| 394 CFX_WordArray pageArray; | 376 CPDF_Document* pSrcDoc = (CPDF_Document*)src_doc; |
| 395 CPDF_Document* pSrcDoc = (CPDF_Document*)src_doc; | 377 int nCount = pSrcDoc->GetPageCount(); |
| 396 int nCount = pSrcDoc->GetPageCount(); | 378 if (pagerange) { |
| 397 if (pagerange) { | 379 if (!ParserPageRangeString(pagerange, &pageArray, nCount)) |
| 398 if (!ParserPageRangeString(pagerange,&pageArray,nCount)) | 380 return FALSE; |
| 399 return FALSE; | 381 } else { |
| 400 } else { | 382 for (int i = 1; i <= nCount; ++i) { |
| 401 for (int i = 1; i <= nCount; ++i) { | 383 pageArray.Add(i); |
| 402 pageArray.Add(i); | 384 } |
| 403 } | 385 } |
| 404 } | 386 |
| 405 | 387 CPDF_Document* pDestDoc = (CPDF_Document*)dest_doc; |
| 406 CPDF_Document* pDestDoc = (CPDF_Document*)dest_doc; | 388 CPDF_PageOrganizer pageOrg; |
| 407 CPDF_PageOrganizer pageOrg; | 389 |
| 408 | 390 pageOrg.PDFDocInit(pDestDoc, pSrcDoc); |
| 409 pageOrg.PDFDocInit(pDestDoc, pSrcDoc); | 391 |
| 410 | 392 return pageOrg.ExportPage(pSrcDoc, &pageArray, pDestDoc, index); |
| 411 return pageOrg.ExportPage(pSrcDoc,&pageArray,pDestDoc,index); | |
| 412 } | 393 } |
| 413 | 394 |
| 414 DLLEXPORT FPDF_BOOL STDCALL FPDF_CopyViewerPreferences(FPDF_DOCUMENT dest_doc, | 395 DLLEXPORT FPDF_BOOL STDCALL FPDF_CopyViewerPreferences(FPDF_DOCUMENT dest_doc, |
| 415 FPDF_DOCUMENT src_doc) | 396 FPDF_DOCUMENT src_doc) { |
| 416 { | 397 if (!src_doc || !dest_doc) |
| 417 if (!src_doc || !dest_doc) | 398 return false; |
| 418 return false; | 399 |
| 419 | 400 CPDF_Document* pSrcDoc = (CPDF_Document*)src_doc; |
| 420 CPDF_Document* pSrcDoc = (CPDF_Document*)src_doc; | 401 CPDF_Dictionary* pSrcDict = pSrcDoc->GetRoot(); |
| 421 CPDF_Dictionary* pSrcDict = pSrcDoc->GetRoot(); | 402 pSrcDict = pSrcDict->GetDict(FX_BSTRC("ViewerPreferences")); |
| 422 pSrcDict = pSrcDict->GetDict(FX_BSTRC("ViewerPreferences"));; | 403 ; |
| 423 if (!pSrcDict) | 404 if (!pSrcDict) |
| 424 return FALSE; | 405 return FALSE; |
| 425 | 406 |
| 426 CPDF_Document* pDstDoc = (CPDF_Document*)dest_doc; | 407 CPDF_Document* pDstDoc = (CPDF_Document*)dest_doc; |
| 427 CPDF_Dictionary* pDstDict = pDstDoc->GetRoot(); | 408 CPDF_Dictionary* pDstDict = pDstDoc->GetRoot(); |
| 428 if (!pDstDict) | 409 if (!pDstDict) |
| 429 return FALSE; | 410 return FALSE; |
| 430 pDstDict->SetAt(FX_BSTRC("ViewerPreferences"), pSrcDict->Clone(TRUE)); | 411 pDstDict->SetAt(FX_BSTRC("ViewerPreferences"), pSrcDict->Clone(TRUE)); |
| 431 return TRUE; | 412 return TRUE; |
| 432 } | 413 } |
| OLD | NEW |