blob: a6c14206cece327a501103c86e1b500694979749 [file] [log] [blame]
Svet Ganove6986e12015-06-04 14:52:15 -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.
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -08004
Svet Ganove6986e12015-06-04 14:52:15 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -08007#include "public/fpdfview.h"
Svet Ganove6986e12015-06-04 14:52:15 -07008
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -08009#include <memory>
10
11#include "core/include/fxcodec/fx_codec.h"
12#include "core/include/fxcrt/fx_safe_types.h"
13#include "fpdfsdk/include/fsdk_define.h"
14#include "fpdfsdk/include/fsdk_mgr.h"
15#include "fpdfsdk/include/fsdk_rendercontext.h"
16#include "fpdfsdk/include/javascript/IJavaScript.h"
17#include "public/fpdf_ext.h"
18#include "public/fpdf_progressive.h"
19#include "third_party/base/numerics/safe_conversions_impl.h"
20
21#ifdef PDF_ENABLE_XFA
22#include "core/include/fpdfapi/fpdf_module.h"
23#include "fpdfsdk/include/fpdfxfa/fpdfxfa_app.h"
24#include "fpdfsdk/include/fpdfxfa/fpdfxfa_doc.h"
25#include "fpdfsdk/include/fpdfxfa/fpdfxfa_page.h"
26#include "fpdfsdk/include/fpdfxfa/fpdfxfa_util.h"
27#include "public/fpdf_formfill.h"
28#endif // PDF_ENABLE_XFA
29
30UnderlyingDocumentType* UnderlyingFromFPDFDocument(FPDF_DOCUMENT doc) {
31 return static_cast<UnderlyingDocumentType*>(doc);
Svet Ganove6986e12015-06-04 14:52:15 -070032}
33
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -080034FPDF_DOCUMENT FPDFDocumentFromUnderlying(UnderlyingDocumentType* doc) {
35 return static_cast<FPDF_DOCUMENT>(doc);
Svet Ganove6986e12015-06-04 14:52:15 -070036}
37
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -080038UnderlyingPageType* UnderlyingFromFPDFPage(FPDF_PAGE page) {
39 return static_cast<UnderlyingPageType*>(page);
40}
41
42CPDF_Document* CPDFDocumentFromFPDFDocument(FPDF_DOCUMENT doc) {
43#ifdef PDF_ENABLE_XFA
44 return doc ? UnderlyingFromFPDFDocument(doc)->GetPDFDoc() : nullptr;
45#else // PDF_ENABLE_XFA
46 return UnderlyingFromFPDFDocument(doc);
47#endif // PDF_ENABLE_XFA
48}
49
50FPDF_DOCUMENT FPDFDocumentFromCPDFDocument(CPDF_Document* doc) {
51#ifdef PDF_ENABLE_XFA
52 return doc ? FPDFDocumentFromUnderlying(
53 new CPDFXFA_Document(doc, CPDFXFA_App::GetInstance()))
54 : nullptr;
55#else // PDF_ENABLE_XFA
56 return FPDFDocumentFromUnderlying(doc);
57#endif // PDF_ENABLE_XFA
58}
59
60CPDF_Page* CPDFPageFromFPDFPage(FPDF_PAGE page) {
61#ifdef PDF_ENABLE_XFA
62 return page ? UnderlyingFromFPDFPage(page)->GetPDFPage() : nullptr;
63#else // PDF_ENABLE_XFA
64 return UnderlyingFromFPDFPage(page);
65#endif // PDF_ENABLE_XFA
66}
67
68#ifdef PDF_ENABLE_XFA
69CFPDF_FileStream::CFPDF_FileStream(FPDF_FILEHANDLER* pFS) {
70 m_pFS = pFS;
71 m_nCurPos = 0;
72}
73
74IFX_FileStream* CFPDF_FileStream::Retain() {
75 return this;
76}
77
78void CFPDF_FileStream::Release() {
79 if (m_pFS && m_pFS->Release)
80 m_pFS->Release(m_pFS->clientData);
81 delete this;
82}
83
84FX_FILESIZE CFPDF_FileStream::GetSize() {
85 if (m_pFS && m_pFS->GetSize)
86 return (FX_FILESIZE)m_pFS->GetSize(m_pFS->clientData);
87 return 0;
88}
89
90FX_BOOL CFPDF_FileStream::IsEOF() {
91 return m_nCurPos >= GetSize();
92}
93
94FX_BOOL CFPDF_FileStream::ReadBlock(void* buffer,
95 FX_FILESIZE offset,
96 size_t size) {
97 if (!buffer || !size || !m_pFS->ReadBlock)
98 return FALSE;
99
100 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
101 (FPDF_DWORD)size) == 0) {
102 m_nCurPos = offset + size;
103 return TRUE;
104 }
105 return FALSE;
106}
107
108size_t CFPDF_FileStream::ReadBlock(void* buffer, size_t size) {
109 if (!buffer || !size || !m_pFS->ReadBlock)
110 return 0;
111
112 FX_FILESIZE nSize = GetSize();
113 if (m_nCurPos >= nSize)
114 return 0;
115 FX_FILESIZE dwAvail = nSize - m_nCurPos;
116 if (dwAvail < (FX_FILESIZE)size)
117 size = (size_t)dwAvail;
118 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)m_nCurPos, buffer,
119 (FPDF_DWORD)size) == 0) {
120 m_nCurPos += size;
121 return size;
122 }
123
124 return 0;
125}
126
127FX_BOOL CFPDF_FileStream::WriteBlock(const void* buffer,
128 FX_FILESIZE offset,
129 size_t size) {
130 if (!m_pFS || !m_pFS->WriteBlock)
131 return FALSE;
132
133 if (m_pFS->WriteBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
134 (FPDF_DWORD)size) == 0) {
135 m_nCurPos = offset + size;
136 return TRUE;
137 }
138 return FALSE;
139}
140
141FX_BOOL CFPDF_FileStream::Flush() {
142 if (!m_pFS || !m_pFS->Flush)
143 return TRUE;
144
145 return m_pFS->Flush(m_pFS->clientData) == 0;
146}
147#endif // PDF_ENABLE_XFA
148
149CPDF_CustomAccess::CPDF_CustomAccess(FPDF_FILEACCESS* pFileAccess) {
150 m_FileAccess = *pFileAccess;
151#ifdef PDF_ENABLE_XFA
152 m_BufferOffset = (FX_DWORD)-1;
153#endif // PDF_ENABLE_XFA
154}
155
156#ifdef PDF_ENABLE_XFA
157FX_BOOL CPDF_CustomAccess::GetByte(FX_DWORD pos, uint8_t& ch) {
158 if (pos >= m_FileAccess.m_FileLen)
159 return FALSE;
160 if (m_BufferOffset == (FX_DWORD)-1 || pos < m_BufferOffset ||
161 pos >= m_BufferOffset + 512) {
162 // Need to read from file access
163 m_BufferOffset = pos;
164 int size = 512;
165 if (pos + 512 > m_FileAccess.m_FileLen)
166 size = m_FileAccess.m_FileLen - pos;
167 if (!m_FileAccess.m_GetBlock(m_FileAccess.m_Param, m_BufferOffset, m_Buffer,
168 size))
169 return FALSE;
170 }
171 ch = m_Buffer[pos - m_BufferOffset];
172 return TRUE;
173}
174
175FX_BOOL CPDF_CustomAccess::GetBlock(FX_DWORD pos,
176 uint8_t* pBuf,
177 FX_DWORD size) {
178 if (pos + size > m_FileAccess.m_FileLen)
179 return FALSE;
180 return m_FileAccess.m_GetBlock(m_FileAccess.m_Param, pos, pBuf, size);
181}
182#endif // PDF_ENABLE_XFA
183
184FX_BOOL CPDF_CustomAccess::ReadBlock(void* buffer,
185 FX_FILESIZE offset,
186 size_t size) {
187 if (offset < 0) {
188 return FALSE;
189 }
190 FX_SAFE_FILESIZE newPos =
191 pdfium::base::checked_cast<FX_FILESIZE, size_t>(size);
192 newPos += offset;
193 if (!newPos.IsValid() || newPos.ValueOrDie() > m_FileAccess.m_FileLen) {
194 return FALSE;
195 }
196 return m_FileAccess.m_GetBlock(m_FileAccess.m_Param, offset, (uint8_t*)buffer,
197 size);
198}
199
200// 0 bit: FPDF_POLICY_MACHINETIME_ACCESS
Svet Ganove6986e12015-06-04 14:52:15 -0700201static FX_DWORD foxit_sandbox_policy = 0xFFFFFFFF;
202
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800203void FSDK_SetSandBoxPolicy(FPDF_DWORD policy, FPDF_BOOL enable) {
204 switch (policy) {
205 case FPDF_POLICY_MACHINETIME_ACCESS: {
206 if (enable)
207 foxit_sandbox_policy |= 0x01;
208 else
209 foxit_sandbox_policy &= 0xFFFFFFFE;
210 } break;
211 default:
212 break;
213 }
Svet Ganove6986e12015-06-04 14:52:15 -0700214}
215
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800216FPDF_BOOL FSDK_IsSandBoxPolicyEnabled(FPDF_DWORD policy) {
217 switch (policy) {
218 case FPDF_POLICY_MACHINETIME_ACCESS:
219 return !!(foxit_sandbox_policy & 0x01);
220 default:
221 return FALSE;
222 }
Svet Ganove6986e12015-06-04 14:52:15 -0700223}
224
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800225CCodec_ModuleMgr* g_pCodecModule = nullptr;
Svet Ganove6986e12015-06-04 14:52:15 -0700226
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800227DLLEXPORT void STDCALL FPDF_InitLibrary() {
228 FPDF_InitLibraryWithConfig(nullptr);
Svet Ganove6986e12015-06-04 14:52:15 -0700229}
230
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800231DLLEXPORT void STDCALL FPDF_InitLibraryWithConfig(
232 const FPDF_LIBRARY_CONFIG* cfg) {
233 g_pCodecModule = new CCodec_ModuleMgr();
Svet Ganove6986e12015-06-04 14:52:15 -0700234
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800235 CFX_GEModule::Create(cfg ? cfg->m_pUserFontPaths : nullptr);
236 CFX_GEModule::Get()->SetCodecModule(g_pCodecModule);
Svet Ganove6986e12015-06-04 14:52:15 -0700237
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800238 CPDF_ModuleMgr::Create();
239 CPDF_ModuleMgr* pModuleMgr = CPDF_ModuleMgr::Get();
240 pModuleMgr->SetCodecModule(g_pCodecModule);
241 pModuleMgr->InitPageModule();
242 pModuleMgr->InitRenderModule();
243#ifdef PDF_ENABLE_XFA
244 CPDFXFA_App::GetInstance()->Initialize();
245#else // PDF_ENABLE_XFA
246 pModuleMgr->LoadEmbeddedGB1CMaps();
247 pModuleMgr->LoadEmbeddedJapan1CMaps();
248 pModuleMgr->LoadEmbeddedCNS1CMaps();
249 pModuleMgr->LoadEmbeddedKorea1CMaps();
250#endif // PDF_ENABLE_XFA
251 if (cfg && cfg->version >= 2)
252 IJS_Runtime::Initialize(cfg->m_v8EmbedderSlot, cfg->m_pIsolate);
253}
254
255DLLEXPORT void STDCALL FPDF_DestroyLibrary() {
256#ifdef PDF_ENABLE_XFA
257 CPDFXFA_App::ReleaseInstance();
258#endif // PDF_ENABLE_XFA
259 CPDF_ModuleMgr::Destroy();
260 CFX_GEModule::Destroy();
261
262 delete g_pCodecModule;
263 g_pCodecModule = nullptr;
Svet Ganove6986e12015-06-04 14:52:15 -0700264}
265
266#ifndef _WIN32
267int g_LastError;
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800268void SetLastError(int err) {
269 g_LastError = err;
Svet Ganove6986e12015-06-04 14:52:15 -0700270}
271
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800272int GetLastError() {
273 return g_LastError;
Svet Ganove6986e12015-06-04 14:52:15 -0700274}
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800275#endif // _WIN32
Svet Ganove6986e12015-06-04 14:52:15 -0700276
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800277void ProcessParseError(FX_DWORD err_code) {
278 // Translate FPDFAPI error code to FPDFVIEW error code
279 switch (err_code) {
280 case PDFPARSE_ERROR_FILE:
281 err_code = FPDF_ERR_FILE;
282 break;
283 case PDFPARSE_ERROR_FORMAT:
284 err_code = FPDF_ERR_FORMAT;
285 break;
286 case PDFPARSE_ERROR_PASSWORD:
287 err_code = FPDF_ERR_PASSWORD;
288 break;
289 case PDFPARSE_ERROR_HANDLER:
290 err_code = FPDF_ERR_SECURITY;
291 break;
292 }
293 SetLastError(err_code);
Svet Ganove6986e12015-06-04 14:52:15 -0700294}
295
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800296DLLEXPORT void STDCALL FPDF_SetSandBoxPolicy(FPDF_DWORD policy,
297 FPDF_BOOL enable) {
298 return FSDK_SetSandBoxPolicy(policy, enable);
Svet Ganove6986e12015-06-04 14:52:15 -0700299}
300
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800301DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadDocument(FPDF_STRING file_path,
302 FPDF_BYTESTRING password) {
303 // NOTE: the creation of the file needs to be by the embedder on the
304 // other side of this API.
305 IFX_FileRead* pFileAccess = FX_CreateFileRead((const FX_CHAR*)file_path);
306 if (!pFileAccess) {
307 return nullptr;
308 }
Svet Ganove6986e12015-06-04 14:52:15 -0700309
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800310 CPDF_Parser* pParser = new CPDF_Parser;
311 pParser->SetPassword(password);
312
313 FX_DWORD err_code = pParser->StartParse(pFileAccess);
314 if (err_code) {
315 delete pParser;
316 ProcessParseError(err_code);
317 return NULL;
318 }
319#ifdef PDF_ENABLE_XFA
320 CPDF_Document* pPDFDoc = pParser->GetDocument();
321 if (!pPDFDoc)
322 return NULL;
323
324 CPDFXFA_App* pProvider = CPDFXFA_App::GetInstance();
325 return new CPDFXFA_Document(pPDFDoc, pProvider);
326#else // PDF_ENABLE_XFA
327 return pParser->GetDocument();
328#endif // PDF_ENABLE_XFA
Svet Ganove6986e12015-06-04 14:52:15 -0700329}
330
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800331#ifdef PDF_ENABLE_XFA
332DLLEXPORT FPDF_BOOL STDCALL FPDF_HasXFAField(FPDF_DOCUMENT document,
333 int* docType) {
334 if (!document)
335 return FALSE;
Svet Ganove6986e12015-06-04 14:52:15 -0700336
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800337 CPDF_Document* pdfDoc =
338 (static_cast<CPDFXFA_Document*>(document))->GetPDFDoc();
339 if (!pdfDoc)
340 return FALSE;
Svet Ganove6986e12015-06-04 14:52:15 -0700341
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800342 CPDF_Dictionary* pRoot = pdfDoc->GetRoot();
343 if (!pRoot)
344 return FALSE;
345
346 CPDF_Dictionary* pAcroForm = pRoot->GetDict("AcroForm");
347 if (!pAcroForm)
348 return FALSE;
349
350 CPDF_Object* pXFA = pAcroForm->GetElement("XFA");
351 if (!pXFA)
352 return FALSE;
353
354 FX_BOOL bDynamicXFA = pRoot->GetBoolean("NeedsRendering", FALSE);
355
356 if (bDynamicXFA)
357 *docType = DOCTYPE_DYNAMIC_XFA;
358 else
359 *docType = DOCTYPE_STATIC_XFA;
360
361 return TRUE;
362}
363
364DLLEXPORT FPDF_BOOL STDCALL FPDF_LoadXFA(FPDF_DOCUMENT document) {
365 return document && (static_cast<CPDFXFA_Document*>(document))->LoadXFADoc();
366}
367#endif // PDF_ENABLE_XFA
368
369class CMemFile final : public IFX_FileRead {
370 public:
371 CMemFile(uint8_t* pBuf, FX_FILESIZE size) : m_pBuf(pBuf), m_size(size) {}
372
373 void Release() override { delete this; }
374 FX_FILESIZE GetSize() override { return m_size; }
375 FX_BOOL ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override {
376 if (offset < 0) {
377 return FALSE;
378 }
379 FX_SAFE_FILESIZE newPos =
380 pdfium::base::checked_cast<FX_FILESIZE, size_t>(size);
381 newPos += offset;
382 if (!newPos.IsValid() || newPos.ValueOrDie() > (FX_DWORD)m_size) {
383 return FALSE;
384 }
385 FXSYS_memcpy(buffer, m_pBuf + offset, size);
386 return TRUE;
387 }
388
389 private:
390 ~CMemFile() override {}
391
392 uint8_t* const m_pBuf;
393 const FX_FILESIZE m_size;
Svet Ganove6986e12015-06-04 14:52:15 -0700394};
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800395
396DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadMemDocument(const void* data_buf,
397 int size,
398 FPDF_BYTESTRING password) {
399 CPDF_Parser* pParser = new CPDF_Parser;
400 pParser->SetPassword(password);
401 CMemFile* pMemFile = new CMemFile((uint8_t*)data_buf, size);
402 FX_DWORD err_code = pParser->StartParse(pMemFile);
403 if (err_code) {
404 delete pParser;
405 ProcessParseError(err_code);
406 return NULL;
407 }
408 CPDF_Document* pDoc = NULL;
409 pDoc = pParser ? pParser->GetDocument() : NULL;
410 CheckUnSupportError(pDoc, err_code);
411 return FPDFDocumentFromCPDFDocument(pParser->GetDocument());
Svet Ganove6986e12015-06-04 14:52:15 -0700412}
413
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800414DLLEXPORT FPDF_DOCUMENT STDCALL
415FPDF_LoadCustomDocument(FPDF_FILEACCESS* pFileAccess,
416 FPDF_BYTESTRING password) {
417 CPDF_Parser* pParser = new CPDF_Parser;
418 pParser->SetPassword(password);
419 CPDF_CustomAccess* pFile = new CPDF_CustomAccess(pFileAccess);
420 FX_DWORD err_code = pParser->StartParse(pFile);
421 if (err_code) {
422 delete pParser;
423 ProcessParseError(err_code);
424 return NULL;
425 }
426 CPDF_Document* pDoc = NULL;
427 pDoc = pParser ? pParser->GetDocument() : NULL;
428 CheckUnSupportError(pDoc, err_code);
429 return FPDFDocumentFromCPDFDocument(pParser->GetDocument());
Svet Ganove6986e12015-06-04 14:52:15 -0700430}
431
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800432DLLEXPORT FPDF_BOOL STDCALL FPDF_GetFileVersion(FPDF_DOCUMENT doc,
433 int* fileVersion) {
434 if (!fileVersion)
435 return FALSE;
436
437 *fileVersion = 0;
438 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(doc);
439 if (!pDoc)
440 return FALSE;
441
442 CPDF_Parser* pParser = pDoc->GetParser();
443 if (!pParser)
444 return FALSE;
445
446 *fileVersion = pParser->GetFileVersion();
447 return TRUE;
Svet Ganove6986e12015-06-04 14:52:15 -0700448}
449
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800450// jabdelmalek: changed return type from FX_DWORD to build on Linux (and match
451// header).
452DLLEXPORT unsigned long STDCALL FPDF_GetDocPermissions(FPDF_DOCUMENT document) {
453 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
454 if (!pDoc)
455#ifndef PDF_ENABLE_XFA
456 return 0;
457#else // PDF_ENABLE_XFA
458 return (FX_DWORD)-1;
459#endif // PDF_ENABLE_XFA
Svet Ganove6986e12015-06-04 14:52:15 -0700460
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800461 CPDF_Dictionary* pDict = pDoc->GetParser()->GetEncryptDict();
462 return pDict ? pDict->GetInteger("P") : (FX_DWORD)-1;
Svet Ganove6986e12015-06-04 14:52:15 -0700463}
464
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800465DLLEXPORT int STDCALL FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document) {
466 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
467 if (!pDoc)
468 return -1;
Svet Ganove6986e12015-06-04 14:52:15 -0700469
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800470 CPDF_Dictionary* pDict = pDoc->GetParser()->GetEncryptDict();
471 return pDict ? pDict->GetInteger("R") : -1;
Svet Ganove6986e12015-06-04 14:52:15 -0700472}
473
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800474DLLEXPORT int STDCALL FPDF_GetPageCount(FPDF_DOCUMENT document) {
475 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
476 return pDoc ? pDoc->GetPageCount() : 0;
Svet Ganove6986e12015-06-04 14:52:15 -0700477}
478
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800479DLLEXPORT FPDF_PAGE STDCALL FPDF_LoadPage(FPDF_DOCUMENT document,
480 int page_index) {
481 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
482 if (!pDoc)
483 return nullptr;
Svet Ganove6986e12015-06-04 14:52:15 -0700484
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800485 if (page_index < 0 || page_index >= pDoc->GetPageCount())
486 return nullptr;
487
488#ifdef PDF_ENABLE_XFA
489 return pDoc->GetPage(page_index);
490#else // PDF_ENABLE_XFA
491 CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
492 if (!pDict)
493 return NULL;
494 CPDF_Page* pPage = new CPDF_Page;
495 pPage->Load(pDoc, pDict);
496 pPage->ParseContent();
497 return pPage;
498#endif // PDF_ENABLE_XFA
Svet Ganove6986e12015-06-04 14:52:15 -0700499}
500
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800501DLLEXPORT double STDCALL FPDF_GetPageWidth(FPDF_PAGE page) {
502 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
503 return pPage ? pPage->GetPageWidth() : 0.0;
Svet Ganove6986e12015-06-04 14:52:15 -0700504}
505
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800506DLLEXPORT double STDCALL FPDF_GetPageHeight(FPDF_PAGE page) {
507 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
508 return pPage ? pPage->GetPageHeight() : 0.0;
Svet Ganove6986e12015-06-04 14:52:15 -0700509}
510
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800511void DropContext(void* data) {
512 delete (CRenderContext*)data;
Svet Ganove6986e12015-06-04 14:52:15 -0700513}
514
Svet Ganove6986e12015-06-04 14:52:15 -0700515#if defined(_DEBUG) || defined(DEBUG)
516#define DEBUG_TRACE
517#endif
518
519#if defined(_WIN32)
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800520DLLEXPORT void STDCALL FPDF_RenderPage(HDC dc,
521 FPDF_PAGE page,
522 int start_x,
523 int start_y,
524 int size_x,
525 int size_y,
526 int rotate,
527 int flags) {
528 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
529 if (!pPage)
530 return;
Svet Ganove6986e12015-06-04 14:52:15 -0700531
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800532 CRenderContext* pContext = new CRenderContext;
533 pPage->SetPrivateData((void*)1, pContext, DropContext);
Svet Ganove6986e12015-06-04 14:52:15 -0700534
535#ifndef _WIN32_WCE
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800536 CFX_DIBitmap* pBitmap = nullptr;
537 FX_BOOL bBackgroundAlphaNeeded = pPage->BackgroundAlphaNeeded();
538 FX_BOOL bHasImageMask = pPage->HasImageMask();
539 if (bBackgroundAlphaNeeded || bHasImageMask) {
540 pBitmap = new CFX_DIBitmap;
541 pBitmap->Create(size_x, size_y, FXDIB_Argb);
542 pBitmap->Clear(0x00ffffff);
Svet Ganove6986e12015-06-04 14:52:15 -0700543#ifdef _SKIA_SUPPORT_
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800544 pContext->m_pDevice = new CFX_SkiaDevice;
545 ((CFX_SkiaDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)pBitmap);
Svet Ganove6986e12015-06-04 14:52:15 -0700546#else
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800547 pContext->m_pDevice = new CFX_FxgeDevice;
548 ((CFX_FxgeDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)pBitmap);
Svet Ganove6986e12015-06-04 14:52:15 -0700549#endif
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800550 } else {
551 pContext->m_pDevice = new CFX_WindowsDevice(dc);
552 }
Svet Ganove6986e12015-06-04 14:52:15 -0700553
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800554 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
555 rotate, flags, TRUE, NULL);
Svet Ganove6986e12015-06-04 14:52:15 -0700556
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800557 if (bBackgroundAlphaNeeded || bHasImageMask) {
558 if (pBitmap) {
559 CFX_WindowsDevice WinDC(dc);
Svet Ganove6986e12015-06-04 14:52:15 -0700560
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800561 if (WinDC.GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
562 CFX_DIBitmap* pDst = new CFX_DIBitmap;
563 int pitch = pBitmap->GetPitch();
564 pDst->Create(size_x, size_y, FXDIB_Rgb32);
565 FXSYS_memset(pDst->GetBuffer(), -1, pitch * size_y);
566 pDst->CompositeBitmap(0, 0, size_x, size_y, pBitmap, 0, 0,
567 FXDIB_BLEND_NORMAL, NULL, FALSE, NULL);
568 WinDC.StretchDIBits(pDst, 0, 0, size_x, size_y);
569 delete pDst;
570 } else {
571 WinDC.SetDIBits(pBitmap, 0, 0);
572 }
Svet Ganove6986e12015-06-04 14:52:15 -0700573 }
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800574 }
Svet Ganove6986e12015-06-04 14:52:15 -0700575#else
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800576 // get clip region
577 RECT rect, cliprect;
578 rect.left = start_x;
579 rect.top = start_y;
580 rect.right = start_x + size_x;
581 rect.bottom = start_y + size_y;
582 GetClipBox(dc, &cliprect);
583 IntersectRect(&rect, &rect, &cliprect);
584 int width = rect.right - rect.left;
585 int height = rect.bottom - rect.top;
586
587#ifdef DEBUG_TRACE
588 {
589 char str[128];
590 memset(str, 0, sizeof(str));
591 FXSYS_snprintf(str, sizeof(str) - 1, "Rendering DIB %d x %d", width,
592 height);
593 CPDF_ModuleMgr::Get()->ReportError(999, str);
594 }
Svet Ganove6986e12015-06-04 14:52:15 -0700595#endif
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800596
597 // Create a DIB section
598 LPVOID pBuffer;
599 BITMAPINFOHEADER bmih;
600 FXSYS_memset(&bmih, 0, sizeof bmih);
601 bmih.biSize = sizeof bmih;
602 bmih.biBitCount = 24;
603 bmih.biHeight = -height;
604 bmih.biPlanes = 1;
605 bmih.biWidth = width;
606 pContext->m_hBitmap = CreateDIBSection(dc, (BITMAPINFO*)&bmih, DIB_RGB_COLORS,
607 &pBuffer, NULL, 0);
608 if (!pContext->m_hBitmap) {
609#if defined(DEBUG) || defined(_DEBUG)
610 char str[128];
611 memset(str, 0, sizeof(str));
612 FXSYS_snprintf(str, sizeof(str) - 1,
613 "Error CreateDIBSection: %d x %d, error code = %d", width,
614 height, GetLastError());
615 CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, str);
616#else
617 CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, NULL);
618#endif
619 }
620 FXSYS_memset(pBuffer, 0xff, height * ((width * 3 + 3) / 4 * 4));
621
622#ifdef DEBUG_TRACE
623 { CPDF_ModuleMgr::Get()->ReportError(999, "DIBSection created"); }
624#endif
625
626 // Create a device with this external buffer
627 pContext->m_pBitmap = new CFX_DIBitmap;
628 pContext->m_pBitmap->Create(width, height, FXDIB_Rgb, (uint8_t*)pBuffer);
629 pContext->m_pDevice = new CPDF_FxgeDevice;
630 ((CPDF_FxgeDevice*)pContext->m_pDevice)->Attach(pContext->m_pBitmap);
631
632#ifdef DEBUG_TRACE
633 CPDF_ModuleMgr::Get()->ReportError(999, "Ready for PDF rendering");
634#endif
635
636 // output to bitmap device
637 FPDF_RenderPage_Retail(pContext, page, start_x - rect.left,
638 start_y - rect.top, size_x, size_y, rotate, flags);
639
640#ifdef DEBUG_TRACE
641 CPDF_ModuleMgr::Get()->ReportError(999, "Finished PDF rendering");
642#endif
643
644 // Now output to real device
645 HDC hMemDC = CreateCompatibleDC(dc);
646 if (!hMemDC) {
647#if defined(DEBUG) || defined(_DEBUG)
648 char str[128];
649 memset(str, 0, sizeof(str));
650 FXSYS_snprintf(str, sizeof(str) - 1,
651 "Error CreateCompatibleDC. Error code = %d", GetLastError());
652 CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, str);
653#else
654 CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, NULL);
655#endif
656 }
657
658 HGDIOBJ hOldBitmap = SelectObject(hMemDC, pContext->m_hBitmap);
659
660#ifdef DEBUG_TRACE
661 CPDF_ModuleMgr::Get()->ReportError(999, "Ready for screen rendering");
662#endif
663
664 BitBlt(dc, rect.left, rect.top, width, height, hMemDC, 0, 0, SRCCOPY);
665 SelectObject(hMemDC, hOldBitmap);
666 DeleteDC(hMemDC);
667
668#ifdef DEBUG_TRACE
669 CPDF_ModuleMgr::Get()->ReportError(999, "Finished screen rendering");
670#endif
671
672#endif
673 if (bBackgroundAlphaNeeded || bHasImageMask)
674 delete pBitmap;
675
676 delete pContext;
677 pPage->RemovePrivateData((void*)1);
678}
679#endif
680
681DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap,
682 FPDF_PAGE page,
683 int start_x,
684 int start_y,
685 int size_x,
686 int size_y,
687 int rotate,
688 int flags) {
689 if (!bitmap)
690 return;
691 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
692 if (!pPage)
693 return;
694 CRenderContext* pContext = new CRenderContext;
695 pPage->SetPrivateData((void*)1, pContext, DropContext);
696#ifdef _SKIA_SUPPORT_
697 pContext->m_pDevice = new CFX_SkiaDevice;
698
699 if (flags & FPDF_REVERSE_BYTE_ORDER)
700 ((CFX_SkiaDevice*)pContext->m_pDevice)
701 ->Attach((CFX_DIBitmap*)bitmap, 0, TRUE);
702 else
703 ((CFX_SkiaDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)bitmap);
704#else
705 pContext->m_pDevice = new CFX_FxgeDevice;
706
707 if (flags & FPDF_REVERSE_BYTE_ORDER)
708 ((CFX_FxgeDevice*)pContext->m_pDevice)
709 ->Attach((CFX_DIBitmap*)bitmap, 0, TRUE);
710 else
711 ((CFX_FxgeDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)bitmap);
712#endif
713
714 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
715 rotate, flags, TRUE, NULL);
716
717 delete pContext;
718 pPage->RemovePrivateData((void*)1);
Svet Ganove6986e12015-06-04 14:52:15 -0700719}
720
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800721DLLEXPORT void STDCALL FPDF_ClosePage(FPDF_PAGE page) {
722 if (!page)
723 return;
724#ifdef PDF_ENABLE_XFA
725 CPDFXFA_Page* pPage = (CPDFXFA_Page*)page;
726 pPage->Release();
727#else // PDF_ENABLE_XFA
728 CPDFSDK_PageView* pPageView =
729 (CPDFSDK_PageView*)(((CPDF_Page*)page))->GetPrivateData((void*)page);
730 if (pPageView && pPageView->IsLocked()) {
731 pPageView->TakeOverPage();
732 return;
733 }
734 delete (CPDF_Page*)page;
735#endif // PDF_ENABLE_XFA
Svet Ganove6986e12015-06-04 14:52:15 -0700736}
737
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800738DLLEXPORT void STDCALL FPDF_CloseDocument(FPDF_DOCUMENT document) {
739#ifdef PDF_ENABLE_XFA
740 delete UnderlyingFromFPDFDocument(document);
741#else // PDF_ENABLE_XFA
742 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
743 if (!pDoc)
744 return;
745 CPDF_Parser* pParser = pDoc->GetParser();
746 if (!pParser) {
747 delete pDoc;
748 return;
749 }
750 delete pParser;
751#endif // PDF_ENABLE_XFA
Svet Ganove6986e12015-06-04 14:52:15 -0700752}
753
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800754DLLEXPORT unsigned long STDCALL FPDF_GetLastError() {
755 return GetLastError();
Svet Ganove6986e12015-06-04 14:52:15 -0700756}
757
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800758DLLEXPORT void STDCALL FPDF_DeviceToPage(FPDF_PAGE page,
759 int start_x,
760 int start_y,
761 int size_x,
762 int size_y,
763 int rotate,
764 int device_x,
765 int device_y,
766 double* page_x,
767 double* page_y) {
768 if (!page || !page_x || !page_y)
769 return;
770 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
771#ifdef PDF_ENABLE_XFA
772 pPage->DeviceToPage(start_x, start_y, size_x, size_y, rotate, device_x,
773 device_y, page_x, page_y);
774#else // PDF_ENABLE_XFA
775 CFX_Matrix page2device;
776 pPage->GetDisplayMatrix(page2device, start_x, start_y, size_x, size_y,
777 rotate);
778 CFX_Matrix device2page;
779 device2page.SetReverse(page2device);
780 FX_FLOAT page_x_f, page_y_f;
781 device2page.Transform((FX_FLOAT)(device_x), (FX_FLOAT)(device_y), page_x_f,
782 page_y_f);
783 *page_x = (page_x_f);
784 *page_y = (page_y_f);
785#endif // PDF_ENABLE_XFA
Svet Ganove6986e12015-06-04 14:52:15 -0700786}
787
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800788DLLEXPORT void STDCALL FPDF_PageToDevice(FPDF_PAGE page,
789 int start_x,
790 int start_y,
791 int size_x,
792 int size_y,
793 int rotate,
794 double page_x,
795 double page_y,
796 int* device_x,
797 int* device_y) {
798 if (!device_x || !device_y)
799 return;
800 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
801 if (!pPage)
802 return;
803#ifdef PDF_ENABLE_XFA
804 pPage->PageToDevice(start_x, start_y, size_x, size_y, rotate, page_x, page_y,
805 device_x, device_y);
806#else // PDF_ENABLE_XFA
807 CFX_Matrix page2device;
808 pPage->GetDisplayMatrix(page2device, start_x, start_y, size_x, size_y,
809 rotate);
810 FX_FLOAT device_x_f, device_y_f;
811 page2device.Transform(((FX_FLOAT)page_x), ((FX_FLOAT)page_y), device_x_f,
812 device_y_f);
813 *device_x = FXSYS_round(device_x_f);
814 *device_y = FXSYS_round(device_y_f);
815#endif // PDF_ENABLE_XFA
Svet Ganove6986e12015-06-04 14:52:15 -0700816}
817
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800818DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_Create(int width,
819 int height,
820 int alpha) {
821 std::unique_ptr<CFX_DIBitmap> pBitmap(new CFX_DIBitmap);
822 if (!pBitmap->Create(width, height, alpha ? FXDIB_Argb : FXDIB_Rgb32)) {
823 return NULL;
824 }
825 return pBitmap.release();
Svet Ganove6986e12015-06-04 14:52:15 -0700826}
827
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800828DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_CreateEx(int width,
829 int height,
830 int format,
831 void* first_scan,
832 int stride) {
833 FXDIB_Format fx_format;
834 switch (format) {
835 case FPDFBitmap_Gray:
836 fx_format = FXDIB_8bppRgb;
837 break;
838 case FPDFBitmap_BGR:
839 fx_format = FXDIB_Rgb;
840 break;
841 case FPDFBitmap_BGRx:
842 fx_format = FXDIB_Rgb32;
843 break;
844 case FPDFBitmap_BGRA:
845 fx_format = FXDIB_Argb;
846 break;
847 default:
848 return NULL;
849 }
850 CFX_DIBitmap* pBitmap = new CFX_DIBitmap;
851 pBitmap->Create(width, height, fx_format, (uint8_t*)first_scan, stride);
852 return pBitmap;
Svet Ganove6986e12015-06-04 14:52:15 -0700853}
854
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800855DLLEXPORT void STDCALL FPDFBitmap_FillRect(FPDF_BITMAP bitmap,
856 int left,
857 int top,
858 int width,
859 int height,
860 FPDF_DWORD color) {
861 if (!bitmap)
862 return;
863#ifdef _SKIA_SUPPORT_
864 CFX_SkiaDevice device;
865#else
866 CFX_FxgeDevice device;
867#endif
868 device.Attach((CFX_DIBitmap*)bitmap);
869 if (!((CFX_DIBitmap*)bitmap)->HasAlpha())
870 color |= 0xFF000000;
871 FX_RECT rect(left, top, left + width, top + height);
872 device.FillRect(&rect, color);
Svet Ganove6986e12015-06-04 14:52:15 -0700873}
874
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800875DLLEXPORT void* STDCALL FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap) {
876 return bitmap ? ((CFX_DIBitmap*)bitmap)->GetBuffer() : nullptr;
Svet Ganove6986e12015-06-04 14:52:15 -0700877}
878
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800879DLLEXPORT int STDCALL FPDFBitmap_GetWidth(FPDF_BITMAP bitmap) {
880 return bitmap ? ((CFX_DIBitmap*)bitmap)->GetWidth() : 0;
Svet Ganove6986e12015-06-04 14:52:15 -0700881}
882
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -0800883DLLEXPORT int STDCALL FPDFBitmap_GetHeight(FPDF_BITMAP bitmap) {
884 return bitmap ? ((CFX_DIBitmap*)bitmap)->GetHeight() : 0;
885}
886
887DLLEXPORT int STDCALL FPDFBitmap_GetStride(FPDF_BITMAP bitmap) {
888 return bitmap ? ((CFX_DIBitmap*)bitmap)->GetPitch() : 0;
889}
890
891DLLEXPORT void STDCALL FPDFBitmap_Destroy(FPDF_BITMAP bitmap) {
892 delete (CFX_DIBitmap*)bitmap;
893}
894
895void FPDF_RenderPage_Retail(CRenderContext* pContext,
896 FPDF_PAGE page,
897 int start_x,
898 int start_y,
899 int size_x,
900 int size_y,
901 int rotate,
902 int flags,
903 FX_BOOL bNeedToRestore,
904 IFSDK_PAUSE_Adapter* pause) {
905 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
906 if (!pPage)
907 return;
908
909 if (!pContext->m_pOptions)
910 pContext->m_pOptions = new CPDF_RenderOptions;
911
912 if (flags & FPDF_LCD_TEXT)
913 pContext->m_pOptions->m_Flags |= RENDER_CLEARTYPE;
914 else
915 pContext->m_pOptions->m_Flags &= ~RENDER_CLEARTYPE;
916 if (flags & FPDF_NO_NATIVETEXT)
917 pContext->m_pOptions->m_Flags |= RENDER_NO_NATIVETEXT;
918 if (flags & FPDF_RENDER_LIMITEDIMAGECACHE)
919 pContext->m_pOptions->m_Flags |= RENDER_LIMITEDIMAGECACHE;
920 if (flags & FPDF_RENDER_FORCEHALFTONE)
921 pContext->m_pOptions->m_Flags |= RENDER_FORCE_HALFTONE;
922#ifndef PDF_ENABLE_XFA
923 if (flags & FPDF_RENDER_NO_SMOOTHTEXT)
924 pContext->m_pOptions->m_Flags |= RENDER_NOTEXTSMOOTH;
925 if (flags & FPDF_RENDER_NO_SMOOTHIMAGE)
926 pContext->m_pOptions->m_Flags |= RENDER_NOIMAGESMOOTH;
927 if (flags & FPDF_RENDER_NO_SMOOTHPATH)
928 pContext->m_pOptions->m_Flags |= RENDER_NOPATHSMOOTH;
929#endif // PDF_ENABLE_XFA
930 // Grayscale output
931 if (flags & FPDF_GRAYSCALE) {
932 pContext->m_pOptions->m_ColorMode = RENDER_COLOR_GRAY;
933 pContext->m_pOptions->m_ForeColor = 0;
934 pContext->m_pOptions->m_BackColor = 0xffffff;
935 }
936 const CPDF_OCContext::UsageType usage =
937 (flags & FPDF_PRINTING) ? CPDF_OCContext::Print : CPDF_OCContext::View;
938 pContext->m_pOptions->m_AddFlags = flags >> 8;
939 pContext->m_pOptions->m_pOCContext =
940 new CPDF_OCContext(pPage->m_pDocument, usage);
941
942 CFX_Matrix matrix;
943 pPage->GetDisplayMatrix(matrix, start_x, start_y, size_x, size_y, rotate);
944
945 FX_RECT clip;
946 clip.left = start_x;
947 clip.right = start_x + size_x;
948 clip.top = start_y;
949 clip.bottom = start_y + size_y;
950 pContext->m_pDevice->SaveState();
951 pContext->m_pDevice->SetClip_Rect(&clip);
952
953 pContext->m_pContext = new CPDF_RenderContext(pPage);
954 pContext->m_pContext->AppendObjectList(pPage, &matrix);
955
956 if (flags & FPDF_ANNOT) {
957 pContext->m_pAnnots = new CPDF_AnnotList(pPage);
958 FX_BOOL bPrinting = pContext->m_pDevice->GetDeviceClass() != FXDC_DISPLAY;
959 pContext->m_pAnnots->DisplayAnnots(pPage, pContext->m_pContext, bPrinting,
960 &matrix, TRUE, NULL);
961 }
962
963 pContext->m_pRenderer = new CPDF_ProgressiveRenderer(
964 pContext->m_pContext, pContext->m_pDevice, pContext->m_pOptions);
965 pContext->m_pRenderer->Start(pause);
966 if (bNeedToRestore)
967 pContext->m_pDevice->RestoreState();
968}
969
970DLLEXPORT int STDCALL FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document,
971 int page_index,
972 double* width,
973 double* height) {
974 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
975 if (!pDoc)
976 return FALSE;
977
978#ifdef PDF_ENABLE_XFA
979 int count = pDoc->GetPageCount();
980 if (page_index < 0 || page_index >= count)
981 return FALSE;
982 CPDFXFA_Page* pPage = pDoc->GetPage(page_index);
983 if (!pPage)
984 return FALSE;
985 *width = pPage->GetPageWidth();
986 *height = pPage->GetPageHeight();
987#else // PDF_ENABLE_XFA
988 CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
989 if (!pDict)
990 return FALSE;
991 CPDF_Page page;
992 page.Load(pDoc, pDict);
993 *width = page.GetPageWidth();
994 *height = page.GetPageHeight();
995#endif // PDF_ENABLE_XFA
996
997 return TRUE;
998}
999
1000DLLEXPORT FPDF_BOOL STDCALL
1001FPDF_VIEWERREF_GetPrintScaling(FPDF_DOCUMENT document) {
1002 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1003 if (!pDoc)
1004 return TRUE;
1005 CPDF_ViewerPreferences viewRef(pDoc);
1006 return viewRef.PrintScaling();
1007}
1008
1009DLLEXPORT int STDCALL FPDF_VIEWERREF_GetNumCopies(FPDF_DOCUMENT document) {
1010 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1011 if (!pDoc)
1012 return 1;
1013 CPDF_ViewerPreferences viewRef(pDoc);
1014 return viewRef.NumCopies();
1015}
1016
1017DLLEXPORT FPDF_PAGERANGE STDCALL
1018FPDF_VIEWERREF_GetPrintPageRange(FPDF_DOCUMENT document) {
1019 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1020 if (!pDoc)
1021 return NULL;
1022 CPDF_ViewerPreferences viewRef(pDoc);
1023 return viewRef.PrintPageRange();
1024}
1025
1026DLLEXPORT FPDF_DUPLEXTYPE STDCALL
1027FPDF_VIEWERREF_GetDuplex(FPDF_DOCUMENT document) {
1028 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1029 if (!pDoc)
Svet Ganove6986e12015-06-04 14:52:15 -07001030 return DuplexUndefined;
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -08001031 CPDF_ViewerPreferences viewRef(pDoc);
1032 CFX_ByteString duplex = viewRef.Duplex();
1033 if ("Simplex" == duplex)
1034 return Simplex;
1035 if ("DuplexFlipShortEdge" == duplex)
1036 return DuplexFlipShortEdge;
1037 if ("DuplexFlipLongEdge" == duplex)
1038 return DuplexFlipLongEdge;
1039 return DuplexUndefined;
Svet Ganove6986e12015-06-04 14:52:15 -07001040}
1041
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -08001042DLLEXPORT FPDF_DWORD STDCALL FPDF_CountNamedDests(FPDF_DOCUMENT document) {
1043 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1044 if (!pDoc)
1045 return 0;
Svet Ganove6986e12015-06-04 14:52:15 -07001046
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -08001047 CPDF_Dictionary* pRoot = pDoc->GetRoot();
1048 if (!pRoot)
1049 return 0;
Svet Ganove6986e12015-06-04 14:52:15 -07001050
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -08001051 CPDF_NameTree nameTree(pDoc, "Dests");
1052 pdfium::base::CheckedNumeric<FPDF_DWORD> count = nameTree.GetCount();
1053 CPDF_Dictionary* pDest = pRoot->GetDict("Dests");
1054 if (pDest)
1055 count += pDest->GetCount();
1056
1057 if (!count.IsValid())
1058 return 0;
1059
1060 return count.ValueOrDie();
Svet Ganove6986e12015-06-04 14:52:15 -07001061}
1062
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -08001063DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDestByName(FPDF_DOCUMENT document,
1064 FPDF_BYTESTRING name) {
1065 if (!name || name[0] == 0)
1066 return nullptr;
Svet Ganove6986e12015-06-04 14:52:15 -07001067
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -08001068 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1069 if (!pDoc)
1070 return nullptr;
1071
1072 CPDF_NameTree name_tree(pDoc, "Dests");
1073 return name_tree.LookupNamedDest(pDoc, name);
Svet Ganove6986e12015-06-04 14:52:15 -07001074}
1075
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -08001076#ifdef PDF_ENABLE_XFA
1077FPDF_RESULT FPDF_BStr_Init(FPDF_BSTR* str) {
1078 if (!str)
1079 return -1;
Svet Ganove6986e12015-06-04 14:52:15 -07001080
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -08001081 FXSYS_memset(str, 0, sizeof(FPDF_BSTR));
1082 return 0;
1083}
Svet Ganove6986e12015-06-04 14:52:15 -07001084
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -08001085FPDF_RESULT FPDF_BStr_Set(FPDF_BSTR* str, FPDF_LPCSTR bstr, int length) {
1086 if (!str)
1087 return -1;
1088 if (!bstr || !length)
1089 return -1;
1090 if (length == -1)
1091 length = FXSYS_strlen(bstr);
1092
1093 if (length == 0) {
1094 if (str->str) {
1095 FX_Free(str->str);
1096 str->str = NULL;
Svet Ganove6986e12015-06-04 14:52:15 -07001097 }
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -08001098 str->len = 0;
1099 return 0;
1100 }
1101
1102 if (str->str && str->len < length)
1103 str->str = FX_Realloc(char, str->str, length + 1);
1104 else if (!str->str)
1105 str->str = FX_Alloc(char, length + 1);
1106
1107 str->str[length] = 0;
1108 if (str->str == NULL)
1109 return -1;
1110
1111 FXSYS_memcpy(str->str, bstr, length);
1112 str->len = length;
1113
1114 return 0;
1115}
1116
1117FPDF_RESULT FPDF_BStr_Clear(FPDF_BSTR* str) {
1118 if (!str)
1119 return -1;
1120
1121 if (str->str) {
1122 FX_Free(str->str);
1123 str->str = NULL;
1124 }
1125 str->len = 0;
1126 return 0;
1127}
1128#endif // PDF_ENABLE_XFA
1129
1130DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDest(FPDF_DOCUMENT document,
1131 int index,
1132 void* buffer,
1133 long* buflen) {
1134 if (!buffer)
1135 *buflen = 0;
1136
1137 if (index < 0)
1138 return nullptr;
1139
1140 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1141 if (!pDoc)
1142 return nullptr;
1143
1144 CPDF_Dictionary* pRoot = pDoc->GetRoot();
1145 if (!pRoot)
1146 return nullptr;
1147
1148 CPDF_Object* pDestObj = nullptr;
1149 CFX_ByteString bsName;
1150 CPDF_NameTree nameTree(pDoc, "Dests");
1151 int count = nameTree.GetCount();
1152 if (index >= count) {
1153 CPDF_Dictionary* pDest = pRoot->GetDict("Dests");
1154 if (!pDest)
1155 return nullptr;
1156
1157 pdfium::base::CheckedNumeric<int> checked_count = count;
1158 checked_count += pDest->GetCount();
1159 if (!checked_count.IsValid() || index >= checked_count.ValueOrDie())
1160 return nullptr;
1161
1162 index -= count;
1163 int i = 0;
1164 for (const auto& it : *pDest) {
1165 bsName = it.first;
1166 pDestObj = it.second;
1167 if (!pDestObj)
1168 continue;
1169 if (i == index)
1170 break;
1171 i++;
Svet Ganove6986e12015-06-04 14:52:15 -07001172 }
Philip P. Moltmannac3d58c2016-03-04 15:19:21 -08001173 } else {
1174 pDestObj = nameTree.LookupValue(index, bsName);
1175 }
1176 if (!pDestObj)
1177 return nullptr;
1178 if (CPDF_Dictionary* pDict = pDestObj->AsDictionary()) {
1179 pDestObj = pDict->GetArray("D");
1180 if (!pDestObj)
1181 return nullptr;
1182 }
1183 if (!pDestObj->IsArray())
1184 return nullptr;
1185
1186 CFX_WideString wsName = PDF_DecodeText(bsName);
1187 CFX_ByteString utf16Name = wsName.UTF16LE_Encode();
1188 unsigned int len = utf16Name.GetLength();
1189 if (!buffer) {
1190 *buflen = len;
1191 } else if (*buflen >= len) {
1192 memcpy(buffer, utf16Name.c_str(), len);
1193 *buflen = len;
1194 } else {
1195 *buflen = -1;
1196 }
1197 return (FPDF_DEST)pDestObj;
Svet Ganove6986e12015-06-04 14:52:15 -07001198}