blob: 96de5d56e1ee29090756b5d6fb2d8c7e565d3432 [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/fpdfview.h"
8
Tom Sepez2d11d722018-05-31 23:38:32 +00009#include <memory>
thestigd4c34f22016-09-28 17:04:51 -070010#include <utility>
rbpottercec01802017-04-17 09:10:21 -070011#include <vector>
Lei Zhangaa8bf7e2015-12-24 19:13:32 -080012
dsinclair39c62fd2016-09-29 12:49:17 -070013#include "core/fpdfapi/cpdf_modulemgr.h"
14#include "core/fpdfapi/cpdf_pagerendercontext.h"
dsinclair41872fa2016-10-04 11:29:35 -070015#include "core/fpdfapi/page/cpdf_page.h"
dsinclair488b7ad2016-10-04 11:55:50 -070016#include "core/fpdfapi/parser/cpdf_array.h"
Jane Liu4fd9a472017-06-01 18:56:09 -040017#include "core/fpdfapi/parser/cpdf_dictionary.h"
dsinclair488b7ad2016-10-04 11:55:50 -070018#include "core/fpdfapi/parser/cpdf_document.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +000019#include "core/fpdfapi/parser/cpdf_name.h"
20#include "core/fpdfapi/parser/cpdf_parser.h"
dsinclair488b7ad2016-10-04 11:55:50 -070021#include "core/fpdfapi/parser/fpdf_parser_decode.h"
dsinclair69d9c682016-10-04 12:18:35 -070022#include "core/fpdfapi/render/cpdf_progressiverenderer.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +000023#include "core/fpdfapi/render/cpdf_rendercontext.h"
dsinclair69d9c682016-10-04 12:18:35 -070024#include "core/fpdfapi/render/cpdf_renderoptions.h"
dsinclair1727aee2016-09-29 13:12:56 -070025#include "core/fpdfdoc/cpdf_annotlist.h"
26#include "core/fpdfdoc/cpdf_nametree.h"
27#include "core/fpdfdoc/cpdf_occontext.h"
28#include "core/fpdfdoc/cpdf_viewerpreferences.h"
Dan Sinclairbcd1e702017-08-31 13:19:18 -040029#include "core/fxcrt/fx_stream.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +000030#include "core/fxcrt/fx_system.h"
Tom Sepeze7f4d332018-05-03 20:27:05 +000031#include "core/fxcrt/unowned_ptr.h"
Dan Sinclaira5085d42017-05-11 16:26:50 -040032#include "core/fxge/cfx_defaultrenderdevice.h"
dsinclair74a34fc2016-09-29 16:41:42 -070033#include "core/fxge/cfx_gemodule.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +000034#include "core/fxge/cfx_renderdevice.h"
35#include "fpdfsdk/cpdfsdk_customaccess.h"
dsinclairb402b172016-10-11 09:26:32 -070036#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
Dan Sinclair00d47a62018-03-28 18:39:04 +000037#include "fpdfsdk/cpdfsdk_helpers.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +000038#include "fpdfsdk/cpdfsdk_memoryaccess.h"
dsinclair114e46a2016-09-29 17:18:21 -070039#include "fpdfsdk/cpdfsdk_pageview.h"
Dan Sinclair7d125322018-03-28 18:49:34 +000040#include "fpdfsdk/ipdfsdk_pauseadapter.h"
Dan Sinclaire0345a42017-10-30 20:20:42 +000041#include "fxjs/ijs_runtime.h"
Ryan Harrisona74a6272017-10-16 10:57:48 -040042#include "public/fpdf_formfill.h"
tsepez36eb4bd2016-10-03 15:24:27 -070043#include "third_party/base/ptr_util.h"
Bo Xufdc00a72014-10-28 23:03:33 -070044
Tom Sepez40e9ff32015-11-30 12:39:54 -080045#ifdef PDF_ENABLE_XFA
dsinclair521b7502016-11-02 13:02:28 -070046#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
dsinclair4d29e782016-10-04 14:02:47 -070047#include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
Dan Sinclaire7786682017-03-29 15:18:41 -040048#include "fxbarcode/BC_Library.h"
Tom Sepez40e9ff32015-11-30 12:39:54 -080049#endif // PDF_ENABLE_XFA
50
Dan Sinclair698aed72017-09-26 16:24:49 -040051#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
Dan Sinclaira5085d42017-05-11 16:26:50 -040052#include "core/fxge/cfx_windowsrenderdevice.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +000053#include "public/fpdf_edit.h"
rbpottere8468c42017-07-11 10:04:29 -070054
55// These checks are here because core/ and public/ cannot depend on each other.
56static_assert(WindowsPrintMode::kModeEmf == FPDF_PRINTMODE_EMF,
57 "WindowsPrintMode::kModeEmf value mismatch");
58static_assert(WindowsPrintMode::kModeTextOnly == FPDF_PRINTMODE_TEXTONLY,
59 "WindowsPrintMode::kModeTextOnly value mismatch");
60static_assert(WindowsPrintMode::kModePostScript2 == FPDF_PRINTMODE_POSTSCRIPT2,
61 "WindowsPrintMode::kModePostScript2 value mismatch");
62static_assert(WindowsPrintMode::kModePostScript3 == FPDF_PRINTMODE_POSTSCRIPT3,
63 "WindowsPrintMode::kModePostScript3 value mismatch");
Lei Zhang9ed6bd72018-04-25 21:10:05 +000064static_assert(WindowsPrintMode::kModePostScript2PassThrough ==
65 FPDF_PRINTMODE_POSTSCRIPT2_PASSTHROUGH,
66 "WindowsPrintMode::kModePostScript2PassThrough value mismatch");
67static_assert(WindowsPrintMode::kModePostScript3PassThrough ==
68 FPDF_PRINTMODE_POSTSCRIPT3_PASSTHROUGH,
69 "WindowsPrintMode::kModePostScript3PassThrough value mismatch");
thestig25fa42f2016-05-25 21:39:46 -070070#endif
71
thestiga78ba602016-11-23 15:25:48 -080072namespace {
73
Dan Sinclair830897a2017-05-11 14:36:10 -040074bool g_bLibraryInitialized = false;
tsepez02759102016-12-01 08:29:25 -080075
thestiga78ba602016-11-23 15:25:48 -080076void RenderPageImpl(CPDF_PageRenderContext* pContext,
77 CPDF_Page* pPage,
78 const CFX_Matrix& matrix,
79 const FX_RECT& clipping_rect,
80 int flags,
81 bool bNeedToRestore,
Dan Sinclair7d125322018-03-28 18:49:34 +000082 IPDFSDK_PauseAdapter* pause) {
thestiga78ba602016-11-23 15:25:48 -080083 if (!pContext->m_pOptions)
84 pContext->m_pOptions = pdfium::MakeUnique<CPDF_RenderOptions>();
85
Dan Sinclair921fe6b2017-10-05 11:14:12 -040086 uint32_t option_flags = pContext->m_pOptions->GetFlags();
thestiga78ba602016-11-23 15:25:48 -080087 if (flags & FPDF_LCD_TEXT)
Dan Sinclair921fe6b2017-10-05 11:14:12 -040088 option_flags |= RENDER_CLEARTYPE;
thestiga78ba602016-11-23 15:25:48 -080089 else
Dan Sinclair921fe6b2017-10-05 11:14:12 -040090 option_flags &= ~RENDER_CLEARTYPE;
thestiga78ba602016-11-23 15:25:48 -080091
92 if (flags & FPDF_NO_NATIVETEXT)
Dan Sinclair921fe6b2017-10-05 11:14:12 -040093 option_flags |= RENDER_NO_NATIVETEXT;
thestiga78ba602016-11-23 15:25:48 -080094 if (flags & FPDF_RENDER_LIMITEDIMAGECACHE)
Dan Sinclair921fe6b2017-10-05 11:14:12 -040095 option_flags |= RENDER_LIMITEDIMAGECACHE;
thestiga78ba602016-11-23 15:25:48 -080096 if (flags & FPDF_RENDER_FORCEHALFTONE)
Dan Sinclair921fe6b2017-10-05 11:14:12 -040097 option_flags |= RENDER_FORCE_HALFTONE;
thestiga78ba602016-11-23 15:25:48 -080098 if (flags & FPDF_RENDER_NO_SMOOTHTEXT)
Dan Sinclair921fe6b2017-10-05 11:14:12 -040099 option_flags |= RENDER_NOTEXTSMOOTH;
thestiga78ba602016-11-23 15:25:48 -0800100 if (flags & FPDF_RENDER_NO_SMOOTHIMAGE)
Dan Sinclair921fe6b2017-10-05 11:14:12 -0400101 option_flags |= RENDER_NOIMAGESMOOTH;
thestiga78ba602016-11-23 15:25:48 -0800102 if (flags & FPDF_RENDER_NO_SMOOTHPATH)
Dan Sinclair921fe6b2017-10-05 11:14:12 -0400103 option_flags |= RENDER_NOPATHSMOOTH;
Tom Sepezca0273392018-05-25 23:37:50 +0000104
Dan Sinclair921fe6b2017-10-05 11:14:12 -0400105 pContext->m_pOptions->SetFlags(option_flags);
thestiga78ba602016-11-23 15:25:48 -0800106
107 // Grayscale output
Dan Sinclairf55e72e2017-07-13 14:53:28 -0400108 if (flags & FPDF_GRAYSCALE)
Dan Sinclair921fe6b2017-10-05 11:14:12 -0400109 pContext->m_pOptions->SetColorMode(CPDF_RenderOptions::kGray);
thestiga78ba602016-11-23 15:25:48 -0800110
111 const CPDF_OCContext::UsageType usage =
112 (flags & FPDF_PRINTING) ? CPDF_OCContext::Print : CPDF_OCContext::View;
Dan Sinclair921fe6b2017-10-05 11:14:12 -0400113 pContext->m_pOptions->SetOCContext(
Lei Zhang8f637632018-05-07 23:36:26 +0000114 pdfium::MakeRetain<CPDF_OCContext>(pPage->GetDocument(), usage));
thestiga78ba602016-11-23 15:25:48 -0800115
116 pContext->m_pDevice->SaveState();
117 pContext->m_pDevice->SetClip_Rect(clipping_rect);
thestiga78ba602016-11-23 15:25:48 -0800118 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
Artem Strygin3f7ff052017-07-27 22:16:13 +0300136FPDF_DOCUMENT LoadDocumentImpl(
Dan Sinclair0b950422017-09-21 15:49:49 -0400137 const RetainPtr<IFX_SeekableReadStream>& pFileAccess,
Artem Strygin3f7ff052017-07-27 22:16:13 +0300138 FPDF_BYTESTRING password) {
Jane Liu8a1081f2017-08-22 16:28:05 -0400139 if (!pFileAccess) {
140 ProcessParseError(CPDF_Parser::FILE_ERROR);
Artem Strygin3f7ff052017-07-27 22:16:13 +0300141 return nullptr;
Jane Liu8a1081f2017-08-22 16:28:05 -0400142 }
Artem Strygin3f7ff052017-07-27 22:16:13 +0300143
144 auto pParser = pdfium::MakeUnique<CPDF_Parser>();
145 pParser->SetPassword(password);
146
147 auto pDocument = pdfium::MakeUnique<CPDF_Document>(std::move(pParser));
148 CPDF_Parser::Error error =
149 pDocument->GetParser()->StartParse(pFileAccess, pDocument.get());
150 if (error != CPDF_Parser::SUCCESS) {
151 ProcessParseError(error);
152 return nullptr;
153 }
154 CheckUnSupportError(pDocument.get(), error);
Tom Sepezb80edf32018-06-01 17:42:33 +0000155
156#ifdef PDF_ENABLE_XFA
157 pDocument->SetExtension(pdfium::MakeUnique<CPDFXFA_Context>(pDocument.get()));
158#endif // PDF_ENABLE_XFA
159
Artem Strygin3f7ff052017-07-27 22:16:13 +0300160 return FPDFDocumentFromCPDFDocument(pDocument.release());
161}
162
tsepezfa89a202016-12-02 09:48:30 -0800163} // namespace
164
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400165FPDF_EXPORT void FPDF_CALLCONV FPDF_InitLibrary() {
Lei Zhang6f62d532015-09-23 15:31:44 -0700166 FPDF_InitLibraryWithConfig(nullptr);
167}
168
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400169FPDF_EXPORT void FPDF_CALLCONV
Dan Sinclairf766ad22016-03-14 13:51:24 -0400170FPDF_InitLibraryWithConfig(const FPDF_LIBRARY_CONFIG* cfg) {
Dan Sinclair830897a2017-05-11 14:36:10 -0400171 if (g_bLibraryInitialized)
tsepez02759102016-12-01 08:29:25 -0800172 return;
173
Dan Sinclairdbc3d3e2017-05-11 13:41:38 -0400174 FXMEM_InitializePartitionAlloc();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700175
weili47228ac2016-07-20 10:35:31 -0700176 CFX_GEModule* pModule = CFX_GEModule::Get();
Dan Sinclair830897a2017-05-11 14:36:10 -0400177 pModule->Init(cfg ? cfg->m_pUserFontPaths : nullptr);
tsepez02759102016-12-01 08:29:25 -0800178
Tom Sepez1b246282015-11-25 15:15:31 -0800179 CPDF_ModuleMgr* pModuleMgr = CPDF_ModuleMgr::Get();
Lei Zhang76020fc2017-05-18 15:51:20 -0700180 pModuleMgr->Init();
Tom Sepezb4a26182017-03-01 12:15:00 -0800181
Tom Sepez40e9ff32015-11-30 12:39:54 -0800182#ifdef PDF_ENABLE_XFA
dsinclair8837c912016-11-01 11:22:37 -0700183 BC_Library_Init();
Tom Sepez40e9ff32015-11-30 12:39:54 -0800184#endif // PDF_ENABLE_XFA
Tom Sepez452b4f32015-10-13 09:27:27 -0700185 if (cfg && cfg->version >= 2)
186 IJS_Runtime::Initialize(cfg->m_v8EmbedderSlot, cfg->m_pIsolate);
Dan Sinclair830897a2017-05-11 14:36:10 -0400187
188 g_bLibraryInitialized = true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700189}
190
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400191FPDF_EXPORT void FPDF_CALLCONV FPDF_DestroyLibrary() {
Dan Sinclair830897a2017-05-11 14:36:10 -0400192 if (!g_bLibraryInitialized)
tsepez02759102016-12-01 08:29:25 -0800193 return;
194
Tom Sepez51da0932015-11-25 16:05:49 -0800195#ifdef PDF_ENABLE_XFA
Tom Sepez5628fd72017-04-27 14:58:53 -0700196 BC_Library_Destroy();
Tom Sepez40e9ff32015-11-30 12:39:54 -0800197#endif // PDF_ENABLE_XFA
dsinclair8837c912016-11-01 11:22:37 -0700198
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700199 CPDF_ModuleMgr::Destroy();
200 CFX_GEModule::Destroy();
Tom Sepez2c286192015-06-18 12:47:11 -0700201
thestig2d6dda12016-06-28 07:39:09 -0700202 IJS_Runtime::Destroy();
Dan Sinclair830897a2017-05-11 14:36:10 -0400203
204 g_bLibraryInitialized = false;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700205}
206
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400207FPDF_EXPORT void FPDF_CALLCONV FPDF_SetSandBoxPolicy(FPDF_DWORD policy,
208 FPDF_BOOL enable) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700209 return FSDK_SetSandBoxPolicy(policy, enable);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700210}
211
rbpotterdb764702017-01-12 10:31:43 -0800212#if defined(_WIN32)
213#if defined(PDFIUM_PRINT_TEXT_WITH_GDI)
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400214FPDF_EXPORT void FPDF_CALLCONV
thestigfdb35ff2016-07-18 13:45:44 -0700215FPDF_SetTypefaceAccessibleFunc(PDFiumEnsureTypefaceCharactersAccessible func) {
216 g_pdfium_typeface_accessible_func = func;
217}
218
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400219FPDF_EXPORT void FPDF_CALLCONV FPDF_SetPrintTextWithGDI(FPDF_BOOL use_gdi) {
thestigfdb35ff2016-07-18 13:45:44 -0700220 g_pdfium_print_text_with_gdi = !!use_gdi;
221}
rbpotterdb764702017-01-12 10:31:43 -0800222#endif // PDFIUM_PRINT_TEXT_WITH_GDI
223
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400224FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_SetPrintMode(int mode) {
Lei Zhang9ed6bd72018-04-25 21:10:05 +0000225 if (mode < FPDF_PRINTMODE_EMF ||
226 mode > FPDF_PRINTMODE_POSTSCRIPT3_PASSTHROUGH) {
rbpotterdb764702017-01-12 10:31:43 -0800227 return FALSE;
Lei Zhang9ed6bd72018-04-25 21:10:05 +0000228 }
Lei Zhang537f4c72018-04-25 18:01:52 +0000229 g_pdfium_print_mode = static_cast<WindowsPrintMode>(mode);
rbpotterdb764702017-01-12 10:31:43 -0800230 return TRUE;
231}
232#endif // defined(_WIN32)
thestigfdb35ff2016-07-18 13:45:44 -0700233
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400234FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV
235FPDF_LoadDocument(FPDF_STRING file_path, FPDF_BYTESTRING password) {
Tom Sepeze3166a82015-08-05 10:50:32 -0700236 // NOTE: the creation of the file needs to be by the embedder on the
237 // other side of this API.
Lei Zhanga6adac82017-11-02 19:27:08 +0000238 return LoadDocumentImpl(IFX_SeekableReadStream::CreateFromFilename(file_path),
239 password);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700240}
Jun Fange118ce92015-02-17 06:50:08 -0800241
Ryan Harrison854d71c2017-10-18 12:28:14 -0400242FPDF_EXPORT int FPDF_CALLCONV FPDF_GetFormType(FPDF_DOCUMENT document) {
Ryan Harrisona74a6272017-10-16 10:57:48 -0400243 const CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Lei Zhang01581062017-08-30 14:19:26 -0700244 if (!pDoc)
Ryan Harrison854d71c2017-10-18 12:28:14 -0400245 return FORMTYPE_NONE;
JUN FANG827a1722015-03-05 13:39:21 -0800246
Lei Zhang01581062017-08-30 14:19:26 -0700247 const CPDF_Dictionary* pRoot = pDoc->GetRoot();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700248 if (!pRoot)
Ryan Harrison854d71c2017-10-18 12:28:14 -0400249 return FORMTYPE_NONE;
JUN FANG827a1722015-03-05 13:39:21 -0800250
Lei Zhang55bbb0a2018-05-08 19:26:37 +0000251 const CPDF_Dictionary* pAcroForm = pRoot->GetDictFor("AcroForm");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700252 if (!pAcroForm)
Ryan Harrison854d71c2017-10-18 12:28:14 -0400253 return FORMTYPE_NONE;
JUN FANG827a1722015-03-05 13:39:21 -0800254
Lei Zhang55bbb0a2018-05-08 19:26:37 +0000255 const CPDF_Object* pXFA = pAcroForm->GetObjectFor("XFA");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700256 if (!pXFA)
Ryan Harrison854d71c2017-10-18 12:28:14 -0400257 return FORMTYPE_ACRO_FORM;
JUN FANG827a1722015-03-05 13:39:21 -0800258
Lei Zhangd6e92bd2018-01-29 19:01:26 +0000259 bool bNeedsRendering = pRoot->GetBooleanFor("NeedsRendering", false);
260 return bNeedsRendering ? FORMTYPE_XFA_FULL : FORMTYPE_XFA_FOREGROUND;
Jun Fange118ce92015-02-17 06:50:08 -0800261}
262
Ryan Harrisona74a6272017-10-16 10:57:48 -0400263#ifdef PDF_ENABLE_XFA
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400264FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_LoadXFA(FPDF_DOCUMENT document) {
Tom Sepezfe06d512018-05-01 17:25:25 +0000265 auto* pDoc = CPDFDocumentFromFPDFDocument(document);
Tom Sepez3f3c39d2018-05-01 17:46:34 +0000266 if (!pDoc)
267 return false;
268
269 auto* pContext = static_cast<CPDFXFA_Context*>(pDoc->GetExtension());
270 return pContext && pContext->LoadXFADoc();
Bo Xufdc00a72014-10-28 23:03:33 -0700271}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800272#endif // PDF_ENABLE_XFA
Bo Xufdc00a72014-10-28 23:03:33 -0700273
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400274FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV
275FPDF_LoadMemDocument(const void* data_buf, int size, FPDF_BYTESTRING password) {
Dan Sinclair7aba4722018-03-28 17:04:16 +0000276 return LoadDocumentImpl(pdfium::MakeRetain<CPDFSDK_MemoryAccess>(
277 static_cast<const uint8_t*>(data_buf), size),
278 password);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700279}
280
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400281FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700282FPDF_LoadCustomDocument(FPDF_FILEACCESS* pFileAccess,
283 FPDF_BYTESTRING password) {
Dan Sinclair7aba4722018-03-28 17:04:16 +0000284 return LoadDocumentImpl(pdfium::MakeRetain<CPDFSDK_CustomAccess>(pFileAccess),
Artem Strygin3f7ff052017-07-27 22:16:13 +0300285 password);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700286}
287
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400288FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_GetFileVersion(FPDF_DOCUMENT doc,
289 int* fileVersion) {
Tom Sepez471a1032015-10-15 16:17:18 -0700290 if (!fileVersion)
tsepez4cf55152016-11-02 14:37:54 -0700291 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700292
Tom Sepez471a1032015-10-15 16:17:18 -0700293 *fileVersion = 0;
294 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(doc);
295 if (!pDoc)
tsepez4cf55152016-11-02 14:37:54 -0700296 return false;
Tom Sepez471a1032015-10-15 16:17:18 -0700297
Lei Zhang01581062017-08-30 14:19:26 -0700298 const CPDF_Parser* pParser = pDoc->GetParser();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700299 if (!pParser)
tsepez4cf55152016-11-02 14:37:54 -0700300 return false;
Tom Sepez471a1032015-10-15 16:17:18 -0700301
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700302 *fileVersion = pParser->GetFileVersion();
tsepez4cf55152016-11-02 14:37:54 -0700303 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700304}
305
tsepezc3255f52016-03-25 14:52:27 -0700306// jabdelmalek: changed return type from uint32_t to build on Linux (and match
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700307// header).
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400308FPDF_EXPORT unsigned long FPDF_CALLCONV
309FPDF_GetDocPermissions(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700310 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Tom Sepez28d30b42018-06-04 17:12:27 +0000311 // https://bugs.chromium.org/p/pdfium/issues/detail?id=499
312 if (!pDoc) {
313#ifndef PDF_ENABLE_XFA
314 return 0;
315#else // PDF_ENABLE_XFA
316 return 0xFFFFFFFF;
317#endif // PDF_ENABLE_XFA
318 }
319
320 return pDoc->GetUserPermissions();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700321}
322
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400323FPDF_EXPORT int FPDF_CALLCONV
324FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700325 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
thestigb8db5112016-04-06 12:12:52 -0700326 if (!pDoc || !pDoc->GetParser())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700327 return -1;
Bo Xuc5cab022014-09-19 19:16:31 -0700328
Tom Sepez471a1032015-10-15 16:17:18 -0700329 CPDF_Dictionary* pDict = pDoc->GetParser()->GetEncryptDict();
dsinclair38fd8442016-09-15 10:15:32 -0700330 return pDict ? pDict->GetIntegerFor("R") : -1;
Bo Xuc5cab022014-09-19 19:16:31 -0700331}
332
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400333FPDF_EXPORT int FPDF_CALLCONV FPDF_GetPageCount(FPDF_DOCUMENT document) {
Tom Sepezfe06d512018-05-01 17:25:25 +0000334 auto* pDoc = CPDFDocumentFromFPDFDocument(document);
335 if (!pDoc)
336 return 0;
Tom Sepez3f3c39d2018-05-01 17:46:34 +0000337
Tom Sepez5f3e4f12018-05-02 13:33:50 +0000338 auto* pExtension = pDoc->GetExtension();
339 return pExtension ? pExtension->GetPageCount() : pDoc->GetPageCount();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700340}
341
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400342FPDF_EXPORT FPDF_PAGE FPDF_CALLCONV FPDF_LoadPage(FPDF_DOCUMENT document,
343 int page_index) {
Tom Sepezfe06d512018-05-01 17:25:25 +0000344 auto* pDoc = CPDFDocumentFromFPDFDocument(document);
Tom Sepez50d12ad2015-11-24 09:50:51 -0800345 if (!pDoc)
Tom Sepez471a1032015-10-15 16:17:18 -0700346 return nullptr;
Tom Sepez1b246282015-11-25 15:15:31 -0800347
Tom Sepezfe06d512018-05-01 17:25:25 +0000348 if (page_index < 0 || page_index >= FPDF_GetPageCount(document))
Tom Sepez471a1032015-10-15 16:17:18 -0700349 return nullptr;
350
Tom Sepez40e9ff32015-11-30 12:39:54 -0800351#ifdef PDF_ENABLE_XFA
Tom Sepez3f3c39d2018-05-01 17:46:34 +0000352 auto* pContext = static_cast<CPDFXFA_Context*>(pDoc->GetExtension());
353 if (pContext)
Tom Sepez168c7632018-06-04 18:07:47 +0000354 return FPDFPageFromUnderlying(pContext->GetXFAPage(page_index).Leak());
Tom Sepez3f3c39d2018-05-01 17:46:34 +0000355
Tom Sepez037d9382018-06-04 16:52:57 +0000356 // Eventually, fallthrough into non-xfa case once page type made consistent.
357 return nullptr;
358#else // PDF_ENABLE_XFA
Tom Sepez967aa072018-05-08 13:40:20 +0000359 CPDF_Dictionary* pDict = pDoc->GetPageDictionary(page_index);
Lei Zhang412e9082015-12-14 18:34:00 -0800360 if (!pDict)
thestig5cc24652016-04-26 11:46:02 -0700361 return nullptr;
362
Tom Sepezf06ed6d2018-06-04 18:26:07 +0000363 auto pPage = pdfium::MakeRetain<CPDF_Page>(pDoc, pDict, true);
364 pPage->ParseContent();
Tom Sepez168c7632018-06-04 18:07:47 +0000365 return FPDFPageFromUnderlying(pPage.Leak());
Tom Sepez037d9382018-06-04 16:52:57 +0000366#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700367}
368
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400369FPDF_EXPORT double FPDF_CALLCONV FPDF_GetPageWidth(FPDF_PAGE page) {
Tom Sepez168c7632018-06-04 18:07:47 +0000370 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezbf59a072015-10-21 14:07:23 -0700371 return pPage ? pPage->GetPageWidth() : 0.0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700372}
373
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400374FPDF_EXPORT double FPDF_CALLCONV FPDF_GetPageHeight(FPDF_PAGE page) {
Tom Sepez168c7632018-06-04 18:07:47 +0000375 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezbf59a072015-10-21 14:07:23 -0700376 return pPage ? pPage->GetPageHeight() : 0.0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700377}
378
Henrique Nakashima26155902018-01-16 16:39:05 +0000379FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_GetPageBoundingBox(FPDF_PAGE page,
380 FS_RECTF* rect) {
381 if (!rect)
382 return false;
383
384 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
385 if (!pPage)
386 return false;
387
Tom Sepez778e59e2018-06-05 19:24:42 +0000388 FSRECTFFromCFXFloatRect(pPage->GetBBox(), rect);
Henrique Nakashima26155902018-01-16 16:39:05 +0000389 return true;
390}
391
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700392#if defined(_WIN32)
rbpottercec01802017-04-17 09:10:21 -0700393namespace {
394
395const double kEpsilonSize = 0.01f;
396
397void GetScaling(CPDF_Page* pPage,
398 int size_x,
399 int size_y,
400 int rotate,
401 double* scale_x,
402 double* scale_y) {
403 ASSERT(pPage);
404 ASSERT(scale_x);
405 ASSERT(scale_y);
406 double page_width = pPage->GetPageWidth();
407 double page_height = pPage->GetPageHeight();
408 if (page_width < kEpsilonSize || page_height < kEpsilonSize)
409 return;
410
411 if (rotate % 2 == 0) {
412 *scale_x = size_x / page_width;
413 *scale_y = size_y / page_height;
414 } else {
415 *scale_x = size_y / page_width;
416 *scale_y = size_x / page_height;
417 }
418}
419
420FX_RECT GetMaskDimensionsAndOffsets(CPDF_Page* pPage,
421 int start_x,
422 int start_y,
423 int size_x,
424 int size_y,
425 int rotate,
426 const CFX_FloatRect& mask_box) {
427 double scale_x = 0.0f;
428 double scale_y = 0.0f;
429 GetScaling(pPage, size_x, size_y, rotate, &scale_x, &scale_y);
430 if (scale_x < kEpsilonSize || scale_y < kEpsilonSize)
431 return FX_RECT();
432
433 // Compute sizes in page points. Round down to catch the entire bitmap.
434 int start_x_bm = static_cast<int>(mask_box.left * scale_x);
435 int start_y_bm = static_cast<int>(mask_box.bottom * scale_y);
436 int size_x_bm = static_cast<int>(mask_box.right * scale_x + 1.0f) -
437 static_cast<int>(mask_box.left * scale_x);
438 int size_y_bm = static_cast<int>(mask_box.top * scale_y + 1.0f) -
439 static_cast<int>(mask_box.bottom * scale_y);
440
441 // Get page rotation
rbpotterce8e51e2017-04-28 12:42:47 -0700442 int page_rotation = pPage->GetPageRotation();
rbpottercec01802017-04-17 09:10:21 -0700443
444 // Compute offsets
445 int offset_x = 0;
446 int offset_y = 0;
rbpotter8d7672e2017-08-16 16:45:44 -0700447 if (size_x > size_y)
448 std::swap(size_x_bm, size_y_bm);
449
rbpottercec01802017-04-17 09:10:21 -0700450 switch ((rotate + page_rotation) % 4) {
451 case 0:
452 offset_x = start_x_bm + start_x;
453 offset_y = start_y + size_y - size_y_bm - start_y_bm;
454 break;
455 case 1:
456 offset_x = start_y_bm + start_x;
457 offset_y = start_x_bm + start_y;
458 break;
459 case 2:
460 offset_x = start_x + size_x - size_x_bm - start_x_bm;
461 offset_y = start_y_bm + start_y;
462 break;
463 case 3:
464 offset_x = start_x + size_x - size_x_bm - start_y_bm;
465 offset_y = start_y + size_y - size_y_bm - start_x_bm;
466 break;
467 }
468 return FX_RECT(offset_x, offset_y, offset_x + size_x_bm,
469 offset_y + size_y_bm);
470}
471
472// Get a bitmap of just the mask section defined by |mask_box| from a full page
473// bitmap |pBitmap|.
Dan Sinclair0b950422017-09-21 15:49:49 -0400474RetainPtr<CFX_DIBitmap> GetMaskBitmap(CPDF_Page* pPage,
475 int start_x,
476 int start_y,
477 int size_x,
478 int size_y,
479 int rotate,
Lei Zhang8a884a42017-11-02 18:30:30 +0000480 const RetainPtr<CFX_DIBitmap>& pSrc,
Dan Sinclair0b950422017-09-21 15:49:49 -0400481 const CFX_FloatRect& mask_box,
482 FX_RECT* bitmap_area) {
rbpottercec01802017-04-17 09:10:21 -0700483 ASSERT(bitmap_area);
484 *bitmap_area = GetMaskDimensionsAndOffsets(pPage, start_x, start_y, size_x,
485 size_y, rotate, mask_box);
486 if (bitmap_area->IsEmpty())
487 return nullptr;
488
489 // Create a new bitmap to transfer part of the page bitmap to.
Dan Sinclair0b950422017-09-21 15:49:49 -0400490 RetainPtr<CFX_DIBitmap> pDst = pdfium::MakeRetain<CFX_DIBitmap>();
Nicolas Penad08667c2018-04-16 17:41:47 +0000491 if (!pDst->Create(bitmap_area->Width(), bitmap_area->Height(), FXDIB_Argb))
492 return nullptr;
493
rbpottercec01802017-04-17 09:10:21 -0700494 pDst->Clear(0x00ffffff);
495 pDst->TransferBitmap(0, 0, bitmap_area->Width(), bitmap_area->Height(), pSrc,
496 bitmap_area->left, bitmap_area->top);
497 return pDst;
498}
499
500void RenderBitmap(CFX_RenderDevice* device,
Dan Sinclair0b950422017-09-21 15:49:49 -0400501 const RetainPtr<CFX_DIBitmap>& pSrc,
rbpottercec01802017-04-17 09:10:21 -0700502 const FX_RECT& mask_area) {
503 int size_x_bm = mask_area.Width();
504 int size_y_bm = mask_area.Height();
505 if (size_x_bm == 0 || size_y_bm == 0)
506 return;
507
508 // Create a new bitmap from the old one
Dan Sinclair0b950422017-09-21 15:49:49 -0400509 RetainPtr<CFX_DIBitmap> pDst = pdfium::MakeRetain<CFX_DIBitmap>();
Nicolas Penad08667c2018-04-16 17:41:47 +0000510 if (!pDst->Create(size_x_bm, size_y_bm, FXDIB_Rgb32))
511 return;
512
rbpottercec01802017-04-17 09:10:21 -0700513 pDst->Clear(0xffffffff);
514 pDst->CompositeBitmap(0, 0, size_x_bm, size_y_bm, pSrc, 0, 0,
515 FXDIB_BLEND_NORMAL, nullptr, false);
516
517 if (device->GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
rbpotter8d7672e2017-08-16 16:45:44 -0700518 device->StretchDIBits(pDst, mask_area.left, mask_area.top, size_x_bm,
519 size_y_bm);
rbpottercec01802017-04-17 09:10:21 -0700520 } else {
521 device->SetDIBits(pDst, mask_area.left, mask_area.top);
522 }
523}
524
525} // namespace
526
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400527FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPage(HDC dc,
528 FPDF_PAGE page,
529 int start_x,
530 int start_y,
531 int size_x,
532 int size_y,
533 int rotate,
534 int flags) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700535 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700536 if (!pPage)
537 return;
rbpottercec01802017-04-17 09:10:21 -0700538 pPage->SetRenderContext(pdfium::MakeUnique<CPDF_PageRenderContext>());
539 CPDF_PageRenderContext* pContext = pPage->GetRenderContext();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700540
Dan Sinclair0b950422017-09-21 15:49:49 -0400541 RetainPtr<CFX_DIBitmap> pBitmap;
rbpottercec01802017-04-17 09:10:21 -0700542 // Don't render the full page to bitmap for a mask unless there are a lot
543 // of masks. Full page bitmaps result in large spool sizes, so they should
544 // only be used when necessary. For large numbers of masks, rendering each
545 // individually is inefficient and unlikely to significantly improve spool
rbpotter78b334a2017-10-25 11:58:41 -0700546 // size. TODO (rbpotter): Find out why this still breaks printing for some
547 // PDFs (see crbug.com/777837).
548 const bool bEnableImageMasks = false;
549 const bool bNewBitmap = pPage->BackgroundAlphaNeeded() ||
550 (pPage->HasImageMask() && !bEnableImageMasks) ||
551 pPage->GetMaskBoundingBoxes().size() > 100;
rbpottercec01802017-04-17 09:10:21 -0700552 const bool bHasMask = pPage->HasImageMask() && !bNewBitmap;
553 if (bNewBitmap || bHasMask) {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700554 pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
Nicolas Penad08667c2018-04-16 17:41:47 +0000555 // Create will probably work fine even if it fails here: we will just attach
556 // a zero-sized bitmap to |pDevice|.
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700557 pBitmap->Create(size_x, size_y, FXDIB_Argb);
558 pBitmap->Clear(0x00ffffff);
Dan Sinclaira5085d42017-05-11 16:26:50 -0400559 CFX_DefaultRenderDevice* pDevice = new CFX_DefaultRenderDevice;
tsepez36eb4bd2016-10-03 15:24:27 -0700560 pContext->m_pDevice = pdfium::WrapUnique(pDevice);
Tom Sepezf0799fe2017-03-28 09:31:32 -0700561 pDevice->Attach(pBitmap, false, nullptr, false);
rbpottercec01802017-04-17 09:10:21 -0700562 if (bHasMask) {
563 pContext->m_pOptions = pdfium::MakeUnique<CPDF_RenderOptions>();
Dan Sinclair921fe6b2017-10-05 11:14:12 -0400564 uint32_t option_flags = pContext->m_pOptions->GetFlags();
565 option_flags |= RENDER_BREAKFORMASKS;
566 pContext->m_pOptions->SetFlags(option_flags);
rbpottercec01802017-04-17 09:10:21 -0700567 }
Jun Fang1aeeceb2015-12-29 10:27:44 +0800568 } else {
Dan Sinclaira5085d42017-05-11 16:26:50 -0400569 pContext->m_pDevice = pdfium::MakeUnique<CFX_WindowsRenderDevice>(dc);
Jun Fang1aeeceb2015-12-29 10:27:44 +0800570 }
rbpottercec01802017-04-17 09:10:21 -0700571
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700572 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
tsepez4cf55152016-11-02 14:37:54 -0700573 rotate, flags, true, nullptr);
Bo Xud4e406e2014-08-13 11:03:19 -0700574
rbpottercec01802017-04-17 09:10:21 -0700575 if (bHasMask) {
576 // Finish rendering the page to bitmap and copy the correct segments
577 // of the page to individual image mask bitmaps.
578 const std::vector<CFX_FloatRect>& mask_boxes =
579 pPage->GetMaskBoundingBoxes();
580 std::vector<FX_RECT> bitmap_areas(mask_boxes.size());
Dan Sinclair0b950422017-09-21 15:49:49 -0400581 std::vector<RetainPtr<CFX_DIBitmap>> bitmaps(mask_boxes.size());
rbpottercec01802017-04-17 09:10:21 -0700582 for (size_t i = 0; i < mask_boxes.size(); i++) {
583 bitmaps[i] =
584 GetMaskBitmap(pPage, start_x, start_y, size_x, size_y, rotate,
585 pBitmap, mask_boxes[i], &bitmap_areas[i]);
586 pContext->m_pRenderer->Continue(nullptr);
587 }
588
589 // Reset rendering context
590 pPage->SetRenderContext(nullptr);
591
592 // Begin rendering to the printer. Add flag to indicate the renderer should
593 // pause after each image mask.
594 pPage->SetRenderContext(pdfium::MakeUnique<CPDF_PageRenderContext>());
595 pContext = pPage->GetRenderContext();
Dan Sinclaira5085d42017-05-11 16:26:50 -0400596 pContext->m_pDevice = pdfium::MakeUnique<CFX_WindowsRenderDevice>(dc);
rbpottercec01802017-04-17 09:10:21 -0700597 pContext->m_pOptions = pdfium::MakeUnique<CPDF_RenderOptions>();
Dan Sinclair921fe6b2017-10-05 11:14:12 -0400598
599 uint32_t option_flags = pContext->m_pOptions->GetFlags();
600 option_flags |= RENDER_BREAKFORMASKS;
601 pContext->m_pOptions->SetFlags(option_flags);
602
rbpottercec01802017-04-17 09:10:21 -0700603 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
604 rotate, flags, true, nullptr);
605
606 // Render masks
607 for (size_t i = 0; i < mask_boxes.size(); i++) {
608 // Render the bitmap for the mask and free the bitmap.
609 if (bitmaps[i]) { // will be null if mask has zero area
610 RenderBitmap(pContext->m_pDevice.get(), bitmaps[i], bitmap_areas[i]);
611 }
612 // Render the next portion of page.
613 pContext->m_pRenderer->Continue(nullptr);
614 }
615 } else if (bNewBitmap) {
Dan Sinclaira5085d42017-05-11 16:26:50 -0400616 CFX_WindowsRenderDevice WinDC(dc);
Nicolas Penad08667c2018-04-16 17:41:47 +0000617 bool bitsStretched = false;
thestig84144e82016-09-27 15:06:01 -0700618 if (WinDC.GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700619 auto pDst = pdfium::MakeRetain<CFX_DIBitmap>();
Nicolas Penad08667c2018-04-16 17:41:47 +0000620 if (pDst->Create(size_x, size_y, FXDIB_Rgb32)) {
621 memset(pDst->GetBuffer(), -1, pBitmap->GetPitch() * size_y);
622 pDst->CompositeBitmap(0, 0, size_x, size_y, pBitmap, 0, 0,
623 FXDIB_BLEND_NORMAL, nullptr, false);
624 WinDC.StretchDIBits(pDst, 0, 0, size_x, size_y);
625 bitsStretched = true;
626 }
Lei Zhang6d8b1c22015-06-19 17:26:17 -0700627 }
Nicolas Penad08667c2018-04-16 17:41:47 +0000628 if (!bitsStretched)
629 WinDC.SetDIBits(pBitmap, 0, 0);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700630 }
rbpottercec01802017-04-17 09:10:21 -0700631
tsepeze5cb0b12016-10-26 15:06:11 -0700632 pPage->SetRenderContext(nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700633}
Lei Zhangae85f872016-02-19 14:57:07 -0800634#endif // defined(_WIN32)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700635
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400636FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPageBitmap(FPDF_BITMAP bitmap,
637 FPDF_PAGE page,
638 int start_x,
639 int start_y,
640 int size_x,
641 int size_y,
642 int rotate,
643 int flags) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700644 if (!bitmap)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700645 return;
tsepez1e2c5572016-05-25 14:58:09 -0700646
Tom Sepezdb0be962015-10-16 14:00:21 -0700647 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700648 if (!pPage)
649 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700650
weili9f515bc2016-07-24 08:08:24 -0700651 CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
tsepez36eb4bd2016-10-03 15:24:27 -0700652 pPage->SetRenderContext(pdfium::WrapUnique(pContext));
Tom Sepezf0799fe2017-03-28 09:31:32 -0700653
Dan Sinclaira5085d42017-05-11 16:26:50 -0400654 CFX_DefaultRenderDevice* pDevice = new CFX_DefaultRenderDevice;
weili9f515bc2016-07-24 08:08:24 -0700655 pContext->m_pDevice.reset(pDevice);
dsinclair31b08d42017-03-28 15:47:47 +0000656
Tom Sepez525147a2018-05-03 17:19:53 +0000657 RetainPtr<CFX_DIBitmap> pBitmap(CFXDIBitmapFromFPDFBitmap(bitmap));
Tom Sepezf0799fe2017-03-28 09:31:32 -0700658 pDevice->Attach(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER), nullptr, false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700659 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
tsepez4cf55152016-11-02 14:37:54 -0700660 rotate, flags, true, nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700661
caryclark687fbde2016-11-22 12:44:25 -0800662#ifdef _SKIA_SUPPORT_PATHS_
Cary Clark364d18b2017-07-25 10:39:10 -0400663 pDevice->Flush(true);
caryclark687fbde2016-11-22 12:44:25 -0800664 pBitmap->UnPreMultiply();
665#endif
tsepeze5cb0b12016-10-26 15:06:11 -0700666 pPage->SetRenderContext(nullptr);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700667}
668
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400669FPDF_EXPORT void FPDF_CALLCONV
670FPDF_RenderPageBitmapWithMatrix(FPDF_BITMAP bitmap,
671 FPDF_PAGE page,
672 const FS_MATRIX* matrix,
673 const FS_RECTF* clipping,
674 int flags) {
thestiga78ba602016-11-23 15:25:48 -0800675 if (!bitmap)
676 return;
677
678 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
679 if (!pPage)
680 return;
681
Tom Sepez525147a2018-05-03 17:19:53 +0000682 auto pOwnedContext = pdfium::MakeUnique<CPDF_PageRenderContext>();
683 CPDF_PageRenderContext* pContext = pOwnedContext.get();
684 pPage->SetRenderContext(std::move(pOwnedContext));
Tom Sepezf0799fe2017-03-28 09:31:32 -0700685
Tom Sepez525147a2018-05-03 17:19:53 +0000686 auto pOwnedDevice = pdfium::MakeUnique<CFX_DefaultRenderDevice>();
687 CFX_DefaultRenderDevice* pDevice = pOwnedDevice.get();
688 pContext->m_pDevice = std::move(pOwnedDevice);
Tom Sepezf0799fe2017-03-28 09:31:32 -0700689
Tom Sepez525147a2018-05-03 17:19:53 +0000690 RetainPtr<CFX_DIBitmap> pBitmap(CFXDIBitmapFromFPDFBitmap(bitmap));
thestiga78ba602016-11-23 15:25:48 -0800691 pDevice->Attach(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER), nullptr, false);
692
thestiga78ba602016-11-23 15:25:48 -0800693 CFX_FloatRect clipping_rect;
Lei Zhang367e7de2017-10-31 13:32:17 +0000694 if (clipping)
695 clipping_rect = CFXFloatRectFromFSRECTF(*clipping);
Nicolas Pena60bde102017-07-26 13:50:12 -0400696 FX_RECT clip_rect = clipping_rect.ToFxRect();
Henrique Nakashima2914b6f2018-01-17 20:00:37 +0000697
Lei Zhangc4242b22018-04-12 15:50:49 +0000698 const FX_RECT rect(0, 0, pPage->GetPageWidth(), pPage->GetPageHeight());
699 CFX_Matrix transform_matrix = pPage->GetDisplayMatrix(rect, 0);
Henrique Nakashima2914b6f2018-01-17 20:00:37 +0000700 if (matrix) {
701 transform_matrix.Concat(CFX_Matrix(matrix->a, matrix->b, matrix->c,
702 matrix->d, matrix->e, matrix->f));
703 }
704 RenderPageImpl(pContext, pPage, transform_matrix, clip_rect, flags, true,
705 nullptr);
thestiga78ba602016-11-23 15:25:48 -0800706
707 pPage->SetRenderContext(nullptr);
708}
709
Cary Clark399be5b2016-03-14 16:51:29 -0400710#ifdef _SKIA_SUPPORT_
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400711FPDF_EXPORT FPDF_RECORDER FPDF_CALLCONV FPDF_RenderPageSkp(FPDF_PAGE page,
712 int size_x,
713 int size_y) {
Cary Clark399be5b2016-03-14 16:51:29 -0400714 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
715 if (!pPage)
716 return nullptr;
tsepez1e2c5572016-05-25 14:58:09 -0700717
weili9f515bc2016-07-24 08:08:24 -0700718 CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
tsepez36eb4bd2016-10-03 15:24:27 -0700719 pPage->SetRenderContext(pdfium::WrapUnique(pContext));
Dan Sinclaira5085d42017-05-11 16:26:50 -0400720 CFX_DefaultRenderDevice* skDevice = new CFX_DefaultRenderDevice;
Cary Clark399be5b2016-03-14 16:51:29 -0400721 FPDF_RECORDER recorder = skDevice->CreateRecorder(size_x, size_y);
weili9f515bc2016-07-24 08:08:24 -0700722 pContext->m_pDevice.reset(skDevice);
tsepez4cf55152016-11-02 14:37:54 -0700723 FPDF_RenderPage_Retail(pContext, page, 0, 0, size_x, size_y, 0, 0, true,
tsepez1e2c5572016-05-25 14:58:09 -0700724 nullptr);
tsepeze5cb0b12016-10-26 15:06:11 -0700725 pPage->SetRenderContext(nullptr);
Cary Clark399be5b2016-03-14 16:51:29 -0400726 return recorder;
727}
728#endif
729
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400730FPDF_EXPORT void FPDF_CALLCONV FPDF_ClosePage(FPDF_PAGE page) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700731 if (!page)
732 return;
Tom Sepez2aa4b2f2018-05-25 22:38:49 +0000733
734 // Take it back across the API and hold for duration of this function.
Tom Sepez168c7632018-06-04 18:07:47 +0000735 RetainPtr<UnderlyingPageType> pPage;
736 pPage.Unleak(UnderlyingFromFPDFPage(page));
Tom Sepez2aa4b2f2018-05-25 22:38:49 +0000737
Tom Sepez24919902018-06-04 17:47:28 +0000738#ifndef PDF_ENABLE_XFA
Tom Sepez51da0932015-11-25 16:05:49 -0800739 CPDFSDK_PageView* pPageView =
Tom Sepez168c7632018-06-04 18:07:47 +0000740 static_cast<CPDFSDK_PageView*>(pPage->GetView());
Tom Sepez2aa4b2f2018-05-25 22:38:49 +0000741 if (!pPageView || pPageView->IsBeingDestroyed())
742 return;
dsinclairbcf46232016-10-03 13:02:27 -0700743
Tom Sepez2aa4b2f2018-05-25 22:38:49 +0000744 if (pPageView->IsLocked()) {
745 pPageView->TakePageOwnership();
746 return;
Tom Sepez51da0932015-11-25 16:05:49 -0800747 }
Tom Sepez2aa4b2f2018-05-25 22:38:49 +0000748
749 // This will delete the |pPageView| object. We must cleanup the PageView
750 // first because it will attempt to reset the View on the |pPage| during
751 // destruction.
752 pPageView->GetFormFillEnv()->RemovePageView(pPage.Get());
Tom Sepez24919902018-06-04 17:47:28 +0000753#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700754}
755
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400756FPDF_EXPORT void FPDF_CALLCONV FPDF_CloseDocument(FPDF_DOCUMENT document) {
Tom Sepez2d11d722018-05-31 23:38:32 +0000757 // Take it back across the API and throw it away,
758 std::unique_ptr<CPDF_Document>(CPDFDocumentFromFPDFDocument(document));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700759}
760
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400761FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_GetLastError() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700762 return GetLastError();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700763}
764
Lei Zhang822886b2018-04-12 17:24:45 +0000765FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_DeviceToPage(FPDF_PAGE page,
766 int start_x,
767 int start_y,
768 int size_x,
769 int size_y,
770 int rotate,
771 int device_x,
772 int device_y,
773 double* page_x,
774 double* page_y) {
Lei Zhang412e9082015-12-14 18:34:00 -0800775 if (!page || !page_x || !page_y)
Lei Zhang822886b2018-04-12 17:24:45 +0000776 return false;
Lei Zhanga105fa12018-04-12 16:23:01 +0000777
Tom Sepez168c7632018-06-04 18:07:47 +0000778 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Lei Zhangc4242b22018-04-12 15:50:49 +0000779 const FX_RECT rect(start_x, start_y, start_x + size_x, start_y + size_y);
Lei Zhang822886b2018-04-12 17:24:45 +0000780 Optional<CFX_PointF> pos =
781 pPage->DeviceToPage(rect, rotate, CFX_PointF(device_x, device_y));
782 if (!pos)
783 return false;
784
785 *page_x = pos->x;
786 *page_y = pos->y;
787 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700788}
789
Lei Zhang822886b2018-04-12 17:24:45 +0000790FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_PageToDevice(FPDF_PAGE page,
791 int start_x,
792 int start_y,
793 int size_x,
794 int size_y,
795 int rotate,
796 double page_x,
797 double page_y,
798 int* device_x,
799 int* device_y) {
Lei Zhanga105fa12018-04-12 16:23:01 +0000800 if (!page || !device_x || !device_y)
Lei Zhang822886b2018-04-12 17:24:45 +0000801 return false;
Lei Zhanga105fa12018-04-12 16:23:01 +0000802
Tom Sepez168c7632018-06-04 18:07:47 +0000803 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Lei Zhangc4242b22018-04-12 15:50:49 +0000804 const FX_RECT rect(start_x, start_y, start_x + size_x, start_y + size_y);
Lei Zhanga8db06a2018-04-12 17:53:15 +0000805 CFX_PointF page_point(static_cast<float>(page_x), static_cast<float>(page_y));
806 Optional<CFX_PointF> pos = pPage->PageToDevice(rect, rotate, page_point);
Lei Zhang822886b2018-04-12 17:24:45 +0000807 if (!pos)
808 return false;
809
810 *device_x = FXSYS_round(pos->x);
811 *device_y = FXSYS_round(pos->y);
812 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700813}
814
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400815FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV FPDFBitmap_Create(int width,
816 int height,
817 int alpha) {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700818 auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
tsepez37b12ad2016-12-14 19:50:23 -0800819 if (!pBitmap->Create(width, height, alpha ? FXDIB_Argb : FXDIB_Rgb32))
thestig1cd352e2016-06-07 17:53:06 -0700820 return nullptr;
tsepez37b12ad2016-12-14 19:50:23 -0800821
Tom Sepez525147a2018-05-03 17:19:53 +0000822 return FPDFBitmapFromCFXDIBitmap(pBitmap.Leak());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700823}
824
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400825FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV FPDFBitmap_CreateEx(int width,
826 int height,
827 int format,
828 void* first_scan,
829 int stride) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700830 FXDIB_Format fx_format;
831 switch (format) {
832 case FPDFBitmap_Gray:
833 fx_format = FXDIB_8bppRgb;
834 break;
835 case FPDFBitmap_BGR:
836 fx_format = FXDIB_Rgb;
837 break;
838 case FPDFBitmap_BGRx:
839 fx_format = FXDIB_Rgb32;
840 break;
841 case FPDFBitmap_BGRA:
842 fx_format = FXDIB_Argb;
843 break;
844 default:
thestig1cd352e2016-06-07 17:53:06 -0700845 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700846 }
Tom Sepeze7f4d332018-05-03 20:27:05 +0000847
848 // Ensure external memory is good at least for the duration of this call.
849 UnownedPtr<uint8_t> pChecker(static_cast<uint8_t*>(first_scan));
Tom Sepezf0799fe2017-03-28 09:31:32 -0700850 auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
Tom Sepeze7f4d332018-05-03 20:27:05 +0000851 if (!pBitmap->Create(width, height, fx_format, pChecker.Get(), stride))
Nicolas Penad08667c2018-04-16 17:41:47 +0000852 return nullptr;
Tom Sepeze7f4d332018-05-03 20:27:05 +0000853
Tom Sepez525147a2018-05-03 17:19:53 +0000854 return FPDFBitmapFromCFXDIBitmap(pBitmap.Leak());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700855}
856
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400857FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetFormat(FPDF_BITMAP bitmap) {
Jane Liu28fb7ba2017-08-02 21:45:57 -0400858 if (!bitmap)
859 return FPDFBitmap_Unknown;
860
Tom Sepez525147a2018-05-03 17:19:53 +0000861 FXDIB_Format format = CFXDIBitmapFromFPDFBitmap(bitmap)->GetFormat();
Jane Liu28fb7ba2017-08-02 21:45:57 -0400862 switch (format) {
863 case FXDIB_8bppRgb:
864 case FXDIB_8bppMask:
865 return FPDFBitmap_Gray;
866 case FXDIB_Rgb:
867 return FPDFBitmap_BGR;
868 case FXDIB_Rgb32:
869 return FPDFBitmap_BGRx;
870 case FXDIB_Argb:
871 return FPDFBitmap_BGRA;
872 default:
873 return FPDFBitmap_Unknown;
874 }
875}
876
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400877FPDF_EXPORT void FPDF_CALLCONV FPDFBitmap_FillRect(FPDF_BITMAP bitmap,
878 int left,
879 int top,
880 int width,
881 int height,
882 FPDF_DWORD color) {
Lei Zhang412e9082015-12-14 18:34:00 -0800883 if (!bitmap)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700884 return;
thestigbefa4502016-05-26 20:15:19 -0700885
Dan Sinclaira5085d42017-05-11 16:26:50 -0400886 CFX_DefaultRenderDevice device;
Tom Sepez525147a2018-05-03 17:19:53 +0000887 RetainPtr<CFX_DIBitmap> pBitmap(CFXDIBitmapFromFPDFBitmap(bitmap));
thestigbefa4502016-05-26 20:15:19 -0700888 device.Attach(pBitmap, false, nullptr, false);
889 if (!pBitmap->HasAlpha())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700890 color |= 0xFF000000;
Lei Zhange5c3ebd2018-04-10 19:02:15 +0000891 device.FillRect(FX_RECT(left, top, left + width, top + height), color);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700892}
893
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400894FPDF_EXPORT void* FPDF_CALLCONV FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap) {
Tom Sepez525147a2018-05-03 17:19:53 +0000895 return bitmap ? CFXDIBitmapFromFPDFBitmap(bitmap)->GetBuffer() : nullptr;
Bo Xu9114e832014-07-14 13:22:47 -0700896}
897
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400898FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetWidth(FPDF_BITMAP bitmap) {
Tom Sepez525147a2018-05-03 17:19:53 +0000899 return bitmap ? CFXDIBitmapFromFPDFBitmap(bitmap)->GetWidth() : 0;
Bo Xu9114e832014-07-14 13:22:47 -0700900}
901
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400902FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetHeight(FPDF_BITMAP bitmap) {
Tom Sepez525147a2018-05-03 17:19:53 +0000903 return bitmap ? CFXDIBitmapFromFPDFBitmap(bitmap)->GetHeight() : 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700904}
905
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400906FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetStride(FPDF_BITMAP bitmap) {
Tom Sepez525147a2018-05-03 17:19:53 +0000907 return bitmap ? CFXDIBitmapFromFPDFBitmap(bitmap)->GetPitch() : 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700908}
909
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400910FPDF_EXPORT void FPDF_CALLCONV FPDFBitmap_Destroy(FPDF_BITMAP bitmap) {
Dan Sinclair0b950422017-09-21 15:49:49 -0400911 RetainPtr<CFX_DIBitmap> destroyer;
Tom Sepez525147a2018-05-03 17:19:53 +0000912 destroyer.Unleak(CFXDIBitmapFromFPDFBitmap(bitmap));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700913}
914
weili9f515bc2016-07-24 08:08:24 -0700915void FPDF_RenderPage_Retail(CPDF_PageRenderContext* pContext,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700916 FPDF_PAGE page,
917 int start_x,
918 int start_y,
919 int size_x,
920 int size_y,
921 int rotate,
922 int flags,
tsepez4cf55152016-11-02 14:37:54 -0700923 bool bNeedToRestore,
Dan Sinclair7d125322018-03-28 18:49:34 +0000924 IPDFSDK_PauseAdapter* pause) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700925 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
926 if (!pPage)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700927 return;
928
Lei Zhangc4242b22018-04-12 15:50:49 +0000929 const FX_RECT rect(start_x, start_y, start_x + size_x, start_y + size_y);
930 RenderPageImpl(pContext, pPage, pPage->GetDisplayMatrix(rect, rotate), rect,
931 flags, bNeedToRestore, pause);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700932}
933
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400934FPDF_EXPORT int FPDF_CALLCONV FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document,
935 int page_index,
936 double* width,
937 double* height) {
Tom Sepezfe06d512018-05-01 17:25:25 +0000938 auto* pDoc = CPDFDocumentFromFPDFDocument(document);
Tom Sepez540c4362015-11-24 13:33:57 -0800939 if (!pDoc)
tsepez4cf55152016-11-02 14:37:54 -0700940 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700941
Tom Sepez40e9ff32015-11-30 12:39:54 -0800942#ifdef PDF_ENABLE_XFA
Tom Sepezfe06d512018-05-01 17:25:25 +0000943 if (page_index < 0 || page_index >= FPDF_GetPageCount(document))
tsepez4cf55152016-11-02 14:37:54 -0700944 return false;
Tom Sepez3f3c39d2018-05-01 17:46:34 +0000945
946 auto* pContext = static_cast<CPDFXFA_Context*>(pDoc->GetExtension());
947 if (pContext) {
948 RetainPtr<CPDFXFA_Page> pPage = pContext->GetXFAPage(page_index);
949 if (!pPage)
950 return false;
951
952 *width = pPage->GetPageWidth();
953 *height = pPage->GetPageHeight();
954 return true;
955 }
956#endif // PDF_ENABLE_XFA
957
Tom Sepez967aa072018-05-08 13:40:20 +0000958 CPDF_Dictionary* pDict = pDoc->GetPageDictionary(page_index);
Tom Sepez40e9ff32015-11-30 12:39:54 -0800959 if (!pDict)
tsepez4cf55152016-11-02 14:37:54 -0700960 return false;
thestig5cc24652016-04-26 11:46:02 -0700961
Tom Sepezf06ed6d2018-06-04 18:26:07 +0000962 auto page = pdfium::MakeRetain<CPDF_Page>(pDoc, pDict, true);
Tom Sepez2aa4b2f2018-05-25 22:38:49 +0000963 *width = page->GetPageWidth();
964 *height = page->GetPageHeight();
tsepez4cf55152016-11-02 14:37:54 -0700965 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700966}
967
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400968FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700969FPDF_VIEWERREF_GetPrintScaling(FPDF_DOCUMENT document) {
Lei Zhang55bbb0a2018-05-08 19:26:37 +0000970 const CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700971 if (!pDoc)
tsepez4cf55152016-11-02 14:37:54 -0700972 return true;
Tom Sepez471a1032015-10-15 16:17:18 -0700973 CPDF_ViewerPreferences viewRef(pDoc);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700974 return viewRef.PrintScaling();
975}
976
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400977FPDF_EXPORT int FPDF_CALLCONV
978FPDF_VIEWERREF_GetNumCopies(FPDF_DOCUMENT document) {
Lei Zhang55bbb0a2018-05-08 19:26:37 +0000979 const CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700980 if (!pDoc)
981 return 1;
982 CPDF_ViewerPreferences viewRef(pDoc);
983 return viewRef.NumCopies();
984}
985
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400986FPDF_EXPORT FPDF_PAGERANGE FPDF_CALLCONV
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700987FPDF_VIEWERREF_GetPrintPageRange(FPDF_DOCUMENT document) {
Lei Zhang55bbb0a2018-05-08 19:26:37 +0000988 const CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700989 if (!pDoc)
thestig1cd352e2016-06-07 17:53:06 -0700990 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700991 CPDF_ViewerPreferences viewRef(pDoc);
Tom Sepez525147a2018-05-03 17:19:53 +0000992 return FPDFPageRangeFromCPDFArray(viewRef.PrintPageRange());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700993}
994
Lei Zhang9c6204f2018-05-08 19:20:57 +0000995FPDF_EXPORT size_t FPDF_CALLCONV
996FPDF_VIEWERREF_GetPrintPageRangeCount(FPDF_PAGERANGE pagerange) {
997 const CPDF_Array* pArray = CPDFArrayFromFPDFPageRange(pagerange);
998 return pArray ? pArray->GetCount() : 0;
999}
1000
1001FPDF_EXPORT int FPDF_CALLCONV
1002FPDF_VIEWERREF_GetPrintPageRangeElement(FPDF_PAGERANGE pagerange,
1003 size_t index) {
1004 const CPDF_Array* pArray = CPDFArrayFromFPDFPageRange(pagerange);
1005 if (!pArray || index >= pArray->GetCount())
1006 return -1;
1007 return pArray->GetIntegerAt(index);
1008}
1009
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001010FPDF_EXPORT FPDF_DUPLEXTYPE FPDF_CALLCONV
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001011FPDF_VIEWERREF_GetDuplex(FPDF_DOCUMENT document) {
Lei Zhang55bbb0a2018-05-08 19:26:37 +00001012 const CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001013 if (!pDoc)
Bo Xu9114e832014-07-14 13:22:47 -07001014 return DuplexUndefined;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001015 CPDF_ViewerPreferences viewRef(pDoc);
Ryan Harrison275e2602017-09-18 14:23:18 -04001016 ByteString duplex = viewRef.Duplex();
Lei Zhangd983b092015-12-14 16:58:33 -08001017 if ("Simplex" == duplex)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001018 return Simplex;
Lei Zhangd983b092015-12-14 16:58:33 -08001019 if ("DuplexFlipShortEdge" == duplex)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001020 return DuplexFlipShortEdge;
Lei Zhangd983b092015-12-14 16:58:33 -08001021 if ("DuplexFlipLongEdge" == duplex)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001022 return DuplexFlipLongEdge;
1023 return DuplexUndefined;
Bo Xu9114e832014-07-14 13:22:47 -07001024}
1025
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001026FPDF_EXPORT unsigned long FPDF_CALLCONV
1027FPDF_VIEWERREF_GetName(FPDF_DOCUMENT document,
1028 FPDF_BYTESTRING key,
1029 char* buffer,
1030 unsigned long length) {
Lei Zhang55bbb0a2018-05-08 19:26:37 +00001031 const CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
thestig04bebfe2016-11-04 16:07:25 -07001032 if (!pDoc)
1033 return 0;
1034
1035 CPDF_ViewerPreferences viewRef(pDoc);
Lei Zhang55bbb0a2018-05-08 19:26:37 +00001036 Optional<ByteString> bsVal = viewRef.GenericName(key);
1037 if (!bsVal)
thestig04bebfe2016-11-04 16:07:25 -07001038 return 0;
1039
Lei Zhang55bbb0a2018-05-08 19:26:37 +00001040 unsigned long dwStringLen = bsVal->GetLength() + 1;
thestig04bebfe2016-11-04 16:07:25 -07001041 if (buffer && length >= dwStringLen)
Lei Zhang55bbb0a2018-05-08 19:26:37 +00001042 memcpy(buffer, bsVal->c_str(), dwStringLen);
thestig04bebfe2016-11-04 16:07:25 -07001043 return dwStringLen;
1044}
1045
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001046FPDF_EXPORT FPDF_DWORD FPDF_CALLCONV
1047FPDF_CountNamedDests(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001048 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1049 if (!pDoc)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001050 return 0;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001051
Lei Zhang01581062017-08-30 14:19:26 -07001052 const CPDF_Dictionary* pRoot = pDoc->GetRoot();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001053 if (!pRoot)
1054 return 0;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001055
Lei Zhangd983b092015-12-14 16:58:33 -08001056 CPDF_NameTree nameTree(pDoc, "Dests");
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001057 pdfium::base::CheckedNumeric<FPDF_DWORD> count = nameTree.GetCount();
Lei Zhang55bbb0a2018-05-08 19:26:37 +00001058 const CPDF_Dictionary* pDest = pRoot->GetDictFor("Dests");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001059 if (pDest)
1060 count += pDest->GetCount();
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001061
1062 if (!count.IsValid())
1063 return 0;
1064
1065 return count.ValueOrDie();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001066}
1067
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001068FPDF_EXPORT FPDF_DEST FPDF_CALLCONV
1069FPDF_GetNamedDestByName(FPDF_DOCUMENT document, FPDF_BYTESTRING name) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001070 if (!name || name[0] == 0)
Tom Sepez471a1032015-10-15 16:17:18 -07001071 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001072
Tom Sepez471a1032015-10-15 16:17:18 -07001073 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1074 if (!pDoc)
1075 return nullptr;
1076
Lei Zhangd983b092015-12-14 16:58:33 -08001077 CPDF_NameTree name_tree(pDoc, "Dests");
Tom Sepez525147a2018-05-03 17:19:53 +00001078 return FPDFDestFromCPDFArray(
1079 name_tree.LookupNamedDest(pDoc, PDF_DecodeText(ByteString(name))));
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001080}
1081
Tom Sepez51da0932015-11-25 16:05:49 -08001082#ifdef PDF_ENABLE_XFA
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001083FPDF_EXPORT FPDF_RESULT FPDF_CALLCONV FPDF_BStr_Init(FPDF_BSTR* str) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001084 if (!str)
1085 return -1;
1086
Dan Sinclair1c5d0b42017-04-03 15:05:11 -04001087 memset(str, 0, sizeof(FPDF_BSTR));
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001088 return 0;
1089}
1090
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001091FPDF_EXPORT FPDF_RESULT FPDF_CALLCONV FPDF_BStr_Set(FPDF_BSTR* str,
1092 FPDF_LPCSTR bstr,
1093 int length) {
Lei Zhanga88e3052017-12-15 15:51:52 -08001094 if (!str || !bstr || !length)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001095 return -1;
Lei Zhanga88e3052017-12-15 15:51:52 -08001096
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001097 if (length == -1)
Ryan Harrison8b1408e2017-09-27 11:07:51 -04001098 length = strlen(bstr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001099
1100 if (length == 0) {
Lei Zhanga88e3052017-12-15 15:51:52 -08001101 FPDF_BStr_Clear(str);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001102 return 0;
1103 }
1104
1105 if (str->str && str->len < length)
1106 str->str = FX_Realloc(char, str->str, length + 1);
1107 else if (!str->str)
1108 str->str = FX_Alloc(char, length + 1);
1109
1110 str->str[length] = 0;
Dan Sinclair1c5d0b42017-04-03 15:05:11 -04001111 memcpy(str->str, bstr, length);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001112 str->len = length;
1113
1114 return 0;
1115}
1116
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001117FPDF_EXPORT FPDF_RESULT FPDF_CALLCONV FPDF_BStr_Clear(FPDF_BSTR* str) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001118 if (!str)
1119 return -1;
1120
1121 if (str->str) {
1122 FX_Free(str->str);
thestig1cd352e2016-06-07 17:53:06 -07001123 str->str = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001124 }
1125 str->len = 0;
1126 return 0;
1127}
Tom Sepez40e9ff32015-11-30 12:39:54 -08001128#endif // PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001129
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001130FPDF_EXPORT FPDF_DEST FPDF_CALLCONV FPDF_GetNamedDest(FPDF_DOCUMENT document,
1131 int index,
1132 void* buffer,
1133 long* buflen) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001134 if (!buffer)
1135 *buflen = 0;
Tom Sepez540c4362015-11-24 13:33:57 -08001136
1137 if (index < 0)
1138 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001139
Tom Sepezbf59a072015-10-21 14:07:23 -07001140 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Tom Sepez540c4362015-11-24 13:33:57 -08001141 if (!pDoc)
1142 return nullptr;
1143
Lei Zhang01581062017-08-30 14:19:26 -07001144 const CPDF_Dictionary* pRoot = pDoc->GetRoot();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001145 if (!pRoot)
Tom Sepez540c4362015-11-24 13:33:57 -08001146 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001147
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001148 CPDF_Object* pDestObj = nullptr;
Ryan Harrison275e2602017-09-18 14:23:18 -04001149 WideString wsName;
Lei Zhangd983b092015-12-14 16:58:33 -08001150 CPDF_NameTree nameTree(pDoc, "Dests");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001151 int count = nameTree.GetCount();
1152 if (index >= count) {
Lei Zhang55bbb0a2018-05-08 19:26:37 +00001153 const CPDF_Dictionary* pDest = pRoot->GetDictFor("Dests");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001154 if (!pDest)
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001155 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
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001162 index -= count;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001163 int i = 0;
Ryan Harrison275e2602017-09-18 14:23:18 -04001164 ByteString bsName;
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001165 for (const auto& it : *pDest) {
1166 bsName = it.first;
tsepez0e606b52016-11-18 16:22:41 -08001167 pDestObj = it.second.get();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001168 if (!pDestObj)
1169 continue;
1170 if (i == index)
1171 break;
1172 i++;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001173 }
Jane Liu67ccef72017-07-19 13:10:50 -04001174 wsName = PDF_DecodeText(bsName);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001175 } else {
Jane Liu67ccef72017-07-19 13:10:50 -04001176 pDestObj = nameTree.LookupValueAndName(index, &wsName);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001177 }
1178 if (!pDestObj)
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001179 return nullptr;
Dan Sinclairf1251c12015-10-20 16:24:45 -04001180 if (CPDF_Dictionary* pDict = pDestObj->AsDictionary()) {
dsinclair38fd8442016-09-15 10:15:32 -07001181 pDestObj = pDict->GetArrayFor("D");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001182 if (!pDestObj)
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001183 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001184 }
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001185 if (!pDestObj->IsArray())
1186 return nullptr;
1187
Ryan Harrison275e2602017-09-18 14:23:18 -04001188 ByteString utf16Name = wsName.UTF16LE_Encode();
weili47ca6922016-03-31 15:08:27 -07001189 int len = utf16Name.GetLength();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001190 if (!buffer) {
1191 *buflen = len;
thestig9067fd62016-11-23 14:10:06 -08001192 } else if (len <= *buflen) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001193 memcpy(buffer, utf16Name.c_str(), len);
1194 *buflen = len;
1195 } else {
1196 *buflen = -1;
1197 }
Tom Sepez525147a2018-05-03 17:19:53 +00001198 return FPDFDestFromCPDFArray(pDestObj->AsArray());
Bo Xu4d62b6b2015-01-10 22:52:59 -08001199}