blob: 915de1ad0730f8726865dbc031c0d55f4912a2f2 [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>
Dan Sinclair3ebd1212016-03-09 09:59:23 -050011#include <vector>
Lei Zhangaa8bf7e2015-12-24 19:13:32 -080012
dsinclair488b7ad2016-10-04 11:55:50 -070013#include "core/fpdfapi/parser/cpdf_array.h"
14#include "core/fpdfapi/parser/cpdf_document.h"
15#include "core/fpdfapi/parser/cpdf_name.h"
16#include "core/fpdfapi/parser/cpdf_number.h"
17#include "core/fpdfapi/parser/cpdf_reference.h"
18#include "core/fpdfapi/parser/cpdf_stream.h"
19#include "core/fpdfapi/parser/cpdf_string.h"
dsinclair114e46a2016-09-29 17:18:21 -070020#include "fpdfsdk/fsdk_define.h"
thestig88d87c12016-11-14 14:06:20 -080021#include "third_party/base/ptr_util.h"
Tom Sepez11d93552016-02-09 09:55:54 -080022#include "third_party/base/stl_util.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070023
thestig88d87c12016-11-14 14:06:20 -080024namespace {
Lei Zhanga6d9f0e2015-06-13 00:48:38 -070025
thestig88d87c12016-11-14 14:06:20 -080026CPDF_Object* PageDictGetInheritableTag(CPDF_Dictionary* pDict,
27 const CFX_ByteString& bsSrcTag) {
tsepez71a452f2016-05-13 17:51:27 -070028 if (!pDict || bsSrcTag.IsEmpty())
Tom Sepezc7e4c4f2015-11-20 09:45:24 -080029 return nullptr;
30 if (!pDict->KeyExist("Parent") || !pDict->KeyExist("Type"))
31 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070032
dsinclair38fd8442016-09-15 10:15:32 -070033 CPDF_Object* pType = pDict->GetObjectFor("Type")->GetDirect();
Dan Sinclair710c9092015-10-21 15:46:10 -040034 if (!ToName(pType))
35 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070036 if (pType->GetString().Compare("Page"))
Tom Sepezc7e4c4f2015-11-20 09:45:24 -080037 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070038
dsinclair38fd8442016-09-15 10:15:32 -070039 CPDF_Dictionary* pp =
40 ToDictionary(pDict->GetObjectFor("Parent")->GetDirect());
Dan Sinclairf1251c12015-10-20 16:24:45 -040041 if (!pp)
42 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070043
tsepez71a452f2016-05-13 17:51:27 -070044 if (pDict->KeyExist(bsSrcTag))
dsinclair38fd8442016-09-15 10:15:32 -070045 return pDict->GetObjectFor(bsSrcTag);
Dan Sinclairf1251c12015-10-20 16:24:45 -040046
Nico Weber9d8ec5a2015-08-04 13:00:21 -070047 while (pp) {
tsepez71a452f2016-05-13 17:51:27 -070048 if (pp->KeyExist(bsSrcTag))
dsinclair38fd8442016-09-15 10:15:32 -070049 return pp->GetObjectFor(bsSrcTag);
Tom Sepezc7e4c4f2015-11-20 09:45:24 -080050 if (!pp->KeyExist("Parent"))
Nico Weber9d8ec5a2015-08-04 13:00:21 -070051 break;
dsinclair38fd8442016-09-15 10:15:32 -070052 pp = ToDictionary(pp->GetObjectFor("Parent")->GetDirect());
Nico Weber9d8ec5a2015-08-04 13:00:21 -070053 }
Dan Sinclairf1251c12015-10-20 16:24:45 -040054 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070055}
56
thestig88d87c12016-11-14 14:06:20 -080057bool 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
71bool 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
125class CPDF_PageOrganizer {
126 public:
127 CPDF_PageOrganizer(CPDF_Document* pDestPDFDoc, CPDF_Document* pSrcPDFDoc);
128 ~CPDF_PageOrganizer();
129
130 bool PDFDocInit();
131 bool ExportPage(const std::vector<uint16_t>& pageNums, int nIndex);
132
133 private:
134 using ObjectNumberMap = std::map<uint32_t, uint32_t>;
135
136 bool UpdateReference(CPDF_Object* pObj, ObjectNumberMap* pObjNumberMap);
137 uint32_t GetNewObjId(ObjectNumberMap* pObjNumberMap, CPDF_Reference* pRef);
138
139 CPDF_Document* m_pDestPDFDoc;
140 CPDF_Document* m_pSrcPDFDoc;
141};
142
143CPDF_PageOrganizer::CPDF_PageOrganizer(CPDF_Document* pDestPDFDoc,
144 CPDF_Document* pSrcPDFDoc)
145 : m_pDestPDFDoc(pDestPDFDoc), m_pSrcPDFDoc(pSrcPDFDoc) {}
146
147CPDF_PageOrganizer::~CPDF_PageOrganizer() {}
148
149bool CPDF_PageOrganizer::PDFDocInit() {
150 ASSERT(m_pDestPDFDoc);
151 ASSERT(m_pSrcPDFDoc);
152
153 CPDF_Dictionary* pNewRoot = m_pDestPDFDoc->GetRoot();
154 if (!pNewRoot)
155 return false;
156
157 CPDF_Dictionary* pDocInfoDict = m_pDestPDFDoc->GetInfo();
158 if (!pDocInfoDict)
159 return false;
160
161 CFX_ByteString producerstr;
162 producerstr.Format("PDFium");
tsepez5913a6c2016-11-16 17:31:18 -0800163 pDocInfoDict->SetFor("Producer",
164 new CPDF_String(nullptr, producerstr, false));
thestig88d87c12016-11-14 14:06:20 -0800165
166 CFX_ByteString cbRootType = pNewRoot->GetStringFor("Type", "");
167 if (cbRootType.IsEmpty())
tsepez5913a6c2016-11-16 17:31:18 -0800168 pNewRoot->SetFor("Type", new CPDF_Name(nullptr, "Catalog"));
thestig88d87c12016-11-14 14:06:20 -0800169
170 CPDF_Object* pElement = pNewRoot->GetObjectFor("Pages");
171 CPDF_Dictionary* pNewPages =
172 pElement ? ToDictionary(pElement->GetDirect()) : nullptr;
173 if (!pNewPages) {
tsepez5913a6c2016-11-16 17:31:18 -0800174 pNewPages = m_pDestPDFDoc->NewIndirect<CPDF_Dictionary>();
tsepez70c4afd2016-11-15 11:33:44 -0800175 pNewRoot->SetReferenceFor("Pages", m_pDestPDFDoc, pNewPages);
thestig88d87c12016-11-14 14:06:20 -0800176 }
177
178 CFX_ByteString cbPageType = pNewPages->GetStringFor("Type", "");
179 if (cbPageType.IsEmpty())
tsepez5913a6c2016-11-16 17:31:18 -0800180 pNewPages->SetFor("Type", new CPDF_Name(nullptr, "Pages"));
thestig88d87c12016-11-14 14:06:20 -0800181
182 if (!pNewPages->GetArrayFor("Kids")) {
183 pNewPages->SetIntegerFor("Count", 0);
tsepez70c4afd2016-11-15 11:33:44 -0800184 pNewPages->SetReferenceFor("Kids", m_pDestPDFDoc,
185 m_pDestPDFDoc->NewIndirect<CPDF_Array>());
thestig88d87c12016-11-14 14:06:20 -0800186 }
187
188 return true;
189}
190
191bool CPDF_PageOrganizer::ExportPage(const std::vector<uint16_t>& pageNums,
192 int nIndex) {
193 int curpage = nIndex;
194 auto pObjNumberMap = pdfium::MakeUnique<ObjectNumberMap>();
195 int nSize = pdfium::CollectionSize<int>(pageNums);
196 for (int i = 0; i < nSize; ++i) {
197 CPDF_Dictionary* pCurPageDict = m_pDestPDFDoc->CreateNewPage(curpage);
198 CPDF_Dictionary* pSrcPageDict = m_pSrcPDFDoc->GetPage(pageNums[i] - 1);
199 if (!pSrcPageDict || !pCurPageDict)
200 return false;
201
202 // Clone the page dictionary
203 for (const auto& it : *pSrcPageDict) {
204 const CFX_ByteString& cbSrcKeyStr = it.first;
205 CPDF_Object* pObj = it.second;
206 if (cbSrcKeyStr == "Type" || cbSrcKeyStr == "Parent")
207 continue;
208
209 pCurPageDict->SetFor(cbSrcKeyStr, pObj->Clone().release());
210 }
211
212 // inheritable item
213 // 1 MediaBox - required
214 if (!CopyInheritable(pCurPageDict, pSrcPageDict, "MediaBox")) {
215 // Search for "CropBox" in the source page dictionary,
216 // if it does not exists, use the default letter size.
217 CPDF_Object* pInheritable =
218 PageDictGetInheritableTag(pSrcPageDict, "CropBox");
219 if (pInheritable) {
220 pCurPageDict->SetFor("MediaBox", pInheritable->Clone().release());
221 } else {
222 // Make the default size to be letter size (8.5'x11')
223 CPDF_Array* pArray = new CPDF_Array;
tsepez8a3aa452016-11-16 12:26:06 -0800224 pArray->AddNew<CPDF_Number>(0);
225 pArray->AddNew<CPDF_Number>(0);
226 pArray->AddNew<CPDF_Number>(612);
227 pArray->AddNew<CPDF_Number>(792);
thestig88d87c12016-11-14 14:06:20 -0800228 pCurPageDict->SetFor("MediaBox", pArray);
229 }
230 }
231
232 // 2 Resources - required
233 if (!CopyInheritable(pCurPageDict, pSrcPageDict, "Resources"))
234 return false;
235
236 // 3 CropBox - optional
237 CopyInheritable(pCurPageDict, pSrcPageDict, "CropBox");
238 // 4 Rotate - optional
239 CopyInheritable(pCurPageDict, pSrcPageDict, "Rotate");
240
241 // Update the reference
242 uint32_t dwOldPageObj = pSrcPageDict->GetObjNum();
243 uint32_t dwNewPageObj = pCurPageDict->GetObjNum();
244 (*pObjNumberMap)[dwOldPageObj] = dwNewPageObj;
245 UpdateReference(pCurPageDict, pObjNumberMap.get());
246 ++curpage;
247 }
248
249 return true;
250}
251
tsepez4cf55152016-11-02 14:37:54 -0700252bool CPDF_PageOrganizer::UpdateReference(CPDF_Object* pObj,
tsepez4cf55152016-11-02 14:37:54 -0700253 ObjectNumberMap* pObjNumberMap) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700254 switch (pObj->GetType()) {
Tom Sepez8e5cd192016-01-26 13:20:26 -0800255 case CPDF_Object::REFERENCE: {
Dan Sinclairbf81c142015-10-26 16:54:39 -0400256 CPDF_Reference* pReference = pObj->AsReference();
thestig88d87c12016-11-14 14:06:20 -0800257 uint32_t newobjnum = GetNewObjId(pObjNumberMap, pReference);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700258 if (newobjnum == 0)
tsepez4cf55152016-11-02 14:37:54 -0700259 return false;
thestig88d87c12016-11-14 14:06:20 -0800260 pReference->SetRef(m_pDestPDFDoc, newobjnum);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700261 break;
262 }
Tom Sepez8e5cd192016-01-26 13:20:26 -0800263 case CPDF_Object::DICTIONARY: {
Dan Sinclairf1251c12015-10-20 16:24:45 -0400264 CPDF_Dictionary* pDict = pObj->AsDictionary();
Oliver Changbd292ae2016-01-13 18:46:09 -0800265 auto it = pDict->begin();
266 while (it != pDict->end()) {
267 const CFX_ByteString& key = it->first;
tsepezd5bd8a12016-10-17 11:13:54 -0700268 CPDF_Object* pNextObj = it->second;
Oliver Changbd292ae2016-01-13 18:46:09 -0800269 ++it;
tsepezf86ca382016-09-13 12:23:30 -0700270 if (key == "Parent" || key == "Prev" || key == "First")
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700271 continue;
tsepezf86ca382016-09-13 12:23:30 -0700272 if (!pNextObj)
tsepez4cf55152016-11-02 14:37:54 -0700273 return false;
thestig88d87c12016-11-14 14:06:20 -0800274 if (!UpdateReference(pNextObj, pObjNumberMap))
dsinclair38fd8442016-09-15 10:15:32 -0700275 pDict->RemoveFor(key);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700276 }
277 break;
278 }
Tom Sepez8e5cd192016-01-26 13:20:26 -0800279 case CPDF_Object::ARRAY: {
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400280 CPDF_Array* pArray = pObj->AsArray();
Wei Lie1aebd42016-04-11 10:02:09 -0700281 for (size_t i = 0; i < pArray->GetCount(); ++i) {
tsepezbd567552016-03-29 14:51:50 -0700282 CPDF_Object* pNextObj = pArray->GetObjectAt(i);
Tom Sepezc7e4c4f2015-11-20 09:45:24 -0800283 if (!pNextObj)
tsepez4cf55152016-11-02 14:37:54 -0700284 return false;
thestig88d87c12016-11-14 14:06:20 -0800285 if (!UpdateReference(pNextObj, pObjNumberMap))
tsepez4cf55152016-11-02 14:37:54 -0700286 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700287 }
288 break;
289 }
Tom Sepez8e5cd192016-01-26 13:20:26 -0800290 case CPDF_Object::STREAM: {
Dan Sinclairaa435ba2015-10-22 16:45:48 -0400291 CPDF_Stream* pStream = pObj->AsStream();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700292 CPDF_Dictionary* pDict = pStream->GetDict();
thestig88d87c12016-11-14 14:06:20 -0800293 if (!pDict)
tsepez4cf55152016-11-02 14:37:54 -0700294 return false;
thestig88d87c12016-11-14 14:06:20 -0800295 if (!UpdateReference(pDict, pObjNumberMap))
296 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700297 break;
298 }
299 default:
300 break;
301 }
302
tsepez4cf55152016-11-02 14:37:54 -0700303 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700304}
305
thestig88d87c12016-11-14 14:06:20 -0800306uint32_t CPDF_PageOrganizer::GetNewObjId(ObjectNumberMap* pObjNumberMap,
Tom Sepezc7e4c4f2015-11-20 09:45:24 -0800307 CPDF_Reference* pRef) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700308 if (!pRef)
309 return 0;
310
tsepezc3255f52016-03-25 14:52:27 -0700311 uint32_t dwObjnum = pRef->GetRefObjNum();
312 uint32_t dwNewObjNum = 0;
Tom Sepezc7e4c4f2015-11-20 09:45:24 -0800313 const auto it = pObjNumberMap->find(dwObjnum);
314 if (it != pObjNumberMap->end())
315 dwNewObjNum = it->second;
316 if (dwNewObjNum)
317 return dwNewObjNum;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700318
319 CPDF_Object* pDirect = pRef->GetDirect();
Tom Sepezc7e4c4f2015-11-20 09:45:24 -0800320 if (!pDirect)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700321 return 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700322
tsepez335cf092016-11-09 13:28:26 -0800323 std::unique_ptr<CPDF_Object> pClone = pDirect->Clone();
Dan Sinclairf1251c12015-10-20 16:24:45 -0400324 if (CPDF_Dictionary* pDictClone = pClone->AsDictionary()) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700325 if (pDictClone->KeyExist("Type")) {
dsinclair38fd8442016-09-15 10:15:32 -0700326 CFX_ByteString strType = pDictClone->GetStringFor("Type");
tsepez335cf092016-11-09 13:28:26 -0800327 if (!FXSYS_stricmp(strType.c_str(), "Pages"))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700328 return 4;
tsepez335cf092016-11-09 13:28:26 -0800329 if (!FXSYS_stricmp(strType.c_str(), "Page"))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700330 return 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700331 }
332 }
tsepez70c4afd2016-11-15 11:33:44 -0800333 CPDF_Object* pUnownedClone =
334 m_pDestPDFDoc->AddIndirectObject(std::move(pClone));
335 dwNewObjNum = pUnownedClone->GetObjNum();
Tom Sepezc7e4c4f2015-11-20 09:45:24 -0800336 (*pObjNumberMap)[dwObjnum] = dwNewObjNum;
thestig88d87c12016-11-14 14:06:20 -0800337 if (!UpdateReference(pUnownedClone, pObjNumberMap))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700338 return 0;
tsepez335cf092016-11-09 13:28:26 -0800339
Tom Sepezc7e4c4f2015-11-20 09:45:24 -0800340 return dwNewObjNum;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700341}
342
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700343DLLEXPORT FPDF_BOOL STDCALL FPDF_ImportPages(FPDF_DOCUMENT dest_doc,
344 FPDF_DOCUMENT src_doc,
345 FPDF_BYTESTRING pagerange,
346 int index) {
Tom Sepez471a1032015-10-15 16:17:18 -0700347 CPDF_Document* pDestDoc = CPDFDocumentFromFPDFDocument(dest_doc);
348 if (!dest_doc)
tsepez4cf55152016-11-02 14:37:54 -0700349 return false;
Tom Sepez471a1032015-10-15 16:17:18 -0700350
351 CPDF_Document* pSrcDoc = CPDFDocumentFromFPDFDocument(src_doc);
352 if (!pSrcDoc)
tsepez4cf55152016-11-02 14:37:54 -0700353 return false;
Tom Sepezc7e4c4f2015-11-20 09:45:24 -0800354
Tom Sepez62a70f92016-03-21 15:00:20 -0700355 std::vector<uint16_t> pageArray;
Tom Sepez471a1032015-10-15 16:17:18 -0700356 int nCount = pSrcDoc->GetPageCount();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700357 if (pagerange) {
Tom Sepezc7e4c4f2015-11-20 09:45:24 -0800358 if (!ParserPageRangeString(pagerange, &pageArray, nCount))
tsepez4cf55152016-11-02 14:37:54 -0700359 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700360 } else {
Tom Sepezc7e4c4f2015-11-20 09:45:24 -0800361 for (int i = 1; i <= nCount; ++i) {
Tom Sepez11d93552016-02-09 09:55:54 -0800362 pageArray.push_back(i);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700363 }
364 }
365
thestig88d87c12016-11-14 14:06:20 -0800366 CPDF_PageOrganizer pageOrg(pDestDoc, pSrcDoc);
367 return pageOrg.PDFDocInit() && pageOrg.ExportPage(pageArray, index);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700368}
369
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700370DLLEXPORT FPDF_BOOL STDCALL FPDF_CopyViewerPreferences(FPDF_DOCUMENT dest_doc,
371 FPDF_DOCUMENT src_doc) {
Tom Sepez471a1032015-10-15 16:17:18 -0700372 CPDF_Document* pDstDoc = CPDFDocumentFromFPDFDocument(dest_doc);
373 if (!pDstDoc)
tsepez4cf55152016-11-02 14:37:54 -0700374 return false;
Tom Sepez471a1032015-10-15 16:17:18 -0700375
376 CPDF_Document* pSrcDoc = CPDFDocumentFromFPDFDocument(src_doc);
377 if (!pSrcDoc)
tsepez4cf55152016-11-02 14:37:54 -0700378 return false;
Tom Sepez471a1032015-10-15 16:17:18 -0700379
380 CPDF_Dictionary* pSrcDict = pSrcDoc->GetRoot();
dsinclair38fd8442016-09-15 10:15:32 -0700381 pSrcDict = pSrcDict->GetDictFor("ViewerPreferences");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700382 if (!pSrcDict)
tsepez4cf55152016-11-02 14:37:54 -0700383 return false;
Tom Sepez471a1032015-10-15 16:17:18 -0700384
385 CPDF_Dictionary* pDstDict = pDstDoc->GetRoot();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700386 if (!pDstDict)
tsepez4cf55152016-11-02 14:37:54 -0700387 return false;
Tom Sepez471a1032015-10-15 16:17:18 -0700388
tsepez335cf092016-11-09 13:28:26 -0800389 pDstDict->SetFor("ViewerPreferences",
390 pSrcDict->CloneDirectObject().release());
tsepez4cf55152016-11-02 14:37:54 -0700391 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700392}