blob: 2e52ad6487d7f9f18cb2a576726538f959ef2cba [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
Lei Zhangaa8bf7e2015-12-24 19:13:32 -08009#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"
rbpottercec01802017-04-17 09:10:21 -070015#include "core/fpdfapi/page/cpdf_image.h"
16#include "core/fpdfapi/page/cpdf_imageobject.h"
dsinclair41872fa2016-10-04 11:29:35 -070017#include "core/fpdfapi/page/cpdf_page.h"
rbpottercec01802017-04-17 09:10:21 -070018#include "core/fpdfapi/page/cpdf_pageobject.h"
Jane Liu3b057432017-06-19 10:44:01 -040019#include "core/fpdfapi/page/cpdf_pathobject.h"
dsinclair488b7ad2016-10-04 11:55:50 -070020#include "core/fpdfapi/parser/cpdf_array.h"
Jane Liu4fd9a472017-06-01 18:56:09 -040021#include "core/fpdfapi/parser/cpdf_dictionary.h"
dsinclair488b7ad2016-10-04 11:55:50 -070022#include "core/fpdfapi/parser/cpdf_document.h"
23#include "core/fpdfapi/parser/fpdf_parser_decode.h"
dsinclair69d9c682016-10-04 12:18:35 -070024#include "core/fpdfapi/render/cpdf_progressiverenderer.h"
25#include "core/fpdfapi/render/cpdf_renderoptions.h"
dsinclair1727aee2016-09-29 13:12:56 -070026#include "core/fpdfdoc/cpdf_annotlist.h"
27#include "core/fpdfdoc/cpdf_nametree.h"
28#include "core/fpdfdoc/cpdf_occontext.h"
29#include "core/fpdfdoc/cpdf_viewerpreferences.h"
dsinclair8a4e2862016-09-29 13:43:30 -070030#include "core/fxcodec/fx_codec.h"
dsinclaira52ab742016-09-29 13:59:29 -070031#include "core/fxcrt/fx_memory.h"
32#include "core/fxcrt/fx_safe_types.h"
Dan Sinclaira5085d42017-05-11 16:26:50 -040033#include "core/fxge/cfx_defaultrenderdevice.h"
dsinclair74a34fc2016-09-29 16:41:42 -070034#include "core/fxge/cfx_gemodule.h"
dsinclairb402b172016-10-11 09:26:32 -070035#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
dsinclair114e46a2016-09-29 17:18:21 -070036#include "fpdfsdk/cpdfsdk_pageview.h"
37#include "fpdfsdk/fsdk_define.h"
38#include "fpdfsdk/fsdk_pauseadapter.h"
dsinclair64376be2016-03-31 20:03:24 -070039#include "fpdfsdk/javascript/ijs_runtime.h"
rbpottere8468c42017-07-11 10:04:29 -070040#include "public/fpdf_edit.h"
Lei Zhangb4e7f302015-11-06 15:52:32 -080041#include "public/fpdf_ext.h"
Lei Zhangb4e7f302015-11-06 15:52:32 -080042#include "public/fpdf_progressive.h"
Chris Palmere4b035b2017-03-26 15:48:34 -070043#include "third_party/base/allocator/partition_allocator/partition_alloc.h"
Lei Zhang8241df72015-11-06 14:38:48 -080044#include "third_party/base/numerics/safe_conversions_impl.h"
tsepez36eb4bd2016-10-03 15:24:27 -070045#include "third_party/base/ptr_util.h"
Bo Xufdc00a72014-10-28 23:03:33 -070046
Tom Sepez40e9ff32015-11-30 12:39:54 -080047#ifdef PDF_ENABLE_XFA
dsinclair521b7502016-11-02 13:02:28 -070048#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
dsinclair4d29e782016-10-04 14:02:47 -070049#include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
50#include "fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h"
Dan Sinclaire7786682017-03-29 15:18:41 -040051#include "fxbarcode/BC_Library.h"
Tom Sepez40e9ff32015-11-30 12:39:54 -080052#include "public/fpdf_formfill.h"
53#endif // PDF_ENABLE_XFA
54
thestig25fa42f2016-05-25 21:39:46 -070055#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
Dan Sinclaira5085d42017-05-11 16:26:50 -040056#include "core/fxge/cfx_windowsrenderdevice.h"
rbpottere8468c42017-07-11 10:04:29 -070057
58// These checks are here because core/ and public/ cannot depend on each other.
59static_assert(WindowsPrintMode::kModeEmf == FPDF_PRINTMODE_EMF,
60 "WindowsPrintMode::kModeEmf value mismatch");
61static_assert(WindowsPrintMode::kModeTextOnly == FPDF_PRINTMODE_TEXTONLY,
62 "WindowsPrintMode::kModeTextOnly value mismatch");
63static_assert(WindowsPrintMode::kModePostScript2 == FPDF_PRINTMODE_POSTSCRIPT2,
64 "WindowsPrintMode::kModePostScript2 value mismatch");
65static_assert(WindowsPrintMode::kModePostScript3 == FPDF_PRINTMODE_POSTSCRIPT3,
66 "WindowsPrintMode::kModePostScript3 value mismatch");
thestig25fa42f2016-05-25 21:39:46 -070067#endif
68
thestiga78ba602016-11-23 15:25:48 -080069namespace {
70
Dan Sinclair830897a2017-05-11 14:36:10 -040071bool g_bLibraryInitialized = false;
tsepez02759102016-12-01 08:29:25 -080072
thestiga78ba602016-11-23 15:25:48 -080073void RenderPageImpl(CPDF_PageRenderContext* pContext,
74 CPDF_Page* pPage,
75 const CFX_Matrix& matrix,
76 const FX_RECT& clipping_rect,
77 int flags,
78 bool bNeedToRestore,
79 IFSDK_PAUSE_Adapter* pause) {
80 if (!pContext->m_pOptions)
81 pContext->m_pOptions = pdfium::MakeUnique<CPDF_RenderOptions>();
82
83 if (flags & FPDF_LCD_TEXT)
84 pContext->m_pOptions->m_Flags |= RENDER_CLEARTYPE;
85 else
86 pContext->m_pOptions->m_Flags &= ~RENDER_CLEARTYPE;
87
88 if (flags & FPDF_NO_NATIVETEXT)
89 pContext->m_pOptions->m_Flags |= RENDER_NO_NATIVETEXT;
90 if (flags & FPDF_RENDER_LIMITEDIMAGECACHE)
91 pContext->m_pOptions->m_Flags |= RENDER_LIMITEDIMAGECACHE;
92 if (flags & FPDF_RENDER_FORCEHALFTONE)
93 pContext->m_pOptions->m_Flags |= RENDER_FORCE_HALFTONE;
94#ifndef PDF_ENABLE_XFA
95 if (flags & FPDF_RENDER_NO_SMOOTHTEXT)
96 pContext->m_pOptions->m_Flags |= RENDER_NOTEXTSMOOTH;
97 if (flags & FPDF_RENDER_NO_SMOOTHIMAGE)
98 pContext->m_pOptions->m_Flags |= RENDER_NOIMAGESMOOTH;
99 if (flags & FPDF_RENDER_NO_SMOOTHPATH)
100 pContext->m_pOptions->m_Flags |= RENDER_NOPATHSMOOTH;
101#endif // PDF_ENABLE_XFA
102
103 // Grayscale output
Dan Sinclairf55e72e2017-07-13 14:53:28 -0400104 if (flags & FPDF_GRAYSCALE)
105 pContext->m_pOptions->m_ColorMode = CPDF_RenderOptions::kGray;
thestiga78ba602016-11-23 15:25:48 -0800106
107 const CPDF_OCContext::UsageType usage =
108 (flags & FPDF_PRINTING) ? CPDF_OCContext::Print : CPDF_OCContext::View;
thestiga78ba602016-11-23 15:25:48 -0800109 pContext->m_pOptions->m_pOCContext =
Tom Sepez4cb82ee2017-05-22 15:15:30 -0700110 pdfium::MakeRetain<CPDF_OCContext>(pPage->m_pDocument.Get(), usage);
thestiga78ba602016-11-23 15:25:48 -0800111
112 pContext->m_pDevice->SaveState();
113 pContext->m_pDevice->SetClip_Rect(clipping_rect);
thestiga78ba602016-11-23 15:25:48 -0800114 pContext->m_pContext = pdfium::MakeUnique<CPDF_RenderContext>(pPage);
115 pContext->m_pContext->AppendLayer(pPage, &matrix);
116
117 if (flags & FPDF_ANNOT) {
118 pContext->m_pAnnots = pdfium::MakeUnique<CPDF_AnnotList>(pPage);
119 bool bPrinting = pContext->m_pDevice->GetDeviceClass() != FXDC_DISPLAY;
120 pContext->m_pAnnots->DisplayAnnots(pPage, pContext->m_pContext.get(),
121 bPrinting, &matrix, false, nullptr);
122 }
123
124 pContext->m_pRenderer = pdfium::MakeUnique<CPDF_ProgressiveRenderer>(
125 pContext->m_pContext.get(), pContext->m_pDevice.get(),
126 pContext->m_pOptions.get());
127 pContext->m_pRenderer->Start(pause);
128 if (bNeedToRestore)
129 pContext->m_pDevice->RestoreState(false);
130}
131
tsepezbea04972016-12-01 13:54:42 -0800132class CPDF_CustomAccess final : public IFX_SeekableReadStream {
133 public:
Tom Sepez40badde2017-05-01 13:21:39 -0700134 template <typename T, typename... Args>
135 friend CFX_RetainPtr<T> pdfium::MakeRetain(Args&&... args);
tsepezbea04972016-12-01 13:54:42 -0800136
137 // IFX_SeekableReadStream
138 FX_FILESIZE GetSize() override;
tsepezbea04972016-12-01 13:54:42 -0800139 bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override;
140
141 private:
tsepez833619b2016-12-07 09:21:17 -0800142 explicit CPDF_CustomAccess(FPDF_FILEACCESS* pFileAccess);
143
tsepezbea04972016-12-01 13:54:42 -0800144 FPDF_FILEACCESS m_FileAccess;
145};
146
147CPDF_CustomAccess::CPDF_CustomAccess(FPDF_FILEACCESS* pFileAccess)
148 : m_FileAccess(*pFileAccess) {}
149
150FX_FILESIZE CPDF_CustomAccess::GetSize() {
151 return m_FileAccess.m_FileLen;
152}
153
tsepezbea04972016-12-01 13:54:42 -0800154bool CPDF_CustomAccess::ReadBlock(void* buffer,
155 FX_FILESIZE offset,
156 size_t size) {
157 if (offset < 0)
158 return false;
159
160 FX_SAFE_FILESIZE newPos = pdfium::base::checked_cast<FX_FILESIZE>(size);
161 newPos += offset;
162 if (!newPos.IsValid() ||
163 newPos.ValueOrDie() > static_cast<FX_FILESIZE>(m_FileAccess.m_FileLen)) {
164 return false;
165 }
166 return !!m_FileAccess.m_GetBlock(m_FileAccess.m_Param, offset,
Nicolas Pena46abb662017-05-17 17:23:22 -0400167 static_cast<uint8_t*>(buffer), size);
tsepezbea04972016-12-01 13:54:42 -0800168}
169
Tom Sepez40e9ff32015-11-30 12:39:54 -0800170#ifdef PDF_ENABLE_XFA
tsepezfa89a202016-12-02 09:48:30 -0800171class CFPDF_FileStream : public IFX_SeekableStream {
172 public:
Tom Sepez40badde2017-05-01 13:21:39 -0700173 template <typename T, typename... Args>
174 friend CFX_RetainPtr<T> pdfium::MakeRetain(Args&&... args);
175
tsepez833619b2016-12-07 09:21:17 -0800176 ~CFPDF_FileStream() override;
Tom Sepez471a1032015-10-15 16:17:18 -0700177
tsepezfa89a202016-12-02 09:48:30 -0800178 // IFX_SeekableStream:
tsepezfa89a202016-12-02 09:48:30 -0800179 FX_FILESIZE GetSize() override;
180 bool IsEOF() override;
181 FX_FILESIZE GetPosition() override;
182 bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override;
183 size_t ReadBlock(void* buffer, size_t size) override;
184 bool WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size) override;
185 bool Flush() override;
Tom Sepezbf59a072015-10-21 14:07:23 -0700186
tsepezfa89a202016-12-02 09:48:30 -0800187 void SetPosition(FX_FILESIZE pos) { m_nCurPos = pos; }
Tom Sepezdb0be962015-10-16 14:00:21 -0700188
tsepezfa89a202016-12-02 09:48:30 -0800189 protected:
tsepez833619b2016-12-07 09:21:17 -0800190 explicit CFPDF_FileStream(FPDF_FILEHANDLER* pFS);
191
tsepezfa89a202016-12-02 09:48:30 -0800192 FPDF_FILEHANDLER* m_pFS;
193 FX_FILESIZE m_nCurPos;
194};
thestigbefa4502016-05-26 20:15:19 -0700195
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700196CFPDF_FileStream::CFPDF_FileStream(FPDF_FILEHANDLER* pFS) {
197 m_pFS = pFS;
198 m_nCurPos = 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700199}
200
tsepez833619b2016-12-07 09:21:17 -0800201CFPDF_FileStream::~CFPDF_FileStream() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700202 if (m_pFS && m_pFS->Release)
203 m_pFS->Release(m_pFS->clientData);
Bo Xufdc00a72014-10-28 23:03:33 -0700204}
205
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700206FX_FILESIZE CFPDF_FileStream::GetSize() {
207 if (m_pFS && m_pFS->GetSize)
208 return (FX_FILESIZE)m_pFS->GetSize(m_pFS->clientData);
209 return 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700210}
211
tsepezf39074c2016-10-26 15:33:58 -0700212bool CFPDF_FileStream::IsEOF() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700213 return m_nCurPos >= GetSize();
Bo Xufdc00a72014-10-28 23:03:33 -0700214}
215
weili625ad662016-06-15 11:21:33 -0700216FX_FILESIZE CFPDF_FileStream::GetPosition() {
217 return m_nCurPos;
218}
219
tsepezf39074c2016-10-26 15:33:58 -0700220bool CFPDF_FileStream::ReadBlock(void* buffer,
221 FX_FILESIZE offset,
222 size_t size) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700223 if (!buffer || !size || !m_pFS->ReadBlock)
tsepezf39074c2016-10-26 15:33:58 -0700224 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700225
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700226 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
227 (FPDF_DWORD)size) == 0) {
228 m_nCurPos = offset + size;
tsepezf39074c2016-10-26 15:33:58 -0700229 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700230 }
tsepezf39074c2016-10-26 15:33:58 -0700231 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700232}
233
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700234size_t CFPDF_FileStream::ReadBlock(void* buffer, size_t size) {
235 if (!buffer || !size || !m_pFS->ReadBlock)
236 return 0;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700237
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700238 FX_FILESIZE nSize = GetSize();
239 if (m_nCurPos >= nSize)
240 return 0;
241 FX_FILESIZE dwAvail = nSize - m_nCurPos;
242 if (dwAvail < (FX_FILESIZE)size)
243 size = (size_t)dwAvail;
244 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)m_nCurPos, buffer,
245 (FPDF_DWORD)size) == 0) {
246 m_nCurPos += size;
247 return size;
248 }
Bo Xufdc00a72014-10-28 23:03:33 -0700249
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700250 return 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700251}
252
tsepezf39074c2016-10-26 15:33:58 -0700253bool CFPDF_FileStream::WriteBlock(const void* buffer,
254 FX_FILESIZE offset,
255 size_t size) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700256 if (!m_pFS || !m_pFS->WriteBlock)
tsepezf39074c2016-10-26 15:33:58 -0700257 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700258
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700259 if (m_pFS->WriteBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
260 (FPDF_DWORD)size) == 0) {
261 m_nCurPos = offset + size;
tsepezf39074c2016-10-26 15:33:58 -0700262 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700263 }
tsepezf39074c2016-10-26 15:33:58 -0700264 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700265}
266
tsepezf39074c2016-10-26 15:33:58 -0700267bool CFPDF_FileStream::Flush() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700268 if (!m_pFS || !m_pFS->Flush)
tsepezf39074c2016-10-26 15:33:58 -0700269 return true;
Bo Xufdc00a72014-10-28 23:03:33 -0700270
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700271 return m_pFS->Flush(m_pFS->clientData) == 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700272}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800273#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700274
tsepezfa89a202016-12-02 09:48:30 -0800275} // namespace
276
277UnderlyingDocumentType* UnderlyingFromFPDFDocument(FPDF_DOCUMENT doc) {
278 return static_cast<UnderlyingDocumentType*>(doc);
279}
280
281FPDF_DOCUMENT FPDFDocumentFromUnderlying(UnderlyingDocumentType* doc) {
282 return static_cast<FPDF_DOCUMENT>(doc);
283}
284
285UnderlyingPageType* UnderlyingFromFPDFPage(FPDF_PAGE page) {
286 return static_cast<UnderlyingPageType*>(page);
287}
288
289CPDF_Document* CPDFDocumentFromFPDFDocument(FPDF_DOCUMENT doc) {
290#ifdef PDF_ENABLE_XFA
291 return doc ? UnderlyingFromFPDFDocument(doc)->GetPDFDoc() : nullptr;
292#else // PDF_ENABLE_XFA
293 return UnderlyingFromFPDFDocument(doc);
294#endif // PDF_ENABLE_XFA
295}
296
297FPDF_DOCUMENT FPDFDocumentFromCPDFDocument(CPDF_Document* doc) {
298#ifdef PDF_ENABLE_XFA
299 return doc ? FPDFDocumentFromUnderlying(
300 new CPDFXFA_Context(pdfium::WrapUnique(doc)))
301 : nullptr;
302#else // PDF_ENABLE_XFA
303 return FPDFDocumentFromUnderlying(doc);
304#endif // PDF_ENABLE_XFA
305}
306
307CPDF_Page* CPDFPageFromFPDFPage(FPDF_PAGE page) {
308#ifdef PDF_ENABLE_XFA
309 return page ? UnderlyingFromFPDFPage(page)->GetPDFPage() : nullptr;
310#else // PDF_ENABLE_XFA
311 return UnderlyingFromFPDFPage(page);
312#endif // PDF_ENABLE_XFA
313}
314
Jane Liu3b057432017-06-19 10:44:01 -0400315CPDF_PathObject* CPDFPathObjectFromFPDFPageObject(FPDF_PAGEOBJECT page_object) {
316 return static_cast<CPDF_PathObject*>(page_object);
317}
318
Jane Liubaa7ff42017-06-29 19:18:23 -0400319CPDF_PageObject* CPDFPageObjectFromFPDFPageObject(FPDF_PAGEOBJECT page_object) {
320 return static_cast<CPDF_PageObject*>(page_object);
321}
322
tsepezfa89a202016-12-02 09:48:30 -0800323CFX_DIBitmap* CFXBitmapFromFPDFBitmap(FPDF_BITMAP bitmap) {
324 return static_cast<CFX_DIBitmap*>(bitmap);
325}
326
tsepez833619b2016-12-07 09:21:17 -0800327CFX_RetainPtr<IFX_SeekableReadStream> MakeSeekableReadStream(
328 FPDF_FILEACCESS* pFileAccess) {
Tom Sepez40badde2017-05-01 13:21:39 -0700329 return pdfium::MakeRetain<CPDF_CustomAccess>(pFileAccess);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700330}
331
tsepezfa89a202016-12-02 09:48:30 -0800332#ifdef PDF_ENABLE_XFA
tsepez833619b2016-12-07 09:21:17 -0800333CFX_RetainPtr<IFX_SeekableStream> MakeSeekableStream(
334 FPDF_FILEHANDLER* pFilehandler) {
Tom Sepez40badde2017-05-01 13:21:39 -0700335 return pdfium::MakeRetain<CFPDF_FileStream>(pFilehandler);
tsepezfa89a202016-12-02 09:48:30 -0800336}
337#endif // PDF_ENABLE_XFA
338
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700339// 0 bit: FPDF_POLICY_MACHINETIME_ACCESS
tsepezc3255f52016-03-25 14:52:27 -0700340static uint32_t foxit_sandbox_policy = 0xFFFFFFFF;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700341
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700342void FSDK_SetSandBoxPolicy(FPDF_DWORD policy, FPDF_BOOL enable) {
343 switch (policy) {
344 case FPDF_POLICY_MACHINETIME_ACCESS: {
345 if (enable)
346 foxit_sandbox_policy |= 0x01;
347 else
348 foxit_sandbox_policy &= 0xFFFFFFFE;
349 } break;
350 default:
351 break;
352 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700353}
354
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700355FPDF_BOOL FSDK_IsSandBoxPolicyEnabled(FPDF_DWORD policy) {
356 switch (policy) {
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700357 case FPDF_POLICY_MACHINETIME_ACCESS:
Lei Zhangb0748bb2015-10-19 12:11:49 -0700358 return !!(foxit_sandbox_policy & 0x01);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700359 default:
tsepez4cf55152016-11-02 14:37:54 -0700360 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700361 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700362}
363
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700364DLLEXPORT void STDCALL FPDF_InitLibrary() {
Lei Zhang6f62d532015-09-23 15:31:44 -0700365 FPDF_InitLibraryWithConfig(nullptr);
366}
367
Dan Sinclairf766ad22016-03-14 13:51:24 -0400368DLLEXPORT void STDCALL
369FPDF_InitLibraryWithConfig(const FPDF_LIBRARY_CONFIG* cfg) {
Dan Sinclair830897a2017-05-11 14:36:10 -0400370 if (g_bLibraryInitialized)
tsepez02759102016-12-01 08:29:25 -0800371 return;
372
Dan Sinclairdbc3d3e2017-05-11 13:41:38 -0400373 FXMEM_InitializePartitionAlloc();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700374
weili47228ac2016-07-20 10:35:31 -0700375 CFX_GEModule* pModule = CFX_GEModule::Get();
Dan Sinclair830897a2017-05-11 14:36:10 -0400376 pModule->Init(cfg ? cfg->m_pUserFontPaths : nullptr);
tsepez02759102016-12-01 08:29:25 -0800377
Tom Sepez1b246282015-11-25 15:15:31 -0800378 CPDF_ModuleMgr* pModuleMgr = CPDF_ModuleMgr::Get();
Lei Zhang76020fc2017-05-18 15:51:20 -0700379 pModuleMgr->Init();
Tom Sepezb4a26182017-03-01 12:15:00 -0800380
Tom Sepez40e9ff32015-11-30 12:39:54 -0800381#ifdef PDF_ENABLE_XFA
dsinclair8837c912016-11-01 11:22:37 -0700382 FXJSE_Initialize();
383 BC_Library_Init();
Tom Sepez40e9ff32015-11-30 12:39:54 -0800384#endif // PDF_ENABLE_XFA
Tom Sepez452b4f32015-10-13 09:27:27 -0700385 if (cfg && cfg->version >= 2)
386 IJS_Runtime::Initialize(cfg->m_v8EmbedderSlot, cfg->m_pIsolate);
Dan Sinclair830897a2017-05-11 14:36:10 -0400387
388 g_bLibraryInitialized = true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700389}
390
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700391DLLEXPORT void STDCALL FPDF_DestroyLibrary() {
Dan Sinclair830897a2017-05-11 14:36:10 -0400392 if (!g_bLibraryInitialized)
tsepez02759102016-12-01 08:29:25 -0800393 return;
394
Tom Sepez51da0932015-11-25 16:05:49 -0800395#ifdef PDF_ENABLE_XFA
Tom Sepez5628fd72017-04-27 14:58:53 -0700396 BC_Library_Destroy();
dsinclair8837c912016-11-01 11:22:37 -0700397 FXJSE_Finalize();
Tom Sepez40e9ff32015-11-30 12:39:54 -0800398#endif // PDF_ENABLE_XFA
dsinclair8837c912016-11-01 11:22:37 -0700399
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700400 CPDF_ModuleMgr::Destroy();
401 CFX_GEModule::Destroy();
Tom Sepez2c286192015-06-18 12:47:11 -0700402
thestig2d6dda12016-06-28 07:39:09 -0700403 IJS_Runtime::Destroy();
Dan Sinclair830897a2017-05-11 14:36:10 -0400404
405 g_bLibraryInitialized = false;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700406}
407
408#ifndef _WIN32
409int g_LastError;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700410void SetLastError(int err) {
411 g_LastError = err;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700412}
413
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700414int GetLastError() {
415 return g_LastError;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700416}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800417#endif // _WIN32
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700418
Tom Sepezf10ae632016-01-26 14:19:52 -0800419void ProcessParseError(CPDF_Parser::Error err) {
tsepezc3255f52016-03-25 14:52:27 -0700420 uint32_t err_code = FPDF_ERR_SUCCESS;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700421 // Translate FPDFAPI error code to FPDFVIEW error code
Tom Sepezf10ae632016-01-26 14:19:52 -0800422 switch (err) {
423 case CPDF_Parser::SUCCESS:
424 err_code = FPDF_ERR_SUCCESS;
425 break;
426 case CPDF_Parser::FILE_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700427 err_code = FPDF_ERR_FILE;
428 break;
Tom Sepezf10ae632016-01-26 14:19:52 -0800429 case CPDF_Parser::FORMAT_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700430 err_code = FPDF_ERR_FORMAT;
431 break;
Tom Sepezf10ae632016-01-26 14:19:52 -0800432 case CPDF_Parser::PASSWORD_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700433 err_code = FPDF_ERR_PASSWORD;
434 break;
Tom Sepezf10ae632016-01-26 14:19:52 -0800435 case CPDF_Parser::HANDLER_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700436 err_code = FPDF_ERR_SECURITY;
437 break;
438 }
439 SetLastError(err_code);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700440}
441
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700442DLLEXPORT void STDCALL FPDF_SetSandBoxPolicy(FPDF_DWORD policy,
443 FPDF_BOOL enable) {
444 return FSDK_SetSandBoxPolicy(policy, enable);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700445}
446
rbpotterdb764702017-01-12 10:31:43 -0800447#if defined(_WIN32)
448#if defined(PDFIUM_PRINT_TEXT_WITH_GDI)
thestigfdb35ff2016-07-18 13:45:44 -0700449DLLEXPORT void STDCALL
450FPDF_SetTypefaceAccessibleFunc(PDFiumEnsureTypefaceCharactersAccessible func) {
451 g_pdfium_typeface_accessible_func = func;
452}
453
454DLLEXPORT void STDCALL FPDF_SetPrintTextWithGDI(FPDF_BOOL use_gdi) {
455 g_pdfium_print_text_with_gdi = !!use_gdi;
456}
rbpotterdb764702017-01-12 10:31:43 -0800457#endif // PDFIUM_PRINT_TEXT_WITH_GDI
458
rbpotter38a01b92017-07-13 11:58:01 -0700459DLLEXPORT FPDF_BOOL STDCALL FPDF_SetPrintPostscriptLevel(int postscript_level) {
460 return postscript_level != 1 && FPDF_SetPrintMode(postscript_level);
461}
462
rbpottere8468c42017-07-11 10:04:29 -0700463DLLEXPORT FPDF_BOOL STDCALL FPDF_SetPrintMode(int mode) {
464 if (mode < FPDF_PRINTMODE_EMF || mode > FPDF_PRINTMODE_POSTSCRIPT3)
rbpotterdb764702017-01-12 10:31:43 -0800465 return FALSE;
rbpottere8468c42017-07-11 10:04:29 -0700466 g_pdfium_print_mode = mode;
rbpotterdb764702017-01-12 10:31:43 -0800467 return TRUE;
468}
469#endif // defined(_WIN32)
thestigfdb35ff2016-07-18 13:45:44 -0700470
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700471DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadDocument(FPDF_STRING file_path,
472 FPDF_BYTESTRING password) {
Tom Sepeze3166a82015-08-05 10:50:32 -0700473 // NOTE: the creation of the file needs to be by the embedder on the
474 // other side of this API.
tsepez833619b2016-12-07 09:21:17 -0800475 CFX_RetainPtr<IFX_SeekableReadStream> pFileAccess =
Dan Sinclair812e96c2017-03-13 16:43:37 -0400476 IFX_SeekableReadStream::CreateFromFilename((const char*)file_path);
tsepez345d4892016-11-30 15:10:55 -0800477 if (!pFileAccess)
Tom Sepeze3166a82015-08-05 10:50:32 -0700478 return nullptr;
Tom Sepeze3166a82015-08-05 10:50:32 -0700479
tsepez345d4892016-11-30 15:10:55 -0800480 auto pParser = pdfium::MakeUnique<CPDF_Parser>();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700481 pParser->SetPassword(password);
Bo Xud4e406e2014-08-13 11:03:19 -0700482
tsepez345d4892016-11-30 15:10:55 -0800483 auto pDocument = pdfium::MakeUnique<CPDF_Document>(std::move(pParser));
dsinclair156de022016-08-24 11:58:24 -0700484 CPDF_Parser::Error error =
485 pDocument->GetParser()->StartParse(pFileAccess, pDocument.get());
Tom Sepezf10ae632016-01-26 14:19:52 -0800486 if (error != CPDF_Parser::SUCCESS) {
Tom Sepezf10ae632016-01-26 14:19:52 -0800487 ProcessParseError(error);
thestig1cd352e2016-06-07 17:53:06 -0700488 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700489 }
Dan Sinclaircb377be2017-05-11 16:05:32 -0400490 CheckUnSupportError(pDocument.get(), error);
dsinclair8837c912016-11-01 11:22:37 -0700491 return FPDFDocumentFromCPDFDocument(pDocument.release());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700492}
Jun Fange118ce92015-02-17 06:50:08 -0800493
Tom Sepez40e9ff32015-11-30 12:39:54 -0800494#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700495DLLEXPORT FPDF_BOOL STDCALL FPDF_HasXFAField(FPDF_DOCUMENT document,
496 int* docType) {
497 if (!document)
tsepez4cf55152016-11-02 14:37:54 -0700498 return false;
JUN FANG827a1722015-03-05 13:39:21 -0800499
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700500 CPDF_Document* pdfDoc =
dsinclair521b7502016-11-02 13:02:28 -0700501 (static_cast<CPDFXFA_Context*>(document))->GetPDFDoc();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700502 if (!pdfDoc)
tsepez4cf55152016-11-02 14:37:54 -0700503 return false;
JUN FANG827a1722015-03-05 13:39:21 -0800504
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700505 CPDF_Dictionary* pRoot = pdfDoc->GetRoot();
506 if (!pRoot)
tsepez4cf55152016-11-02 14:37:54 -0700507 return false;
JUN FANG827a1722015-03-05 13:39:21 -0800508
dsinclair38fd8442016-09-15 10:15:32 -0700509 CPDF_Dictionary* pAcroForm = pRoot->GetDictFor("AcroForm");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700510 if (!pAcroForm)
tsepez4cf55152016-11-02 14:37:54 -0700511 return false;
JUN FANG827a1722015-03-05 13:39:21 -0800512
dsinclair38fd8442016-09-15 10:15:32 -0700513 CPDF_Object* pXFA = pAcroForm->GetObjectFor("XFA");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700514 if (!pXFA)
tsepez4cf55152016-11-02 14:37:54 -0700515 return false;
JUN FANG827a1722015-03-05 13:39:21 -0800516
dsinclair38fd8442016-09-15 10:15:32 -0700517 bool bDynamicXFA = pRoot->GetBooleanFor("NeedsRendering", false);
thestigded36342016-05-23 17:54:02 -0700518 *docType = bDynamicXFA ? DOCTYPE_DYNAMIC_XFA : DOCTYPE_STATIC_XFA;
tsepez4cf55152016-11-02 14:37:54 -0700519 return true;
Jun Fange118ce92015-02-17 06:50:08 -0800520}
521
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700522DLLEXPORT FPDF_BOOL STDCALL FPDF_LoadXFA(FPDF_DOCUMENT document) {
dsinclair521b7502016-11-02 13:02:28 -0700523 return document && (static_cast<CPDFXFA_Context*>(document))->LoadXFADoc();
Bo Xufdc00a72014-10-28 23:03:33 -0700524}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800525#endif // PDF_ENABLE_XFA
Bo Xufdc00a72014-10-28 23:03:33 -0700526
tsepezad2441e2016-10-24 10:19:11 -0700527class CMemFile final : public IFX_SeekableReadStream {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700528 public:
tsepez833619b2016-12-07 09:21:17 -0800529 static CFX_RetainPtr<CMemFile> Create(uint8_t* pBuf, FX_FILESIZE size) {
530 return CFX_RetainPtr<CMemFile>(new CMemFile(pBuf, size));
531 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700532
Lei Zhang3884dba2015-10-19 17:27:53 -0700533 FX_FILESIZE GetSize() override { return m_size; }
tsepezf39074c2016-10-26 15:33:58 -0700534 bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override {
tsepez833619b2016-12-07 09:21:17 -0800535 if (offset < 0)
tsepezf39074c2016-10-26 15:33:58 -0700536 return false;
tsepez833619b2016-12-07 09:21:17 -0800537
tsepez4e597c82016-11-07 15:16:01 -0800538 FX_SAFE_FILESIZE newPos = pdfium::base::checked_cast<FX_FILESIZE>(size);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700539 newPos += offset;
tsepez833619b2016-12-07 09:21:17 -0800540 if (!newPos.IsValid() || newPos.ValueOrDie() > m_size)
tsepezf39074c2016-10-26 15:33:58 -0700541 return false;
tsepez833619b2016-12-07 09:21:17 -0800542
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400543 memcpy(buffer, m_pBuf + offset, size);
tsepezf39074c2016-10-26 15:33:58 -0700544 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700545 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700546
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700547 private:
tsepez833619b2016-12-07 09:21:17 -0800548 CMemFile(uint8_t* pBuf, FX_FILESIZE size) : m_pBuf(pBuf), m_size(size) {}
Lei Zhang2b1a2d52015-08-14 22:16:22 -0700549
Lei Zhang3884dba2015-10-19 17:27:53 -0700550 uint8_t* const m_pBuf;
551 const FX_FILESIZE m_size;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700552};
Lei Zhang3884dba2015-10-19 17:27:53 -0700553
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700554DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadMemDocument(const void* data_buf,
555 int size,
556 FPDF_BYTESTRING password) {
tsepez833619b2016-12-07 09:21:17 -0800557 CFX_RetainPtr<CMemFile> pMemFile = CMemFile::Create((uint8_t*)data_buf, size);
558 auto pParser = pdfium::MakeUnique<CPDF_Parser>();
tsepez4540fba2016-08-16 11:12:21 -0700559 pParser->SetPassword(password);
560
tsepez833619b2016-12-07 09:21:17 -0800561 auto pDocument = pdfium::MakeUnique<CPDF_Document>(std::move(pParser));
tsepez4540fba2016-08-16 11:12:21 -0700562 CPDF_Parser::Error error =
dsinclaircedaa552016-08-24 11:12:19 -0700563 pDocument->GetParser()->StartParse(pMemFile, pDocument.get());
Tom Sepezf10ae632016-01-26 14:19:52 -0800564 if (error != CPDF_Parser::SUCCESS) {
Tom Sepezf10ae632016-01-26 14:19:52 -0800565 ProcessParseError(error);
thestig1cd352e2016-06-07 17:53:06 -0700566 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700567 }
dsinclaircedaa552016-08-24 11:12:19 -0700568 CheckUnSupportError(pDocument.get(), error);
569 return FPDFDocumentFromCPDFDocument(pDocument.release());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700570}
571
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700572DLLEXPORT FPDF_DOCUMENT STDCALL
573FPDF_LoadCustomDocument(FPDF_FILEACCESS* pFileAccess,
574 FPDF_BYTESTRING password) {
Tom Sepez40badde2017-05-01 13:21:39 -0700575 auto pFile = pdfium::MakeRetain<CPDF_CustomAccess>(pFileAccess);
tsepez833619b2016-12-07 09:21:17 -0800576 auto pParser = pdfium::MakeUnique<CPDF_Parser>();
tsepez4540fba2016-08-16 11:12:21 -0700577 pParser->SetPassword(password);
578
tsepez833619b2016-12-07 09:21:17 -0800579 auto pDocument = pdfium::MakeUnique<CPDF_Document>(std::move(pParser));
dsinclaircedaa552016-08-24 11:12:19 -0700580 CPDF_Parser::Error error =
581 pDocument->GetParser()->StartParse(pFile, pDocument.get());
Tom Sepezf10ae632016-01-26 14:19:52 -0800582 if (error != CPDF_Parser::SUCCESS) {
Tom Sepezf10ae632016-01-26 14:19:52 -0800583 ProcessParseError(error);
thestig1cd352e2016-06-07 17:53:06 -0700584 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700585 }
dsinclaircedaa552016-08-24 11:12:19 -0700586 CheckUnSupportError(pDocument.get(), error);
587 return FPDFDocumentFromCPDFDocument(pDocument.release());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700588}
589
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700590DLLEXPORT FPDF_BOOL STDCALL FPDF_GetFileVersion(FPDF_DOCUMENT doc,
591 int* fileVersion) {
Tom Sepez471a1032015-10-15 16:17:18 -0700592 if (!fileVersion)
tsepez4cf55152016-11-02 14:37:54 -0700593 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700594
Tom Sepez471a1032015-10-15 16:17:18 -0700595 *fileVersion = 0;
596 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(doc);
597 if (!pDoc)
tsepez4cf55152016-11-02 14:37:54 -0700598 return false;
Tom Sepez471a1032015-10-15 16:17:18 -0700599
600 CPDF_Parser* pParser = pDoc->GetParser();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700601 if (!pParser)
tsepez4cf55152016-11-02 14:37:54 -0700602 return false;
Tom Sepez471a1032015-10-15 16:17:18 -0700603
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700604 *fileVersion = pParser->GetFileVersion();
tsepez4cf55152016-11-02 14:37:54 -0700605 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700606}
607
tsepezc3255f52016-03-25 14:52:27 -0700608// jabdelmalek: changed return type from uint32_t to build on Linux (and match
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700609// header).
610DLLEXPORT unsigned long STDCALL FPDF_GetDocPermissions(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700611 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
thestig27ddf162016-05-23 15:06:59 -0700612 // https://bugs.chromium.org/p/pdfium/issues/detail?id=499
613 if (!pDoc) {
Tom Sepez51da0932015-11-25 16:05:49 -0800614#ifndef PDF_ENABLE_XFA
615 return 0;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800616#else // PDF_ENABLE_XFA
thestig27ddf162016-05-23 15:06:59 -0700617 return 0xFFFFFFFF;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800618#endif // PDF_ENABLE_XFA
thestig27ddf162016-05-23 15:06:59 -0700619 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700620
thestig27ddf162016-05-23 15:06:59 -0700621 return pDoc->GetUserPermissions();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700622}
623
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700624DLLEXPORT int STDCALL FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700625 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
thestigb8db5112016-04-06 12:12:52 -0700626 if (!pDoc || !pDoc->GetParser())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700627 return -1;
Bo Xuc5cab022014-09-19 19:16:31 -0700628
Tom Sepez471a1032015-10-15 16:17:18 -0700629 CPDF_Dictionary* pDict = pDoc->GetParser()->GetEncryptDict();
dsinclair38fd8442016-09-15 10:15:32 -0700630 return pDict ? pDict->GetIntegerFor("R") : -1;
Bo Xuc5cab022014-09-19 19:16:31 -0700631}
632
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700633DLLEXPORT int STDCALL FPDF_GetPageCount(FPDF_DOCUMENT document) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800634 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
Tom Sepez471a1032015-10-15 16:17:18 -0700635 return pDoc ? pDoc->GetPageCount() : 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700636}
637
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700638DLLEXPORT FPDF_PAGE STDCALL FPDF_LoadPage(FPDF_DOCUMENT document,
639 int page_index) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800640 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
641 if (!pDoc)
Tom Sepez471a1032015-10-15 16:17:18 -0700642 return nullptr;
Tom Sepez1b246282015-11-25 15:15:31 -0800643
Tom Sepezbbe0e4d2015-10-20 15:41:40 -0700644 if (page_index < 0 || page_index >= pDoc->GetPageCount())
Tom Sepez471a1032015-10-15 16:17:18 -0700645 return nullptr;
646
Tom Sepez40e9ff32015-11-30 12:39:54 -0800647#ifdef PDF_ENABLE_XFA
Tom Sepez9792f162017-05-16 14:11:30 -0700648 return pDoc->GetXFAPage(page_index).Leak();
Tom Sepez40e9ff32015-11-30 12:39:54 -0800649#else // PDF_ENABLE_XFA
Tom Sepez51da0932015-11-25 16:05:49 -0800650 CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
Lei Zhang412e9082015-12-14 18:34:00 -0800651 if (!pDict)
thestig5cc24652016-04-26 11:46:02 -0700652 return nullptr;
653
654 CPDF_Page* pPage = new CPDF_Page(pDoc, pDict, true);
655 pPage->ParseContent();
Tom Sepez51da0932015-11-25 16:05:49 -0800656 return pPage;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800657#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700658}
659
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700660DLLEXPORT double STDCALL FPDF_GetPageWidth(FPDF_PAGE page) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800661 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezbf59a072015-10-21 14:07:23 -0700662 return pPage ? pPage->GetPageWidth() : 0.0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700663}
664
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700665DLLEXPORT double STDCALL FPDF_GetPageHeight(FPDF_PAGE page) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800666 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezbf59a072015-10-21 14:07:23 -0700667 return pPage ? pPage->GetPageHeight() : 0.0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700668}
669
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700670#if defined(_WIN32)
rbpottercec01802017-04-17 09:10:21 -0700671namespace {
672
673const double kEpsilonSize = 0.01f;
674
675void GetScaling(CPDF_Page* pPage,
676 int size_x,
677 int size_y,
678 int rotate,
679 double* scale_x,
680 double* scale_y) {
681 ASSERT(pPage);
682 ASSERT(scale_x);
683 ASSERT(scale_y);
684 double page_width = pPage->GetPageWidth();
685 double page_height = pPage->GetPageHeight();
686 if (page_width < kEpsilonSize || page_height < kEpsilonSize)
687 return;
688
689 if (rotate % 2 == 0) {
690 *scale_x = size_x / page_width;
691 *scale_y = size_y / page_height;
692 } else {
693 *scale_x = size_y / page_width;
694 *scale_y = size_x / page_height;
695 }
696}
697
698FX_RECT GetMaskDimensionsAndOffsets(CPDF_Page* pPage,
699 int start_x,
700 int start_y,
701 int size_x,
702 int size_y,
703 int rotate,
704 const CFX_FloatRect& mask_box) {
705 double scale_x = 0.0f;
706 double scale_y = 0.0f;
707 GetScaling(pPage, size_x, size_y, rotate, &scale_x, &scale_y);
708 if (scale_x < kEpsilonSize || scale_y < kEpsilonSize)
709 return FX_RECT();
710
711 // Compute sizes in page points. Round down to catch the entire bitmap.
712 int start_x_bm = static_cast<int>(mask_box.left * scale_x);
713 int start_y_bm = static_cast<int>(mask_box.bottom * scale_y);
714 int size_x_bm = static_cast<int>(mask_box.right * scale_x + 1.0f) -
715 static_cast<int>(mask_box.left * scale_x);
716 int size_y_bm = static_cast<int>(mask_box.top * scale_y + 1.0f) -
717 static_cast<int>(mask_box.bottom * scale_y);
718
719 // Get page rotation
rbpotterce8e51e2017-04-28 12:42:47 -0700720 int page_rotation = pPage->GetPageRotation();
rbpottercec01802017-04-17 09:10:21 -0700721
722 // Compute offsets
723 int offset_x = 0;
724 int offset_y = 0;
725 switch ((rotate + page_rotation) % 4) {
726 case 0:
727 offset_x = start_x_bm + start_x;
728 offset_y = start_y + size_y - size_y_bm - start_y_bm;
729 break;
730 case 1:
731 offset_x = start_y_bm + start_x;
732 offset_y = start_x_bm + start_y;
733 break;
734 case 2:
735 offset_x = start_x + size_x - size_x_bm - start_x_bm;
736 offset_y = start_y_bm + start_y;
737 break;
738 case 3:
739 offset_x = start_x + size_x - size_x_bm - start_y_bm;
740 offset_y = start_y + size_y - size_y_bm - start_x_bm;
741 break;
742 }
743 return FX_RECT(offset_x, offset_y, offset_x + size_x_bm,
744 offset_y + size_y_bm);
745}
746
747// Get a bitmap of just the mask section defined by |mask_box| from a full page
748// bitmap |pBitmap|.
749CFX_RetainPtr<CFX_DIBitmap> GetMaskBitmap(CPDF_Page* pPage,
750 int start_x,
751 int start_y,
752 int size_x,
753 int size_y,
754 int rotate,
755 CFX_RetainPtr<CFX_DIBitmap>& pSrc,
756 const CFX_FloatRect& mask_box,
757 FX_RECT* bitmap_area) {
758 ASSERT(bitmap_area);
759 *bitmap_area = GetMaskDimensionsAndOffsets(pPage, start_x, start_y, size_x,
760 size_y, rotate, mask_box);
761 if (bitmap_area->IsEmpty())
762 return nullptr;
763
764 // Create a new bitmap to transfer part of the page bitmap to.
765 CFX_RetainPtr<CFX_DIBitmap> pDst = pdfium::MakeRetain<CFX_DIBitmap>();
766 pDst->Create(bitmap_area->Width(), bitmap_area->Height(), FXDIB_Argb);
767 pDst->Clear(0x00ffffff);
768 pDst->TransferBitmap(0, 0, bitmap_area->Width(), bitmap_area->Height(), pSrc,
769 bitmap_area->left, bitmap_area->top);
770 return pDst;
771}
772
773void RenderBitmap(CFX_RenderDevice* device,
774 const CFX_RetainPtr<CFX_DIBitmap>& pSrc,
775 const FX_RECT& mask_area) {
776 int size_x_bm = mask_area.Width();
777 int size_y_bm = mask_area.Height();
778 if (size_x_bm == 0 || size_y_bm == 0)
779 return;
780
781 // Create a new bitmap from the old one
782 CFX_RetainPtr<CFX_DIBitmap> pDst = pdfium::MakeRetain<CFX_DIBitmap>();
783 pDst->Create(size_x_bm, size_y_bm, FXDIB_Rgb32);
784 pDst->Clear(0xffffffff);
785 pDst->CompositeBitmap(0, 0, size_x_bm, size_y_bm, pSrc, 0, 0,
786 FXDIB_BLEND_NORMAL, nullptr, false);
787
788 if (device->GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
789 device->StretchDIBitsWithFlagsAndBlend(pDst, mask_area.left, mask_area.top,
790 size_x_bm, size_y_bm, 0,
791 FXDIB_BLEND_NORMAL);
792 } else {
793 device->SetDIBits(pDst, mask_area.left, mask_area.top);
794 }
795}
796
797} // namespace
798
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700799DLLEXPORT void STDCALL FPDF_RenderPage(HDC dc,
800 FPDF_PAGE page,
801 int start_x,
802 int start_y,
803 int size_x,
804 int size_y,
805 int rotate,
806 int flags) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700807 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700808 if (!pPage)
809 return;
rbpottercec01802017-04-17 09:10:21 -0700810 pPage->SetRenderContext(pdfium::MakeUnique<CPDF_PageRenderContext>());
811 CPDF_PageRenderContext* pContext = pPage->GetRenderContext();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700812
Tom Sepezf0799fe2017-03-28 09:31:32 -0700813 CFX_RetainPtr<CFX_DIBitmap> pBitmap;
rbpottercec01802017-04-17 09:10:21 -0700814 // Don't render the full page to bitmap for a mask unless there are a lot
815 // of masks. Full page bitmaps result in large spool sizes, so they should
816 // only be used when necessary. For large numbers of masks, rendering each
817 // individually is inefficient and unlikely to significantly improve spool
818 // size.
thestig84144e82016-09-27 15:06:01 -0700819 const bool bNewBitmap =
rbpottercec01802017-04-17 09:10:21 -0700820 pPage->BackgroundAlphaNeeded() ||
821 (pPage->HasImageMask() && pPage->GetMaskBoundingBoxes().size() > 100);
822 const bool bHasMask = pPage->HasImageMask() && !bNewBitmap;
823 if (bNewBitmap || bHasMask) {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700824 pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700825 pBitmap->Create(size_x, size_y, FXDIB_Argb);
826 pBitmap->Clear(0x00ffffff);
Dan Sinclaira5085d42017-05-11 16:26:50 -0400827 CFX_DefaultRenderDevice* pDevice = new CFX_DefaultRenderDevice;
tsepez36eb4bd2016-10-03 15:24:27 -0700828 pContext->m_pDevice = pdfium::WrapUnique(pDevice);
Tom Sepezf0799fe2017-03-28 09:31:32 -0700829 pDevice->Attach(pBitmap, false, nullptr, false);
rbpottercec01802017-04-17 09:10:21 -0700830 if (bHasMask) {
831 pContext->m_pOptions = pdfium::MakeUnique<CPDF_RenderOptions>();
832 pContext->m_pOptions->m_Flags |= RENDER_BREAKFORMASKS;
833 }
Jun Fang1aeeceb2015-12-29 10:27:44 +0800834 } else {
Dan Sinclaira5085d42017-05-11 16:26:50 -0400835 pContext->m_pDevice = pdfium::MakeUnique<CFX_WindowsRenderDevice>(dc);
Jun Fang1aeeceb2015-12-29 10:27:44 +0800836 }
rbpottercec01802017-04-17 09:10:21 -0700837
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700838 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
tsepez4cf55152016-11-02 14:37:54 -0700839 rotate, flags, true, nullptr);
Bo Xud4e406e2014-08-13 11:03:19 -0700840
rbpottercec01802017-04-17 09:10:21 -0700841 if (bHasMask) {
842 // Finish rendering the page to bitmap and copy the correct segments
843 // of the page to individual image mask bitmaps.
844 const std::vector<CFX_FloatRect>& mask_boxes =
845 pPage->GetMaskBoundingBoxes();
846 std::vector<FX_RECT> bitmap_areas(mask_boxes.size());
847 std::vector<CFX_RetainPtr<CFX_DIBitmap>> bitmaps(mask_boxes.size());
848 for (size_t i = 0; i < mask_boxes.size(); i++) {
849 bitmaps[i] =
850 GetMaskBitmap(pPage, start_x, start_y, size_x, size_y, rotate,
851 pBitmap, mask_boxes[i], &bitmap_areas[i]);
852 pContext->m_pRenderer->Continue(nullptr);
853 }
854
855 // Reset rendering context
856 pPage->SetRenderContext(nullptr);
857
858 // Begin rendering to the printer. Add flag to indicate the renderer should
859 // pause after each image mask.
860 pPage->SetRenderContext(pdfium::MakeUnique<CPDF_PageRenderContext>());
861 pContext = pPage->GetRenderContext();
Dan Sinclaira5085d42017-05-11 16:26:50 -0400862 pContext->m_pDevice = pdfium::MakeUnique<CFX_WindowsRenderDevice>(dc);
rbpottercec01802017-04-17 09:10:21 -0700863 pContext->m_pOptions = pdfium::MakeUnique<CPDF_RenderOptions>();
864 pContext->m_pOptions->m_Flags |= RENDER_BREAKFORMASKS;
865 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
866 rotate, flags, true, nullptr);
867
868 // Render masks
869 for (size_t i = 0; i < mask_boxes.size(); i++) {
870 // Render the bitmap for the mask and free the bitmap.
871 if (bitmaps[i]) { // will be null if mask has zero area
872 RenderBitmap(pContext->m_pDevice.get(), bitmaps[i], bitmap_areas[i]);
873 }
874 // Render the next portion of page.
875 pContext->m_pRenderer->Continue(nullptr);
876 }
877 } else if (bNewBitmap) {
Dan Sinclaira5085d42017-05-11 16:26:50 -0400878 CFX_WindowsRenderDevice WinDC(dc);
thestig84144e82016-09-27 15:06:01 -0700879 if (WinDC.GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700880 auto pDst = pdfium::MakeRetain<CFX_DIBitmap>();
thestig84144e82016-09-27 15:06:01 -0700881 int pitch = pBitmap->GetPitch();
882 pDst->Create(size_x, size_y, FXDIB_Rgb32);
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400883 memset(pDst->GetBuffer(), -1, pitch * size_y);
Tom Sepezf0799fe2017-03-28 09:31:32 -0700884 pDst->CompositeBitmap(0, 0, size_x, size_y, pBitmap, 0, 0,
Nicolas Pena6a5c20c2017-04-07 14:12:31 -0400885 FXDIB_BLEND_NORMAL, nullptr, false);
Tom Sepezf0799fe2017-03-28 09:31:32 -0700886 WinDC.StretchDIBits(pDst, 0, 0, size_x, size_y);
thestig84144e82016-09-27 15:06:01 -0700887 } else {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700888 WinDC.SetDIBits(pBitmap, 0, 0);
Lei Zhang6d8b1c22015-06-19 17:26:17 -0700889 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700890 }
rbpottercec01802017-04-17 09:10:21 -0700891
tsepeze5cb0b12016-10-26 15:06:11 -0700892 pPage->SetRenderContext(nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700893}
Lei Zhangae85f872016-02-19 14:57:07 -0800894#endif // defined(_WIN32)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700895
896DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap,
897 FPDF_PAGE page,
898 int start_x,
899 int start_y,
900 int size_x,
901 int size_y,
902 int rotate,
903 int flags) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700904 if (!bitmap)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700905 return;
tsepez1e2c5572016-05-25 14:58:09 -0700906
Tom Sepezdb0be962015-10-16 14:00:21 -0700907 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700908 if (!pPage)
909 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700910
weili9f515bc2016-07-24 08:08:24 -0700911 CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
tsepez36eb4bd2016-10-03 15:24:27 -0700912 pPage->SetRenderContext(pdfium::WrapUnique(pContext));
Tom Sepezf0799fe2017-03-28 09:31:32 -0700913
Dan Sinclaira5085d42017-05-11 16:26:50 -0400914 CFX_DefaultRenderDevice* pDevice = new CFX_DefaultRenderDevice;
weili9f515bc2016-07-24 08:08:24 -0700915 pContext->m_pDevice.reset(pDevice);
dsinclair31b08d42017-03-28 15:47:47 +0000916
Tom Sepezf0799fe2017-03-28 09:31:32 -0700917 CFX_RetainPtr<CFX_DIBitmap> pBitmap(CFXBitmapFromFPDFBitmap(bitmap));
918 pDevice->Attach(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER), nullptr, false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700919 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
tsepez4cf55152016-11-02 14:37:54 -0700920 rotate, flags, true, nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700921
caryclark687fbde2016-11-22 12:44:25 -0800922#ifdef _SKIA_SUPPORT_PATHS_
caryclark8f875502016-12-06 13:49:34 -0800923 pDevice->Flush();
caryclark687fbde2016-11-22 12:44:25 -0800924 pBitmap->UnPreMultiply();
925#endif
tsepeze5cb0b12016-10-26 15:06:11 -0700926 pPage->SetRenderContext(nullptr);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700927}
928
thestiga78ba602016-11-23 15:25:48 -0800929DLLEXPORT void STDCALL FPDF_RenderPageBitmapWithMatrix(FPDF_BITMAP bitmap,
930 FPDF_PAGE page,
931 const FS_MATRIX* matrix,
932 const FS_RECTF* clipping,
933 int flags) {
934 if (!bitmap)
935 return;
936
937 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
938 if (!pPage)
939 return;
940
941 CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
942 pPage->SetRenderContext(pdfium::WrapUnique(pContext));
Tom Sepezf0799fe2017-03-28 09:31:32 -0700943
Dan Sinclaira5085d42017-05-11 16:26:50 -0400944 CFX_DefaultRenderDevice* pDevice = new CFX_DefaultRenderDevice;
thestiga78ba602016-11-23 15:25:48 -0800945 pContext->m_pDevice.reset(pDevice);
Tom Sepezf0799fe2017-03-28 09:31:32 -0700946
947 CFX_RetainPtr<CFX_DIBitmap> pBitmap(CFXBitmapFromFPDFBitmap(bitmap));
thestiga78ba602016-11-23 15:25:48 -0800948 pDevice->Attach(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER), nullptr, false);
949
950 CFX_Matrix transform_matrix = pPage->GetPageMatrix();
951 if (matrix) {
Dan Sinclairbba2a7c2017-02-07 16:36:39 -0500952 transform_matrix.Concat(CFX_Matrix(matrix->a, matrix->b, matrix->c,
953 matrix->d, matrix->e, matrix->f));
thestiga78ba602016-11-23 15:25:48 -0800954 }
955
956 CFX_FloatRect clipping_rect;
957 if (clipping) {
958 clipping_rect.left = clipping->left;
959 clipping_rect.bottom = clipping->bottom;
960 clipping_rect.right = clipping->right;
961 clipping_rect.top = clipping->top;
962 }
963 RenderPageImpl(pContext, pPage, transform_matrix, clipping_rect.ToFxRect(),
964 flags, true, nullptr);
965
966 pPage->SetRenderContext(nullptr);
967}
968
Cary Clark399be5b2016-03-14 16:51:29 -0400969#ifdef _SKIA_SUPPORT_
970DLLEXPORT FPDF_RECORDER STDCALL FPDF_RenderPageSkp(FPDF_PAGE page,
971 int size_x,
972 int size_y) {
973 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
974 if (!pPage)
975 return nullptr;
tsepez1e2c5572016-05-25 14:58:09 -0700976
weili9f515bc2016-07-24 08:08:24 -0700977 CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
tsepez36eb4bd2016-10-03 15:24:27 -0700978 pPage->SetRenderContext(pdfium::WrapUnique(pContext));
Dan Sinclaira5085d42017-05-11 16:26:50 -0400979 CFX_DefaultRenderDevice* skDevice = new CFX_DefaultRenderDevice;
Cary Clark399be5b2016-03-14 16:51:29 -0400980 FPDF_RECORDER recorder = skDevice->CreateRecorder(size_x, size_y);
weili9f515bc2016-07-24 08:08:24 -0700981 pContext->m_pDevice.reset(skDevice);
tsepez4cf55152016-11-02 14:37:54 -0700982 FPDF_RenderPage_Retail(pContext, page, 0, 0, size_x, size_y, 0, 0, true,
tsepez1e2c5572016-05-25 14:58:09 -0700983 nullptr);
tsepeze5cb0b12016-10-26 15:06:11 -0700984 pPage->SetRenderContext(nullptr);
Cary Clark399be5b2016-03-14 16:51:29 -0400985 return recorder;
986}
987#endif
988
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700989DLLEXPORT void STDCALL FPDF_ClosePage(FPDF_PAGE page) {
tsepez1e2c5572016-05-25 14:58:09 -0700990 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700991 if (!page)
992 return;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800993#ifdef PDF_ENABLE_XFA
Tom Sepez9792f162017-05-16 14:11:30 -0700994 // Take it back across the API and throw it away.
995 CFX_RetainPtr<CPDFXFA_Page>().Unleak(pPage);
Tom Sepez40e9ff32015-11-30 12:39:54 -0800996#else // PDF_ENABLE_XFA
Tom Sepez51da0932015-11-25 16:05:49 -0800997 CPDFSDK_PageView* pPageView =
tsepez1e2c5572016-05-25 14:58:09 -0700998 static_cast<CPDFSDK_PageView*>(pPage->GetView());
dsinclair1df1efa2016-09-07 09:55:37 -0700999 if (pPageView) {
dsinclairbcf46232016-10-03 13:02:27 -07001000 // We're already destroying the pageview, so bail early.
1001 if (pPageView->IsBeingDestroyed())
1002 return;
1003
dsinclair1df1efa2016-09-07 09:55:37 -07001004 if (pPageView->IsLocked()) {
1005 pPageView->TakePageOwnership();
1006 return;
1007 }
1008
1009 bool owned = pPageView->OwnsPage();
1010 // This will delete the |pPageView| object. We must cleanup the PageView
1011 // first because it will attempt to reset the View on the |pPage| during
1012 // destruction.
dsinclair7cbe68e2016-10-12 11:56:23 -07001013 pPageView->GetFormFillEnv()->RemovePageView(pPage);
dsinclair1df1efa2016-09-07 09:55:37 -07001014 // If the page was owned then the pageview will have deleted the page.
1015 if (owned)
1016 return;
Tom Sepez51da0932015-11-25 16:05:49 -08001017 }
tsepez1e2c5572016-05-25 14:58:09 -07001018 delete pPage;
Tom Sepez40e9ff32015-11-30 12:39:54 -08001019#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001020}
1021
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001022DLLEXPORT void STDCALL FPDF_CloseDocument(FPDF_DOCUMENT document) {
Jun Fangfc751362015-12-16 21:23:39 -08001023 delete UnderlyingFromFPDFDocument(document);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001024}
1025
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001026DLLEXPORT unsigned long STDCALL FPDF_GetLastError() {
1027 return GetLastError();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001028}
1029
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001030DLLEXPORT void STDCALL FPDF_DeviceToPage(FPDF_PAGE page,
1031 int start_x,
1032 int start_y,
1033 int size_x,
1034 int size_y,
1035 int rotate,
1036 int device_x,
1037 int device_y,
1038 double* page_x,
1039 double* page_y) {
Lei Zhang412e9082015-12-14 18:34:00 -08001040 if (!page || !page_x || !page_y)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001041 return;
Tom Sepez50d12ad2015-11-24 09:50:51 -08001042 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepez40e9ff32015-11-30 12:39:54 -08001043#ifdef PDF_ENABLE_XFA
1044 pPage->DeviceToPage(start_x, start_y, size_x, size_y, rotate, device_x,
1045 device_y, page_x, page_y);
1046#else // PDF_ENABLE_XFA
Dan Sinclair1b08df12017-02-09 09:17:20 -05001047 CFX_Matrix page2device =
1048 pPage->GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate);
Dan Sinclair1b08df12017-02-09 09:17:20 -05001049
Nicolas Penab21f1742017-06-29 12:02:06 -04001050 CFX_PointF pos = page2device.GetInverse().Transform(
Dan Sinclair05df0752017-03-14 14:43:42 -04001051 CFX_PointF(static_cast<float>(device_x), static_cast<float>(device_y)));
Dan Sinclairafb44562017-02-09 13:07:43 -05001052
Dan Sinclaira0061af2017-02-23 09:25:17 -05001053 *page_x = pos.x;
1054 *page_y = pos.y;
Tom Sepez40e9ff32015-11-30 12:39:54 -08001055#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001056}
1057
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001058DLLEXPORT void STDCALL FPDF_PageToDevice(FPDF_PAGE page,
1059 int start_x,
1060 int start_y,
1061 int size_x,
1062 int size_y,
1063 int rotate,
1064 double page_x,
1065 double page_y,
1066 int* device_x,
1067 int* device_y) {
Tom Sepezdb0be962015-10-16 14:00:21 -07001068 if (!device_x || !device_y)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001069 return;
Tom Sepez50d12ad2015-11-24 09:50:51 -08001070 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezdb0be962015-10-16 14:00:21 -07001071 if (!pPage)
1072 return;
Tom Sepez40e9ff32015-11-30 12:39:54 -08001073#ifdef PDF_ENABLE_XFA
1074 pPage->PageToDevice(start_x, start_y, size_x, size_y, rotate, page_x, page_y,
1075 device_x, device_y);
1076#else // PDF_ENABLE_XFA
Dan Sinclair1b08df12017-02-09 09:17:20 -05001077 CFX_Matrix page2device =
1078 pPage->GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate);
Dan Sinclaira0061af2017-02-23 09:25:17 -05001079 CFX_PointF pos = page2device.Transform(
Dan Sinclair05df0752017-03-14 14:43:42 -04001080 CFX_PointF(static_cast<float>(page_x), static_cast<float>(page_y)));
Dan Sinclairafb44562017-02-09 13:07:43 -05001081
Dan Sinclaira0061af2017-02-23 09:25:17 -05001082 *device_x = FXSYS_round(pos.x);
1083 *device_y = FXSYS_round(pos.y);
Tom Sepez40e9ff32015-11-30 12:39:54 -08001084#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001085}
1086
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001087DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_Create(int width,
1088 int height,
1089 int alpha) {
Tom Sepezf0799fe2017-03-28 09:31:32 -07001090 auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
tsepez37b12ad2016-12-14 19:50:23 -08001091 if (!pBitmap->Create(width, height, alpha ? FXDIB_Argb : FXDIB_Rgb32))
thestig1cd352e2016-06-07 17:53:06 -07001092 return nullptr;
tsepez37b12ad2016-12-14 19:50:23 -08001093
Tom Sepezf0799fe2017-03-28 09:31:32 -07001094 return pBitmap.Leak();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001095}
1096
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001097DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_CreateEx(int width,
1098 int height,
1099 int format,
1100 void* first_scan,
1101 int stride) {
1102 FXDIB_Format fx_format;
1103 switch (format) {
1104 case FPDFBitmap_Gray:
1105 fx_format = FXDIB_8bppRgb;
1106 break;
1107 case FPDFBitmap_BGR:
1108 fx_format = FXDIB_Rgb;
1109 break;
1110 case FPDFBitmap_BGRx:
1111 fx_format = FXDIB_Rgb32;
1112 break;
1113 case FPDFBitmap_BGRA:
1114 fx_format = FXDIB_Argb;
1115 break;
1116 default:
thestig1cd352e2016-06-07 17:53:06 -07001117 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001118 }
Tom Sepezf0799fe2017-03-28 09:31:32 -07001119 auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001120 pBitmap->Create(width, height, fx_format, (uint8_t*)first_scan, stride);
Tom Sepezf0799fe2017-03-28 09:31:32 -07001121 return pBitmap.Leak();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001122}
1123
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001124DLLEXPORT void STDCALL FPDFBitmap_FillRect(FPDF_BITMAP bitmap,
1125 int left,
1126 int top,
1127 int width,
1128 int height,
1129 FPDF_DWORD color) {
Lei Zhang412e9082015-12-14 18:34:00 -08001130 if (!bitmap)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001131 return;
thestigbefa4502016-05-26 20:15:19 -07001132
Dan Sinclaira5085d42017-05-11 16:26:50 -04001133 CFX_DefaultRenderDevice device;
Tom Sepezf0799fe2017-03-28 09:31:32 -07001134 CFX_RetainPtr<CFX_DIBitmap> pBitmap(CFXBitmapFromFPDFBitmap(bitmap));
thestigbefa4502016-05-26 20:15:19 -07001135 device.Attach(pBitmap, false, nullptr, false);
1136 if (!pBitmap->HasAlpha())
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001137 color |= 0xFF000000;
1138 FX_RECT rect(left, top, left + width, top + height);
1139 device.FillRect(&rect, color);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001140}
1141
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001142DLLEXPORT void* STDCALL FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap) {
thestigbefa4502016-05-26 20:15:19 -07001143 return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetBuffer() : nullptr;
Bo Xu9114e832014-07-14 13:22:47 -07001144}
1145
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001146DLLEXPORT int STDCALL FPDFBitmap_GetWidth(FPDF_BITMAP bitmap) {
thestigbefa4502016-05-26 20:15:19 -07001147 return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetWidth() : 0;
Bo Xu9114e832014-07-14 13:22:47 -07001148}
1149
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001150DLLEXPORT int STDCALL FPDFBitmap_GetHeight(FPDF_BITMAP bitmap) {
thestigbefa4502016-05-26 20:15:19 -07001151 return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetHeight() : 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001152}
1153
1154DLLEXPORT int STDCALL FPDFBitmap_GetStride(FPDF_BITMAP bitmap) {
thestigbefa4502016-05-26 20:15:19 -07001155 return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetPitch() : 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001156}
1157
1158DLLEXPORT void STDCALL FPDFBitmap_Destroy(FPDF_BITMAP bitmap) {
Tom Sepezf0799fe2017-03-28 09:31:32 -07001159 CFX_RetainPtr<CFX_DIBitmap> destroyer;
1160 destroyer.Unleak(CFXBitmapFromFPDFBitmap(bitmap));
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001161}
1162
weili9f515bc2016-07-24 08:08:24 -07001163void FPDF_RenderPage_Retail(CPDF_PageRenderContext* pContext,
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001164 FPDF_PAGE page,
1165 int start_x,
1166 int start_y,
1167 int size_x,
1168 int size_y,
1169 int rotate,
1170 int flags,
tsepez4cf55152016-11-02 14:37:54 -07001171 bool bNeedToRestore,
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001172 IFSDK_PAUSE_Adapter* pause) {
Tom Sepezdb0be962015-10-16 14:00:21 -07001173 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
1174 if (!pPage)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001175 return;
1176
Dan Sinclair1b08df12017-02-09 09:17:20 -05001177 RenderPageImpl(pContext, pPage, pPage->GetDisplayMatrix(
1178 start_x, start_y, size_x, size_y, rotate),
1179 FX_RECT(start_x, start_y, start_x + size_x, start_y + size_y),
1180 flags, bNeedToRestore, pause);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001181}
1182
1183DLLEXPORT int STDCALL FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document,
1184 int page_index,
1185 double* width,
1186 double* height) {
Tom Sepez540c4362015-11-24 13:33:57 -08001187 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
1188 if (!pDoc)
tsepez4cf55152016-11-02 14:37:54 -07001189 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001190
Tom Sepez40e9ff32015-11-30 12:39:54 -08001191#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001192 int count = pDoc->GetPageCount();
1193 if (page_index < 0 || page_index >= count)
tsepez4cf55152016-11-02 14:37:54 -07001194 return false;
Tom Sepez9792f162017-05-16 14:11:30 -07001195 CFX_RetainPtr<CPDFXFA_Page> pPage = pDoc->GetXFAPage(page_index);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001196 if (!pPage)
tsepez4cf55152016-11-02 14:37:54 -07001197 return false;
Tom Sepez40e9ff32015-11-30 12:39:54 -08001198 *width = pPage->GetPageWidth();
1199 *height = pPage->GetPageHeight();
1200#else // PDF_ENABLE_XFA
1201 CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
1202 if (!pDict)
tsepez4cf55152016-11-02 14:37:54 -07001203 return false;
thestig5cc24652016-04-26 11:46:02 -07001204
1205 CPDF_Page page(pDoc, pDict, true);
Tom Sepez51da0932015-11-25 16:05:49 -08001206 *width = page.GetPageWidth();
1207 *height = page.GetPageHeight();
Tom Sepez40e9ff32015-11-30 12:39:54 -08001208#endif // PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001209
tsepez4cf55152016-11-02 14:37:54 -07001210 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001211}
1212
1213DLLEXPORT FPDF_BOOL STDCALL
1214FPDF_VIEWERREF_GetPrintScaling(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001215 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001216 if (!pDoc)
tsepez4cf55152016-11-02 14:37:54 -07001217 return true;
Tom Sepez471a1032015-10-15 16:17:18 -07001218 CPDF_ViewerPreferences viewRef(pDoc);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001219 return viewRef.PrintScaling();
1220}
1221
1222DLLEXPORT int STDCALL FPDF_VIEWERREF_GetNumCopies(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001223 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001224 if (!pDoc)
1225 return 1;
1226 CPDF_ViewerPreferences viewRef(pDoc);
1227 return viewRef.NumCopies();
1228}
1229
1230DLLEXPORT FPDF_PAGERANGE STDCALL
1231FPDF_VIEWERREF_GetPrintPageRange(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001232 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001233 if (!pDoc)
thestig1cd352e2016-06-07 17:53:06 -07001234 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001235 CPDF_ViewerPreferences viewRef(pDoc);
1236 return viewRef.PrintPageRange();
1237}
1238
1239DLLEXPORT FPDF_DUPLEXTYPE STDCALL
1240FPDF_VIEWERREF_GetDuplex(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001241 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001242 if (!pDoc)
Bo Xu9114e832014-07-14 13:22:47 -07001243 return DuplexUndefined;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001244 CPDF_ViewerPreferences viewRef(pDoc);
1245 CFX_ByteString duplex = viewRef.Duplex();
Lei Zhangd983b092015-12-14 16:58:33 -08001246 if ("Simplex" == duplex)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001247 return Simplex;
Lei Zhangd983b092015-12-14 16:58:33 -08001248 if ("DuplexFlipShortEdge" == duplex)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001249 return DuplexFlipShortEdge;
Lei Zhangd983b092015-12-14 16:58:33 -08001250 if ("DuplexFlipLongEdge" == duplex)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001251 return DuplexFlipLongEdge;
1252 return DuplexUndefined;
Bo Xu9114e832014-07-14 13:22:47 -07001253}
1254
thestig04bebfe2016-11-04 16:07:25 -07001255DLLEXPORT unsigned long STDCALL FPDF_VIEWERREF_GetName(FPDF_DOCUMENT document,
1256 FPDF_BYTESTRING key,
1257 char* buffer,
1258 unsigned long length) {
1259 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1260 if (!pDoc)
1261 return 0;
1262
1263 CPDF_ViewerPreferences viewRef(pDoc);
1264 CFX_ByteString bsVal;
1265 if (!viewRef.GenericName(key, &bsVal))
1266 return 0;
1267
1268 unsigned long dwStringLen = bsVal.GetLength() + 1;
1269 if (buffer && length >= dwStringLen)
1270 memcpy(buffer, bsVal.c_str(), dwStringLen);
1271 return dwStringLen;
1272}
1273
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001274DLLEXPORT FPDF_DWORD STDCALL FPDF_CountNamedDests(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001275 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1276 if (!pDoc)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001277 return 0;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001278
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001279 CPDF_Dictionary* pRoot = pDoc->GetRoot();
1280 if (!pRoot)
1281 return 0;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001282
Lei Zhangd983b092015-12-14 16:58:33 -08001283 CPDF_NameTree nameTree(pDoc, "Dests");
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001284 pdfium::base::CheckedNumeric<FPDF_DWORD> count = nameTree.GetCount();
dsinclair38fd8442016-09-15 10:15:32 -07001285 CPDF_Dictionary* pDest = pRoot->GetDictFor("Dests");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001286 if (pDest)
1287 count += pDest->GetCount();
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001288
1289 if (!count.IsValid())
1290 return 0;
1291
1292 return count.ValueOrDie();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001293}
1294
1295DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDestByName(FPDF_DOCUMENT document,
1296 FPDF_BYTESTRING name) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001297 if (!name || name[0] == 0)
Tom Sepez471a1032015-10-15 16:17:18 -07001298 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001299
Tom Sepez471a1032015-10-15 16:17:18 -07001300 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1301 if (!pDoc)
1302 return nullptr;
1303
Lei Zhangd983b092015-12-14 16:58:33 -08001304 CPDF_NameTree name_tree(pDoc, "Dests");
Tom Sepez471a1032015-10-15 16:17:18 -07001305 return name_tree.LookupNamedDest(pDoc, name);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001306}
1307
Tom Sepez51da0932015-11-25 16:05:49 -08001308#ifdef PDF_ENABLE_XFA
thestig77d148d2016-04-06 06:28:31 -07001309DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Init(FPDF_BSTR* str) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001310 if (!str)
1311 return -1;
1312
Dan Sinclair1c5d0b42017-04-03 15:05:11 -04001313 memset(str, 0, sizeof(FPDF_BSTR));
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001314 return 0;
1315}
1316
thestig77d148d2016-04-06 06:28:31 -07001317DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Set(FPDF_BSTR* str,
1318 FPDF_LPCSTR bstr,
1319 int length) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001320 if (!str)
1321 return -1;
1322 if (!bstr || !length)
1323 return -1;
1324 if (length == -1)
1325 length = FXSYS_strlen(bstr);
1326
1327 if (length == 0) {
1328 if (str->str) {
1329 FX_Free(str->str);
thestig1cd352e2016-06-07 17:53:06 -07001330 str->str = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001331 }
1332 str->len = 0;
1333 return 0;
1334 }
1335
1336 if (str->str && str->len < length)
1337 str->str = FX_Realloc(char, str->str, length + 1);
1338 else if (!str->str)
1339 str->str = FX_Alloc(char, length + 1);
1340
1341 str->str[length] = 0;
Dan Sinclair1c5d0b42017-04-03 15:05:11 -04001342 memcpy(str->str, bstr, length);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001343 str->len = length;
1344
1345 return 0;
1346}
1347
thestig77d148d2016-04-06 06:28:31 -07001348DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Clear(FPDF_BSTR* str) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001349 if (!str)
1350 return -1;
1351
1352 if (str->str) {
1353 FX_Free(str->str);
thestig1cd352e2016-06-07 17:53:06 -07001354 str->str = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001355 }
1356 str->len = 0;
1357 return 0;
1358}
Tom Sepez40e9ff32015-11-30 12:39:54 -08001359#endif // PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001360
1361DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDest(FPDF_DOCUMENT document,
1362 int index,
1363 void* buffer,
1364 long* buflen) {
1365 if (!buffer)
1366 *buflen = 0;
Tom Sepez540c4362015-11-24 13:33:57 -08001367
1368 if (index < 0)
1369 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001370
Tom Sepezbf59a072015-10-21 14:07:23 -07001371 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Tom Sepez540c4362015-11-24 13:33:57 -08001372 if (!pDoc)
1373 return nullptr;
1374
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001375 CPDF_Dictionary* pRoot = pDoc->GetRoot();
1376 if (!pRoot)
Tom Sepez540c4362015-11-24 13:33:57 -08001377 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001378
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001379 CPDF_Object* pDestObj = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001380 CFX_ByteString bsName;
Lei Zhangd983b092015-12-14 16:58:33 -08001381 CPDF_NameTree nameTree(pDoc, "Dests");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001382 int count = nameTree.GetCount();
1383 if (index >= count) {
dsinclair38fd8442016-09-15 10:15:32 -07001384 CPDF_Dictionary* pDest = pRoot->GetDictFor("Dests");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001385 if (!pDest)
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001386 return nullptr;
1387
1388 pdfium::base::CheckedNumeric<int> checked_count = count;
1389 checked_count += pDest->GetCount();
1390 if (!checked_count.IsValid() || index >= checked_count.ValueOrDie())
1391 return nullptr;
1392
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001393 index -= count;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001394 int i = 0;
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001395 for (const auto& it : *pDest) {
1396 bsName = it.first;
tsepez0e606b52016-11-18 16:22:41 -08001397 pDestObj = it.second.get();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001398 if (!pDestObj)
1399 continue;
1400 if (i == index)
1401 break;
1402 i++;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001403 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001404 } else {
Tom Sepezc4a2b752017-04-07 13:56:13 -07001405 pDestObj = nameTree.LookupValueAndName(index, &bsName);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001406 }
1407 if (!pDestObj)
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001408 return nullptr;
Dan Sinclairf1251c12015-10-20 16:24:45 -04001409 if (CPDF_Dictionary* pDict = pDestObj->AsDictionary()) {
dsinclair38fd8442016-09-15 10:15:32 -07001410 pDestObj = pDict->GetArrayFor("D");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001411 if (!pDestObj)
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001412 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001413 }
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001414 if (!pDestObj->IsArray())
1415 return nullptr;
1416
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001417 CFX_WideString wsName = PDF_DecodeText(bsName);
1418 CFX_ByteString utf16Name = wsName.UTF16LE_Encode();
weili47ca6922016-03-31 15:08:27 -07001419 int len = utf16Name.GetLength();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001420 if (!buffer) {
1421 *buflen = len;
thestig9067fd62016-11-23 14:10:06 -08001422 } else if (len <= *buflen) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001423 memcpy(buffer, utf16Name.c_str(), len);
1424 *buflen = len;
1425 } else {
1426 *buflen = -1;
1427 }
1428 return (FPDF_DEST)pDestObj;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001429}