blob: 4fea392228499b3377c52c3fee24e457139d60a2 [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"
dsinclair488b7ad2016-10-04 11:55:50 -070019#include "core/fpdfapi/parser/cpdf_array.h"
20#include "core/fpdfapi/parser/cpdf_document.h"
21#include "core/fpdfapi/parser/fpdf_parser_decode.h"
dsinclair69d9c682016-10-04 12:18:35 -070022#include "core/fpdfapi/render/cpdf_progressiverenderer.h"
23#include "core/fpdfapi/render/cpdf_renderoptions.h"
dsinclair1727aee2016-09-29 13:12:56 -070024#include "core/fpdfdoc/cpdf_annotlist.h"
25#include "core/fpdfdoc/cpdf_nametree.h"
26#include "core/fpdfdoc/cpdf_occontext.h"
27#include "core/fpdfdoc/cpdf_viewerpreferences.h"
dsinclair8a4e2862016-09-29 13:43:30 -070028#include "core/fxcodec/fx_codec.h"
dsinclaira52ab742016-09-29 13:59:29 -070029#include "core/fxcrt/fx_memory.h"
30#include "core/fxcrt/fx_safe_types.h"
dsinclair74a34fc2016-09-29 16:41:42 -070031#include "core/fxge/cfx_fxgedevice.h"
32#include "core/fxge/cfx_gemodule.h"
dsinclairb402b172016-10-11 09:26:32 -070033#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
dsinclair114e46a2016-09-29 17:18:21 -070034#include "fpdfsdk/cpdfsdk_pageview.h"
35#include "fpdfsdk/fsdk_define.h"
36#include "fpdfsdk/fsdk_pauseadapter.h"
dsinclair64376be2016-03-31 20:03:24 -070037#include "fpdfsdk/javascript/ijs_runtime.h"
Lei Zhangb4e7f302015-11-06 15:52:32 -080038#include "public/fpdf_ext.h"
Lei Zhangb4e7f302015-11-06 15:52:32 -080039#include "public/fpdf_progressive.h"
Chris Palmere4b035b2017-03-26 15:48:34 -070040#include "third_party/base/allocator/partition_allocator/partition_alloc.h"
Lei Zhang8241df72015-11-06 14:38:48 -080041#include "third_party/base/numerics/safe_conversions_impl.h"
tsepez36eb4bd2016-10-03 15:24:27 -070042#include "third_party/base/ptr_util.h"
Bo Xufdc00a72014-10-28 23:03:33 -070043
Tom Sepez40e9ff32015-11-30 12:39:54 -080044#ifdef PDF_ENABLE_XFA
dsinclair521b7502016-11-02 13:02:28 -070045#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
dsinclair4d29e782016-10-04 14:02:47 -070046#include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
47#include "fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h"
Dan Sinclaire7786682017-03-29 15:18:41 -040048#include "fxbarcode/BC_Library.h"
Tom Sepez40e9ff32015-11-30 12:39:54 -080049#include "public/fpdf_formfill.h"
50#endif // PDF_ENABLE_XFA
51
Tom Sepezb4a26182017-03-01 12:15:00 -080052#ifdef PDF_ENABLE_XFA_BMP
53#include "core/fxcodec/codec/ccodec_bmpmodule.h"
54#endif
55
56#ifdef PDF_ENABLE_XFA_GIF
57#include "core/fxcodec/codec/ccodec_gifmodule.h"
58#endif
59
60#ifdef PDF_ENABLE_XFA_PNG
61#include "core/fxcodec/codec/ccodec_pngmodule.h"
62#endif
63
64#ifdef PDF_ENABLE_XFA_TIFF
65#include "core/fxcodec/codec/ccodec_tiffmodule.h"
66#endif
67
thestig25fa42f2016-05-25 21:39:46 -070068#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
dsinclair74a34fc2016-09-29 16:41:42 -070069#include "core/fxge/cfx_windowsdevice.h"
thestig25fa42f2016-05-25 21:39:46 -070070#endif
71
thestiga78ba602016-11-23 15:25:48 -080072namespace {
73
tsepez02759102016-12-01 08:29:25 -080074// Also indicates whether library is currently initialized.
75CCodec_ModuleMgr* g_pCodecModule = nullptr;
76
thestiga78ba602016-11-23 15:25:48 -080077void RenderPageImpl(CPDF_PageRenderContext* pContext,
78 CPDF_Page* pPage,
79 const CFX_Matrix& matrix,
80 const FX_RECT& clipping_rect,
81 int flags,
82 bool bNeedToRestore,
83 IFSDK_PAUSE_Adapter* pause) {
84 if (!pContext->m_pOptions)
85 pContext->m_pOptions = pdfium::MakeUnique<CPDF_RenderOptions>();
86
87 if (flags & FPDF_LCD_TEXT)
88 pContext->m_pOptions->m_Flags |= RENDER_CLEARTYPE;
89 else
90 pContext->m_pOptions->m_Flags &= ~RENDER_CLEARTYPE;
91
92 if (flags & FPDF_NO_NATIVETEXT)
93 pContext->m_pOptions->m_Flags |= RENDER_NO_NATIVETEXT;
94 if (flags & FPDF_RENDER_LIMITEDIMAGECACHE)
95 pContext->m_pOptions->m_Flags |= RENDER_LIMITEDIMAGECACHE;
96 if (flags & FPDF_RENDER_FORCEHALFTONE)
97 pContext->m_pOptions->m_Flags |= RENDER_FORCE_HALFTONE;
98#ifndef PDF_ENABLE_XFA
99 if (flags & FPDF_RENDER_NO_SMOOTHTEXT)
100 pContext->m_pOptions->m_Flags |= RENDER_NOTEXTSMOOTH;
101 if (flags & FPDF_RENDER_NO_SMOOTHIMAGE)
102 pContext->m_pOptions->m_Flags |= RENDER_NOIMAGESMOOTH;
103 if (flags & FPDF_RENDER_NO_SMOOTHPATH)
104 pContext->m_pOptions->m_Flags |= RENDER_NOPATHSMOOTH;
105#endif // PDF_ENABLE_XFA
106
107 // Grayscale output
108 if (flags & FPDF_GRAYSCALE) {
109 pContext->m_pOptions->m_ColorMode = RENDER_COLOR_GRAY;
110 pContext->m_pOptions->m_ForeColor = 0;
111 pContext->m_pOptions->m_BackColor = 0xffffff;
112 }
113
114 const CPDF_OCContext::UsageType usage =
115 (flags & FPDF_PRINTING) ? CPDF_OCContext::Print : CPDF_OCContext::View;
116 pContext->m_pOptions->m_AddFlags = flags >> 8;
117 pContext->m_pOptions->m_pOCContext =
Tom Sepezf716f0b2017-01-30 10:04:07 -0800118 pdfium::MakeRetain<CPDF_OCContext>(pPage->m_pDocument, usage);
thestiga78ba602016-11-23 15:25:48 -0800119
120 pContext->m_pDevice->SaveState();
121 pContext->m_pDevice->SetClip_Rect(clipping_rect);
122
123 pContext->m_pContext = pdfium::MakeUnique<CPDF_RenderContext>(pPage);
124 pContext->m_pContext->AppendLayer(pPage, &matrix);
125
126 if (flags & FPDF_ANNOT) {
127 pContext->m_pAnnots = pdfium::MakeUnique<CPDF_AnnotList>(pPage);
128 bool bPrinting = pContext->m_pDevice->GetDeviceClass() != FXDC_DISPLAY;
129 pContext->m_pAnnots->DisplayAnnots(pPage, pContext->m_pContext.get(),
130 bPrinting, &matrix, false, nullptr);
131 }
132
133 pContext->m_pRenderer = pdfium::MakeUnique<CPDF_ProgressiveRenderer>(
134 pContext->m_pContext.get(), pContext->m_pDevice.get(),
135 pContext->m_pOptions.get());
136 pContext->m_pRenderer->Start(pause);
137 if (bNeedToRestore)
138 pContext->m_pDevice->RestoreState(false);
139}
140
tsepezbea04972016-12-01 13:54:42 -0800141class CPDF_CustomAccess final : public IFX_SeekableReadStream {
142 public:
tsepez833619b2016-12-07 09:21:17 -0800143 static CFX_RetainPtr<CPDF_CustomAccess> Create(FPDF_FILEACCESS* pFileAccess) {
144 return CFX_RetainPtr<CPDF_CustomAccess>(new CPDF_CustomAccess(pFileAccess));
145 }
tsepezbea04972016-12-01 13:54:42 -0800146
147 // IFX_SeekableReadStream
148 FX_FILESIZE GetSize() override;
tsepezbea04972016-12-01 13:54:42 -0800149 bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override;
150
151 private:
tsepez833619b2016-12-07 09:21:17 -0800152 explicit CPDF_CustomAccess(FPDF_FILEACCESS* pFileAccess);
153
tsepezbea04972016-12-01 13:54:42 -0800154 FPDF_FILEACCESS m_FileAccess;
155};
156
157CPDF_CustomAccess::CPDF_CustomAccess(FPDF_FILEACCESS* pFileAccess)
158 : m_FileAccess(*pFileAccess) {}
159
160FX_FILESIZE CPDF_CustomAccess::GetSize() {
161 return m_FileAccess.m_FileLen;
162}
163
tsepezbea04972016-12-01 13:54:42 -0800164bool CPDF_CustomAccess::ReadBlock(void* buffer,
165 FX_FILESIZE offset,
166 size_t size) {
167 if (offset < 0)
168 return false;
169
170 FX_SAFE_FILESIZE newPos = pdfium::base::checked_cast<FX_FILESIZE>(size);
171 newPos += offset;
172 if (!newPos.IsValid() ||
173 newPos.ValueOrDie() > static_cast<FX_FILESIZE>(m_FileAccess.m_FileLen)) {
174 return false;
175 }
176 return !!m_FileAccess.m_GetBlock(m_FileAccess.m_Param, offset,
177 reinterpret_cast<uint8_t*>(buffer), size);
178}
179
Tom Sepez40e9ff32015-11-30 12:39:54 -0800180#ifdef PDF_ENABLE_XFA
tsepezfa89a202016-12-02 09:48:30 -0800181class CFPDF_FileStream : public IFX_SeekableStream {
182 public:
tsepez833619b2016-12-07 09:21:17 -0800183 static CFX_RetainPtr<CFPDF_FileStream> Create(FPDF_FILEHANDLER* pFS) {
184 return CFX_RetainPtr<CFPDF_FileStream>(new CFPDF_FileStream(pFS));
185 }
186 ~CFPDF_FileStream() override;
Tom Sepez471a1032015-10-15 16:17:18 -0700187
tsepezfa89a202016-12-02 09:48:30 -0800188 // IFX_SeekableStream:
tsepezfa89a202016-12-02 09:48:30 -0800189 FX_FILESIZE GetSize() override;
190 bool IsEOF() override;
191 FX_FILESIZE GetPosition() override;
192 bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override;
193 size_t ReadBlock(void* buffer, size_t size) override;
194 bool WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size) override;
195 bool Flush() override;
Tom Sepezbf59a072015-10-21 14:07:23 -0700196
tsepezfa89a202016-12-02 09:48:30 -0800197 void SetPosition(FX_FILESIZE pos) { m_nCurPos = pos; }
Tom Sepezdb0be962015-10-16 14:00:21 -0700198
tsepezfa89a202016-12-02 09:48:30 -0800199 protected:
tsepez833619b2016-12-07 09:21:17 -0800200 explicit CFPDF_FileStream(FPDF_FILEHANDLER* pFS);
201
tsepezfa89a202016-12-02 09:48:30 -0800202 FPDF_FILEHANDLER* m_pFS;
203 FX_FILESIZE m_nCurPos;
204};
thestigbefa4502016-05-26 20:15:19 -0700205
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700206CFPDF_FileStream::CFPDF_FileStream(FPDF_FILEHANDLER* pFS) {
207 m_pFS = pFS;
208 m_nCurPos = 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700209}
210
tsepez833619b2016-12-07 09:21:17 -0800211CFPDF_FileStream::~CFPDF_FileStream() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700212 if (m_pFS && m_pFS->Release)
213 m_pFS->Release(m_pFS->clientData);
Bo Xufdc00a72014-10-28 23:03:33 -0700214}
215
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700216FX_FILESIZE CFPDF_FileStream::GetSize() {
217 if (m_pFS && m_pFS->GetSize)
218 return (FX_FILESIZE)m_pFS->GetSize(m_pFS->clientData);
219 return 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700220}
221
tsepezf39074c2016-10-26 15:33:58 -0700222bool CFPDF_FileStream::IsEOF() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700223 return m_nCurPos >= GetSize();
Bo Xufdc00a72014-10-28 23:03:33 -0700224}
225
weili625ad662016-06-15 11:21:33 -0700226FX_FILESIZE CFPDF_FileStream::GetPosition() {
227 return m_nCurPos;
228}
229
tsepezf39074c2016-10-26 15:33:58 -0700230bool CFPDF_FileStream::ReadBlock(void* buffer,
231 FX_FILESIZE offset,
232 size_t size) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700233 if (!buffer || !size || !m_pFS->ReadBlock)
tsepezf39074c2016-10-26 15:33:58 -0700234 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700235
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700236 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
237 (FPDF_DWORD)size) == 0) {
238 m_nCurPos = offset + size;
tsepezf39074c2016-10-26 15:33:58 -0700239 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700240 }
tsepezf39074c2016-10-26 15:33:58 -0700241 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700242}
243
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700244size_t CFPDF_FileStream::ReadBlock(void* buffer, size_t size) {
245 if (!buffer || !size || !m_pFS->ReadBlock)
246 return 0;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700247
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700248 FX_FILESIZE nSize = GetSize();
249 if (m_nCurPos >= nSize)
250 return 0;
251 FX_FILESIZE dwAvail = nSize - m_nCurPos;
252 if (dwAvail < (FX_FILESIZE)size)
253 size = (size_t)dwAvail;
254 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)m_nCurPos, buffer,
255 (FPDF_DWORD)size) == 0) {
256 m_nCurPos += size;
257 return size;
258 }
Bo Xufdc00a72014-10-28 23:03:33 -0700259
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700260 return 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700261}
262
tsepezf39074c2016-10-26 15:33:58 -0700263bool CFPDF_FileStream::WriteBlock(const void* buffer,
264 FX_FILESIZE offset,
265 size_t size) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700266 if (!m_pFS || !m_pFS->WriteBlock)
tsepezf39074c2016-10-26 15:33:58 -0700267 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700268
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700269 if (m_pFS->WriteBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
270 (FPDF_DWORD)size) == 0) {
271 m_nCurPos = offset + size;
tsepezf39074c2016-10-26 15:33:58 -0700272 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700273 }
tsepezf39074c2016-10-26 15:33:58 -0700274 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700275}
276
tsepezf39074c2016-10-26 15:33:58 -0700277bool CFPDF_FileStream::Flush() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700278 if (!m_pFS || !m_pFS->Flush)
tsepezf39074c2016-10-26 15:33:58 -0700279 return true;
Bo Xufdc00a72014-10-28 23:03:33 -0700280
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700281 return m_pFS->Flush(m_pFS->clientData) == 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700282}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800283#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700284
tsepezfa89a202016-12-02 09:48:30 -0800285} // namespace
286
287UnderlyingDocumentType* UnderlyingFromFPDFDocument(FPDF_DOCUMENT doc) {
288 return static_cast<UnderlyingDocumentType*>(doc);
289}
290
291FPDF_DOCUMENT FPDFDocumentFromUnderlying(UnderlyingDocumentType* doc) {
292 return static_cast<FPDF_DOCUMENT>(doc);
293}
294
295UnderlyingPageType* UnderlyingFromFPDFPage(FPDF_PAGE page) {
296 return static_cast<UnderlyingPageType*>(page);
297}
298
299CPDF_Document* CPDFDocumentFromFPDFDocument(FPDF_DOCUMENT doc) {
300#ifdef PDF_ENABLE_XFA
301 return doc ? UnderlyingFromFPDFDocument(doc)->GetPDFDoc() : nullptr;
302#else // PDF_ENABLE_XFA
303 return UnderlyingFromFPDFDocument(doc);
304#endif // PDF_ENABLE_XFA
305}
306
307FPDF_DOCUMENT FPDFDocumentFromCPDFDocument(CPDF_Document* doc) {
308#ifdef PDF_ENABLE_XFA
309 return doc ? FPDFDocumentFromUnderlying(
310 new CPDFXFA_Context(pdfium::WrapUnique(doc)))
311 : nullptr;
312#else // PDF_ENABLE_XFA
313 return FPDFDocumentFromUnderlying(doc);
314#endif // PDF_ENABLE_XFA
315}
316
317CPDF_Page* CPDFPageFromFPDFPage(FPDF_PAGE page) {
318#ifdef PDF_ENABLE_XFA
319 return page ? UnderlyingFromFPDFPage(page)->GetPDFPage() : nullptr;
320#else // PDF_ENABLE_XFA
321 return UnderlyingFromFPDFPage(page);
322#endif // PDF_ENABLE_XFA
323}
324
325CFX_DIBitmap* CFXBitmapFromFPDFBitmap(FPDF_BITMAP bitmap) {
326 return static_cast<CFX_DIBitmap*>(bitmap);
327}
328
tsepez833619b2016-12-07 09:21:17 -0800329CFX_RetainPtr<IFX_SeekableReadStream> MakeSeekableReadStream(
330 FPDF_FILEACCESS* pFileAccess) {
331 return CPDF_CustomAccess::Create(pFileAccess);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700332}
333
tsepezfa89a202016-12-02 09:48:30 -0800334#ifdef PDF_ENABLE_XFA
tsepez833619b2016-12-07 09:21:17 -0800335CFX_RetainPtr<IFX_SeekableStream> MakeSeekableStream(
336 FPDF_FILEHANDLER* pFilehandler) {
337 return CFPDF_FileStream::Create(pFilehandler);
tsepezfa89a202016-12-02 09:48:30 -0800338}
339#endif // PDF_ENABLE_XFA
340
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700341// 0 bit: FPDF_POLICY_MACHINETIME_ACCESS
tsepezc3255f52016-03-25 14:52:27 -0700342static uint32_t foxit_sandbox_policy = 0xFFFFFFFF;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700343
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700344void FSDK_SetSandBoxPolicy(FPDF_DWORD policy, FPDF_BOOL enable) {
345 switch (policy) {
346 case FPDF_POLICY_MACHINETIME_ACCESS: {
347 if (enable)
348 foxit_sandbox_policy |= 0x01;
349 else
350 foxit_sandbox_policy &= 0xFFFFFFFE;
351 } break;
352 default:
353 break;
354 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700355}
356
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700357FPDF_BOOL FSDK_IsSandBoxPolicyEnabled(FPDF_DWORD policy) {
358 switch (policy) {
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700359 case FPDF_POLICY_MACHINETIME_ACCESS:
Lei Zhangb0748bb2015-10-19 12:11:49 -0700360 return !!(foxit_sandbox_policy & 0x01);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700361 default:
tsepez4cf55152016-11-02 14:37:54 -0700362 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700363 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700364}
365
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700366DLLEXPORT void STDCALL FPDF_InitLibrary() {
Lei Zhang6f62d532015-09-23 15:31:44 -0700367 FPDF_InitLibraryWithConfig(nullptr);
368}
369
Dan Sinclairf766ad22016-03-14 13:51:24 -0400370DLLEXPORT void STDCALL
371FPDF_InitLibraryWithConfig(const FPDF_LIBRARY_CONFIG* cfg) {
tsepez02759102016-12-01 08:29:25 -0800372 if (g_pCodecModule)
373 return;
374
Chris Palmer2b797292017-04-06 14:45:39 -0700375 FXMEM_InitalizePartitionAlloc();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700376 g_pCodecModule = new CCodec_ModuleMgr();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700377
weili47228ac2016-07-20 10:35:31 -0700378 CFX_GEModule* pModule = CFX_GEModule::Get();
379 pModule->Init(cfg ? cfg->m_pUserFontPaths : nullptr, g_pCodecModule);
tsepez02759102016-12-01 08:29:25 -0800380
Tom Sepez1b246282015-11-25 15:15:31 -0800381 CPDF_ModuleMgr* pModuleMgr = CPDF_ModuleMgr::Get();
382 pModuleMgr->SetCodecModule(g_pCodecModule);
383 pModuleMgr->InitPageModule();
dsinclairab5b60e2016-06-23 08:18:36 -0700384 pModuleMgr->LoadEmbeddedGB1CMaps();
385 pModuleMgr->LoadEmbeddedJapan1CMaps();
386 pModuleMgr->LoadEmbeddedCNS1CMaps();
387 pModuleMgr->LoadEmbeddedKorea1CMaps();
dsinclaird647a6b2016-04-26 13:13:20 -0700388
Tom Sepezb4a26182017-03-01 12:15:00 -0800389#ifdef PDF_ENABLE_XFA_BMP
390 pModuleMgr->GetCodecModule()->SetBmpModule(
391 pdfium::MakeUnique<CCodec_BmpModule>());
392#endif
393
394#ifdef PDF_ENABLE_XFA_GIF
395 pModuleMgr->GetCodecModule()->SetGifModule(
396 pdfium::MakeUnique<CCodec_GifModule>());
397#endif
398
399#ifdef PDF_ENABLE_XFA_PNG
400 pModuleMgr->GetCodecModule()->SetPngModule(
401 pdfium::MakeUnique<CCodec_PngModule>());
402#endif
403
404#ifdef PDF_ENABLE_XFA_TIFF
405 pModuleMgr->GetCodecModule()->SetTiffModule(
406 pdfium::MakeUnique<CCodec_TiffModule>());
407#endif
408
Tom Sepez40e9ff32015-11-30 12:39:54 -0800409#ifdef PDF_ENABLE_XFA
dsinclair8837c912016-11-01 11:22:37 -0700410 FXJSE_Initialize();
411 BC_Library_Init();
Tom Sepez40e9ff32015-11-30 12:39:54 -0800412#endif // PDF_ENABLE_XFA
Tom Sepez452b4f32015-10-13 09:27:27 -0700413 if (cfg && cfg->version >= 2)
414 IJS_Runtime::Initialize(cfg->m_v8EmbedderSlot, cfg->m_pIsolate);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700415}
416
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700417DLLEXPORT void STDCALL FPDF_DestroyLibrary() {
tsepez02759102016-12-01 08:29:25 -0800418 if (!g_pCodecModule)
419 return;
420
Tom Sepez51da0932015-11-25 16:05:49 -0800421#ifdef PDF_ENABLE_XFA
Tom Sepez5628fd72017-04-27 14:58:53 -0700422 BC_Library_Destroy();
dsinclair8837c912016-11-01 11:22:37 -0700423 FXJSE_Finalize();
Tom Sepez40e9ff32015-11-30 12:39:54 -0800424#endif // PDF_ENABLE_XFA
dsinclair8837c912016-11-01 11:22:37 -0700425
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700426 CPDF_ModuleMgr::Destroy();
427 CFX_GEModule::Destroy();
Tom Sepez2c286192015-06-18 12:47:11 -0700428
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700429 delete g_pCodecModule;
430 g_pCodecModule = nullptr;
thestig2d6dda12016-06-28 07:39:09 -0700431
432 IJS_Runtime::Destroy();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700433}
434
435#ifndef _WIN32
436int g_LastError;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700437void SetLastError(int err) {
438 g_LastError = err;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700439}
440
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700441int GetLastError() {
442 return g_LastError;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700443}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800444#endif // _WIN32
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700445
Tom Sepezf10ae632016-01-26 14:19:52 -0800446void ProcessParseError(CPDF_Parser::Error err) {
tsepezc3255f52016-03-25 14:52:27 -0700447 uint32_t err_code = FPDF_ERR_SUCCESS;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700448 // Translate FPDFAPI error code to FPDFVIEW error code
Tom Sepezf10ae632016-01-26 14:19:52 -0800449 switch (err) {
450 case CPDF_Parser::SUCCESS:
451 err_code = FPDF_ERR_SUCCESS;
452 break;
453 case CPDF_Parser::FILE_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700454 err_code = FPDF_ERR_FILE;
455 break;
Tom Sepezf10ae632016-01-26 14:19:52 -0800456 case CPDF_Parser::FORMAT_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700457 err_code = FPDF_ERR_FORMAT;
458 break;
Tom Sepezf10ae632016-01-26 14:19:52 -0800459 case CPDF_Parser::PASSWORD_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700460 err_code = FPDF_ERR_PASSWORD;
461 break;
Tom Sepezf10ae632016-01-26 14:19:52 -0800462 case CPDF_Parser::HANDLER_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700463 err_code = FPDF_ERR_SECURITY;
464 break;
465 }
466 SetLastError(err_code);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700467}
468
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700469DLLEXPORT void STDCALL FPDF_SetSandBoxPolicy(FPDF_DWORD policy,
470 FPDF_BOOL enable) {
471 return FSDK_SetSandBoxPolicy(policy, enable);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700472}
473
rbpotterdb764702017-01-12 10:31:43 -0800474#if defined(_WIN32)
475#if defined(PDFIUM_PRINT_TEXT_WITH_GDI)
thestigfdb35ff2016-07-18 13:45:44 -0700476DLLEXPORT void STDCALL
477FPDF_SetTypefaceAccessibleFunc(PDFiumEnsureTypefaceCharactersAccessible func) {
478 g_pdfium_typeface_accessible_func = func;
479}
480
481DLLEXPORT void STDCALL FPDF_SetPrintTextWithGDI(FPDF_BOOL use_gdi) {
482 g_pdfium_print_text_with_gdi = !!use_gdi;
483}
rbpotterdb764702017-01-12 10:31:43 -0800484#endif // PDFIUM_PRINT_TEXT_WITH_GDI
485
486DLLEXPORT FPDF_BOOL STDCALL FPDF_SetPrintPostscriptLevel(int postscript_level) {
487 if (postscript_level != 0 && postscript_level != 2 && postscript_level != 3)
488 return FALSE;
489 g_pdfium_print_postscript_level = postscript_level;
490 return TRUE;
491}
492#endif // defined(_WIN32)
thestigfdb35ff2016-07-18 13:45:44 -0700493
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700494DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadDocument(FPDF_STRING file_path,
495 FPDF_BYTESTRING password) {
Tom Sepeze3166a82015-08-05 10:50:32 -0700496 // NOTE: the creation of the file needs to be by the embedder on the
497 // other side of this API.
tsepez833619b2016-12-07 09:21:17 -0800498 CFX_RetainPtr<IFX_SeekableReadStream> pFileAccess =
Dan Sinclair812e96c2017-03-13 16:43:37 -0400499 IFX_SeekableReadStream::CreateFromFilename((const char*)file_path);
tsepez345d4892016-11-30 15:10:55 -0800500 if (!pFileAccess)
Tom Sepeze3166a82015-08-05 10:50:32 -0700501 return nullptr;
Tom Sepeze3166a82015-08-05 10:50:32 -0700502
tsepez345d4892016-11-30 15:10:55 -0800503 auto pParser = pdfium::MakeUnique<CPDF_Parser>();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700504 pParser->SetPassword(password);
Bo Xud4e406e2014-08-13 11:03:19 -0700505
tsepez345d4892016-11-30 15:10:55 -0800506 auto pDocument = pdfium::MakeUnique<CPDF_Document>(std::move(pParser));
dsinclair156de022016-08-24 11:58:24 -0700507 CPDF_Parser::Error error =
508 pDocument->GetParser()->StartParse(pFileAccess, pDocument.get());
Tom Sepezf10ae632016-01-26 14:19:52 -0800509 if (error != CPDF_Parser::SUCCESS) {
Tom Sepezf10ae632016-01-26 14:19:52 -0800510 ProcessParseError(error);
thestig1cd352e2016-06-07 17:53:06 -0700511 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700512 }
dsinclair8837c912016-11-01 11:22:37 -0700513 return FPDFDocumentFromCPDFDocument(pDocument.release());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700514}
Jun Fange118ce92015-02-17 06:50:08 -0800515
Tom Sepez40e9ff32015-11-30 12:39:54 -0800516#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700517DLLEXPORT FPDF_BOOL STDCALL FPDF_HasXFAField(FPDF_DOCUMENT document,
518 int* docType) {
519 if (!document)
tsepez4cf55152016-11-02 14:37:54 -0700520 return false;
JUN FANG827a1722015-03-05 13:39:21 -0800521
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700522 CPDF_Document* pdfDoc =
dsinclair521b7502016-11-02 13:02:28 -0700523 (static_cast<CPDFXFA_Context*>(document))->GetPDFDoc();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700524 if (!pdfDoc)
tsepez4cf55152016-11-02 14:37:54 -0700525 return false;
JUN FANG827a1722015-03-05 13:39:21 -0800526
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700527 CPDF_Dictionary* pRoot = pdfDoc->GetRoot();
528 if (!pRoot)
tsepez4cf55152016-11-02 14:37:54 -0700529 return false;
JUN FANG827a1722015-03-05 13:39:21 -0800530
dsinclair38fd8442016-09-15 10:15:32 -0700531 CPDF_Dictionary* pAcroForm = pRoot->GetDictFor("AcroForm");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700532 if (!pAcroForm)
tsepez4cf55152016-11-02 14:37:54 -0700533 return false;
JUN FANG827a1722015-03-05 13:39:21 -0800534
dsinclair38fd8442016-09-15 10:15:32 -0700535 CPDF_Object* pXFA = pAcroForm->GetObjectFor("XFA");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700536 if (!pXFA)
tsepez4cf55152016-11-02 14:37:54 -0700537 return false;
JUN FANG827a1722015-03-05 13:39:21 -0800538
dsinclair38fd8442016-09-15 10:15:32 -0700539 bool bDynamicXFA = pRoot->GetBooleanFor("NeedsRendering", false);
thestigded36342016-05-23 17:54:02 -0700540 *docType = bDynamicXFA ? DOCTYPE_DYNAMIC_XFA : DOCTYPE_STATIC_XFA;
tsepez4cf55152016-11-02 14:37:54 -0700541 return true;
Jun Fange118ce92015-02-17 06:50:08 -0800542}
543
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700544DLLEXPORT FPDF_BOOL STDCALL FPDF_LoadXFA(FPDF_DOCUMENT document) {
dsinclair521b7502016-11-02 13:02:28 -0700545 return document && (static_cast<CPDFXFA_Context*>(document))->LoadXFADoc();
Bo Xufdc00a72014-10-28 23:03:33 -0700546}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800547#endif // PDF_ENABLE_XFA
Bo Xufdc00a72014-10-28 23:03:33 -0700548
tsepezad2441e2016-10-24 10:19:11 -0700549class CMemFile final : public IFX_SeekableReadStream {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700550 public:
tsepez833619b2016-12-07 09:21:17 -0800551 static CFX_RetainPtr<CMemFile> Create(uint8_t* pBuf, FX_FILESIZE size) {
552 return CFX_RetainPtr<CMemFile>(new CMemFile(pBuf, size));
553 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700554
Lei Zhang3884dba2015-10-19 17:27:53 -0700555 FX_FILESIZE GetSize() override { return m_size; }
tsepezf39074c2016-10-26 15:33:58 -0700556 bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override {
tsepez833619b2016-12-07 09:21:17 -0800557 if (offset < 0)
tsepezf39074c2016-10-26 15:33:58 -0700558 return false;
tsepez833619b2016-12-07 09:21:17 -0800559
tsepez4e597c82016-11-07 15:16:01 -0800560 FX_SAFE_FILESIZE newPos = pdfium::base::checked_cast<FX_FILESIZE>(size);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700561 newPos += offset;
tsepez833619b2016-12-07 09:21:17 -0800562 if (!newPos.IsValid() || newPos.ValueOrDie() > m_size)
tsepezf39074c2016-10-26 15:33:58 -0700563 return false;
tsepez833619b2016-12-07 09:21:17 -0800564
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400565 memcpy(buffer, m_pBuf + offset, size);
tsepezf39074c2016-10-26 15:33:58 -0700566 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700567 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700568
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700569 private:
tsepez833619b2016-12-07 09:21:17 -0800570 CMemFile(uint8_t* pBuf, FX_FILESIZE size) : m_pBuf(pBuf), m_size(size) {}
Lei Zhang2b1a2d52015-08-14 22:16:22 -0700571
Lei Zhang3884dba2015-10-19 17:27:53 -0700572 uint8_t* const m_pBuf;
573 const FX_FILESIZE m_size;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700574};
Lei Zhang3884dba2015-10-19 17:27:53 -0700575
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700576DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadMemDocument(const void* data_buf,
577 int size,
578 FPDF_BYTESTRING password) {
tsepez833619b2016-12-07 09:21:17 -0800579 CFX_RetainPtr<CMemFile> pMemFile = CMemFile::Create((uint8_t*)data_buf, size);
580 auto pParser = pdfium::MakeUnique<CPDF_Parser>();
tsepez4540fba2016-08-16 11:12:21 -0700581 pParser->SetPassword(password);
582
tsepez833619b2016-12-07 09:21:17 -0800583 auto pDocument = pdfium::MakeUnique<CPDF_Document>(std::move(pParser));
tsepez4540fba2016-08-16 11:12:21 -0700584 CPDF_Parser::Error error =
dsinclaircedaa552016-08-24 11:12:19 -0700585 pDocument->GetParser()->StartParse(pMemFile, pDocument.get());
Tom Sepezf10ae632016-01-26 14:19:52 -0800586 if (error != CPDF_Parser::SUCCESS) {
Tom Sepezf10ae632016-01-26 14:19:52 -0800587 ProcessParseError(error);
thestig1cd352e2016-06-07 17:53:06 -0700588 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700589 }
dsinclaircedaa552016-08-24 11:12:19 -0700590 CheckUnSupportError(pDocument.get(), error);
591 return FPDFDocumentFromCPDFDocument(pDocument.release());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700592}
593
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700594DLLEXPORT FPDF_DOCUMENT STDCALL
595FPDF_LoadCustomDocument(FPDF_FILEACCESS* pFileAccess,
596 FPDF_BYTESTRING password) {
tsepez833619b2016-12-07 09:21:17 -0800597 CFX_RetainPtr<CPDF_CustomAccess> pFile =
598 CPDF_CustomAccess::Create(pFileAccess);
599 auto pParser = pdfium::MakeUnique<CPDF_Parser>();
tsepez4540fba2016-08-16 11:12:21 -0700600 pParser->SetPassword(password);
601
tsepez833619b2016-12-07 09:21:17 -0800602 auto pDocument = pdfium::MakeUnique<CPDF_Document>(std::move(pParser));
dsinclaircedaa552016-08-24 11:12:19 -0700603 CPDF_Parser::Error error =
604 pDocument->GetParser()->StartParse(pFile, pDocument.get());
Tom Sepezf10ae632016-01-26 14:19:52 -0800605 if (error != CPDF_Parser::SUCCESS) {
Tom Sepezf10ae632016-01-26 14:19:52 -0800606 ProcessParseError(error);
thestig1cd352e2016-06-07 17:53:06 -0700607 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700608 }
dsinclaircedaa552016-08-24 11:12:19 -0700609 CheckUnSupportError(pDocument.get(), error);
610 return FPDFDocumentFromCPDFDocument(pDocument.release());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700611}
612
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700613DLLEXPORT FPDF_BOOL STDCALL FPDF_GetFileVersion(FPDF_DOCUMENT doc,
614 int* fileVersion) {
Tom Sepez471a1032015-10-15 16:17:18 -0700615 if (!fileVersion)
tsepez4cf55152016-11-02 14:37:54 -0700616 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700617
Tom Sepez471a1032015-10-15 16:17:18 -0700618 *fileVersion = 0;
619 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(doc);
620 if (!pDoc)
tsepez4cf55152016-11-02 14:37:54 -0700621 return false;
Tom Sepez471a1032015-10-15 16:17:18 -0700622
623 CPDF_Parser* pParser = pDoc->GetParser();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700624 if (!pParser)
tsepez4cf55152016-11-02 14:37:54 -0700625 return false;
Tom Sepez471a1032015-10-15 16:17:18 -0700626
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700627 *fileVersion = pParser->GetFileVersion();
tsepez4cf55152016-11-02 14:37:54 -0700628 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700629}
630
tsepezc3255f52016-03-25 14:52:27 -0700631// jabdelmalek: changed return type from uint32_t to build on Linux (and match
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700632// header).
633DLLEXPORT unsigned long STDCALL FPDF_GetDocPermissions(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700634 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
thestig27ddf162016-05-23 15:06:59 -0700635 // https://bugs.chromium.org/p/pdfium/issues/detail?id=499
636 if (!pDoc) {
Tom Sepez51da0932015-11-25 16:05:49 -0800637#ifndef PDF_ENABLE_XFA
638 return 0;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800639#else // PDF_ENABLE_XFA
thestig27ddf162016-05-23 15:06:59 -0700640 return 0xFFFFFFFF;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800641#endif // PDF_ENABLE_XFA
thestig27ddf162016-05-23 15:06:59 -0700642 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700643
thestig27ddf162016-05-23 15:06:59 -0700644 return pDoc->GetUserPermissions();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700645}
646
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700647DLLEXPORT int STDCALL FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700648 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
thestigb8db5112016-04-06 12:12:52 -0700649 if (!pDoc || !pDoc->GetParser())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700650 return -1;
Bo Xuc5cab022014-09-19 19:16:31 -0700651
Tom Sepez471a1032015-10-15 16:17:18 -0700652 CPDF_Dictionary* pDict = pDoc->GetParser()->GetEncryptDict();
dsinclair38fd8442016-09-15 10:15:32 -0700653 return pDict ? pDict->GetIntegerFor("R") : -1;
Bo Xuc5cab022014-09-19 19:16:31 -0700654}
655
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700656DLLEXPORT int STDCALL FPDF_GetPageCount(FPDF_DOCUMENT document) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800657 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
Tom Sepez471a1032015-10-15 16:17:18 -0700658 return pDoc ? pDoc->GetPageCount() : 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700659}
660
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700661DLLEXPORT FPDF_PAGE STDCALL FPDF_LoadPage(FPDF_DOCUMENT document,
662 int page_index) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800663 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
664 if (!pDoc)
Tom Sepez471a1032015-10-15 16:17:18 -0700665 return nullptr;
Tom Sepez1b246282015-11-25 15:15:31 -0800666
Tom Sepezbbe0e4d2015-10-20 15:41:40 -0700667 if (page_index < 0 || page_index >= pDoc->GetPageCount())
Tom Sepez471a1032015-10-15 16:17:18 -0700668 return nullptr;
669
Tom Sepez40e9ff32015-11-30 12:39:54 -0800670#ifdef PDF_ENABLE_XFA
dsinclair9f206f02016-09-20 12:17:42 -0700671 return pDoc->GetXFAPage(page_index);
Tom Sepez40e9ff32015-11-30 12:39:54 -0800672#else // PDF_ENABLE_XFA
Tom Sepez51da0932015-11-25 16:05:49 -0800673 CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
Lei Zhang412e9082015-12-14 18:34:00 -0800674 if (!pDict)
thestig5cc24652016-04-26 11:46:02 -0700675 return nullptr;
676
677 CPDF_Page* pPage = new CPDF_Page(pDoc, pDict, true);
678 pPage->ParseContent();
Tom Sepez51da0932015-11-25 16:05:49 -0800679 return pPage;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800680#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700681}
682
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700683DLLEXPORT double STDCALL FPDF_GetPageWidth(FPDF_PAGE page) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800684 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezbf59a072015-10-21 14:07:23 -0700685 return pPage ? pPage->GetPageWidth() : 0.0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700686}
687
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700688DLLEXPORT double STDCALL FPDF_GetPageHeight(FPDF_PAGE page) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800689 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezbf59a072015-10-21 14:07:23 -0700690 return pPage ? pPage->GetPageHeight() : 0.0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700691}
692
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700693#if defined(_WIN32)
rbpottercec01802017-04-17 09:10:21 -0700694namespace {
695
696const double kEpsilonSize = 0.01f;
697
698void GetScaling(CPDF_Page* pPage,
699 int size_x,
700 int size_y,
701 int rotate,
702 double* scale_x,
703 double* scale_y) {
704 ASSERT(pPage);
705 ASSERT(scale_x);
706 ASSERT(scale_y);
707 double page_width = pPage->GetPageWidth();
708 double page_height = pPage->GetPageHeight();
709 if (page_width < kEpsilonSize || page_height < kEpsilonSize)
710 return;
711
712 if (rotate % 2 == 0) {
713 *scale_x = size_x / page_width;
714 *scale_y = size_y / page_height;
715 } else {
716 *scale_x = size_y / page_width;
717 *scale_y = size_x / page_height;
718 }
719}
720
721FX_RECT GetMaskDimensionsAndOffsets(CPDF_Page* pPage,
722 int start_x,
723 int start_y,
724 int size_x,
725 int size_y,
726 int rotate,
727 const CFX_FloatRect& mask_box) {
728 double scale_x = 0.0f;
729 double scale_y = 0.0f;
730 GetScaling(pPage, size_x, size_y, rotate, &scale_x, &scale_y);
731 if (scale_x < kEpsilonSize || scale_y < kEpsilonSize)
732 return FX_RECT();
733
734 // Compute sizes in page points. Round down to catch the entire bitmap.
735 int start_x_bm = static_cast<int>(mask_box.left * scale_x);
736 int start_y_bm = static_cast<int>(mask_box.bottom * scale_y);
737 int size_x_bm = static_cast<int>(mask_box.right * scale_x + 1.0f) -
738 static_cast<int>(mask_box.left * scale_x);
739 int size_y_bm = static_cast<int>(mask_box.top * scale_y + 1.0f) -
740 static_cast<int>(mask_box.bottom * scale_y);
741
742 // Get page rotation
743 int page_rotation = 0;
744 CPDF_Dictionary* pDict = pPage->m_pFormDict;
745 while (pDict) {
746 if (pDict->KeyExist("Rotate")) {
747 CPDF_Object* pRotateObj = pDict->GetObjectFor("Rotate")->GetDirect();
748 page_rotation = pRotateObj ? pRotateObj->GetInteger() / 90 : 0;
749 break;
750 }
751 if (!pDict->KeyExist("Parent"))
752 break;
753
754 pDict = ToDictionary(pDict->GetObjectFor("Parent")->GetDirect());
755 }
756
757 // Compute offsets
758 int offset_x = 0;
759 int offset_y = 0;
760 switch ((rotate + page_rotation) % 4) {
761 case 0:
762 offset_x = start_x_bm + start_x;
763 offset_y = start_y + size_y - size_y_bm - start_y_bm;
764 break;
765 case 1:
766 offset_x = start_y_bm + start_x;
767 offset_y = start_x_bm + start_y;
768 break;
769 case 2:
770 offset_x = start_x + size_x - size_x_bm - start_x_bm;
771 offset_y = start_y_bm + start_y;
772 break;
773 case 3:
774 offset_x = start_x + size_x - size_x_bm - start_y_bm;
775 offset_y = start_y + size_y - size_y_bm - start_x_bm;
776 break;
777 }
778 return FX_RECT(offset_x, offset_y, offset_x + size_x_bm,
779 offset_y + size_y_bm);
780}
781
782// Get a bitmap of just the mask section defined by |mask_box| from a full page
783// bitmap |pBitmap|.
784CFX_RetainPtr<CFX_DIBitmap> GetMaskBitmap(CPDF_Page* pPage,
785 int start_x,
786 int start_y,
787 int size_x,
788 int size_y,
789 int rotate,
790 CFX_RetainPtr<CFX_DIBitmap>& pSrc,
791 const CFX_FloatRect& mask_box,
792 FX_RECT* bitmap_area) {
793 ASSERT(bitmap_area);
794 *bitmap_area = GetMaskDimensionsAndOffsets(pPage, start_x, start_y, size_x,
795 size_y, rotate, mask_box);
796 if (bitmap_area->IsEmpty())
797 return nullptr;
798
799 // Create a new bitmap to transfer part of the page bitmap to.
800 CFX_RetainPtr<CFX_DIBitmap> pDst = pdfium::MakeRetain<CFX_DIBitmap>();
801 pDst->Create(bitmap_area->Width(), bitmap_area->Height(), FXDIB_Argb);
802 pDst->Clear(0x00ffffff);
803 pDst->TransferBitmap(0, 0, bitmap_area->Width(), bitmap_area->Height(), pSrc,
804 bitmap_area->left, bitmap_area->top);
805 return pDst;
806}
807
808void RenderBitmap(CFX_RenderDevice* device,
809 const CFX_RetainPtr<CFX_DIBitmap>& pSrc,
810 const FX_RECT& mask_area) {
811 int size_x_bm = mask_area.Width();
812 int size_y_bm = mask_area.Height();
813 if (size_x_bm == 0 || size_y_bm == 0)
814 return;
815
816 // Create a new bitmap from the old one
817 CFX_RetainPtr<CFX_DIBitmap> pDst = pdfium::MakeRetain<CFX_DIBitmap>();
818 pDst->Create(size_x_bm, size_y_bm, FXDIB_Rgb32);
819 pDst->Clear(0xffffffff);
820 pDst->CompositeBitmap(0, 0, size_x_bm, size_y_bm, pSrc, 0, 0,
821 FXDIB_BLEND_NORMAL, nullptr, false);
822
823 if (device->GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
824 device->StretchDIBitsWithFlagsAndBlend(pDst, mask_area.left, mask_area.top,
825 size_x_bm, size_y_bm, 0,
826 FXDIB_BLEND_NORMAL);
827 } else {
828 device->SetDIBits(pDst, mask_area.left, mask_area.top);
829 }
830}
831
832} // namespace
833
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700834DLLEXPORT void STDCALL FPDF_RenderPage(HDC dc,
835 FPDF_PAGE page,
836 int start_x,
837 int start_y,
838 int size_x,
839 int size_y,
840 int rotate,
841 int flags) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700842 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700843 if (!pPage)
844 return;
rbpottercec01802017-04-17 09:10:21 -0700845 pPage->SetRenderContext(pdfium::MakeUnique<CPDF_PageRenderContext>());
846 CPDF_PageRenderContext* pContext = pPage->GetRenderContext();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700847
Tom Sepezf0799fe2017-03-28 09:31:32 -0700848 CFX_RetainPtr<CFX_DIBitmap> pBitmap;
rbpottercec01802017-04-17 09:10:21 -0700849 // Don't render the full page to bitmap for a mask unless there are a lot
850 // of masks. Full page bitmaps result in large spool sizes, so they should
851 // only be used when necessary. For large numbers of masks, rendering each
852 // individually is inefficient and unlikely to significantly improve spool
853 // size.
thestig84144e82016-09-27 15:06:01 -0700854 const bool bNewBitmap =
rbpottercec01802017-04-17 09:10:21 -0700855 pPage->BackgroundAlphaNeeded() ||
856 (pPage->HasImageMask() && pPage->GetMaskBoundingBoxes().size() > 100);
857 const bool bHasMask = pPage->HasImageMask() && !bNewBitmap;
858 if (bNewBitmap || bHasMask) {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700859 pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700860 pBitmap->Create(size_x, size_y, FXDIB_Argb);
861 pBitmap->Clear(0x00ffffff);
thestigbefa4502016-05-26 20:15:19 -0700862 CFX_FxgeDevice* pDevice = new CFX_FxgeDevice;
tsepez36eb4bd2016-10-03 15:24:27 -0700863 pContext->m_pDevice = pdfium::WrapUnique(pDevice);
Tom Sepezf0799fe2017-03-28 09:31:32 -0700864 pDevice->Attach(pBitmap, false, nullptr, false);
rbpottercec01802017-04-17 09:10:21 -0700865 if (bHasMask) {
866 pContext->m_pOptions = pdfium::MakeUnique<CPDF_RenderOptions>();
867 pContext->m_pOptions->m_Flags |= RENDER_BREAKFORMASKS;
868 }
Jun Fang1aeeceb2015-12-29 10:27:44 +0800869 } else {
tsepez36eb4bd2016-10-03 15:24:27 -0700870 pContext->m_pDevice = pdfium::MakeUnique<CFX_WindowsDevice>(dc);
Jun Fang1aeeceb2015-12-29 10:27:44 +0800871 }
rbpottercec01802017-04-17 09:10:21 -0700872
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700873 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
tsepez4cf55152016-11-02 14:37:54 -0700874 rotate, flags, true, nullptr);
Bo Xud4e406e2014-08-13 11:03:19 -0700875
rbpottercec01802017-04-17 09:10:21 -0700876 if (bHasMask) {
877 // Finish rendering the page to bitmap and copy the correct segments
878 // of the page to individual image mask bitmaps.
879 const std::vector<CFX_FloatRect>& mask_boxes =
880 pPage->GetMaskBoundingBoxes();
881 std::vector<FX_RECT> bitmap_areas(mask_boxes.size());
882 std::vector<CFX_RetainPtr<CFX_DIBitmap>> bitmaps(mask_boxes.size());
883 for (size_t i = 0; i < mask_boxes.size(); i++) {
884 bitmaps[i] =
885 GetMaskBitmap(pPage, start_x, start_y, size_x, size_y, rotate,
886 pBitmap, mask_boxes[i], &bitmap_areas[i]);
887 pContext->m_pRenderer->Continue(nullptr);
888 }
889
890 // Reset rendering context
891 pPage->SetRenderContext(nullptr);
892
893 // Begin rendering to the printer. Add flag to indicate the renderer should
894 // pause after each image mask.
895 pPage->SetRenderContext(pdfium::MakeUnique<CPDF_PageRenderContext>());
896 pContext = pPage->GetRenderContext();
897 pContext->m_pDevice = pdfium::MakeUnique<CFX_WindowsDevice>(dc);
898 pContext->m_pOptions = pdfium::MakeUnique<CPDF_RenderOptions>();
899 pContext->m_pOptions->m_Flags |= RENDER_BREAKFORMASKS;
900 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
901 rotate, flags, true, nullptr);
902
903 // Render masks
904 for (size_t i = 0; i < mask_boxes.size(); i++) {
905 // Render the bitmap for the mask and free the bitmap.
906 if (bitmaps[i]) { // will be null if mask has zero area
907 RenderBitmap(pContext->m_pDevice.get(), bitmaps[i], bitmap_areas[i]);
908 }
909 // Render the next portion of page.
910 pContext->m_pRenderer->Continue(nullptr);
911 }
912 } else if (bNewBitmap) {
thestig84144e82016-09-27 15:06:01 -0700913 CFX_WindowsDevice WinDC(dc);
914 if (WinDC.GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700915 auto pDst = pdfium::MakeRetain<CFX_DIBitmap>();
thestig84144e82016-09-27 15:06:01 -0700916 int pitch = pBitmap->GetPitch();
917 pDst->Create(size_x, size_y, FXDIB_Rgb32);
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400918 memset(pDst->GetBuffer(), -1, pitch * size_y);
Tom Sepezf0799fe2017-03-28 09:31:32 -0700919 pDst->CompositeBitmap(0, 0, size_x, size_y, pBitmap, 0, 0,
Nicolas Pena6a5c20c2017-04-07 14:12:31 -0400920 FXDIB_BLEND_NORMAL, nullptr, false);
Tom Sepezf0799fe2017-03-28 09:31:32 -0700921 WinDC.StretchDIBits(pDst, 0, 0, size_x, size_y);
thestig84144e82016-09-27 15:06:01 -0700922 } else {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700923 WinDC.SetDIBits(pBitmap, 0, 0);
Lei Zhang6d8b1c22015-06-19 17:26:17 -0700924 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700925 }
rbpottercec01802017-04-17 09:10:21 -0700926
tsepeze5cb0b12016-10-26 15:06:11 -0700927 pPage->SetRenderContext(nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700928}
Lei Zhangae85f872016-02-19 14:57:07 -0800929#endif // defined(_WIN32)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700930
931DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap,
932 FPDF_PAGE page,
933 int start_x,
934 int start_y,
935 int size_x,
936 int size_y,
937 int rotate,
938 int flags) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700939 if (!bitmap)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700940 return;
tsepez1e2c5572016-05-25 14:58:09 -0700941
Tom Sepezdb0be962015-10-16 14:00:21 -0700942 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700943 if (!pPage)
944 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700945
weili9f515bc2016-07-24 08:08:24 -0700946 CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
tsepez36eb4bd2016-10-03 15:24:27 -0700947 pPage->SetRenderContext(pdfium::WrapUnique(pContext));
Tom Sepezf0799fe2017-03-28 09:31:32 -0700948
thestigbefa4502016-05-26 20:15:19 -0700949 CFX_FxgeDevice* pDevice = new CFX_FxgeDevice;
weili9f515bc2016-07-24 08:08:24 -0700950 pContext->m_pDevice.reset(pDevice);
dsinclair31b08d42017-03-28 15:47:47 +0000951
Tom Sepezf0799fe2017-03-28 09:31:32 -0700952 CFX_RetainPtr<CFX_DIBitmap> pBitmap(CFXBitmapFromFPDFBitmap(bitmap));
953 pDevice->Attach(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER), nullptr, false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700954 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
tsepez4cf55152016-11-02 14:37:54 -0700955 rotate, flags, true, nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700956
caryclark687fbde2016-11-22 12:44:25 -0800957#ifdef _SKIA_SUPPORT_PATHS_
caryclark8f875502016-12-06 13:49:34 -0800958 pDevice->Flush();
caryclark687fbde2016-11-22 12:44:25 -0800959 pBitmap->UnPreMultiply();
960#endif
tsepeze5cb0b12016-10-26 15:06:11 -0700961 pPage->SetRenderContext(nullptr);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700962}
963
thestiga78ba602016-11-23 15:25:48 -0800964DLLEXPORT void STDCALL FPDF_RenderPageBitmapWithMatrix(FPDF_BITMAP bitmap,
965 FPDF_PAGE page,
966 const FS_MATRIX* matrix,
967 const FS_RECTF* clipping,
968 int flags) {
969 if (!bitmap)
970 return;
971
972 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
973 if (!pPage)
974 return;
975
976 CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
977 pPage->SetRenderContext(pdfium::WrapUnique(pContext));
Tom Sepezf0799fe2017-03-28 09:31:32 -0700978
thestiga78ba602016-11-23 15:25:48 -0800979 CFX_FxgeDevice* pDevice = new CFX_FxgeDevice;
980 pContext->m_pDevice.reset(pDevice);
Tom Sepezf0799fe2017-03-28 09:31:32 -0700981
982 CFX_RetainPtr<CFX_DIBitmap> pBitmap(CFXBitmapFromFPDFBitmap(bitmap));
thestiga78ba602016-11-23 15:25:48 -0800983 pDevice->Attach(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER), nullptr, false);
984
985 CFX_Matrix transform_matrix = pPage->GetPageMatrix();
986 if (matrix) {
Dan Sinclairbba2a7c2017-02-07 16:36:39 -0500987 transform_matrix.Concat(CFX_Matrix(matrix->a, matrix->b, matrix->c,
988 matrix->d, matrix->e, matrix->f));
thestiga78ba602016-11-23 15:25:48 -0800989 }
990
991 CFX_FloatRect clipping_rect;
992 if (clipping) {
993 clipping_rect.left = clipping->left;
994 clipping_rect.bottom = clipping->bottom;
995 clipping_rect.right = clipping->right;
996 clipping_rect.top = clipping->top;
997 }
998 RenderPageImpl(pContext, pPage, transform_matrix, clipping_rect.ToFxRect(),
999 flags, true, nullptr);
1000
1001 pPage->SetRenderContext(nullptr);
1002}
1003
Cary Clark399be5b2016-03-14 16:51:29 -04001004#ifdef _SKIA_SUPPORT_
1005DLLEXPORT FPDF_RECORDER STDCALL FPDF_RenderPageSkp(FPDF_PAGE page,
1006 int size_x,
1007 int size_y) {
1008 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
1009 if (!pPage)
1010 return nullptr;
tsepez1e2c5572016-05-25 14:58:09 -07001011
weili9f515bc2016-07-24 08:08:24 -07001012 CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
tsepez36eb4bd2016-10-03 15:24:27 -07001013 pPage->SetRenderContext(pdfium::WrapUnique(pContext));
caryclarkd6e18872016-05-13 10:57:20 -07001014 CFX_FxgeDevice* skDevice = new CFX_FxgeDevice;
Cary Clark399be5b2016-03-14 16:51:29 -04001015 FPDF_RECORDER recorder = skDevice->CreateRecorder(size_x, size_y);
weili9f515bc2016-07-24 08:08:24 -07001016 pContext->m_pDevice.reset(skDevice);
tsepez4cf55152016-11-02 14:37:54 -07001017 FPDF_RenderPage_Retail(pContext, page, 0, 0, size_x, size_y, 0, 0, true,
tsepez1e2c5572016-05-25 14:58:09 -07001018 nullptr);
tsepeze5cb0b12016-10-26 15:06:11 -07001019 pPage->SetRenderContext(nullptr);
Cary Clark399be5b2016-03-14 16:51:29 -04001020 return recorder;
1021}
1022#endif
1023
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001024DLLEXPORT void STDCALL FPDF_ClosePage(FPDF_PAGE page) {
tsepez1e2c5572016-05-25 14:58:09 -07001025 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001026 if (!page)
1027 return;
Tom Sepez40e9ff32015-11-30 12:39:54 -08001028#ifdef PDF_ENABLE_XFA
Tom Sepez40e9ff32015-11-30 12:39:54 -08001029 pPage->Release();
1030#else // PDF_ENABLE_XFA
Tom Sepez51da0932015-11-25 16:05:49 -08001031 CPDFSDK_PageView* pPageView =
tsepez1e2c5572016-05-25 14:58:09 -07001032 static_cast<CPDFSDK_PageView*>(pPage->GetView());
dsinclair1df1efa2016-09-07 09:55:37 -07001033 if (pPageView) {
dsinclairbcf46232016-10-03 13:02:27 -07001034 // We're already destroying the pageview, so bail early.
1035 if (pPageView->IsBeingDestroyed())
1036 return;
1037
dsinclair1df1efa2016-09-07 09:55:37 -07001038 if (pPageView->IsLocked()) {
1039 pPageView->TakePageOwnership();
1040 return;
1041 }
1042
1043 bool owned = pPageView->OwnsPage();
1044 // This will delete the |pPageView| object. We must cleanup the PageView
1045 // first because it will attempt to reset the View on the |pPage| during
1046 // destruction.
dsinclair7cbe68e2016-10-12 11:56:23 -07001047 pPageView->GetFormFillEnv()->RemovePageView(pPage);
dsinclair1df1efa2016-09-07 09:55:37 -07001048 // If the page was owned then the pageview will have deleted the page.
1049 if (owned)
1050 return;
Tom Sepez51da0932015-11-25 16:05:49 -08001051 }
tsepez1e2c5572016-05-25 14:58:09 -07001052 delete pPage;
Tom Sepez40e9ff32015-11-30 12:39:54 -08001053#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001054}
1055
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001056DLLEXPORT void STDCALL FPDF_CloseDocument(FPDF_DOCUMENT document) {
Jun Fangfc751362015-12-16 21:23:39 -08001057 delete UnderlyingFromFPDFDocument(document);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001058}
1059
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001060DLLEXPORT unsigned long STDCALL FPDF_GetLastError() {
1061 return GetLastError();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001062}
1063
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001064DLLEXPORT void STDCALL FPDF_DeviceToPage(FPDF_PAGE page,
1065 int start_x,
1066 int start_y,
1067 int size_x,
1068 int size_y,
1069 int rotate,
1070 int device_x,
1071 int device_y,
1072 double* page_x,
1073 double* page_y) {
Lei Zhang412e9082015-12-14 18:34:00 -08001074 if (!page || !page_x || !page_y)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001075 return;
Tom Sepez50d12ad2015-11-24 09:50:51 -08001076 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepez40e9ff32015-11-30 12:39:54 -08001077#ifdef PDF_ENABLE_XFA
1078 pPage->DeviceToPage(start_x, start_y, size_x, size_y, rotate, device_x,
1079 device_y, page_x, page_y);
1080#else // PDF_ENABLE_XFA
Dan Sinclair1b08df12017-02-09 09:17:20 -05001081 CFX_Matrix page2device =
1082 pPage->GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate);
Tom Sepez60d909e2015-12-10 15:34:55 -08001083 CFX_Matrix device2page;
Tom Sepez51da0932015-11-25 16:05:49 -08001084 device2page.SetReverse(page2device);
Dan Sinclair1b08df12017-02-09 09:17:20 -05001085
Dan Sinclair05df0752017-03-14 14:43:42 -04001086 CFX_PointF pos = device2page.Transform(
1087 CFX_PointF(static_cast<float>(device_x), static_cast<float>(device_y)));
Dan Sinclairafb44562017-02-09 13:07:43 -05001088
Dan Sinclaira0061af2017-02-23 09:25:17 -05001089 *page_x = pos.x;
1090 *page_y = pos.y;
Tom Sepez40e9ff32015-11-30 12:39:54 -08001091#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001092}
1093
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001094DLLEXPORT void STDCALL FPDF_PageToDevice(FPDF_PAGE page,
1095 int start_x,
1096 int start_y,
1097 int size_x,
1098 int size_y,
1099 int rotate,
1100 double page_x,
1101 double page_y,
1102 int* device_x,
1103 int* device_y) {
Tom Sepezdb0be962015-10-16 14:00:21 -07001104 if (!device_x || !device_y)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001105 return;
Tom Sepez50d12ad2015-11-24 09:50:51 -08001106 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezdb0be962015-10-16 14:00:21 -07001107 if (!pPage)
1108 return;
Tom Sepez40e9ff32015-11-30 12:39:54 -08001109#ifdef PDF_ENABLE_XFA
1110 pPage->PageToDevice(start_x, start_y, size_x, size_y, rotate, page_x, page_y,
1111 device_x, device_y);
1112#else // PDF_ENABLE_XFA
Dan Sinclair1b08df12017-02-09 09:17:20 -05001113 CFX_Matrix page2device =
1114 pPage->GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate);
Dan Sinclaira0061af2017-02-23 09:25:17 -05001115 CFX_PointF pos = page2device.Transform(
Dan Sinclair05df0752017-03-14 14:43:42 -04001116 CFX_PointF(static_cast<float>(page_x), static_cast<float>(page_y)));
Dan Sinclairafb44562017-02-09 13:07:43 -05001117
Dan Sinclaira0061af2017-02-23 09:25:17 -05001118 *device_x = FXSYS_round(pos.x);
1119 *device_y = FXSYS_round(pos.y);
Tom Sepez40e9ff32015-11-30 12:39:54 -08001120#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001121}
1122
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001123DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_Create(int width,
1124 int height,
1125 int alpha) {
Tom Sepezf0799fe2017-03-28 09:31:32 -07001126 auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
tsepez37b12ad2016-12-14 19:50:23 -08001127 if (!pBitmap->Create(width, height, alpha ? FXDIB_Argb : FXDIB_Rgb32))
thestig1cd352e2016-06-07 17:53:06 -07001128 return nullptr;
tsepez37b12ad2016-12-14 19:50:23 -08001129
Tom Sepezf0799fe2017-03-28 09:31:32 -07001130 return pBitmap.Leak();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001131}
1132
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001133DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_CreateEx(int width,
1134 int height,
1135 int format,
1136 void* first_scan,
1137 int stride) {
1138 FXDIB_Format fx_format;
1139 switch (format) {
1140 case FPDFBitmap_Gray:
1141 fx_format = FXDIB_8bppRgb;
1142 break;
1143 case FPDFBitmap_BGR:
1144 fx_format = FXDIB_Rgb;
1145 break;
1146 case FPDFBitmap_BGRx:
1147 fx_format = FXDIB_Rgb32;
1148 break;
1149 case FPDFBitmap_BGRA:
1150 fx_format = FXDIB_Argb;
1151 break;
1152 default:
thestig1cd352e2016-06-07 17:53:06 -07001153 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001154 }
Tom Sepezf0799fe2017-03-28 09:31:32 -07001155 auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001156 pBitmap->Create(width, height, fx_format, (uint8_t*)first_scan, stride);
Tom Sepezf0799fe2017-03-28 09:31:32 -07001157 return pBitmap.Leak();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001158}
1159
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001160DLLEXPORT void STDCALL FPDFBitmap_FillRect(FPDF_BITMAP bitmap,
1161 int left,
1162 int top,
1163 int width,
1164 int height,
1165 FPDF_DWORD color) {
Lei Zhang412e9082015-12-14 18:34:00 -08001166 if (!bitmap)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001167 return;
thestigbefa4502016-05-26 20:15:19 -07001168
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001169 CFX_FxgeDevice device;
Tom Sepezf0799fe2017-03-28 09:31:32 -07001170 CFX_RetainPtr<CFX_DIBitmap> pBitmap(CFXBitmapFromFPDFBitmap(bitmap));
thestigbefa4502016-05-26 20:15:19 -07001171 device.Attach(pBitmap, false, nullptr, false);
1172 if (!pBitmap->HasAlpha())
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001173 color |= 0xFF000000;
1174 FX_RECT rect(left, top, left + width, top + height);
1175 device.FillRect(&rect, color);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001176}
1177
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001178DLLEXPORT void* STDCALL FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap) {
thestigbefa4502016-05-26 20:15:19 -07001179 return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetBuffer() : nullptr;
Bo Xu9114e832014-07-14 13:22:47 -07001180}
1181
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001182DLLEXPORT int STDCALL FPDFBitmap_GetWidth(FPDF_BITMAP bitmap) {
thestigbefa4502016-05-26 20:15:19 -07001183 return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetWidth() : 0;
Bo Xu9114e832014-07-14 13:22:47 -07001184}
1185
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001186DLLEXPORT int STDCALL FPDFBitmap_GetHeight(FPDF_BITMAP bitmap) {
thestigbefa4502016-05-26 20:15:19 -07001187 return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetHeight() : 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001188}
1189
1190DLLEXPORT int STDCALL FPDFBitmap_GetStride(FPDF_BITMAP bitmap) {
thestigbefa4502016-05-26 20:15:19 -07001191 return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetPitch() : 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001192}
1193
1194DLLEXPORT void STDCALL FPDFBitmap_Destroy(FPDF_BITMAP bitmap) {
Tom Sepezf0799fe2017-03-28 09:31:32 -07001195 CFX_RetainPtr<CFX_DIBitmap> destroyer;
1196 destroyer.Unleak(CFXBitmapFromFPDFBitmap(bitmap));
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001197}
1198
weili9f515bc2016-07-24 08:08:24 -07001199void FPDF_RenderPage_Retail(CPDF_PageRenderContext* pContext,
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001200 FPDF_PAGE page,
1201 int start_x,
1202 int start_y,
1203 int size_x,
1204 int size_y,
1205 int rotate,
1206 int flags,
tsepez4cf55152016-11-02 14:37:54 -07001207 bool bNeedToRestore,
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001208 IFSDK_PAUSE_Adapter* pause) {
Tom Sepezdb0be962015-10-16 14:00:21 -07001209 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
1210 if (!pPage)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001211 return;
1212
Dan Sinclair1b08df12017-02-09 09:17:20 -05001213 RenderPageImpl(pContext, pPage, pPage->GetDisplayMatrix(
1214 start_x, start_y, size_x, size_y, rotate),
1215 FX_RECT(start_x, start_y, start_x + size_x, start_y + size_y),
1216 flags, bNeedToRestore, pause);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001217}
1218
1219DLLEXPORT int STDCALL FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document,
1220 int page_index,
1221 double* width,
1222 double* height) {
Tom Sepez540c4362015-11-24 13:33:57 -08001223 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
1224 if (!pDoc)
tsepez4cf55152016-11-02 14:37:54 -07001225 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001226
Tom Sepez40e9ff32015-11-30 12:39:54 -08001227#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001228 int count = pDoc->GetPageCount();
1229 if (page_index < 0 || page_index >= count)
tsepez4cf55152016-11-02 14:37:54 -07001230 return false;
dsinclair9f206f02016-09-20 12:17:42 -07001231 CPDFXFA_Page* pPage = pDoc->GetXFAPage(page_index);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001232 if (!pPage)
tsepez4cf55152016-11-02 14:37:54 -07001233 return false;
Tom Sepez40e9ff32015-11-30 12:39:54 -08001234 *width = pPage->GetPageWidth();
1235 *height = pPage->GetPageHeight();
1236#else // PDF_ENABLE_XFA
1237 CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
1238 if (!pDict)
tsepez4cf55152016-11-02 14:37:54 -07001239 return false;
thestig5cc24652016-04-26 11:46:02 -07001240
1241 CPDF_Page page(pDoc, pDict, true);
Tom Sepez51da0932015-11-25 16:05:49 -08001242 *width = page.GetPageWidth();
1243 *height = page.GetPageHeight();
Tom Sepez40e9ff32015-11-30 12:39:54 -08001244#endif // PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001245
tsepez4cf55152016-11-02 14:37:54 -07001246 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001247}
1248
1249DLLEXPORT FPDF_BOOL STDCALL
1250FPDF_VIEWERREF_GetPrintScaling(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001251 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001252 if (!pDoc)
tsepez4cf55152016-11-02 14:37:54 -07001253 return true;
Tom Sepez471a1032015-10-15 16:17:18 -07001254 CPDF_ViewerPreferences viewRef(pDoc);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001255 return viewRef.PrintScaling();
1256}
1257
1258DLLEXPORT int STDCALL FPDF_VIEWERREF_GetNumCopies(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001259 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001260 if (!pDoc)
1261 return 1;
1262 CPDF_ViewerPreferences viewRef(pDoc);
1263 return viewRef.NumCopies();
1264}
1265
1266DLLEXPORT FPDF_PAGERANGE STDCALL
1267FPDF_VIEWERREF_GetPrintPageRange(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001268 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001269 if (!pDoc)
thestig1cd352e2016-06-07 17:53:06 -07001270 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001271 CPDF_ViewerPreferences viewRef(pDoc);
1272 return viewRef.PrintPageRange();
1273}
1274
1275DLLEXPORT FPDF_DUPLEXTYPE STDCALL
1276FPDF_VIEWERREF_GetDuplex(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001277 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001278 if (!pDoc)
Bo Xu9114e832014-07-14 13:22:47 -07001279 return DuplexUndefined;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001280 CPDF_ViewerPreferences viewRef(pDoc);
1281 CFX_ByteString duplex = viewRef.Duplex();
Lei Zhangd983b092015-12-14 16:58:33 -08001282 if ("Simplex" == duplex)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001283 return Simplex;
Lei Zhangd983b092015-12-14 16:58:33 -08001284 if ("DuplexFlipShortEdge" == duplex)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001285 return DuplexFlipShortEdge;
Lei Zhangd983b092015-12-14 16:58:33 -08001286 if ("DuplexFlipLongEdge" == duplex)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001287 return DuplexFlipLongEdge;
1288 return DuplexUndefined;
Bo Xu9114e832014-07-14 13:22:47 -07001289}
1290
thestig04bebfe2016-11-04 16:07:25 -07001291DLLEXPORT unsigned long STDCALL FPDF_VIEWERREF_GetName(FPDF_DOCUMENT document,
1292 FPDF_BYTESTRING key,
1293 char* buffer,
1294 unsigned long length) {
1295 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1296 if (!pDoc)
1297 return 0;
1298
1299 CPDF_ViewerPreferences viewRef(pDoc);
1300 CFX_ByteString bsVal;
1301 if (!viewRef.GenericName(key, &bsVal))
1302 return 0;
1303
1304 unsigned long dwStringLen = bsVal.GetLength() + 1;
1305 if (buffer && length >= dwStringLen)
1306 memcpy(buffer, bsVal.c_str(), dwStringLen);
1307 return dwStringLen;
1308}
1309
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001310DLLEXPORT FPDF_DWORD STDCALL FPDF_CountNamedDests(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001311 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1312 if (!pDoc)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001313 return 0;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001314
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001315 CPDF_Dictionary* pRoot = pDoc->GetRoot();
1316 if (!pRoot)
1317 return 0;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001318
Lei Zhangd983b092015-12-14 16:58:33 -08001319 CPDF_NameTree nameTree(pDoc, "Dests");
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001320 pdfium::base::CheckedNumeric<FPDF_DWORD> count = nameTree.GetCount();
dsinclair38fd8442016-09-15 10:15:32 -07001321 CPDF_Dictionary* pDest = pRoot->GetDictFor("Dests");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001322 if (pDest)
1323 count += pDest->GetCount();
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001324
1325 if (!count.IsValid())
1326 return 0;
1327
1328 return count.ValueOrDie();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001329}
1330
1331DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDestByName(FPDF_DOCUMENT document,
1332 FPDF_BYTESTRING name) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001333 if (!name || name[0] == 0)
Tom Sepez471a1032015-10-15 16:17:18 -07001334 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001335
Tom Sepez471a1032015-10-15 16:17:18 -07001336 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1337 if (!pDoc)
1338 return nullptr;
1339
Lei Zhangd983b092015-12-14 16:58:33 -08001340 CPDF_NameTree name_tree(pDoc, "Dests");
Tom Sepez471a1032015-10-15 16:17:18 -07001341 return name_tree.LookupNamedDest(pDoc, name);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001342}
1343
Tom Sepez51da0932015-11-25 16:05:49 -08001344#ifdef PDF_ENABLE_XFA
thestig77d148d2016-04-06 06:28:31 -07001345DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Init(FPDF_BSTR* str) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001346 if (!str)
1347 return -1;
1348
Dan Sinclair1c5d0b42017-04-03 15:05:11 -04001349 memset(str, 0, sizeof(FPDF_BSTR));
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001350 return 0;
1351}
1352
thestig77d148d2016-04-06 06:28:31 -07001353DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Set(FPDF_BSTR* str,
1354 FPDF_LPCSTR bstr,
1355 int length) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001356 if (!str)
1357 return -1;
1358 if (!bstr || !length)
1359 return -1;
1360 if (length == -1)
1361 length = FXSYS_strlen(bstr);
1362
1363 if (length == 0) {
1364 if (str->str) {
1365 FX_Free(str->str);
thestig1cd352e2016-06-07 17:53:06 -07001366 str->str = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001367 }
1368 str->len = 0;
1369 return 0;
1370 }
1371
1372 if (str->str && str->len < length)
1373 str->str = FX_Realloc(char, str->str, length + 1);
1374 else if (!str->str)
1375 str->str = FX_Alloc(char, length + 1);
1376
1377 str->str[length] = 0;
Dan Sinclair1c5d0b42017-04-03 15:05:11 -04001378 memcpy(str->str, bstr, length);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001379 str->len = length;
1380
1381 return 0;
1382}
1383
thestig77d148d2016-04-06 06:28:31 -07001384DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Clear(FPDF_BSTR* str) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001385 if (!str)
1386 return -1;
1387
1388 if (str->str) {
1389 FX_Free(str->str);
thestig1cd352e2016-06-07 17:53:06 -07001390 str->str = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001391 }
1392 str->len = 0;
1393 return 0;
1394}
Tom Sepez40e9ff32015-11-30 12:39:54 -08001395#endif // PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001396
1397DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDest(FPDF_DOCUMENT document,
1398 int index,
1399 void* buffer,
1400 long* buflen) {
1401 if (!buffer)
1402 *buflen = 0;
Tom Sepez540c4362015-11-24 13:33:57 -08001403
1404 if (index < 0)
1405 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001406
Tom Sepezbf59a072015-10-21 14:07:23 -07001407 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Tom Sepez540c4362015-11-24 13:33:57 -08001408 if (!pDoc)
1409 return nullptr;
1410
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001411 CPDF_Dictionary* pRoot = pDoc->GetRoot();
1412 if (!pRoot)
Tom Sepez540c4362015-11-24 13:33:57 -08001413 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001414
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001415 CPDF_Object* pDestObj = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001416 CFX_ByteString bsName;
Lei Zhangd983b092015-12-14 16:58:33 -08001417 CPDF_NameTree nameTree(pDoc, "Dests");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001418 int count = nameTree.GetCount();
1419 if (index >= count) {
dsinclair38fd8442016-09-15 10:15:32 -07001420 CPDF_Dictionary* pDest = pRoot->GetDictFor("Dests");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001421 if (!pDest)
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001422 return nullptr;
1423
1424 pdfium::base::CheckedNumeric<int> checked_count = count;
1425 checked_count += pDest->GetCount();
1426 if (!checked_count.IsValid() || index >= checked_count.ValueOrDie())
1427 return nullptr;
1428
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001429 index -= count;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001430 int i = 0;
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001431 for (const auto& it : *pDest) {
1432 bsName = it.first;
tsepez0e606b52016-11-18 16:22:41 -08001433 pDestObj = it.second.get();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001434 if (!pDestObj)
1435 continue;
1436 if (i == index)
1437 break;
1438 i++;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001439 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001440 } else {
Tom Sepezc4a2b752017-04-07 13:56:13 -07001441 pDestObj = nameTree.LookupValueAndName(index, &bsName);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001442 }
1443 if (!pDestObj)
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001444 return nullptr;
Dan Sinclairf1251c12015-10-20 16:24:45 -04001445 if (CPDF_Dictionary* pDict = pDestObj->AsDictionary()) {
dsinclair38fd8442016-09-15 10:15:32 -07001446 pDestObj = pDict->GetArrayFor("D");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001447 if (!pDestObj)
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001448 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001449 }
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001450 if (!pDestObj->IsArray())
1451 return nullptr;
1452
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001453 CFX_WideString wsName = PDF_DecodeText(bsName);
1454 CFX_ByteString utf16Name = wsName.UTF16LE_Encode();
weili47ca6922016-03-31 15:08:27 -07001455 int len = utf16Name.GetLength();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001456 if (!buffer) {
1457 *buflen = len;
thestig9067fd62016-11-23 14:10:06 -08001458 } else if (len <= *buflen) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001459 memcpy(buffer, utf16Name.c_str(), len);
1460 *buflen = len;
1461 } else {
1462 *buflen = -1;
1463 }
1464 return (FPDF_DEST)pDestObj;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001465}