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 |