• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "public/fpdfview.h"
8 
9 #include <memory>
10 #include <utility>
11 
12 #include "core/fpdfapi/cpdf_modulemgr.h"
13 #include "core/fpdfapi/cpdf_pagerendercontext.h"
14 #include "core/fpdfapi/page/cpdf_page.h"
15 #include "core/fpdfapi/parser/cpdf_array.h"
16 #include "core/fpdfapi/parser/cpdf_document.h"
17 #include "core/fpdfapi/parser/fpdf_parser_decode.h"
18 #include "core/fpdfapi/render/cpdf_progressiverenderer.h"
19 #include "core/fpdfapi/render/cpdf_renderoptions.h"
20 #include "core/fpdfdoc/cpdf_annotlist.h"
21 #include "core/fpdfdoc/cpdf_nametree.h"
22 #include "core/fpdfdoc/cpdf_occontext.h"
23 #include "core/fpdfdoc/cpdf_viewerpreferences.h"
24 #include "core/fxcodec/fx_codec.h"
25 #include "core/fxcrt/fx_memory.h"
26 #include "core/fxcrt/fx_safe_types.h"
27 #include "core/fxge/cfx_fxgedevice.h"
28 #include "core/fxge/cfx_gemodule.h"
29 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
30 #include "fpdfsdk/cpdfsdk_pageview.h"
31 #include "fpdfsdk/fsdk_define.h"
32 #include "fpdfsdk/fsdk_pauseadapter.h"
33 #include "fpdfsdk/javascript/ijs_runtime.h"
34 #include "public/fpdf_ext.h"
35 #include "public/fpdf_progressive.h"
36 #include "third_party/base/numerics/safe_conversions_impl.h"
37 #include "third_party/base/ptr_util.h"
38 
39 #ifdef PDF_ENABLE_XFA
40 #include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
41 #include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
42 #include "fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h"
43 #include "public/fpdf_formfill.h"
44 #include "xfa/fxbarcode/BC_Library.h"
45 #endif  // PDF_ENABLE_XFA
46 
47 #ifdef PDF_ENABLE_XFA_BMP
48 #include "core/fxcodec/codec/ccodec_bmpmodule.h"
49 #endif
50 
51 #ifdef PDF_ENABLE_XFA_GIF
52 #include "core/fxcodec/codec/ccodec_gifmodule.h"
53 #endif
54 
55 #ifdef PDF_ENABLE_XFA_PNG
56 #include "core/fxcodec/codec/ccodec_pngmodule.h"
57 #endif
58 
59 #ifdef PDF_ENABLE_XFA_TIFF
60 #include "core/fxcodec/codec/ccodec_tiffmodule.h"
61 #endif
62 
63 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
64 #include "core/fxge/cfx_windowsdevice.h"
65 #endif
66 
67 namespace {
68 
69 // Also indicates whether library is currently initialized.
70 CCodec_ModuleMgr* g_pCodecModule = nullptr;
71 
RenderPageImpl(CPDF_PageRenderContext * pContext,CPDF_Page * pPage,const CFX_Matrix & matrix,const FX_RECT & clipping_rect,int flags,bool bNeedToRestore,IFSDK_PAUSE_Adapter * pause)72 void RenderPageImpl(CPDF_PageRenderContext* pContext,
73                     CPDF_Page* pPage,
74                     const CFX_Matrix& matrix,
75                     const FX_RECT& clipping_rect,
76                     int flags,
77                     bool bNeedToRestore,
78                     IFSDK_PAUSE_Adapter* pause) {
79   if (!pContext->m_pOptions)
80     pContext->m_pOptions = pdfium::MakeUnique<CPDF_RenderOptions>();
81 
82   if (flags & FPDF_LCD_TEXT)
83     pContext->m_pOptions->m_Flags |= RENDER_CLEARTYPE;
84   else
85     pContext->m_pOptions->m_Flags &= ~RENDER_CLEARTYPE;
86 
87   if (flags & FPDF_NO_NATIVETEXT)
88     pContext->m_pOptions->m_Flags |= RENDER_NO_NATIVETEXT;
89   if (flags & FPDF_RENDER_LIMITEDIMAGECACHE)
90     pContext->m_pOptions->m_Flags |= RENDER_LIMITEDIMAGECACHE;
91   if (flags & FPDF_RENDER_FORCEHALFTONE)
92     pContext->m_pOptions->m_Flags |= RENDER_FORCE_HALFTONE;
93 #ifndef PDF_ENABLE_XFA
94   if (flags & FPDF_RENDER_NO_SMOOTHTEXT)
95     pContext->m_pOptions->m_Flags |= RENDER_NOTEXTSMOOTH;
96   if (flags & FPDF_RENDER_NO_SMOOTHIMAGE)
97     pContext->m_pOptions->m_Flags |= RENDER_NOIMAGESMOOTH;
98   if (flags & FPDF_RENDER_NO_SMOOTHPATH)
99     pContext->m_pOptions->m_Flags |= RENDER_NOPATHSMOOTH;
100 #endif  // PDF_ENABLE_XFA
101 
102   // Grayscale output
103   if (flags & FPDF_GRAYSCALE) {
104     pContext->m_pOptions->m_ColorMode = RENDER_COLOR_GRAY;
105     pContext->m_pOptions->m_ForeColor = 0;
106     pContext->m_pOptions->m_BackColor = 0xffffff;
107   }
108 
109   const CPDF_OCContext::UsageType usage =
110       (flags & FPDF_PRINTING) ? CPDF_OCContext::Print : CPDF_OCContext::View;
111   pContext->m_pOptions->m_AddFlags = flags >> 8;
112   pContext->m_pOptions->m_pOCContext =
113       pdfium::MakeRetain<CPDF_OCContext>(pPage->m_pDocument, usage);
114 
115   pContext->m_pDevice->SaveState();
116   pContext->m_pDevice->SetClip_Rect(clipping_rect);
117 
118   pContext->m_pContext = pdfium::MakeUnique<CPDF_RenderContext>(pPage);
119   pContext->m_pContext->AppendLayer(pPage, &matrix);
120 
121   if (flags & FPDF_ANNOT) {
122     pContext->m_pAnnots = pdfium::MakeUnique<CPDF_AnnotList>(pPage);
123     bool bPrinting = pContext->m_pDevice->GetDeviceClass() != FXDC_DISPLAY;
124     pContext->m_pAnnots->DisplayAnnots(pPage, pContext->m_pContext.get(),
125                                        bPrinting, &matrix, false, nullptr);
126   }
127 
128   pContext->m_pRenderer = pdfium::MakeUnique<CPDF_ProgressiveRenderer>(
129       pContext->m_pContext.get(), pContext->m_pDevice.get(),
130       pContext->m_pOptions.get());
131   pContext->m_pRenderer->Start(pause);
132   if (bNeedToRestore)
133     pContext->m_pDevice->RestoreState(false);
134 }
135 
136 class CPDF_CustomAccess final : public IFX_SeekableReadStream {
137  public:
Create(FPDF_FILEACCESS * pFileAccess)138   static CFX_RetainPtr<CPDF_CustomAccess> Create(FPDF_FILEACCESS* pFileAccess) {
139     return CFX_RetainPtr<CPDF_CustomAccess>(new CPDF_CustomAccess(pFileAccess));
140   }
141 
142   // IFX_SeekableReadStream
143   FX_FILESIZE GetSize() override;
144   bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override;
145 
146  private:
147   explicit CPDF_CustomAccess(FPDF_FILEACCESS* pFileAccess);
148 
149   FPDF_FILEACCESS m_FileAccess;
150 };
151 
CPDF_CustomAccess(FPDF_FILEACCESS * pFileAccess)152 CPDF_CustomAccess::CPDF_CustomAccess(FPDF_FILEACCESS* pFileAccess)
153     : m_FileAccess(*pFileAccess) {}
154 
GetSize()155 FX_FILESIZE CPDF_CustomAccess::GetSize() {
156   return m_FileAccess.m_FileLen;
157 }
158 
ReadBlock(void * buffer,FX_FILESIZE offset,size_t size)159 bool CPDF_CustomAccess::ReadBlock(void* buffer,
160                                   FX_FILESIZE offset,
161                                   size_t size) {
162   if (offset < 0)
163     return false;
164 
165   FX_SAFE_FILESIZE newPos = pdfium::base::checked_cast<FX_FILESIZE>(size);
166   newPos += offset;
167   if (!newPos.IsValid() ||
168       newPos.ValueOrDie() > static_cast<FX_FILESIZE>(m_FileAccess.m_FileLen)) {
169     return false;
170   }
171   return !!m_FileAccess.m_GetBlock(m_FileAccess.m_Param, offset,
172                                    reinterpret_cast<uint8_t*>(buffer), size);
173 }
174 
175 #ifdef PDF_ENABLE_XFA
176 class CFPDF_FileStream : public IFX_SeekableStream {
177  public:
Create(FPDF_FILEHANDLER * pFS)178   static CFX_RetainPtr<CFPDF_FileStream> Create(FPDF_FILEHANDLER* pFS) {
179     return CFX_RetainPtr<CFPDF_FileStream>(new CFPDF_FileStream(pFS));
180   }
181   ~CFPDF_FileStream() override;
182 
183   // IFX_SeekableStream:
184   FX_FILESIZE GetSize() override;
185   bool IsEOF() override;
186   FX_FILESIZE GetPosition() override;
187   bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override;
188   size_t ReadBlock(void* buffer, size_t size) override;
189   bool WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size) override;
190   bool Flush() override;
191 
SetPosition(FX_FILESIZE pos)192   void SetPosition(FX_FILESIZE pos) { m_nCurPos = pos; }
193 
194  protected:
195   explicit CFPDF_FileStream(FPDF_FILEHANDLER* pFS);
196 
197   FPDF_FILEHANDLER* m_pFS;
198   FX_FILESIZE m_nCurPos;
199 };
200 
CFPDF_FileStream(FPDF_FILEHANDLER * pFS)201 CFPDF_FileStream::CFPDF_FileStream(FPDF_FILEHANDLER* pFS) {
202   m_pFS = pFS;
203   m_nCurPos = 0;
204 }
205 
~CFPDF_FileStream()206 CFPDF_FileStream::~CFPDF_FileStream() {
207   if (m_pFS && m_pFS->Release)
208     m_pFS->Release(m_pFS->clientData);
209 }
210 
GetSize()211 FX_FILESIZE CFPDF_FileStream::GetSize() {
212   if (m_pFS && m_pFS->GetSize)
213     return (FX_FILESIZE)m_pFS->GetSize(m_pFS->clientData);
214   return 0;
215 }
216 
IsEOF()217 bool CFPDF_FileStream::IsEOF() {
218   return m_nCurPos >= GetSize();
219 }
220 
GetPosition()221 FX_FILESIZE CFPDF_FileStream::GetPosition() {
222   return m_nCurPos;
223 }
224 
ReadBlock(void * buffer,FX_FILESIZE offset,size_t size)225 bool CFPDF_FileStream::ReadBlock(void* buffer,
226                                  FX_FILESIZE offset,
227                                  size_t size) {
228   if (!buffer || !size || !m_pFS->ReadBlock)
229     return false;
230 
231   if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
232                        (FPDF_DWORD)size) == 0) {
233     m_nCurPos = offset + size;
234     return true;
235   }
236   return false;
237 }
238 
ReadBlock(void * buffer,size_t size)239 size_t CFPDF_FileStream::ReadBlock(void* buffer, size_t size) {
240   if (!buffer || !size || !m_pFS->ReadBlock)
241     return 0;
242 
243   FX_FILESIZE nSize = GetSize();
244   if (m_nCurPos >= nSize)
245     return 0;
246   FX_FILESIZE dwAvail = nSize - m_nCurPos;
247   if (dwAvail < (FX_FILESIZE)size)
248     size = (size_t)dwAvail;
249   if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)m_nCurPos, buffer,
250                        (FPDF_DWORD)size) == 0) {
251     m_nCurPos += size;
252     return size;
253   }
254 
255   return 0;
256 }
257 
WriteBlock(const void * buffer,FX_FILESIZE offset,size_t size)258 bool CFPDF_FileStream::WriteBlock(const void* buffer,
259                                   FX_FILESIZE offset,
260                                   size_t size) {
261   if (!m_pFS || !m_pFS->WriteBlock)
262     return false;
263 
264   if (m_pFS->WriteBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
265                         (FPDF_DWORD)size) == 0) {
266     m_nCurPos = offset + size;
267     return true;
268   }
269   return false;
270 }
271 
Flush()272 bool CFPDF_FileStream::Flush() {
273   if (!m_pFS || !m_pFS->Flush)
274     return true;
275 
276   return m_pFS->Flush(m_pFS->clientData) == 0;
277 }
278 #endif  // PDF_ENABLE_XFA
279 
280 }  // namespace
281 
UnderlyingFromFPDFDocument(FPDF_DOCUMENT doc)282 UnderlyingDocumentType* UnderlyingFromFPDFDocument(FPDF_DOCUMENT doc) {
283   return static_cast<UnderlyingDocumentType*>(doc);
284 }
285 
FPDFDocumentFromUnderlying(UnderlyingDocumentType * doc)286 FPDF_DOCUMENT FPDFDocumentFromUnderlying(UnderlyingDocumentType* doc) {
287   return static_cast<FPDF_DOCUMENT>(doc);
288 }
289 
UnderlyingFromFPDFPage(FPDF_PAGE page)290 UnderlyingPageType* UnderlyingFromFPDFPage(FPDF_PAGE page) {
291   return static_cast<UnderlyingPageType*>(page);
292 }
293 
CPDFDocumentFromFPDFDocument(FPDF_DOCUMENT doc)294 CPDF_Document* CPDFDocumentFromFPDFDocument(FPDF_DOCUMENT doc) {
295 #ifdef PDF_ENABLE_XFA
296   return doc ? UnderlyingFromFPDFDocument(doc)->GetPDFDoc() : nullptr;
297 #else   // PDF_ENABLE_XFA
298   return UnderlyingFromFPDFDocument(doc);
299 #endif  // PDF_ENABLE_XFA
300 }
301 
FPDFDocumentFromCPDFDocument(CPDF_Document * doc)302 FPDF_DOCUMENT FPDFDocumentFromCPDFDocument(CPDF_Document* doc) {
303 #ifdef PDF_ENABLE_XFA
304   return doc ? FPDFDocumentFromUnderlying(
305                    new CPDFXFA_Context(pdfium::WrapUnique(doc)))
306              : nullptr;
307 #else   // PDF_ENABLE_XFA
308   return FPDFDocumentFromUnderlying(doc);
309 #endif  // PDF_ENABLE_XFA
310 }
311 
CPDFPageFromFPDFPage(FPDF_PAGE page)312 CPDF_Page* CPDFPageFromFPDFPage(FPDF_PAGE page) {
313 #ifdef PDF_ENABLE_XFA
314   return page ? UnderlyingFromFPDFPage(page)->GetPDFPage() : nullptr;
315 #else   // PDF_ENABLE_XFA
316   return UnderlyingFromFPDFPage(page);
317 #endif  // PDF_ENABLE_XFA
318 }
319 
CFXBitmapFromFPDFBitmap(FPDF_BITMAP bitmap)320 CFX_DIBitmap* CFXBitmapFromFPDFBitmap(FPDF_BITMAP bitmap) {
321   return static_cast<CFX_DIBitmap*>(bitmap);
322 }
323 
MakeSeekableReadStream(FPDF_FILEACCESS * pFileAccess)324 CFX_RetainPtr<IFX_SeekableReadStream> MakeSeekableReadStream(
325     FPDF_FILEACCESS* pFileAccess) {
326   return CPDF_CustomAccess::Create(pFileAccess);
327 }
328 
329 #ifdef PDF_ENABLE_XFA
MakeSeekableStream(FPDF_FILEHANDLER * pFilehandler)330 CFX_RetainPtr<IFX_SeekableStream> MakeSeekableStream(
331     FPDF_FILEHANDLER* pFilehandler) {
332   return CFPDF_FileStream::Create(pFilehandler);
333 }
334 #endif  // PDF_ENABLE_XFA
335 
336 // 0 bit: FPDF_POLICY_MACHINETIME_ACCESS
337 static uint32_t foxit_sandbox_policy = 0xFFFFFFFF;
338 
FSDK_SetSandBoxPolicy(FPDF_DWORD policy,FPDF_BOOL enable)339 void FSDK_SetSandBoxPolicy(FPDF_DWORD policy, FPDF_BOOL enable) {
340   switch (policy) {
341     case FPDF_POLICY_MACHINETIME_ACCESS: {
342       if (enable)
343         foxit_sandbox_policy |= 0x01;
344       else
345         foxit_sandbox_policy &= 0xFFFFFFFE;
346     } break;
347     default:
348       break;
349   }
350 }
351 
FSDK_IsSandBoxPolicyEnabled(FPDF_DWORD policy)352 FPDF_BOOL FSDK_IsSandBoxPolicyEnabled(FPDF_DWORD policy) {
353   switch (policy) {
354     case FPDF_POLICY_MACHINETIME_ACCESS:
355       return !!(foxit_sandbox_policy & 0x01);
356     default:
357       return false;
358   }
359 }
360 
FPDF_InitLibrary()361 DLLEXPORT void STDCALL FPDF_InitLibrary() {
362   FPDF_InitLibraryWithConfig(nullptr);
363 }
364 
365 DLLEXPORT void STDCALL
FPDF_InitLibraryWithConfig(const FPDF_LIBRARY_CONFIG * cfg)366 FPDF_InitLibraryWithConfig(const FPDF_LIBRARY_CONFIG* cfg) {
367   if (g_pCodecModule)
368     return;
369 
370   g_pCodecModule = new CCodec_ModuleMgr();
371 
372   CFX_GEModule* pModule = CFX_GEModule::Get();
373   pModule->Init(cfg ? cfg->m_pUserFontPaths : nullptr, g_pCodecModule);
374 
375   CPDF_ModuleMgr* pModuleMgr = CPDF_ModuleMgr::Get();
376   pModuleMgr->SetCodecModule(g_pCodecModule);
377   pModuleMgr->InitPageModule();
378   pModuleMgr->LoadEmbeddedGB1CMaps();
379   pModuleMgr->LoadEmbeddedJapan1CMaps();
380   pModuleMgr->LoadEmbeddedCNS1CMaps();
381   pModuleMgr->LoadEmbeddedKorea1CMaps();
382 
383 #ifdef PDF_ENABLE_XFA_BMP
384   pModuleMgr->GetCodecModule()->SetBmpModule(
385       pdfium::MakeUnique<CCodec_BmpModule>());
386 #endif
387 
388 #ifdef PDF_ENABLE_XFA_GIF
389   pModuleMgr->GetCodecModule()->SetGifModule(
390       pdfium::MakeUnique<CCodec_GifModule>());
391 #endif
392 
393 #ifdef PDF_ENABLE_XFA_PNG
394   pModuleMgr->GetCodecModule()->SetPngModule(
395       pdfium::MakeUnique<CCodec_PngModule>());
396 #endif
397 
398 #ifdef PDF_ENABLE_XFA_TIFF
399   pModuleMgr->GetCodecModule()->SetTiffModule(
400       pdfium::MakeUnique<CCodec_TiffModule>());
401 #endif
402 
403 #ifdef PDF_ENABLE_XFA
404   FXJSE_Initialize();
405   BC_Library_Init();
406 #endif  // PDF_ENABLE_XFA
407   if (cfg && cfg->version >= 2)
408     IJS_Runtime::Initialize(cfg->m_v8EmbedderSlot, cfg->m_pIsolate);
409 }
410 
FPDF_DestroyLibrary()411 DLLEXPORT void STDCALL FPDF_DestroyLibrary() {
412   if (!g_pCodecModule)
413     return;
414 
415 #ifdef PDF_ENABLE_XFA
416   BC_Library_Destory();
417   FXJSE_Finalize();
418 #endif  // PDF_ENABLE_XFA
419 
420   CPDF_ModuleMgr::Destroy();
421   CFX_GEModule::Destroy();
422 
423   delete g_pCodecModule;
424   g_pCodecModule = nullptr;
425 
426   IJS_Runtime::Destroy();
427 }
428 
429 #ifndef _WIN32
430 int g_LastError;
SetLastError(int err)431 void SetLastError(int err) {
432   g_LastError = err;
433 }
434 
GetLastError()435 int GetLastError() {
436   return g_LastError;
437 }
438 #endif  // _WIN32
439 
ProcessParseError(CPDF_Parser::Error err)440 void ProcessParseError(CPDF_Parser::Error err) {
441   uint32_t err_code = FPDF_ERR_SUCCESS;
442   // Translate FPDFAPI error code to FPDFVIEW error code
443   switch (err) {
444     case CPDF_Parser::SUCCESS:
445       err_code = FPDF_ERR_SUCCESS;
446       break;
447     case CPDF_Parser::FILE_ERROR:
448       err_code = FPDF_ERR_FILE;
449       break;
450     case CPDF_Parser::FORMAT_ERROR:
451       err_code = FPDF_ERR_FORMAT;
452       break;
453     case CPDF_Parser::PASSWORD_ERROR:
454       err_code = FPDF_ERR_PASSWORD;
455       break;
456     case CPDF_Parser::HANDLER_ERROR:
457       err_code = FPDF_ERR_SECURITY;
458       break;
459   }
460   SetLastError(err_code);
461 }
462 
FPDF_SetSandBoxPolicy(FPDF_DWORD policy,FPDF_BOOL enable)463 DLLEXPORT void STDCALL FPDF_SetSandBoxPolicy(FPDF_DWORD policy,
464                                              FPDF_BOOL enable) {
465   return FSDK_SetSandBoxPolicy(policy, enable);
466 }
467 
468 #if defined(_WIN32)
469 #if defined(PDFIUM_PRINT_TEXT_WITH_GDI)
470 DLLEXPORT void STDCALL
FPDF_SetTypefaceAccessibleFunc(PDFiumEnsureTypefaceCharactersAccessible func)471 FPDF_SetTypefaceAccessibleFunc(PDFiumEnsureTypefaceCharactersAccessible func) {
472   g_pdfium_typeface_accessible_func = func;
473 }
474 
FPDF_SetPrintTextWithGDI(FPDF_BOOL use_gdi)475 DLLEXPORT void STDCALL FPDF_SetPrintTextWithGDI(FPDF_BOOL use_gdi) {
476   g_pdfium_print_text_with_gdi = !!use_gdi;
477 }
478 #endif  // PDFIUM_PRINT_TEXT_WITH_GDI
479 
FPDF_SetPrintPostscriptLevel(int postscript_level)480 DLLEXPORT FPDF_BOOL STDCALL FPDF_SetPrintPostscriptLevel(int postscript_level) {
481   if (postscript_level != 0 && postscript_level != 2 && postscript_level != 3)
482     return FALSE;
483   g_pdfium_print_postscript_level = postscript_level;
484   return TRUE;
485 }
486 #endif  // defined(_WIN32)
487 
FPDF_LoadDocument(FPDF_STRING file_path,FPDF_BYTESTRING password)488 DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadDocument(FPDF_STRING file_path,
489                                                   FPDF_BYTESTRING password) {
490   // NOTE: the creation of the file needs to be by the embedder on the
491   // other side of this API.
492   CFX_RetainPtr<IFX_SeekableReadStream> pFileAccess =
493       IFX_SeekableReadStream::CreateFromFilename((const FX_CHAR*)file_path);
494   if (!pFileAccess)
495     return nullptr;
496 
497   auto pParser = pdfium::MakeUnique<CPDF_Parser>();
498   pParser->SetPassword(password);
499 
500   auto pDocument = pdfium::MakeUnique<CPDF_Document>(std::move(pParser));
501   CPDF_Parser::Error error =
502       pDocument->GetParser()->StartParse(pFileAccess, pDocument.get());
503   if (error != CPDF_Parser::SUCCESS) {
504     ProcessParseError(error);
505     return nullptr;
506   }
507   return FPDFDocumentFromCPDFDocument(pDocument.release());
508 }
509 
510 #ifdef PDF_ENABLE_XFA
FPDF_HasXFAField(FPDF_DOCUMENT document,int * docType)511 DLLEXPORT FPDF_BOOL STDCALL FPDF_HasXFAField(FPDF_DOCUMENT document,
512                                              int* docType) {
513   if (!document)
514     return false;
515 
516   CPDF_Document* pdfDoc =
517       (static_cast<CPDFXFA_Context*>(document))->GetPDFDoc();
518   if (!pdfDoc)
519     return false;
520 
521   CPDF_Dictionary* pRoot = pdfDoc->GetRoot();
522   if (!pRoot)
523     return false;
524 
525   CPDF_Dictionary* pAcroForm = pRoot->GetDictFor("AcroForm");
526   if (!pAcroForm)
527     return false;
528 
529   CPDF_Object* pXFA = pAcroForm->GetObjectFor("XFA");
530   if (!pXFA)
531     return false;
532 
533   bool bDynamicXFA = pRoot->GetBooleanFor("NeedsRendering", false);
534   *docType = bDynamicXFA ? DOCTYPE_DYNAMIC_XFA : DOCTYPE_STATIC_XFA;
535   return true;
536 }
537 
FPDF_LoadXFA(FPDF_DOCUMENT document)538 DLLEXPORT FPDF_BOOL STDCALL FPDF_LoadXFA(FPDF_DOCUMENT document) {
539   return document && (static_cast<CPDFXFA_Context*>(document))->LoadXFADoc();
540 }
541 #endif  // PDF_ENABLE_XFA
542 
543 class CMemFile final : public IFX_SeekableReadStream {
544  public:
Create(uint8_t * pBuf,FX_FILESIZE size)545   static CFX_RetainPtr<CMemFile> Create(uint8_t* pBuf, FX_FILESIZE size) {
546     return CFX_RetainPtr<CMemFile>(new CMemFile(pBuf, size));
547   }
548 
GetSize()549   FX_FILESIZE GetSize() override { return m_size; }
ReadBlock(void * buffer,FX_FILESIZE offset,size_t size)550   bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override {
551     if (offset < 0)
552       return false;
553 
554     FX_SAFE_FILESIZE newPos = pdfium::base::checked_cast<FX_FILESIZE>(size);
555     newPos += offset;
556     if (!newPos.IsValid() || newPos.ValueOrDie() > m_size)
557       return false;
558 
559     FXSYS_memcpy(buffer, m_pBuf + offset, size);
560     return true;
561   }
562 
563  private:
CMemFile(uint8_t * pBuf,FX_FILESIZE size)564   CMemFile(uint8_t* pBuf, FX_FILESIZE size) : m_pBuf(pBuf), m_size(size) {}
565 
566   uint8_t* const m_pBuf;
567   const FX_FILESIZE m_size;
568 };
569 
FPDF_LoadMemDocument(const void * data_buf,int size,FPDF_BYTESTRING password)570 DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadMemDocument(const void* data_buf,
571                                                      int size,
572                                                      FPDF_BYTESTRING password) {
573   CFX_RetainPtr<CMemFile> pMemFile = CMemFile::Create((uint8_t*)data_buf, size);
574   auto pParser = pdfium::MakeUnique<CPDF_Parser>();
575   pParser->SetPassword(password);
576 
577   auto pDocument = pdfium::MakeUnique<CPDF_Document>(std::move(pParser));
578   CPDF_Parser::Error error =
579       pDocument->GetParser()->StartParse(pMemFile, pDocument.get());
580   if (error != CPDF_Parser::SUCCESS) {
581     ProcessParseError(error);
582     return nullptr;
583   }
584   CheckUnSupportError(pDocument.get(), error);
585   return FPDFDocumentFromCPDFDocument(pDocument.release());
586 }
587 
588 DLLEXPORT FPDF_DOCUMENT STDCALL
FPDF_LoadCustomDocument(FPDF_FILEACCESS * pFileAccess,FPDF_BYTESTRING password)589 FPDF_LoadCustomDocument(FPDF_FILEACCESS* pFileAccess,
590                         FPDF_BYTESTRING password) {
591   CFX_RetainPtr<CPDF_CustomAccess> pFile =
592       CPDF_CustomAccess::Create(pFileAccess);
593   auto pParser = pdfium::MakeUnique<CPDF_Parser>();
594   pParser->SetPassword(password);
595 
596   auto pDocument = pdfium::MakeUnique<CPDF_Document>(std::move(pParser));
597   CPDF_Parser::Error error =
598       pDocument->GetParser()->StartParse(pFile, pDocument.get());
599   if (error != CPDF_Parser::SUCCESS) {
600     ProcessParseError(error);
601     return nullptr;
602   }
603   CheckUnSupportError(pDocument.get(), error);
604   return FPDFDocumentFromCPDFDocument(pDocument.release());
605 }
606 
FPDF_GetFileVersion(FPDF_DOCUMENT doc,int * fileVersion)607 DLLEXPORT FPDF_BOOL STDCALL FPDF_GetFileVersion(FPDF_DOCUMENT doc,
608                                                 int* fileVersion) {
609   if (!fileVersion)
610     return false;
611 
612   *fileVersion = 0;
613   CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(doc);
614   if (!pDoc)
615     return false;
616 
617   CPDF_Parser* pParser = pDoc->GetParser();
618   if (!pParser)
619     return false;
620 
621   *fileVersion = pParser->GetFileVersion();
622   return true;
623 }
624 
625 // jabdelmalek: changed return type from uint32_t to build on Linux (and match
626 // header).
FPDF_GetDocPermissions(FPDF_DOCUMENT document)627 DLLEXPORT unsigned long STDCALL FPDF_GetDocPermissions(FPDF_DOCUMENT document) {
628   CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
629   // https://bugs.chromium.org/p/pdfium/issues/detail?id=499
630   if (!pDoc) {
631 #ifndef PDF_ENABLE_XFA
632     return 0;
633 #else   // PDF_ENABLE_XFA
634     return 0xFFFFFFFF;
635 #endif  // PDF_ENABLE_XFA
636   }
637 
638   return pDoc->GetUserPermissions();
639 }
640 
FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document)641 DLLEXPORT int STDCALL FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document) {
642   CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
643   if (!pDoc || !pDoc->GetParser())
644     return -1;
645 
646   CPDF_Dictionary* pDict = pDoc->GetParser()->GetEncryptDict();
647   return pDict ? pDict->GetIntegerFor("R") : -1;
648 }
649 
FPDF_GetPageCount(FPDF_DOCUMENT document)650 DLLEXPORT int STDCALL FPDF_GetPageCount(FPDF_DOCUMENT document) {
651   UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
652   return pDoc ? pDoc->GetPageCount() : 0;
653 }
654 
FPDF_LoadPage(FPDF_DOCUMENT document,int page_index)655 DLLEXPORT FPDF_PAGE STDCALL FPDF_LoadPage(FPDF_DOCUMENT document,
656                                           int page_index) {
657   UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
658   if (!pDoc)
659     return nullptr;
660 
661   if (page_index < 0 || page_index >= pDoc->GetPageCount())
662     return nullptr;
663 
664 #ifdef PDF_ENABLE_XFA
665   return pDoc->GetXFAPage(page_index);
666 #else   // PDF_ENABLE_XFA
667   CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
668   if (!pDict)
669     return nullptr;
670 
671   CPDF_Page* pPage = new CPDF_Page(pDoc, pDict, true);
672   pPage->ParseContent();
673   return pPage;
674 #endif  // PDF_ENABLE_XFA
675 }
676 
FPDF_GetPageWidth(FPDF_PAGE page)677 DLLEXPORT double STDCALL FPDF_GetPageWidth(FPDF_PAGE page) {
678   UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
679   return pPage ? pPage->GetPageWidth() : 0.0;
680 }
681 
FPDF_GetPageHeight(FPDF_PAGE page)682 DLLEXPORT double STDCALL FPDF_GetPageHeight(FPDF_PAGE page) {
683   UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
684   return pPage ? pPage->GetPageHeight() : 0.0;
685 }
686 
687 #if defined(_WIN32)
FPDF_RenderPage(HDC dc,FPDF_PAGE page,int start_x,int start_y,int size_x,int size_y,int rotate,int flags)688 DLLEXPORT void STDCALL FPDF_RenderPage(HDC dc,
689                                        FPDF_PAGE page,
690                                        int start_x,
691                                        int start_y,
692                                        int size_x,
693                                        int size_y,
694                                        int rotate,
695                                        int flags) {
696   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
697   if (!pPage)
698     return;
699 
700   CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
701   pPage->SetRenderContext(pdfium::WrapUnique(pContext));
702 
703   std::unique_ptr<CFX_DIBitmap> pBitmap;
704   // TODO: This results in unnecessary rasterization of some PDFs due to
705   // HasImageMask() returning true. If any image on the page is a mask, the
706   // entire page gets rasterized and the spool size gets huge.
707   const bool bNewBitmap =
708       pPage->BackgroundAlphaNeeded() || pPage->HasImageMask();
709   if (bNewBitmap) {
710     pBitmap = pdfium::MakeUnique<CFX_DIBitmap>();
711     pBitmap->Create(size_x, size_y, FXDIB_Argb);
712     pBitmap->Clear(0x00ffffff);
713     CFX_FxgeDevice* pDevice = new CFX_FxgeDevice;
714     pContext->m_pDevice = pdfium::WrapUnique(pDevice);
715     pDevice->Attach(pBitmap.get(), false, nullptr, false);
716   } else {
717     pContext->m_pDevice = pdfium::MakeUnique<CFX_WindowsDevice>(dc);
718   }
719 
720   FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
721                          rotate, flags, true, nullptr);
722 
723   if (bNewBitmap) {
724     CFX_WindowsDevice WinDC(dc);
725     if (WinDC.GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
726       std::unique_ptr<CFX_DIBitmap> pDst = pdfium::MakeUnique<CFX_DIBitmap>();
727       int pitch = pBitmap->GetPitch();
728       pDst->Create(size_x, size_y, FXDIB_Rgb32);
729       FXSYS_memset(pDst->GetBuffer(), -1, pitch * size_y);
730       pDst->CompositeBitmap(0, 0, size_x, size_y, pBitmap.get(), 0, 0,
731                             FXDIB_BLEND_NORMAL, nullptr, false, nullptr);
732       WinDC.StretchDIBits(pDst.get(), 0, 0, size_x, size_y);
733     } else {
734       WinDC.SetDIBits(pBitmap.get(), 0, 0);
735     }
736   }
737 
738   pPage->SetRenderContext(nullptr);
739 }
740 #endif  // defined(_WIN32)
741 
FPDF_RenderPageBitmap(FPDF_BITMAP bitmap,FPDF_PAGE page,int start_x,int start_y,int size_x,int size_y,int rotate,int flags)742 DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap,
743                                              FPDF_PAGE page,
744                                              int start_x,
745                                              int start_y,
746                                              int size_x,
747                                              int size_y,
748                                              int rotate,
749                                              int flags) {
750   if (!bitmap)
751     return;
752 
753   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
754   if (!pPage)
755     return;
756 
757   CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
758   pPage->SetRenderContext(pdfium::WrapUnique(pContext));
759   CFX_FxgeDevice* pDevice = new CFX_FxgeDevice;
760   pContext->m_pDevice.reset(pDevice);
761   CFX_DIBitmap* pBitmap = CFXBitmapFromFPDFBitmap(bitmap);
762   pDevice->Attach(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER), nullptr, false);
763 
764   FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
765                          rotate, flags, true, nullptr);
766 
767 #ifdef _SKIA_SUPPORT_PATHS_
768   pDevice->Flush();
769   pBitmap->UnPreMultiply();
770 #endif
771   pPage->SetRenderContext(nullptr);
772 }
773 
FPDF_RenderPageBitmapWithMatrix(FPDF_BITMAP bitmap,FPDF_PAGE page,const FS_MATRIX * matrix,const FS_RECTF * clipping,int flags)774 DLLEXPORT void STDCALL FPDF_RenderPageBitmapWithMatrix(FPDF_BITMAP bitmap,
775                                                        FPDF_PAGE page,
776                                                        const FS_MATRIX* matrix,
777                                                        const FS_RECTF* clipping,
778                                                        int flags) {
779   if (!bitmap)
780     return;
781 
782   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
783   if (!pPage)
784     return;
785 
786   CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
787   pPage->SetRenderContext(pdfium::WrapUnique(pContext));
788   CFX_FxgeDevice* pDevice = new CFX_FxgeDevice;
789   pContext->m_pDevice.reset(pDevice);
790   CFX_DIBitmap* pBitmap = CFXBitmapFromFPDFBitmap(bitmap);
791   pDevice->Attach(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER), nullptr, false);
792 
793   CFX_Matrix transform_matrix = pPage->GetPageMatrix();
794   if (matrix) {
795     transform_matrix.Concat(CFX_Matrix(matrix->a, matrix->b, matrix->c,
796                                        matrix->d, matrix->e, matrix->f));
797   }
798 
799   CFX_FloatRect clipping_rect;
800   if (clipping) {
801     clipping_rect.left = clipping->left;
802     clipping_rect.bottom = clipping->bottom;
803     clipping_rect.right = clipping->right;
804     clipping_rect.top = clipping->top;
805   }
806   RenderPageImpl(pContext, pPage, transform_matrix, clipping_rect.ToFxRect(),
807                  flags, true, nullptr);
808 
809   pPage->SetRenderContext(nullptr);
810 }
811 
812 #ifdef _SKIA_SUPPORT_
FPDF_RenderPageSkp(FPDF_PAGE page,int size_x,int size_y)813 DLLEXPORT FPDF_RECORDER STDCALL FPDF_RenderPageSkp(FPDF_PAGE page,
814                                                    int size_x,
815                                                    int size_y) {
816   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
817   if (!pPage)
818     return nullptr;
819 
820   CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
821   pPage->SetRenderContext(pdfium::WrapUnique(pContext));
822   CFX_FxgeDevice* skDevice = new CFX_FxgeDevice;
823   FPDF_RECORDER recorder = skDevice->CreateRecorder(size_x, size_y);
824   pContext->m_pDevice.reset(skDevice);
825   FPDF_RenderPage_Retail(pContext, page, 0, 0, size_x, size_y, 0, 0, true,
826                          nullptr);
827   pPage->SetRenderContext(nullptr);
828   return recorder;
829 }
830 #endif
831 
FPDF_ClosePage(FPDF_PAGE page)832 DLLEXPORT void STDCALL FPDF_ClosePage(FPDF_PAGE page) {
833   UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
834   if (!page)
835     return;
836 #ifdef PDF_ENABLE_XFA
837   pPage->Release();
838 #else   // PDF_ENABLE_XFA
839   CPDFSDK_PageView* pPageView =
840       static_cast<CPDFSDK_PageView*>(pPage->GetView());
841   if (pPageView) {
842     // We're already destroying the pageview, so bail early.
843     if (pPageView->IsBeingDestroyed())
844       return;
845 
846     if (pPageView->IsLocked()) {
847       pPageView->TakePageOwnership();
848       return;
849     }
850 
851     bool owned = pPageView->OwnsPage();
852     // This will delete the |pPageView| object. We must cleanup the PageView
853     // first because it will attempt to reset the View on the |pPage| during
854     // destruction.
855     pPageView->GetFormFillEnv()->RemovePageView(pPage);
856     // If the page was owned then the pageview will have deleted the page.
857     if (owned)
858       return;
859   }
860   delete pPage;
861 #endif  // PDF_ENABLE_XFA
862 }
863 
FPDF_CloseDocument(FPDF_DOCUMENT document)864 DLLEXPORT void STDCALL FPDF_CloseDocument(FPDF_DOCUMENT document) {
865   delete UnderlyingFromFPDFDocument(document);
866 }
867 
FPDF_GetLastError()868 DLLEXPORT unsigned long STDCALL FPDF_GetLastError() {
869   return GetLastError();
870 }
871 
FPDF_DeviceToPage(FPDF_PAGE page,int start_x,int start_y,int size_x,int size_y,int rotate,int device_x,int device_y,double * page_x,double * page_y)872 DLLEXPORT void STDCALL FPDF_DeviceToPage(FPDF_PAGE page,
873                                          int start_x,
874                                          int start_y,
875                                          int size_x,
876                                          int size_y,
877                                          int rotate,
878                                          int device_x,
879                                          int device_y,
880                                          double* page_x,
881                                          double* page_y) {
882   if (!page || !page_x || !page_y)
883     return;
884   UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
885 #ifdef PDF_ENABLE_XFA
886   pPage->DeviceToPage(start_x, start_y, size_x, size_y, rotate, device_x,
887                       device_y, page_x, page_y);
888 #else   // PDF_ENABLE_XFA
889   CFX_Matrix page2device =
890       pPage->GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate);
891   CFX_Matrix device2page;
892   device2page.SetReverse(page2device);
893 
894   CFX_PointF pos = device2page.Transform(CFX_PointF(
895       static_cast<FX_FLOAT>(device_x), static_cast<FX_FLOAT>(device_y)));
896 
897   *page_x = pos.x;
898   *page_y = pos.y;
899 #endif  // PDF_ENABLE_XFA
900 }
901 
FPDF_PageToDevice(FPDF_PAGE page,int start_x,int start_y,int size_x,int size_y,int rotate,double page_x,double page_y,int * device_x,int * device_y)902 DLLEXPORT void STDCALL FPDF_PageToDevice(FPDF_PAGE page,
903                                          int start_x,
904                                          int start_y,
905                                          int size_x,
906                                          int size_y,
907                                          int rotate,
908                                          double page_x,
909                                          double page_y,
910                                          int* device_x,
911                                          int* device_y) {
912   if (!device_x || !device_y)
913     return;
914   UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
915   if (!pPage)
916     return;
917 #ifdef PDF_ENABLE_XFA
918   pPage->PageToDevice(start_x, start_y, size_x, size_y, rotate, page_x, page_y,
919                       device_x, device_y);
920 #else   // PDF_ENABLE_XFA
921   CFX_Matrix page2device =
922       pPage->GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate);
923   CFX_PointF pos = page2device.Transform(
924       CFX_PointF(static_cast<FX_FLOAT>(page_x), static_cast<FX_FLOAT>(page_y)));
925 
926   *device_x = FXSYS_round(pos.x);
927   *device_y = FXSYS_round(pos.y);
928 #endif  // PDF_ENABLE_XFA
929 }
930 
FPDFBitmap_Create(int width,int height,int alpha)931 DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_Create(int width,
932                                                 int height,
933                                                 int alpha) {
934   auto pBitmap = pdfium::MakeUnique<CFX_DIBitmap>();
935   if (!pBitmap->Create(width, height, alpha ? FXDIB_Argb : FXDIB_Rgb32))
936     return nullptr;
937 
938   return pBitmap.release();
939 }
940 
FPDFBitmap_CreateEx(int width,int height,int format,void * first_scan,int stride)941 DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_CreateEx(int width,
942                                                   int height,
943                                                   int format,
944                                                   void* first_scan,
945                                                   int stride) {
946   FXDIB_Format fx_format;
947   switch (format) {
948     case FPDFBitmap_Gray:
949       fx_format = FXDIB_8bppRgb;
950       break;
951     case FPDFBitmap_BGR:
952       fx_format = FXDIB_Rgb;
953       break;
954     case FPDFBitmap_BGRx:
955       fx_format = FXDIB_Rgb32;
956       break;
957     case FPDFBitmap_BGRA:
958       fx_format = FXDIB_Argb;
959       break;
960     default:
961       return nullptr;
962   }
963   CFX_DIBitmap* pBitmap = new CFX_DIBitmap;
964   pBitmap->Create(width, height, fx_format, (uint8_t*)first_scan, stride);
965   return pBitmap;
966 }
967 
FPDFBitmap_FillRect(FPDF_BITMAP bitmap,int left,int top,int width,int height,FPDF_DWORD color)968 DLLEXPORT void STDCALL FPDFBitmap_FillRect(FPDF_BITMAP bitmap,
969                                            int left,
970                                            int top,
971                                            int width,
972                                            int height,
973                                            FPDF_DWORD color) {
974   if (!bitmap)
975     return;
976 
977   CFX_FxgeDevice device;
978   CFX_DIBitmap* pBitmap = CFXBitmapFromFPDFBitmap(bitmap);
979   device.Attach(pBitmap, false, nullptr, false);
980   if (!pBitmap->HasAlpha())
981     color |= 0xFF000000;
982   FX_RECT rect(left, top, left + width, top + height);
983   device.FillRect(&rect, color);
984 }
985 
FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap)986 DLLEXPORT void* STDCALL FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap) {
987   return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetBuffer() : nullptr;
988 }
989 
FPDFBitmap_GetWidth(FPDF_BITMAP bitmap)990 DLLEXPORT int STDCALL FPDFBitmap_GetWidth(FPDF_BITMAP bitmap) {
991   return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetWidth() : 0;
992 }
993 
FPDFBitmap_GetHeight(FPDF_BITMAP bitmap)994 DLLEXPORT int STDCALL FPDFBitmap_GetHeight(FPDF_BITMAP bitmap) {
995   return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetHeight() : 0;
996 }
997 
FPDFBitmap_GetStride(FPDF_BITMAP bitmap)998 DLLEXPORT int STDCALL FPDFBitmap_GetStride(FPDF_BITMAP bitmap) {
999   return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetPitch() : 0;
1000 }
1001 
FPDFBitmap_Destroy(FPDF_BITMAP bitmap)1002 DLLEXPORT void STDCALL FPDFBitmap_Destroy(FPDF_BITMAP bitmap) {
1003   delete CFXBitmapFromFPDFBitmap(bitmap);
1004 }
1005 
FPDF_RenderPage_Retail(CPDF_PageRenderContext * pContext,FPDF_PAGE page,int start_x,int start_y,int size_x,int size_y,int rotate,int flags,bool bNeedToRestore,IFSDK_PAUSE_Adapter * pause)1006 void FPDF_RenderPage_Retail(CPDF_PageRenderContext* pContext,
1007                             FPDF_PAGE page,
1008                             int start_x,
1009                             int start_y,
1010                             int size_x,
1011                             int size_y,
1012                             int rotate,
1013                             int flags,
1014                             bool bNeedToRestore,
1015                             IFSDK_PAUSE_Adapter* pause) {
1016   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
1017   if (!pPage)
1018     return;
1019 
1020   RenderPageImpl(pContext, pPage, pPage->GetDisplayMatrix(
1021                                       start_x, start_y, size_x, size_y, rotate),
1022                  FX_RECT(start_x, start_y, start_x + size_x, start_y + size_y),
1023                  flags, bNeedToRestore, pause);
1024 }
1025 
FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document,int page_index,double * width,double * height)1026 DLLEXPORT int STDCALL FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document,
1027                                               int page_index,
1028                                               double* width,
1029                                               double* height) {
1030   UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
1031   if (!pDoc)
1032     return false;
1033 
1034 #ifdef PDF_ENABLE_XFA
1035   int count = pDoc->GetPageCount();
1036   if (page_index < 0 || page_index >= count)
1037     return false;
1038   CPDFXFA_Page* pPage = pDoc->GetXFAPage(page_index);
1039   if (!pPage)
1040     return false;
1041   *width = pPage->GetPageWidth();
1042   *height = pPage->GetPageHeight();
1043 #else   // PDF_ENABLE_XFA
1044   CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
1045   if (!pDict)
1046     return false;
1047 
1048   CPDF_Page page(pDoc, pDict, true);
1049   *width = page.GetPageWidth();
1050   *height = page.GetPageHeight();
1051 #endif  // PDF_ENABLE_XFA
1052 
1053   return true;
1054 }
1055 
1056 DLLEXPORT FPDF_BOOL STDCALL
FPDF_VIEWERREF_GetPrintScaling(FPDF_DOCUMENT document)1057 FPDF_VIEWERREF_GetPrintScaling(FPDF_DOCUMENT document) {
1058   CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1059   if (!pDoc)
1060     return true;
1061   CPDF_ViewerPreferences viewRef(pDoc);
1062   return viewRef.PrintScaling();
1063 }
1064 
FPDF_VIEWERREF_GetNumCopies(FPDF_DOCUMENT document)1065 DLLEXPORT int STDCALL FPDF_VIEWERREF_GetNumCopies(FPDF_DOCUMENT document) {
1066   CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1067   if (!pDoc)
1068     return 1;
1069   CPDF_ViewerPreferences viewRef(pDoc);
1070   return viewRef.NumCopies();
1071 }
1072 
1073 DLLEXPORT FPDF_PAGERANGE STDCALL
FPDF_VIEWERREF_GetPrintPageRange(FPDF_DOCUMENT document)1074 FPDF_VIEWERREF_GetPrintPageRange(FPDF_DOCUMENT document) {
1075   CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1076   if (!pDoc)
1077     return nullptr;
1078   CPDF_ViewerPreferences viewRef(pDoc);
1079   return viewRef.PrintPageRange();
1080 }
1081 
1082 DLLEXPORT FPDF_DUPLEXTYPE STDCALL
FPDF_VIEWERREF_GetDuplex(FPDF_DOCUMENT document)1083 FPDF_VIEWERREF_GetDuplex(FPDF_DOCUMENT document) {
1084   CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1085   if (!pDoc)
1086     return DuplexUndefined;
1087   CPDF_ViewerPreferences viewRef(pDoc);
1088   CFX_ByteString duplex = viewRef.Duplex();
1089   if ("Simplex" == duplex)
1090     return Simplex;
1091   if ("DuplexFlipShortEdge" == duplex)
1092     return DuplexFlipShortEdge;
1093   if ("DuplexFlipLongEdge" == duplex)
1094     return DuplexFlipLongEdge;
1095   return DuplexUndefined;
1096 }
1097 
FPDF_VIEWERREF_GetName(FPDF_DOCUMENT document,FPDF_BYTESTRING key,char * buffer,unsigned long length)1098 DLLEXPORT unsigned long STDCALL FPDF_VIEWERREF_GetName(FPDF_DOCUMENT document,
1099                                                        FPDF_BYTESTRING key,
1100                                                        char* buffer,
1101                                                        unsigned long length) {
1102   CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1103   if (!pDoc)
1104     return 0;
1105 
1106   CPDF_ViewerPreferences viewRef(pDoc);
1107   CFX_ByteString bsVal;
1108   if (!viewRef.GenericName(key, &bsVal))
1109     return 0;
1110 
1111   unsigned long dwStringLen = bsVal.GetLength() + 1;
1112   if (buffer && length >= dwStringLen)
1113     memcpy(buffer, bsVal.c_str(), dwStringLen);
1114   return dwStringLen;
1115 }
1116 
FPDF_CountNamedDests(FPDF_DOCUMENT document)1117 DLLEXPORT FPDF_DWORD STDCALL FPDF_CountNamedDests(FPDF_DOCUMENT document) {
1118   CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1119   if (!pDoc)
1120     return 0;
1121 
1122   CPDF_Dictionary* pRoot = pDoc->GetRoot();
1123   if (!pRoot)
1124     return 0;
1125 
1126   CPDF_NameTree nameTree(pDoc, "Dests");
1127   pdfium::base::CheckedNumeric<FPDF_DWORD> count = nameTree.GetCount();
1128   CPDF_Dictionary* pDest = pRoot->GetDictFor("Dests");
1129   if (pDest)
1130     count += pDest->GetCount();
1131 
1132   if (!count.IsValid())
1133     return 0;
1134 
1135   return count.ValueOrDie();
1136 }
1137 
FPDF_GetNamedDestByName(FPDF_DOCUMENT document,FPDF_BYTESTRING name)1138 DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDestByName(FPDF_DOCUMENT document,
1139                                                     FPDF_BYTESTRING name) {
1140   if (!name || name[0] == 0)
1141     return nullptr;
1142 
1143   CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1144   if (!pDoc)
1145     return nullptr;
1146 
1147   CPDF_NameTree name_tree(pDoc, "Dests");
1148   return name_tree.LookupNamedDest(pDoc, name);
1149 }
1150 
1151 #ifdef PDF_ENABLE_XFA
FPDF_BStr_Init(FPDF_BSTR * str)1152 DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Init(FPDF_BSTR* str) {
1153   if (!str)
1154     return -1;
1155 
1156   FXSYS_memset(str, 0, sizeof(FPDF_BSTR));
1157   return 0;
1158 }
1159 
FPDF_BStr_Set(FPDF_BSTR * str,FPDF_LPCSTR bstr,int length)1160 DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Set(FPDF_BSTR* str,
1161                                             FPDF_LPCSTR bstr,
1162                                             int length) {
1163   if (!str)
1164     return -1;
1165   if (!bstr || !length)
1166     return -1;
1167   if (length == -1)
1168     length = FXSYS_strlen(bstr);
1169 
1170   if (length == 0) {
1171     if (str->str) {
1172       FX_Free(str->str);
1173       str->str = nullptr;
1174     }
1175     str->len = 0;
1176     return 0;
1177   }
1178 
1179   if (str->str && str->len < length)
1180     str->str = FX_Realloc(char, str->str, length + 1);
1181   else if (!str->str)
1182     str->str = FX_Alloc(char, length + 1);
1183 
1184   str->str[length] = 0;
1185   FXSYS_memcpy(str->str, bstr, length);
1186   str->len = length;
1187 
1188   return 0;
1189 }
1190 
FPDF_BStr_Clear(FPDF_BSTR * str)1191 DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Clear(FPDF_BSTR* str) {
1192   if (!str)
1193     return -1;
1194 
1195   if (str->str) {
1196     FX_Free(str->str);
1197     str->str = nullptr;
1198   }
1199   str->len = 0;
1200   return 0;
1201 }
1202 #endif  // PDF_ENABLE_XFA
1203 
FPDF_GetNamedDest(FPDF_DOCUMENT document,int index,void * buffer,long * buflen)1204 DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDest(FPDF_DOCUMENT document,
1205                                               int index,
1206                                               void* buffer,
1207                                               long* buflen) {
1208   if (!buffer)
1209     *buflen = 0;
1210 
1211   if (index < 0)
1212     return nullptr;
1213 
1214   CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1215   if (!pDoc)
1216     return nullptr;
1217 
1218   CPDF_Dictionary* pRoot = pDoc->GetRoot();
1219   if (!pRoot)
1220     return nullptr;
1221 
1222   CPDF_Object* pDestObj = nullptr;
1223   CFX_ByteString bsName;
1224   CPDF_NameTree nameTree(pDoc, "Dests");
1225   int count = nameTree.GetCount();
1226   if (index >= count) {
1227     CPDF_Dictionary* pDest = pRoot->GetDictFor("Dests");
1228     if (!pDest)
1229       return nullptr;
1230 
1231     pdfium::base::CheckedNumeric<int> checked_count = count;
1232     checked_count += pDest->GetCount();
1233     if (!checked_count.IsValid() || index >= checked_count.ValueOrDie())
1234       return nullptr;
1235 
1236     index -= count;
1237     int i = 0;
1238     for (const auto& it : *pDest) {
1239       bsName = it.first;
1240       pDestObj = it.second.get();
1241       if (!pDestObj)
1242         continue;
1243       if (i == index)
1244         break;
1245       i++;
1246     }
1247   } else {
1248     pDestObj = nameTree.LookupValue(index, bsName);
1249   }
1250   if (!pDestObj)
1251     return nullptr;
1252   if (CPDF_Dictionary* pDict = pDestObj->AsDictionary()) {
1253     pDestObj = pDict->GetArrayFor("D");
1254     if (!pDestObj)
1255       return nullptr;
1256   }
1257   if (!pDestObj->IsArray())
1258     return nullptr;
1259 
1260   CFX_WideString wsName = PDF_DecodeText(bsName);
1261   CFX_ByteString utf16Name = wsName.UTF16LE_Encode();
1262   int len = utf16Name.GetLength();
1263   if (!buffer) {
1264     *buflen = len;
1265   } else if (len <= *buflen) {
1266     memcpy(buffer, utf16Name.c_str(), len);
1267     *buflen = len;
1268   } else {
1269     *buflen = -1;
1270   }
1271   return (FPDF_DEST)pDestObj;
1272 }
1273