blob: 3caba0e1e42b3a553ff3e417402091a941846ebf [file] [log] [blame]
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001// Copyright 2014 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
Lei Zhangb4e7f302015-11-06 15:52:32 -08007#include "public/fpdf_ppo.h"
8
Dan Sinclair3ebd1212016-03-09 09:59:23 -05009#include <map>
Lei Zhangaa8bf7e2015-12-24 19:13:32 -080010#include <memory>
tsepez0e606b52016-11-18 16:22:41 -080011#include <utility>
Dan Sinclair3ebd1212016-03-09 09:59:23 -050012#include <vector>
Lei Zhangaa8bf7e2015-12-24 19:13:32 -080013
dsinclair488b7ad2016-10-04 11:55:50 -070014#include "core/fpdfapi/parser/cpdf_array.h"
15#include "core/fpdfapi/parser/cpdf_document.h"
16#include "core/fpdfapi/parser/cpdf_name.h"
17#include "core/fpdfapi/parser/cpdf_number.h"
18#include "core/fpdfapi/parser/cpdf_reference.h"
19#include "core/fpdfapi/parser/cpdf_stream.h"
20#include "core/fpdfapi/parser/cpdf_string.h"
Dan Sinclairaee0db02017-09-21 16:53:58 -040021#include "core/fxcrt/unowned_ptr.h"
dsinclair114e46a2016-09-29 17:18:21 -070022#include "fpdfsdk/fsdk_define.h"
thestig88d87c12016-11-14 14:06:20 -080023#include "third_party/base/ptr_util.h"
Tom Sepez11d93552016-02-09 09:55:54 -080024#include "third_party/base/stl_util.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070025
thestig88d87c12016-11-14 14:06:20 -080026namespace {
Lei Zhanga6d9f0e2015-06-13 00:48:38 -070027
thestig88d87c12016-11-14 14:06:20 -080028CPDF_Object* PageDictGetInheritableTag(CPDF_Dictionary* pDict,
Ryan Harrison275e2602017-09-18 14:23:18 -040029 const ByteString& bsSrcTag) {
tsepez71a452f2016-05-13 17:51:27 -070030 if (!pDict || bsSrcTag.IsEmpty())
Tom Sepezc7e4c4f2015-11-20 09:45:24 -080031 return nullptr;
32 if (!pDict->KeyExist("Parent") || !pDict->KeyExist("Type"))
33 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070034
dsinclair38fd8442016-09-15 10:15:32 -070035 CPDF_Object* pType = pDict->GetObjectFor("Type")->GetDirect();
Dan Sinclair710c9092015-10-21 15:46:10 -040036 if (!ToName(pType))
37 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070038 if (pType->GetString().Compare("Page"))
Tom Sepezc7e4c4f2015-11-20 09:45:24 -080039 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070040
dsinclair38fd8442016-09-15 10:15:32 -070041 CPDF_Dictionary* pp =
42 ToDictionary(pDict->GetObjectFor("Parent")->GetDirect());
Dan Sinclairf1251c12015-10-20 16:24:45 -040043 if (!pp)
44 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070045
tsepez71a452f2016-05-13 17:51:27 -070046 if (pDict->KeyExist(bsSrcTag))
dsinclair38fd8442016-09-15 10:15:32 -070047 return pDict->GetObjectFor(bsSrcTag);
Dan Sinclairf1251c12015-10-20 16:24:45 -040048
Nico Weber9d8ec5a2015-08-04 13:00:21 -070049 while (pp) {
tsepez71a452f2016-05-13 17:51:27 -070050 if (pp->KeyExist(bsSrcTag))
dsinclair38fd8442016-09-15 10:15:32 -070051 return pp->GetObjectFor(bsSrcTag);
Tom Sepezc7e4c4f2015-11-20 09:45:24 -080052 if (!pp->KeyExist("Parent"))
Nico Weber9d8ec5a2015-08-04 13:00:21 -070053 break;
dsinclair38fd8442016-09-15 10:15:32 -070054 pp = ToDictionary(pp->GetObjectFor("Parent")->GetDirect());
Nico Weber9d8ec5a2015-08-04 13:00:21 -070055 }
Dan Sinclairf1251c12015-10-20 16:24:45 -040056 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070057}
58
thestig88d87c12016-11-14 14:06:20 -080059bool CopyInheritable(CPDF_Dictionary* pCurPageDict,
60 CPDF_Dictionary* pSrcPageDict,
Ryan Harrison275e2602017-09-18 14:23:18 -040061 const ByteString& key) {
thestig88d87c12016-11-14 14:06:20 -080062 if (pCurPageDict->KeyExist(key))
63 return true;
64
65 CPDF_Object* pInheritable = PageDictGetInheritableTag(pSrcPageDict, key);
66 if (!pInheritable)
67 return false;
68
tsepez0e606b52016-11-18 16:22:41 -080069 pCurPageDict->SetFor(key, pInheritable->Clone());
thestig88d87c12016-11-14 14:06:20 -080070 return true;
71}
72
Ryan Harrison275e2602017-09-18 14:23:18 -040073bool ParserPageRangeString(ByteString rangstring,
thestig88d87c12016-11-14 14:06:20 -080074 std::vector<uint16_t>* pageArray,
75 int nCount) {
76 if (rangstring.IsEmpty())
77 return true;
78
79 rangstring.Remove(' ');
Ryan Harrison875e98c2017-09-27 10:53:11 -040080 size_t nLength = rangstring.GetLength();
Ryan Harrison275e2602017-09-18 14:23:18 -040081 ByteString cbCompareString("0123456789-,");
Ryan Harrison875e98c2017-09-27 10:53:11 -040082 for (size_t i = 0; i < nLength; ++i) {
Ryan Harrison12db7512017-08-23 10:39:35 -040083 if (!cbCompareString.Contains(rangstring[i]))
thestig88d87c12016-11-14 14:06:20 -080084 return false;
85 }
86
Ryan Harrison275e2602017-09-18 14:23:18 -040087 ByteString cbMidRange;
Ryan Harrison875e98c2017-09-27 10:53:11 -040088 size_t nStringFrom = 0;
89 pdfium::Optional<size_t> nStringTo = 0;
thestig88d87c12016-11-14 14:06:20 -080090 while (nStringTo < nLength) {
91 nStringTo = rangstring.Find(',', nStringFrom);
Ryan Harrison12db7512017-08-23 10:39:35 -040092 if (!nStringTo.has_value())
thestig88d87c12016-11-14 14:06:20 -080093 nStringTo = nLength;
Ryan Harrison12db7512017-08-23 10:39:35 -040094 cbMidRange = rangstring.Mid(nStringFrom, nStringTo.value() - nStringFrom);
95 auto nMid = cbMidRange.Find('-');
96 if (!nMid.has_value()) {
Ryan Harrisonaa3a9cd2017-08-29 16:39:44 -040097 uint16_t pageNum =
98 pdfium::base::checked_cast<uint16_t>(atoi(cbMidRange.c_str()));
99 if (pageNum <= 0 || pageNum > nCount)
thestig88d87c12016-11-14 14:06:20 -0800100 return false;
Ryan Harrisonaa3a9cd2017-08-29 16:39:44 -0400101 pageArray->push_back(pageNum);
thestig88d87c12016-11-14 14:06:20 -0800102 } else {
Ryan Harrisonaa3a9cd2017-08-29 16:39:44 -0400103 uint16_t nStartPageNum = pdfium::base::checked_cast<uint16_t>(
104 atoi(cbMidRange.Left(nMid.value()).c_str()));
thestig88d87c12016-11-14 14:06:20 -0800105 if (nStartPageNum == 0)
106 return false;
107
Ryan Harrison12db7512017-08-23 10:39:35 -0400108 nMid = nMid.value() + 1;
Ryan Harrison875e98c2017-09-27 10:53:11 -0400109 size_t nEnd = cbMidRange.GetLength() - nMid.value();
thestig88d87c12016-11-14 14:06:20 -0800110 if (nEnd == 0)
111 return false;
112
Ryan Harrisonaa3a9cd2017-08-29 16:39:44 -0400113 uint16_t nEndPageNum = pdfium::base::checked_cast<uint16_t>(
114 atoi(cbMidRange.Mid(nMid.value(), nEnd).c_str()));
thestig88d87c12016-11-14 14:06:20 -0800115 if (nStartPageNum < 0 || nStartPageNum > nEndPageNum ||
116 nEndPageNum > nCount) {
117 return false;
118 }
Ryan Harrisonaa3a9cd2017-08-29 16:39:44 -0400119 for (uint16_t i = nStartPageNum; i <= nEndPageNum; ++i) {
thestig88d87c12016-11-14 14:06:20 -0800120 pageArray->push_back(i);
121 }
122 }
Ryan Harrison12db7512017-08-23 10:39:35 -0400123 nStringFrom = nStringTo.value() + 1;
thestig88d87c12016-11-14 14:06:20 -0800124 }
125 return true;
126}
127
128} // namespace
129
130class CPDF_PageOrganizer {
131 public:
132 CPDF_PageOrganizer(CPDF_Document* pDestPDFDoc, CPDF_Document* pSrcPDFDoc);
133 ~CPDF_PageOrganizer();
134
135 bool PDFDocInit();
136 bool ExportPage(const std::vector<uint16_t>& pageNums, int nIndex);
137
138 private:
139 using ObjectNumberMap = std::map<uint32_t, uint32_t>;
140
141 bool UpdateReference(CPDF_Object* pObj, ObjectNumberMap* pObjNumberMap);
142 uint32_t GetNewObjId(ObjectNumberMap* pObjNumberMap, CPDF_Reference* pRef);
143
Dan Sinclairaee0db02017-09-21 16:53:58 -0400144 UnownedPtr<CPDF_Document> m_pDestPDFDoc;
145 UnownedPtr<CPDF_Document> m_pSrcPDFDoc;
thestig88d87c12016-11-14 14:06:20 -0800146};
147
148CPDF_PageOrganizer::CPDF_PageOrganizer(CPDF_Document* pDestPDFDoc,
149 CPDF_Document* pSrcPDFDoc)
150 : m_pDestPDFDoc(pDestPDFDoc), m_pSrcPDFDoc(pSrcPDFDoc) {}
151
152CPDF_PageOrganizer::~CPDF_PageOrganizer() {}
153
154bool CPDF_PageOrganizer::PDFDocInit() {
155 ASSERT(m_pDestPDFDoc);
156 ASSERT(m_pSrcPDFDoc);
157
158 CPDF_Dictionary* pNewRoot = m_pDestPDFDoc->GetRoot();
159 if (!pNewRoot)
160 return false;
161
162 CPDF_Dictionary* pDocInfoDict = m_pDestPDFDoc->GetInfo();
163 if (!pDocInfoDict)
164 return false;
165
tsepez0e606b52016-11-18 16:22:41 -0800166 pDocInfoDict->SetNewFor<CPDF_String>("Producer", "PDFium", false);
thestig88d87c12016-11-14 14:06:20 -0800167
Ryan Harrison275e2602017-09-18 14:23:18 -0400168 ByteString cbRootType = pNewRoot->GetStringFor("Type", "");
thestig88d87c12016-11-14 14:06:20 -0800169 if (cbRootType.IsEmpty())
tsepez0e606b52016-11-18 16:22:41 -0800170 pNewRoot->SetNewFor<CPDF_Name>("Type", "Catalog");
thestig88d87c12016-11-14 14:06:20 -0800171
172 CPDF_Object* pElement = pNewRoot->GetObjectFor("Pages");
173 CPDF_Dictionary* pNewPages =
174 pElement ? ToDictionary(pElement->GetDirect()) : nullptr;
175 if (!pNewPages) {
tsepez5913a6c2016-11-16 17:31:18 -0800176 pNewPages = m_pDestPDFDoc->NewIndirect<CPDF_Dictionary>();
Tom Sepezdc8a2b72017-05-24 13:45:11 -0700177 pNewRoot->SetNewFor<CPDF_Reference>("Pages", m_pDestPDFDoc.Get(),
tsepez0e606b52016-11-18 16:22:41 -0800178 pNewPages->GetObjNum());
thestig88d87c12016-11-14 14:06:20 -0800179 }
180
Ryan Harrison275e2602017-09-18 14:23:18 -0400181 ByteString cbPageType = pNewPages->GetStringFor("Type", "");
thestig88d87c12016-11-14 14:06:20 -0800182 if (cbPageType.IsEmpty())
tsepez0e606b52016-11-18 16:22:41 -0800183 pNewPages->SetNewFor<CPDF_Name>("Type", "Pages");
thestig88d87c12016-11-14 14:06:20 -0800184
185 if (!pNewPages->GetArrayFor("Kids")) {
tsepez0e606b52016-11-18 16:22:41 -0800186 pNewPages->SetNewFor<CPDF_Number>("Count", 0);
187 pNewPages->SetNewFor<CPDF_Reference>(
Tom Sepezdc8a2b72017-05-24 13:45:11 -0700188 "Kids", m_pDestPDFDoc.Get(),
tsepez0e606b52016-11-18 16:22:41 -0800189 m_pDestPDFDoc->NewIndirect<CPDF_Array>()->GetObjNum());
thestig88d87c12016-11-14 14:06:20 -0800190 }
191
192 return true;
193}
194
195bool CPDF_PageOrganizer::ExportPage(const std::vector<uint16_t>& pageNums,
196 int nIndex) {
197 int curpage = nIndex;
198 auto pObjNumberMap = pdfium::MakeUnique<ObjectNumberMap>();
199 int nSize = pdfium::CollectionSize<int>(pageNums);
200 for (int i = 0; i < nSize; ++i) {
201 CPDF_Dictionary* pCurPageDict = m_pDestPDFDoc->CreateNewPage(curpage);
202 CPDF_Dictionary* pSrcPageDict = m_pSrcPDFDoc->GetPage(pageNums[i] - 1);
203 if (!pSrcPageDict || !pCurPageDict)
204 return false;
205
206 // Clone the page dictionary
207 for (const auto& it : *pSrcPageDict) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400208 const ByteString& cbSrcKeyStr = it.first;
thestig88d87c12016-11-14 14:06:20 -0800209 if (cbSrcKeyStr == "Type" || cbSrcKeyStr == "Parent")
210 continue;
211
tsepez0e606b52016-11-18 16:22:41 -0800212 CPDF_Object* pObj = it.second.get();
213 pCurPageDict->SetFor(cbSrcKeyStr, pObj->Clone());
thestig88d87c12016-11-14 14:06:20 -0800214 }
215
216 // inheritable item
rbpotterd5d8f602017-03-29 16:10:45 -0700217 // Even though some entries are required by the PDF spec, there exist
218 // PDFs that omit them. Set some defaults in this case.
thestig88d87c12016-11-14 14:06:20 -0800219 // 1 MediaBox - required
220 if (!CopyInheritable(pCurPageDict, pSrcPageDict, "MediaBox")) {
rbpotterd5d8f602017-03-29 16:10:45 -0700221 // Search for "CropBox" in the source page dictionary.
222 // If it does not exist, use the default letter size.
thestig88d87c12016-11-14 14:06:20 -0800223 CPDF_Object* pInheritable =
224 PageDictGetInheritableTag(pSrcPageDict, "CropBox");
225 if (pInheritable) {
tsepez0e606b52016-11-18 16:22:41 -0800226 pCurPageDict->SetFor("MediaBox", pInheritable->Clone());
thestig88d87c12016-11-14 14:06:20 -0800227 } else {
rbpotterd5d8f602017-03-29 16:10:45 -0700228 // Make the default size letter size (8.5"x11")
tsepez0e606b52016-11-18 16:22:41 -0800229 CPDF_Array* pArray = pCurPageDict->SetNewFor<CPDF_Array>("MediaBox");
tsepez8a3aa452016-11-16 12:26:06 -0800230 pArray->AddNew<CPDF_Number>(0);
231 pArray->AddNew<CPDF_Number>(0);
232 pArray->AddNew<CPDF_Number>(612);
233 pArray->AddNew<CPDF_Number>(792);
thestig88d87c12016-11-14 14:06:20 -0800234 }
235 }
236
237 // 2 Resources - required
rbpotterd5d8f602017-03-29 16:10:45 -0700238 if (!CopyInheritable(pCurPageDict, pSrcPageDict, "Resources")) {
239 // Use a default empty resources if it does not exist.
240 pCurPageDict->SetNewFor<CPDF_Dictionary>("Resources");
241 }
thestig88d87c12016-11-14 14:06:20 -0800242
243 // 3 CropBox - optional
244 CopyInheritable(pCurPageDict, pSrcPageDict, "CropBox");
245 // 4 Rotate - optional
246 CopyInheritable(pCurPageDict, pSrcPageDict, "Rotate");
247
248 // Update the reference
249 uint32_t dwOldPageObj = pSrcPageDict->GetObjNum();
250 uint32_t dwNewPageObj = pCurPageDict->GetObjNum();
251 (*pObjNumberMap)[dwOldPageObj] = dwNewPageObj;
252 UpdateReference(pCurPageDict, pObjNumberMap.get());
253 ++curpage;
254 }
255
256 return true;
257}
258
tsepez4cf55152016-11-02 14:37:54 -0700259bool CPDF_PageOrganizer::UpdateReference(CPDF_Object* pObj,
tsepez4cf55152016-11-02 14:37:54 -0700260 ObjectNumberMap* pObjNumberMap) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700261 switch (pObj->GetType()) {
Tom Sepez8e5cd192016-01-26 13:20:26 -0800262 case CPDF_Object::REFERENCE: {
Dan Sinclairbf81c142015-10-26 16:54:39 -0400263 CPDF_Reference* pReference = pObj->AsReference();
thestig88d87c12016-11-14 14:06:20 -0800264 uint32_t newobjnum = GetNewObjId(pObjNumberMap, pReference);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700265 if (newobjnum == 0)
tsepez4cf55152016-11-02 14:37:54 -0700266 return false;
Tom Sepezdc8a2b72017-05-24 13:45:11 -0700267 pReference->SetRef(m_pDestPDFDoc.Get(), newobjnum);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700268 break;
269 }
Tom Sepez8e5cd192016-01-26 13:20:26 -0800270 case CPDF_Object::DICTIONARY: {
Dan Sinclairf1251c12015-10-20 16:24:45 -0400271 CPDF_Dictionary* pDict = pObj->AsDictionary();
Oliver Changbd292ae2016-01-13 18:46:09 -0800272 auto it = pDict->begin();
273 while (it != pDict->end()) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400274 const ByteString& key = it->first;
tsepez0e606b52016-11-18 16:22:41 -0800275 CPDF_Object* pNextObj = it->second.get();
Oliver Changbd292ae2016-01-13 18:46:09 -0800276 ++it;
tsepezf86ca382016-09-13 12:23:30 -0700277 if (key == "Parent" || key == "Prev" || key == "First")
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700278 continue;
tsepezf86ca382016-09-13 12:23:30 -0700279 if (!pNextObj)
tsepez4cf55152016-11-02 14:37:54 -0700280 return false;
thestig88d87c12016-11-14 14:06:20 -0800281 if (!UpdateReference(pNextObj, pObjNumberMap))
dsinclair38fd8442016-09-15 10:15:32 -0700282 pDict->RemoveFor(key);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700283 }
284 break;
285 }
Tom Sepez8e5cd192016-01-26 13:20:26 -0800286 case CPDF_Object::ARRAY: {
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400287 CPDF_Array* pArray = pObj->AsArray();
Wei Lie1aebd42016-04-11 10:02:09 -0700288 for (size_t i = 0; i < pArray->GetCount(); ++i) {
tsepezbd567552016-03-29 14:51:50 -0700289 CPDF_Object* pNextObj = pArray->GetObjectAt(i);
Tom Sepezc7e4c4f2015-11-20 09:45:24 -0800290 if (!pNextObj)
tsepez4cf55152016-11-02 14:37:54 -0700291 return false;
thestig88d87c12016-11-14 14:06:20 -0800292 if (!UpdateReference(pNextObj, pObjNumberMap))
tsepez4cf55152016-11-02 14:37:54 -0700293 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700294 }
295 break;
296 }
Tom Sepez8e5cd192016-01-26 13:20:26 -0800297 case CPDF_Object::STREAM: {
Dan Sinclairaa435ba2015-10-22 16:45:48 -0400298 CPDF_Stream* pStream = pObj->AsStream();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700299 CPDF_Dictionary* pDict = pStream->GetDict();
thestig88d87c12016-11-14 14:06:20 -0800300 if (!pDict)
tsepez4cf55152016-11-02 14:37:54 -0700301 return false;
thestig88d87c12016-11-14 14:06:20 -0800302 if (!UpdateReference(pDict, pObjNumberMap))
303 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700304 break;
305 }
306 default:
307 break;
308 }
309
tsepez4cf55152016-11-02 14:37:54 -0700310 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700311}
312
thestig88d87c12016-11-14 14:06:20 -0800313uint32_t CPDF_PageOrganizer::GetNewObjId(ObjectNumberMap* pObjNumberMap,
Tom Sepezc7e4c4f2015-11-20 09:45:24 -0800314 CPDF_Reference* pRef) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700315 if (!pRef)
316 return 0;
317
tsepezc3255f52016-03-25 14:52:27 -0700318 uint32_t dwObjnum = pRef->GetRefObjNum();
319 uint32_t dwNewObjNum = 0;
Tom Sepezc7e4c4f2015-11-20 09:45:24 -0800320 const auto it = pObjNumberMap->find(dwObjnum);
321 if (it != pObjNumberMap->end())
322 dwNewObjNum = it->second;
323 if (dwNewObjNum)
324 return dwNewObjNum;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700325
326 CPDF_Object* pDirect = pRef->GetDirect();
Tom Sepezc7e4c4f2015-11-20 09:45:24 -0800327 if (!pDirect)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700328 return 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700329
tsepez335cf092016-11-09 13:28:26 -0800330 std::unique_ptr<CPDF_Object> pClone = pDirect->Clone();
Dan Sinclairf1251c12015-10-20 16:24:45 -0400331 if (CPDF_Dictionary* pDictClone = pClone->AsDictionary()) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700332 if (pDictClone->KeyExist("Type")) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400333 ByteString strType = pDictClone->GetStringFor("Type");
tsepez335cf092016-11-09 13:28:26 -0800334 if (!FXSYS_stricmp(strType.c_str(), "Pages"))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700335 return 4;
tsepez335cf092016-11-09 13:28:26 -0800336 if (!FXSYS_stricmp(strType.c_str(), "Page"))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700337 return 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700338 }
339 }
tsepez70c4afd2016-11-15 11:33:44 -0800340 CPDF_Object* pUnownedClone =
341 m_pDestPDFDoc->AddIndirectObject(std::move(pClone));
342 dwNewObjNum = pUnownedClone->GetObjNum();
Tom Sepezc7e4c4f2015-11-20 09:45:24 -0800343 (*pObjNumberMap)[dwObjnum] = dwNewObjNum;
thestig88d87c12016-11-14 14:06:20 -0800344 if (!UpdateReference(pUnownedClone, pObjNumberMap))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700345 return 0;
tsepez335cf092016-11-09 13:28:26 -0800346
Tom Sepezc7e4c4f2015-11-20 09:45:24 -0800347 return dwNewObjNum;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700348}
349
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400350FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_ImportPages(FPDF_DOCUMENT dest_doc,
351 FPDF_DOCUMENT src_doc,
352 FPDF_BYTESTRING pagerange,
353 int index) {
Tom Sepez471a1032015-10-15 16:17:18 -0700354 CPDF_Document* pDestDoc = CPDFDocumentFromFPDFDocument(dest_doc);
355 if (!dest_doc)
tsepez4cf55152016-11-02 14:37:54 -0700356 return false;
Tom Sepez471a1032015-10-15 16:17:18 -0700357
358 CPDF_Document* pSrcDoc = CPDFDocumentFromFPDFDocument(src_doc);
359 if (!pSrcDoc)
tsepez4cf55152016-11-02 14:37:54 -0700360 return false;
Tom Sepezc7e4c4f2015-11-20 09:45:24 -0800361
Tom Sepez62a70f92016-03-21 15:00:20 -0700362 std::vector<uint16_t> pageArray;
Tom Sepez471a1032015-10-15 16:17:18 -0700363 int nCount = pSrcDoc->GetPageCount();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700364 if (pagerange) {
Tom Sepezc7e4c4f2015-11-20 09:45:24 -0800365 if (!ParserPageRangeString(pagerange, &pageArray, nCount))
tsepez4cf55152016-11-02 14:37:54 -0700366 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700367 } else {
Tom Sepezc7e4c4f2015-11-20 09:45:24 -0800368 for (int i = 1; i <= nCount; ++i) {
Tom Sepez11d93552016-02-09 09:55:54 -0800369 pageArray.push_back(i);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700370 }
371 }
372
thestig88d87c12016-11-14 14:06:20 -0800373 CPDF_PageOrganizer pageOrg(pDestDoc, pSrcDoc);
374 return pageOrg.PDFDocInit() && pageOrg.ExportPage(pageArray, index);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700375}
376
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400377FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
378FPDF_CopyViewerPreferences(FPDF_DOCUMENT dest_doc, FPDF_DOCUMENT src_doc) {
Tom Sepez471a1032015-10-15 16:17:18 -0700379 CPDF_Document* pDstDoc = CPDFDocumentFromFPDFDocument(dest_doc);
380 if (!pDstDoc)
tsepez4cf55152016-11-02 14:37:54 -0700381 return false;
Tom Sepez471a1032015-10-15 16:17:18 -0700382
383 CPDF_Document* pSrcDoc = CPDFDocumentFromFPDFDocument(src_doc);
384 if (!pSrcDoc)
tsepez4cf55152016-11-02 14:37:54 -0700385 return false;
Tom Sepez471a1032015-10-15 16:17:18 -0700386
387 CPDF_Dictionary* pSrcDict = pSrcDoc->GetRoot();
dsinclair38fd8442016-09-15 10:15:32 -0700388 pSrcDict = pSrcDict->GetDictFor("ViewerPreferences");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700389 if (!pSrcDict)
tsepez4cf55152016-11-02 14:37:54 -0700390 return false;
Tom Sepez471a1032015-10-15 16:17:18 -0700391
392 CPDF_Dictionary* pDstDict = pDstDoc->GetRoot();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700393 if (!pDstDict)
tsepez4cf55152016-11-02 14:37:54 -0700394 return false;
Tom Sepez471a1032015-10-15 16:17:18 -0700395
tsepez0e606b52016-11-18 16:22:41 -0800396 pDstDict->SetFor("ViewerPreferences", pSrcDict->CloneDirectObject());
tsepez4cf55152016-11-02 14:37:54 -0700397 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700398}