blob: bda9111b95298e09478f28bdf5a8ecf05d3e16cd [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
thestig25fa42f2016-05-25 21:39:46 -070052#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
dsinclair74a34fc2016-09-29 16:41:42 -070053#include "core/fxge/cfx_windowsdevice.h"
thestig25fa42f2016-05-25 21:39:46 -070054#endif
55
thestiga78ba602016-11-23 15:25:48 -080056namespace {
57
Dan Sinclair830897a2017-05-11 14:36:10 -040058bool g_bLibraryInitialized = false;
tsepez02759102016-12-01 08:29:25 -080059
thestiga78ba602016-11-23 15:25:48 -080060void RenderPageImpl(CPDF_PageRenderContext* pContext,
61 CPDF_Page* pPage,
62 const CFX_Matrix& matrix,
63 const FX_RECT& clipping_rect,
64 int flags,
65 bool bNeedToRestore,
66 IFSDK_PAUSE_Adapter* pause) {
67 if (!pContext->m_pOptions)
68 pContext->m_pOptions = pdfium::MakeUnique<CPDF_RenderOptions>();
69
70 if (flags & FPDF_LCD_TEXT)
71 pContext->m_pOptions->m_Flags |= RENDER_CLEARTYPE;
72 else
73 pContext->m_pOptions->m_Flags &= ~RENDER_CLEARTYPE;
74
75 if (flags & FPDF_NO_NATIVETEXT)
76 pContext->m_pOptions->m_Flags |= RENDER_NO_NATIVETEXT;
77 if (flags & FPDF_RENDER_LIMITEDIMAGECACHE)
78 pContext->m_pOptions->m_Flags |= RENDER_LIMITEDIMAGECACHE;
79 if (flags & FPDF_RENDER_FORCEHALFTONE)
80 pContext->m_pOptions->m_Flags |= RENDER_FORCE_HALFTONE;
81#ifndef PDF_ENABLE_XFA
82 if (flags & FPDF_RENDER_NO_SMOOTHTEXT)
83 pContext->m_pOptions->m_Flags |= RENDER_NOTEXTSMOOTH;
84 if (flags & FPDF_RENDER_NO_SMOOTHIMAGE)
85 pContext->m_pOptions->m_Flags |= RENDER_NOIMAGESMOOTH;
86 if (flags & FPDF_RENDER_NO_SMOOTHPATH)
87 pContext->m_pOptions->m_Flags |= RENDER_NOPATHSMOOTH;
88#endif // PDF_ENABLE_XFA
89
90 // Grayscale output
91 if (flags & FPDF_GRAYSCALE) {
92 pContext->m_pOptions->m_ColorMode = RENDER_COLOR_GRAY;
93 pContext->m_pOptions->m_ForeColor = 0;
94 pContext->m_pOptions->m_BackColor = 0xffffff;
95 }
96
97 const CPDF_OCContext::UsageType usage =
98 (flags & FPDF_PRINTING) ? CPDF_OCContext::Print : CPDF_OCContext::View;
99 pContext->m_pOptions->m_AddFlags = flags >> 8;
100 pContext->m_pOptions->m_pOCContext =
Tom Sepezf716f0b2017-01-30 10:04:07 -0800101 pdfium::MakeRetain<CPDF_OCContext>(pPage->m_pDocument, usage);
thestiga78ba602016-11-23 15:25:48 -0800102
103 pContext->m_pDevice->SaveState();
104 pContext->m_pDevice->SetClip_Rect(clipping_rect);
105
106 pContext->m_pContext = pdfium::MakeUnique<CPDF_RenderContext>(pPage);
107 pContext->m_pContext->AppendLayer(pPage, &matrix);
108
109 if (flags & FPDF_ANNOT) {
110 pContext->m_pAnnots = pdfium::MakeUnique<CPDF_AnnotList>(pPage);
111 bool bPrinting = pContext->m_pDevice->GetDeviceClass() != FXDC_DISPLAY;
112 pContext->m_pAnnots->DisplayAnnots(pPage, pContext->m_pContext.get(),
113 bPrinting, &matrix, false, nullptr);
114 }
115
116 pContext->m_pRenderer = pdfium::MakeUnique<CPDF_ProgressiveRenderer>(
117 pContext->m_pContext.get(), pContext->m_pDevice.get(),
118 pContext->m_pOptions.get());
119 pContext->m_pRenderer->Start(pause);
120 if (bNeedToRestore)
121 pContext->m_pDevice->RestoreState(false);
122}
123
tsepezbea04972016-12-01 13:54:42 -0800124class CPDF_CustomAccess final : public IFX_SeekableReadStream {
125 public:
Tom Sepez40badde2017-05-01 13:21:39 -0700126 template <typename T, typename... Args>
127 friend CFX_RetainPtr<T> pdfium::MakeRetain(Args&&... args);
tsepezbea04972016-12-01 13:54:42 -0800128
129 // IFX_SeekableReadStream
130 FX_FILESIZE GetSize() override;
tsepezbea04972016-12-01 13:54:42 -0800131 bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override;
132
133 private:
tsepez833619b2016-12-07 09:21:17 -0800134 explicit CPDF_CustomAccess(FPDF_FILEACCESS* pFileAccess);
135
tsepezbea04972016-12-01 13:54:42 -0800136 FPDF_FILEACCESS m_FileAccess;
137};
138
139CPDF_CustomAccess::CPDF_CustomAccess(FPDF_FILEACCESS* pFileAccess)
140 : m_FileAccess(*pFileAccess) {}
141
142FX_FILESIZE CPDF_CustomAccess::GetSize() {
143 return m_FileAccess.m_FileLen;
144}
145
tsepezbea04972016-12-01 13:54:42 -0800146bool CPDF_CustomAccess::ReadBlock(void* buffer,
147 FX_FILESIZE offset,
148 size_t size) {
149 if (offset < 0)
150 return false;
151
152 FX_SAFE_FILESIZE newPos = pdfium::base::checked_cast<FX_FILESIZE>(size);
153 newPos += offset;
154 if (!newPos.IsValid() ||
155 newPos.ValueOrDie() > static_cast<FX_FILESIZE>(m_FileAccess.m_FileLen)) {
156 return false;
157 }
158 return !!m_FileAccess.m_GetBlock(m_FileAccess.m_Param, offset,
159 reinterpret_cast<uint8_t*>(buffer), size);
160}
161
Tom Sepez40e9ff32015-11-30 12:39:54 -0800162#ifdef PDF_ENABLE_XFA
tsepezfa89a202016-12-02 09:48:30 -0800163class CFPDF_FileStream : public IFX_SeekableStream {
164 public:
Tom Sepez40badde2017-05-01 13:21:39 -0700165 template <typename T, typename... Args>
166 friend CFX_RetainPtr<T> pdfium::MakeRetain(Args&&... args);
167
tsepez833619b2016-12-07 09:21:17 -0800168 ~CFPDF_FileStream() override;
Tom Sepez471a1032015-10-15 16:17:18 -0700169
tsepezfa89a202016-12-02 09:48:30 -0800170 // IFX_SeekableStream:
tsepezfa89a202016-12-02 09:48:30 -0800171 FX_FILESIZE GetSize() override;
172 bool IsEOF() override;
173 FX_FILESIZE GetPosition() override;
174 bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override;
175 size_t ReadBlock(void* buffer, size_t size) override;
176 bool WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size) override;
177 bool Flush() override;
Tom Sepezbf59a072015-10-21 14:07:23 -0700178
tsepezfa89a202016-12-02 09:48:30 -0800179 void SetPosition(FX_FILESIZE pos) { m_nCurPos = pos; }
Tom Sepezdb0be962015-10-16 14:00:21 -0700180
tsepezfa89a202016-12-02 09:48:30 -0800181 protected:
tsepez833619b2016-12-07 09:21:17 -0800182 explicit CFPDF_FileStream(FPDF_FILEHANDLER* pFS);
183
tsepezfa89a202016-12-02 09:48:30 -0800184 FPDF_FILEHANDLER* m_pFS;
185 FX_FILESIZE m_nCurPos;
186};
thestigbefa4502016-05-26 20:15:19 -0700187
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700188CFPDF_FileStream::CFPDF_FileStream(FPDF_FILEHANDLER* pFS) {
189 m_pFS = pFS;
190 m_nCurPos = 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700191}
192
tsepez833619b2016-12-07 09:21:17 -0800193CFPDF_FileStream::~CFPDF_FileStream() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700194 if (m_pFS && m_pFS->Release)
195 m_pFS->Release(m_pFS->clientData);
Bo Xufdc00a72014-10-28 23:03:33 -0700196}
197
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700198FX_FILESIZE CFPDF_FileStream::GetSize() {
199 if (m_pFS && m_pFS->GetSize)
200 return (FX_FILESIZE)m_pFS->GetSize(m_pFS->clientData);
201 return 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700202}
203
tsepezf39074c2016-10-26 15:33:58 -0700204bool CFPDF_FileStream::IsEOF() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700205 return m_nCurPos >= GetSize();
Bo Xufdc00a72014-10-28 23:03:33 -0700206}
207
weili625ad662016-06-15 11:21:33 -0700208FX_FILESIZE CFPDF_FileStream::GetPosition() {
209 return m_nCurPos;
210}
211
tsepezf39074c2016-10-26 15:33:58 -0700212bool CFPDF_FileStream::ReadBlock(void* buffer,
213 FX_FILESIZE offset,
214 size_t size) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700215 if (!buffer || !size || !m_pFS->ReadBlock)
tsepezf39074c2016-10-26 15:33:58 -0700216 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700217
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700218 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
219 (FPDF_DWORD)size) == 0) {
220 m_nCurPos = offset + size;
tsepezf39074c2016-10-26 15:33:58 -0700221 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700222 }
tsepezf39074c2016-10-26 15:33:58 -0700223 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700224}
225
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700226size_t CFPDF_FileStream::ReadBlock(void* buffer, size_t size) {
227 if (!buffer || !size || !m_pFS->ReadBlock)
228 return 0;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700229
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700230 FX_FILESIZE nSize = GetSize();
231 if (m_nCurPos >= nSize)
232 return 0;
233 FX_FILESIZE dwAvail = nSize - m_nCurPos;
234 if (dwAvail < (FX_FILESIZE)size)
235 size = (size_t)dwAvail;
236 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)m_nCurPos, buffer,
237 (FPDF_DWORD)size) == 0) {
238 m_nCurPos += size;
239 return size;
240 }
Bo Xufdc00a72014-10-28 23:03:33 -0700241
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700242 return 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700243}
244
tsepezf39074c2016-10-26 15:33:58 -0700245bool CFPDF_FileStream::WriteBlock(const void* buffer,
246 FX_FILESIZE offset,
247 size_t size) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700248 if (!m_pFS || !m_pFS->WriteBlock)
tsepezf39074c2016-10-26 15:33:58 -0700249 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700250
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700251 if (m_pFS->WriteBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
252 (FPDF_DWORD)size) == 0) {
253 m_nCurPos = offset + size;
tsepezf39074c2016-10-26 15:33:58 -0700254 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700255 }
tsepezf39074c2016-10-26 15:33:58 -0700256 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700257}
258
tsepezf39074c2016-10-26 15:33:58 -0700259bool CFPDF_FileStream::Flush() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700260 if (!m_pFS || !m_pFS->Flush)
tsepezf39074c2016-10-26 15:33:58 -0700261 return true;
Bo Xufdc00a72014-10-28 23:03:33 -0700262
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700263 return m_pFS->Flush(m_pFS->clientData) == 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700264}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800265#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700266
tsepezfa89a202016-12-02 09:48:30 -0800267} // namespace
268
269UnderlyingDocumentType* UnderlyingFromFPDFDocument(FPDF_DOCUMENT doc) {
270 return static_cast<UnderlyingDocumentType*>(doc);
271}
272
273FPDF_DOCUMENT FPDFDocumentFromUnderlying(UnderlyingDocumentType* doc) {
274 return static_cast<FPDF_DOCUMENT>(doc);
275}
276
277UnderlyingPageType* UnderlyingFromFPDFPage(FPDF_PAGE page) {
278 return static_cast<UnderlyingPageType*>(page);
279}
280
281CPDF_Document* CPDFDocumentFromFPDFDocument(FPDF_DOCUMENT doc) {
282#ifdef PDF_ENABLE_XFA
283 return doc ? UnderlyingFromFPDFDocument(doc)->GetPDFDoc() : nullptr;
284#else // PDF_ENABLE_XFA
285 return UnderlyingFromFPDFDocument(doc);
286#endif // PDF_ENABLE_XFA
287}
288
289FPDF_DOCUMENT FPDFDocumentFromCPDFDocument(CPDF_Document* doc) {
290#ifdef PDF_ENABLE_XFA
291 return doc ? FPDFDocumentFromUnderlying(
292 new CPDFXFA_Context(pdfium::WrapUnique(doc)))
293 : nullptr;
294#else // PDF_ENABLE_XFA
295 return FPDFDocumentFromUnderlying(doc);
296#endif // PDF_ENABLE_XFA
297}
298
299CPDF_Page* CPDFPageFromFPDFPage(FPDF_PAGE page) {
300#ifdef PDF_ENABLE_XFA
301 return page ? UnderlyingFromFPDFPage(page)->GetPDFPage() : nullptr;
302#else // PDF_ENABLE_XFA
303 return UnderlyingFromFPDFPage(page);
304#endif // PDF_ENABLE_XFA
305}
306
307CFX_DIBitmap* CFXBitmapFromFPDFBitmap(FPDF_BITMAP bitmap) {
308 return static_cast<CFX_DIBitmap*>(bitmap);
309}
310
tsepez833619b2016-12-07 09:21:17 -0800311CFX_RetainPtr<IFX_SeekableReadStream> MakeSeekableReadStream(
312 FPDF_FILEACCESS* pFileAccess) {
Tom Sepez40badde2017-05-01 13:21:39 -0700313 return pdfium::MakeRetain<CPDF_CustomAccess>(pFileAccess);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700314}
315
tsepezfa89a202016-12-02 09:48:30 -0800316#ifdef PDF_ENABLE_XFA
tsepez833619b2016-12-07 09:21:17 -0800317CFX_RetainPtr<IFX_SeekableStream> MakeSeekableStream(
318 FPDF_FILEHANDLER* pFilehandler) {
Tom Sepez40badde2017-05-01 13:21:39 -0700319 return pdfium::MakeRetain<CFPDF_FileStream>(pFilehandler);
tsepezfa89a202016-12-02 09:48:30 -0800320}
321#endif // PDF_ENABLE_XFA
322
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700323// 0 bit: FPDF_POLICY_MACHINETIME_ACCESS
tsepezc3255f52016-03-25 14:52:27 -0700324static uint32_t foxit_sandbox_policy = 0xFFFFFFFF;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700325
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700326void FSDK_SetSandBoxPolicy(FPDF_DWORD policy, FPDF_BOOL enable) {
327 switch (policy) {
328 case FPDF_POLICY_MACHINETIME_ACCESS: {
329 if (enable)
330 foxit_sandbox_policy |= 0x01;
331 else
332 foxit_sandbox_policy &= 0xFFFFFFFE;
333 } break;
334 default:
335 break;
336 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700337}
338
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700339FPDF_BOOL FSDK_IsSandBoxPolicyEnabled(FPDF_DWORD policy) {
340 switch (policy) {
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700341 case FPDF_POLICY_MACHINETIME_ACCESS:
Lei Zhangb0748bb2015-10-19 12:11:49 -0700342 return !!(foxit_sandbox_policy & 0x01);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700343 default:
tsepez4cf55152016-11-02 14:37:54 -0700344 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700345 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700346}
347
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700348DLLEXPORT void STDCALL FPDF_InitLibrary() {
Lei Zhang6f62d532015-09-23 15:31:44 -0700349 FPDF_InitLibraryWithConfig(nullptr);
350}
351
Dan Sinclairf766ad22016-03-14 13:51:24 -0400352DLLEXPORT void STDCALL
353FPDF_InitLibraryWithConfig(const FPDF_LIBRARY_CONFIG* cfg) {
Dan Sinclair830897a2017-05-11 14:36:10 -0400354 if (g_bLibraryInitialized)
tsepez02759102016-12-01 08:29:25 -0800355 return;
356
Dan Sinclairdbc3d3e2017-05-11 13:41:38 -0400357 FXMEM_InitializePartitionAlloc();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700358
weili47228ac2016-07-20 10:35:31 -0700359 CFX_GEModule* pModule = CFX_GEModule::Get();
Dan Sinclair830897a2017-05-11 14:36:10 -0400360 pModule->Init(cfg ? cfg->m_pUserFontPaths : nullptr);
tsepez02759102016-12-01 08:29:25 -0800361
Tom Sepez1b246282015-11-25 15:15:31 -0800362 CPDF_ModuleMgr* pModuleMgr = CPDF_ModuleMgr::Get();
Dan Sinclair830897a2017-05-11 14:36:10 -0400363 pModuleMgr->SetCodecModule(pModule->GetCodecModule());
Tom Sepez1b246282015-11-25 15:15:31 -0800364 pModuleMgr->InitPageModule();
Dan Sinclair830897a2017-05-11 14:36:10 -0400365 pModuleMgr->LoadEmbeddedMaps();
366 pModuleMgr->LoadCodecModules();
Tom Sepezb4a26182017-03-01 12:15:00 -0800367
Tom Sepez40e9ff32015-11-30 12:39:54 -0800368#ifdef PDF_ENABLE_XFA
dsinclair8837c912016-11-01 11:22:37 -0700369 FXJSE_Initialize();
370 BC_Library_Init();
Tom Sepez40e9ff32015-11-30 12:39:54 -0800371#endif // PDF_ENABLE_XFA
Tom Sepez452b4f32015-10-13 09:27:27 -0700372 if (cfg && cfg->version >= 2)
373 IJS_Runtime::Initialize(cfg->m_v8EmbedderSlot, cfg->m_pIsolate);
Dan Sinclair830897a2017-05-11 14:36:10 -0400374
375 g_bLibraryInitialized = true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700376}
377
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700378DLLEXPORT void STDCALL FPDF_DestroyLibrary() {
Dan Sinclair830897a2017-05-11 14:36:10 -0400379 if (!g_bLibraryInitialized)
tsepez02759102016-12-01 08:29:25 -0800380 return;
381
Tom Sepez51da0932015-11-25 16:05:49 -0800382#ifdef PDF_ENABLE_XFA
Tom Sepez5628fd72017-04-27 14:58:53 -0700383 BC_Library_Destroy();
dsinclair8837c912016-11-01 11:22:37 -0700384 FXJSE_Finalize();
Tom Sepez40e9ff32015-11-30 12:39:54 -0800385#endif // PDF_ENABLE_XFA
dsinclair8837c912016-11-01 11:22:37 -0700386
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700387 CPDF_ModuleMgr::Destroy();
388 CFX_GEModule::Destroy();
Tom Sepez2c286192015-06-18 12:47:11 -0700389
thestig2d6dda12016-06-28 07:39:09 -0700390 IJS_Runtime::Destroy();
Dan Sinclair830897a2017-05-11 14:36:10 -0400391
392 g_bLibraryInitialized = false;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700393}
394
395#ifndef _WIN32
396int g_LastError;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700397void SetLastError(int err) {
398 g_LastError = err;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700399}
400
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700401int GetLastError() {
402 return g_LastError;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700403}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800404#endif // _WIN32
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700405
Tom Sepezf10ae632016-01-26 14:19:52 -0800406void ProcessParseError(CPDF_Parser::Error err) {
tsepezc3255f52016-03-25 14:52:27 -0700407 uint32_t err_code = FPDF_ERR_SUCCESS;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700408 // Translate FPDFAPI error code to FPDFVIEW error code
Tom Sepezf10ae632016-01-26 14:19:52 -0800409 switch (err) {
410 case CPDF_Parser::SUCCESS:
411 err_code = FPDF_ERR_SUCCESS;
412 break;
413 case CPDF_Parser::FILE_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700414 err_code = FPDF_ERR_FILE;
415 break;
Tom Sepezf10ae632016-01-26 14:19:52 -0800416 case CPDF_Parser::FORMAT_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700417 err_code = FPDF_ERR_FORMAT;
418 break;
Tom Sepezf10ae632016-01-26 14:19:52 -0800419 case CPDF_Parser::PASSWORD_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700420 err_code = FPDF_ERR_PASSWORD;
421 break;
Tom Sepezf10ae632016-01-26 14:19:52 -0800422 case CPDF_Parser::HANDLER_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700423 err_code = FPDF_ERR_SECURITY;
424 break;
425 }
426 SetLastError(err_code);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700427}
428
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700429DLLEXPORT void STDCALL FPDF_SetSandBoxPolicy(FPDF_DWORD policy,
430 FPDF_BOOL enable) {
431 return FSDK_SetSandBoxPolicy(policy, enable);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700432}
433
rbpotterdb764702017-01-12 10:31:43 -0800434#if defined(_WIN32)
435#if defined(PDFIUM_PRINT_TEXT_WITH_GDI)
thestigfdb35ff2016-07-18 13:45:44 -0700436DLLEXPORT void STDCALL
437FPDF_SetTypefaceAccessibleFunc(PDFiumEnsureTypefaceCharactersAccessible func) {
438 g_pdfium_typeface_accessible_func = func;
439}
440
441DLLEXPORT void STDCALL FPDF_SetPrintTextWithGDI(FPDF_BOOL use_gdi) {
442 g_pdfium_print_text_with_gdi = !!use_gdi;
443}
rbpotterdb764702017-01-12 10:31:43 -0800444#endif // PDFIUM_PRINT_TEXT_WITH_GDI
445
446DLLEXPORT FPDF_BOOL STDCALL FPDF_SetPrintPostscriptLevel(int postscript_level) {
447 if (postscript_level != 0 && postscript_level != 2 && postscript_level != 3)
448 return FALSE;
449 g_pdfium_print_postscript_level = postscript_level;
450 return TRUE;
451}
452#endif // defined(_WIN32)
thestigfdb35ff2016-07-18 13:45:44 -0700453
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700454DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadDocument(FPDF_STRING file_path,
455 FPDF_BYTESTRING password) {
Tom Sepeze3166a82015-08-05 10:50:32 -0700456 // NOTE: the creation of the file needs to be by the embedder on the
457 // other side of this API.
tsepez833619b2016-12-07 09:21:17 -0800458 CFX_RetainPtr<IFX_SeekableReadStream> pFileAccess =
Dan Sinclair812e96c2017-03-13 16:43:37 -0400459 IFX_SeekableReadStream::CreateFromFilename((const char*)file_path);
tsepez345d4892016-11-30 15:10:55 -0800460 if (!pFileAccess)
Tom Sepeze3166a82015-08-05 10:50:32 -0700461 return nullptr;
Tom Sepeze3166a82015-08-05 10:50:32 -0700462
tsepez345d4892016-11-30 15:10:55 -0800463 auto pParser = pdfium::MakeUnique<CPDF_Parser>();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700464 pParser->SetPassword(password);
Bo Xud4e406e2014-08-13 11:03:19 -0700465
tsepez345d4892016-11-30 15:10:55 -0800466 auto pDocument = pdfium::MakeUnique<CPDF_Document>(std::move(pParser));
dsinclair156de022016-08-24 11:58:24 -0700467 CPDF_Parser::Error error =
468 pDocument->GetParser()->StartParse(pFileAccess, pDocument.get());
Tom Sepezf10ae632016-01-26 14:19:52 -0800469 if (error != CPDF_Parser::SUCCESS) {
Tom Sepezf10ae632016-01-26 14:19:52 -0800470 ProcessParseError(error);
thestig1cd352e2016-06-07 17:53:06 -0700471 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700472 }
Dan Sinclaircb377be2017-05-11 16:05:32 -0400473 CheckUnSupportError(pDocument.get(), error);
dsinclair8837c912016-11-01 11:22:37 -0700474 return FPDFDocumentFromCPDFDocument(pDocument.release());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700475}
Jun Fange118ce92015-02-17 06:50:08 -0800476
Tom Sepez40e9ff32015-11-30 12:39:54 -0800477#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700478DLLEXPORT FPDF_BOOL STDCALL FPDF_HasXFAField(FPDF_DOCUMENT document,
479 int* docType) {
480 if (!document)
tsepez4cf55152016-11-02 14:37:54 -0700481 return false;
JUN FANG827a1722015-03-05 13:39:21 -0800482
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700483 CPDF_Document* pdfDoc =
dsinclair521b7502016-11-02 13:02:28 -0700484 (static_cast<CPDFXFA_Context*>(document))->GetPDFDoc();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700485 if (!pdfDoc)
tsepez4cf55152016-11-02 14:37:54 -0700486 return false;
JUN FANG827a1722015-03-05 13:39:21 -0800487
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700488 CPDF_Dictionary* pRoot = pdfDoc->GetRoot();
489 if (!pRoot)
tsepez4cf55152016-11-02 14:37:54 -0700490 return false;
JUN FANG827a1722015-03-05 13:39:21 -0800491
dsinclair38fd8442016-09-15 10:15:32 -0700492 CPDF_Dictionary* pAcroForm = pRoot->GetDictFor("AcroForm");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700493 if (!pAcroForm)
tsepez4cf55152016-11-02 14:37:54 -0700494 return false;
JUN FANG827a1722015-03-05 13:39:21 -0800495
dsinclair38fd8442016-09-15 10:15:32 -0700496 CPDF_Object* pXFA = pAcroForm->GetObjectFor("XFA");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700497 if (!pXFA)
tsepez4cf55152016-11-02 14:37:54 -0700498 return false;
JUN FANG827a1722015-03-05 13:39:21 -0800499
dsinclair38fd8442016-09-15 10:15:32 -0700500 bool bDynamicXFA = pRoot->GetBooleanFor("NeedsRendering", false);
thestigded36342016-05-23 17:54:02 -0700501 *docType = bDynamicXFA ? DOCTYPE_DYNAMIC_XFA : DOCTYPE_STATIC_XFA;
tsepez4cf55152016-11-02 14:37:54 -0700502 return true;
Jun Fange118ce92015-02-17 06:50:08 -0800503}
504
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700505DLLEXPORT FPDF_BOOL STDCALL FPDF_LoadXFA(FPDF_DOCUMENT document) {
dsinclair521b7502016-11-02 13:02:28 -0700506 return document && (static_cast<CPDFXFA_Context*>(document))->LoadXFADoc();
Bo Xufdc00a72014-10-28 23:03:33 -0700507}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800508#endif // PDF_ENABLE_XFA
Bo Xufdc00a72014-10-28 23:03:33 -0700509
tsepezad2441e2016-10-24 10:19:11 -0700510class CMemFile final : public IFX_SeekableReadStream {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700511 public:
tsepez833619b2016-12-07 09:21:17 -0800512 static CFX_RetainPtr<CMemFile> Create(uint8_t* pBuf, FX_FILESIZE size) {
513 return CFX_RetainPtr<CMemFile>(new CMemFile(pBuf, size));
514 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700515
Lei Zhang3884dba2015-10-19 17:27:53 -0700516 FX_FILESIZE GetSize() override { return m_size; }
tsepezf39074c2016-10-26 15:33:58 -0700517 bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override {
tsepez833619b2016-12-07 09:21:17 -0800518 if (offset < 0)
tsepezf39074c2016-10-26 15:33:58 -0700519 return false;
tsepez833619b2016-12-07 09:21:17 -0800520
tsepez4e597c82016-11-07 15:16:01 -0800521 FX_SAFE_FILESIZE newPos = pdfium::base::checked_cast<FX_FILESIZE>(size);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700522 newPos += offset;
tsepez833619b2016-12-07 09:21:17 -0800523 if (!newPos.IsValid() || newPos.ValueOrDie() > m_size)
tsepezf39074c2016-10-26 15:33:58 -0700524 return false;
tsepez833619b2016-12-07 09:21:17 -0800525
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400526 memcpy(buffer, m_pBuf + offset, size);
tsepezf39074c2016-10-26 15:33:58 -0700527 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700528 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700529
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700530 private:
tsepez833619b2016-12-07 09:21:17 -0800531 CMemFile(uint8_t* pBuf, FX_FILESIZE size) : m_pBuf(pBuf), m_size(size) {}
Lei Zhang2b1a2d52015-08-14 22:16:22 -0700532
Lei Zhang3884dba2015-10-19 17:27:53 -0700533 uint8_t* const m_pBuf;
534 const FX_FILESIZE m_size;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700535};
Lei Zhang3884dba2015-10-19 17:27:53 -0700536
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700537DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadMemDocument(const void* data_buf,
538 int size,
539 FPDF_BYTESTRING password) {
tsepez833619b2016-12-07 09:21:17 -0800540 CFX_RetainPtr<CMemFile> pMemFile = CMemFile::Create((uint8_t*)data_buf, size);
541 auto pParser = pdfium::MakeUnique<CPDF_Parser>();
tsepez4540fba2016-08-16 11:12:21 -0700542 pParser->SetPassword(password);
543
tsepez833619b2016-12-07 09:21:17 -0800544 auto pDocument = pdfium::MakeUnique<CPDF_Document>(std::move(pParser));
tsepez4540fba2016-08-16 11:12:21 -0700545 CPDF_Parser::Error error =
dsinclaircedaa552016-08-24 11:12:19 -0700546 pDocument->GetParser()->StartParse(pMemFile, pDocument.get());
Tom Sepezf10ae632016-01-26 14:19:52 -0800547 if (error != CPDF_Parser::SUCCESS) {
Tom Sepezf10ae632016-01-26 14:19:52 -0800548 ProcessParseError(error);
thestig1cd352e2016-06-07 17:53:06 -0700549 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700550 }
dsinclaircedaa552016-08-24 11:12:19 -0700551 CheckUnSupportError(pDocument.get(), error);
552 return FPDFDocumentFromCPDFDocument(pDocument.release());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700553}
554
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700555DLLEXPORT FPDF_DOCUMENT STDCALL
556FPDF_LoadCustomDocument(FPDF_FILEACCESS* pFileAccess,
557 FPDF_BYTESTRING password) {
Tom Sepez40badde2017-05-01 13:21:39 -0700558 auto pFile = pdfium::MakeRetain<CPDF_CustomAccess>(pFileAccess);
tsepez833619b2016-12-07 09:21:17 -0800559 auto pParser = pdfium::MakeUnique<CPDF_Parser>();
tsepez4540fba2016-08-16 11:12:21 -0700560 pParser->SetPassword(password);
561
tsepez833619b2016-12-07 09:21:17 -0800562 auto pDocument = pdfium::MakeUnique<CPDF_Document>(std::move(pParser));
dsinclaircedaa552016-08-24 11:12:19 -0700563 CPDF_Parser::Error error =
564 pDocument->GetParser()->StartParse(pFile, pDocument.get());
Tom Sepezf10ae632016-01-26 14:19:52 -0800565 if (error != CPDF_Parser::SUCCESS) {
Tom Sepezf10ae632016-01-26 14:19:52 -0800566 ProcessParseError(error);
thestig1cd352e2016-06-07 17:53:06 -0700567 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700568 }
dsinclaircedaa552016-08-24 11:12:19 -0700569 CheckUnSupportError(pDocument.get(), error);
570 return FPDFDocumentFromCPDFDocument(pDocument.release());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700571}
572
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700573DLLEXPORT FPDF_BOOL STDCALL FPDF_GetFileVersion(FPDF_DOCUMENT doc,
574 int* fileVersion) {
Tom Sepez471a1032015-10-15 16:17:18 -0700575 if (!fileVersion)
tsepez4cf55152016-11-02 14:37:54 -0700576 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700577
Tom Sepez471a1032015-10-15 16:17:18 -0700578 *fileVersion = 0;
579 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(doc);
580 if (!pDoc)
tsepez4cf55152016-11-02 14:37:54 -0700581 return false;
Tom Sepez471a1032015-10-15 16:17:18 -0700582
583 CPDF_Parser* pParser = pDoc->GetParser();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700584 if (!pParser)
tsepez4cf55152016-11-02 14:37:54 -0700585 return false;
Tom Sepez471a1032015-10-15 16:17:18 -0700586
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700587 *fileVersion = pParser->GetFileVersion();
tsepez4cf55152016-11-02 14:37:54 -0700588 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700589}
590
tsepezc3255f52016-03-25 14:52:27 -0700591// jabdelmalek: changed return type from uint32_t to build on Linux (and match
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700592// header).
593DLLEXPORT unsigned long STDCALL FPDF_GetDocPermissions(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700594 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
thestig27ddf162016-05-23 15:06:59 -0700595 // https://bugs.chromium.org/p/pdfium/issues/detail?id=499
596 if (!pDoc) {
Tom Sepez51da0932015-11-25 16:05:49 -0800597#ifndef PDF_ENABLE_XFA
598 return 0;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800599#else // PDF_ENABLE_XFA
thestig27ddf162016-05-23 15:06:59 -0700600 return 0xFFFFFFFF;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800601#endif // PDF_ENABLE_XFA
thestig27ddf162016-05-23 15:06:59 -0700602 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700603
thestig27ddf162016-05-23 15:06:59 -0700604 return pDoc->GetUserPermissions();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700605}
606
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700607DLLEXPORT int STDCALL FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700608 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
thestigb8db5112016-04-06 12:12:52 -0700609 if (!pDoc || !pDoc->GetParser())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700610 return -1;
Bo Xuc5cab022014-09-19 19:16:31 -0700611
Tom Sepez471a1032015-10-15 16:17:18 -0700612 CPDF_Dictionary* pDict = pDoc->GetParser()->GetEncryptDict();
dsinclair38fd8442016-09-15 10:15:32 -0700613 return pDict ? pDict->GetIntegerFor("R") : -1;
Bo Xuc5cab022014-09-19 19:16:31 -0700614}
615
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700616DLLEXPORT int STDCALL FPDF_GetPageCount(FPDF_DOCUMENT document) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800617 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
Tom Sepez471a1032015-10-15 16:17:18 -0700618 return pDoc ? pDoc->GetPageCount() : 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700619}
620
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700621DLLEXPORT FPDF_PAGE STDCALL FPDF_LoadPage(FPDF_DOCUMENT document,
622 int page_index) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800623 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
624 if (!pDoc)
Tom Sepez471a1032015-10-15 16:17:18 -0700625 return nullptr;
Tom Sepez1b246282015-11-25 15:15:31 -0800626
Tom Sepezbbe0e4d2015-10-20 15:41:40 -0700627 if (page_index < 0 || page_index >= pDoc->GetPageCount())
Tom Sepez471a1032015-10-15 16:17:18 -0700628 return nullptr;
629
Tom Sepez40e9ff32015-11-30 12:39:54 -0800630#ifdef PDF_ENABLE_XFA
dsinclair9f206f02016-09-20 12:17:42 -0700631 return pDoc->GetXFAPage(page_index);
Tom Sepez40e9ff32015-11-30 12:39:54 -0800632#else // PDF_ENABLE_XFA
Tom Sepez51da0932015-11-25 16:05:49 -0800633 CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
Lei Zhang412e9082015-12-14 18:34:00 -0800634 if (!pDict)
thestig5cc24652016-04-26 11:46:02 -0700635 return nullptr;
636
637 CPDF_Page* pPage = new CPDF_Page(pDoc, pDict, true);
638 pPage->ParseContent();
Tom Sepez51da0932015-11-25 16:05:49 -0800639 return pPage;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800640#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700641}
642
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700643DLLEXPORT double STDCALL FPDF_GetPageWidth(FPDF_PAGE page) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800644 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezbf59a072015-10-21 14:07:23 -0700645 return pPage ? pPage->GetPageWidth() : 0.0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700646}
647
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700648DLLEXPORT double STDCALL FPDF_GetPageHeight(FPDF_PAGE page) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800649 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezbf59a072015-10-21 14:07:23 -0700650 return pPage ? pPage->GetPageHeight() : 0.0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700651}
652
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700653#if defined(_WIN32)
rbpottercec01802017-04-17 09:10:21 -0700654namespace {
655
656const double kEpsilonSize = 0.01f;
657
658void GetScaling(CPDF_Page* pPage,
659 int size_x,
660 int size_y,
661 int rotate,
662 double* scale_x,
663 double* scale_y) {
664 ASSERT(pPage);
665 ASSERT(scale_x);
666 ASSERT(scale_y);
667 double page_width = pPage->GetPageWidth();
668 double page_height = pPage->GetPageHeight();
669 if (page_width < kEpsilonSize || page_height < kEpsilonSize)
670 return;
671
672 if (rotate % 2 == 0) {
673 *scale_x = size_x / page_width;
674 *scale_y = size_y / page_height;
675 } else {
676 *scale_x = size_y / page_width;
677 *scale_y = size_x / page_height;
678 }
679}
680
681FX_RECT GetMaskDimensionsAndOffsets(CPDF_Page* pPage,
682 int start_x,
683 int start_y,
684 int size_x,
685 int size_y,
686 int rotate,
687 const CFX_FloatRect& mask_box) {
688 double scale_x = 0.0f;
689 double scale_y = 0.0f;
690 GetScaling(pPage, size_x, size_y, rotate, &scale_x, &scale_y);
691 if (scale_x < kEpsilonSize || scale_y < kEpsilonSize)
692 return FX_RECT();
693
694 // Compute sizes in page points. Round down to catch the entire bitmap.
695 int start_x_bm = static_cast<int>(mask_box.left * scale_x);
696 int start_y_bm = static_cast<int>(mask_box.bottom * scale_y);
697 int size_x_bm = static_cast<int>(mask_box.right * scale_x + 1.0f) -
698 static_cast<int>(mask_box.left * scale_x);
699 int size_y_bm = static_cast<int>(mask_box.top * scale_y + 1.0f) -
700 static_cast<int>(mask_box.bottom * scale_y);
701
702 // Get page rotation
rbpotterce8e51e2017-04-28 12:42:47 -0700703 int page_rotation = pPage->GetPageRotation();
rbpottercec01802017-04-17 09:10:21 -0700704
705 // Compute offsets
706 int offset_x = 0;
707 int offset_y = 0;
708 switch ((rotate + page_rotation) % 4) {
709 case 0:
710 offset_x = start_x_bm + start_x;
711 offset_y = start_y + size_y - size_y_bm - start_y_bm;
712 break;
713 case 1:
714 offset_x = start_y_bm + start_x;
715 offset_y = start_x_bm + start_y;
716 break;
717 case 2:
718 offset_x = start_x + size_x - size_x_bm - start_x_bm;
719 offset_y = start_y_bm + start_y;
720 break;
721 case 3:
722 offset_x = start_x + size_x - size_x_bm - start_y_bm;
723 offset_y = start_y + size_y - size_y_bm - start_x_bm;
724 break;
725 }
726 return FX_RECT(offset_x, offset_y, offset_x + size_x_bm,
727 offset_y + size_y_bm);
728}
729
730// Get a bitmap of just the mask section defined by |mask_box| from a full page
731// bitmap |pBitmap|.
732CFX_RetainPtr<CFX_DIBitmap> GetMaskBitmap(CPDF_Page* pPage,
733 int start_x,
734 int start_y,
735 int size_x,
736 int size_y,
737 int rotate,
738 CFX_RetainPtr<CFX_DIBitmap>& pSrc,
739 const CFX_FloatRect& mask_box,
740 FX_RECT* bitmap_area) {
741 ASSERT(bitmap_area);
742 *bitmap_area = GetMaskDimensionsAndOffsets(pPage, start_x, start_y, size_x,
743 size_y, rotate, mask_box);
744 if (bitmap_area->IsEmpty())
745 return nullptr;
746
747 // Create a new bitmap to transfer part of the page bitmap to.
748 CFX_RetainPtr<CFX_DIBitmap> pDst = pdfium::MakeRetain<CFX_DIBitmap>();
749 pDst->Create(bitmap_area->Width(), bitmap_area->Height(), FXDIB_Argb);
750 pDst->Clear(0x00ffffff);
751 pDst->TransferBitmap(0, 0, bitmap_area->Width(), bitmap_area->Height(), pSrc,
752 bitmap_area->left, bitmap_area->top);
753 return pDst;
754}
755
756void RenderBitmap(CFX_RenderDevice* device,
757 const CFX_RetainPtr<CFX_DIBitmap>& pSrc,
758 const FX_RECT& mask_area) {
759 int size_x_bm = mask_area.Width();
760 int size_y_bm = mask_area.Height();
761 if (size_x_bm == 0 || size_y_bm == 0)
762 return;
763
764 // Create a new bitmap from the old one
765 CFX_RetainPtr<CFX_DIBitmap> pDst = pdfium::MakeRetain<CFX_DIBitmap>();
766 pDst->Create(size_x_bm, size_y_bm, FXDIB_Rgb32);
767 pDst->Clear(0xffffffff);
768 pDst->CompositeBitmap(0, 0, size_x_bm, size_y_bm, pSrc, 0, 0,
769 FXDIB_BLEND_NORMAL, nullptr, false);
770
771 if (device->GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
772 device->StretchDIBitsWithFlagsAndBlend(pDst, mask_area.left, mask_area.top,
773 size_x_bm, size_y_bm, 0,
774 FXDIB_BLEND_NORMAL);
775 } else {
776 device->SetDIBits(pDst, mask_area.left, mask_area.top);
777 }
778}
779
780} // namespace
781
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700782DLLEXPORT void STDCALL FPDF_RenderPage(HDC dc,
783 FPDF_PAGE page,
784 int start_x,
785 int start_y,
786 int size_x,
787 int size_y,
788 int rotate,
789 int flags) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700790 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700791 if (!pPage)
792 return;
rbpottercec01802017-04-17 09:10:21 -0700793 pPage->SetRenderContext(pdfium::MakeUnique<CPDF_PageRenderContext>());
794 CPDF_PageRenderContext* pContext = pPage->GetRenderContext();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700795
Tom Sepezf0799fe2017-03-28 09:31:32 -0700796 CFX_RetainPtr<CFX_DIBitmap> pBitmap;
rbpottercec01802017-04-17 09:10:21 -0700797 // Don't render the full page to bitmap for a mask unless there are a lot
798 // of masks. Full page bitmaps result in large spool sizes, so they should
799 // only be used when necessary. For large numbers of masks, rendering each
800 // individually is inefficient and unlikely to significantly improve spool
801 // size.
thestig84144e82016-09-27 15:06:01 -0700802 const bool bNewBitmap =
rbpottercec01802017-04-17 09:10:21 -0700803 pPage->BackgroundAlphaNeeded() ||
804 (pPage->HasImageMask() && pPage->GetMaskBoundingBoxes().size() > 100);
805 const bool bHasMask = pPage->HasImageMask() && !bNewBitmap;
806 if (bNewBitmap || bHasMask) {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700807 pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700808 pBitmap->Create(size_x, size_y, FXDIB_Argb);
809 pBitmap->Clear(0x00ffffff);
thestigbefa4502016-05-26 20:15:19 -0700810 CFX_FxgeDevice* pDevice = new CFX_FxgeDevice;
tsepez36eb4bd2016-10-03 15:24:27 -0700811 pContext->m_pDevice = pdfium::WrapUnique(pDevice);
Tom Sepezf0799fe2017-03-28 09:31:32 -0700812 pDevice->Attach(pBitmap, false, nullptr, false);
rbpottercec01802017-04-17 09:10:21 -0700813 if (bHasMask) {
814 pContext->m_pOptions = pdfium::MakeUnique<CPDF_RenderOptions>();
815 pContext->m_pOptions->m_Flags |= RENDER_BREAKFORMASKS;
816 }
Jun Fang1aeeceb2015-12-29 10:27:44 +0800817 } else {
tsepez36eb4bd2016-10-03 15:24:27 -0700818 pContext->m_pDevice = pdfium::MakeUnique<CFX_WindowsDevice>(dc);
Jun Fang1aeeceb2015-12-29 10:27:44 +0800819 }
rbpottercec01802017-04-17 09:10:21 -0700820
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700821 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
tsepez4cf55152016-11-02 14:37:54 -0700822 rotate, flags, true, nullptr);
Bo Xud4e406e2014-08-13 11:03:19 -0700823
rbpottercec01802017-04-17 09:10:21 -0700824 if (bHasMask) {
825 // Finish rendering the page to bitmap and copy the correct segments
826 // of the page to individual image mask bitmaps.
827 const std::vector<CFX_FloatRect>& mask_boxes =
828 pPage->GetMaskBoundingBoxes();
829 std::vector<FX_RECT> bitmap_areas(mask_boxes.size());
830 std::vector<CFX_RetainPtr<CFX_DIBitmap>> bitmaps(mask_boxes.size());
831 for (size_t i = 0; i < mask_boxes.size(); i++) {
832 bitmaps[i] =
833 GetMaskBitmap(pPage, start_x, start_y, size_x, size_y, rotate,
834 pBitmap, mask_boxes[i], &bitmap_areas[i]);
835 pContext->m_pRenderer->Continue(nullptr);
836 }
837
838 // Reset rendering context
839 pPage->SetRenderContext(nullptr);
840
841 // Begin rendering to the printer. Add flag to indicate the renderer should
842 // pause after each image mask.
843 pPage->SetRenderContext(pdfium::MakeUnique<CPDF_PageRenderContext>());
844 pContext = pPage->GetRenderContext();
845 pContext->m_pDevice = pdfium::MakeUnique<CFX_WindowsDevice>(dc);
846 pContext->m_pOptions = pdfium::MakeUnique<CPDF_RenderOptions>();
847 pContext->m_pOptions->m_Flags |= RENDER_BREAKFORMASKS;
848 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
849 rotate, flags, true, nullptr);
850
851 // Render masks
852 for (size_t i = 0; i < mask_boxes.size(); i++) {
853 // Render the bitmap for the mask and free the bitmap.
854 if (bitmaps[i]) { // will be null if mask has zero area
855 RenderBitmap(pContext->m_pDevice.get(), bitmaps[i], bitmap_areas[i]);
856 }
857 // Render the next portion of page.
858 pContext->m_pRenderer->Continue(nullptr);
859 }
860 } else if (bNewBitmap) {
thestig84144e82016-09-27 15:06:01 -0700861 CFX_WindowsDevice WinDC(dc);
862 if (WinDC.GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700863 auto pDst = pdfium::MakeRetain<CFX_DIBitmap>();
thestig84144e82016-09-27 15:06:01 -0700864 int pitch = pBitmap->GetPitch();
865 pDst->Create(size_x, size_y, FXDIB_Rgb32);
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400866 memset(pDst->GetBuffer(), -1, pitch * size_y);
Tom Sepezf0799fe2017-03-28 09:31:32 -0700867 pDst->CompositeBitmap(0, 0, size_x, size_y, pBitmap, 0, 0,
Nicolas Pena6a5c20c2017-04-07 14:12:31 -0400868 FXDIB_BLEND_NORMAL, nullptr, false);
Tom Sepezf0799fe2017-03-28 09:31:32 -0700869 WinDC.StretchDIBits(pDst, 0, 0, size_x, size_y);
thestig84144e82016-09-27 15:06:01 -0700870 } else {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700871 WinDC.SetDIBits(pBitmap, 0, 0);
Lei Zhang6d8b1c22015-06-19 17:26:17 -0700872 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700873 }
rbpottercec01802017-04-17 09:10:21 -0700874
tsepeze5cb0b12016-10-26 15:06:11 -0700875 pPage->SetRenderContext(nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700876}
Lei Zhangae85f872016-02-19 14:57:07 -0800877#endif // defined(_WIN32)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700878
879DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap,
880 FPDF_PAGE page,
881 int start_x,
882 int start_y,
883 int size_x,
884 int size_y,
885 int rotate,
886 int flags) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700887 if (!bitmap)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700888 return;
tsepez1e2c5572016-05-25 14:58:09 -0700889
Tom Sepezdb0be962015-10-16 14:00:21 -0700890 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700891 if (!pPage)
892 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700893
weili9f515bc2016-07-24 08:08:24 -0700894 CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
tsepez36eb4bd2016-10-03 15:24:27 -0700895 pPage->SetRenderContext(pdfium::WrapUnique(pContext));
Tom Sepezf0799fe2017-03-28 09:31:32 -0700896
thestigbefa4502016-05-26 20:15:19 -0700897 CFX_FxgeDevice* pDevice = new CFX_FxgeDevice;
weili9f515bc2016-07-24 08:08:24 -0700898 pContext->m_pDevice.reset(pDevice);
dsinclair31b08d42017-03-28 15:47:47 +0000899
Tom Sepezf0799fe2017-03-28 09:31:32 -0700900 CFX_RetainPtr<CFX_DIBitmap> pBitmap(CFXBitmapFromFPDFBitmap(bitmap));
901 pDevice->Attach(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER), nullptr, false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700902 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
tsepez4cf55152016-11-02 14:37:54 -0700903 rotate, flags, true, nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700904
caryclark687fbde2016-11-22 12:44:25 -0800905#ifdef _SKIA_SUPPORT_PATHS_
caryclark8f875502016-12-06 13:49:34 -0800906 pDevice->Flush();
caryclark687fbde2016-11-22 12:44:25 -0800907 pBitmap->UnPreMultiply();
908#endif
tsepeze5cb0b12016-10-26 15:06:11 -0700909 pPage->SetRenderContext(nullptr);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700910}
911
thestiga78ba602016-11-23 15:25:48 -0800912DLLEXPORT void STDCALL FPDF_RenderPageBitmapWithMatrix(FPDF_BITMAP bitmap,
913 FPDF_PAGE page,
914 const FS_MATRIX* matrix,
915 const FS_RECTF* clipping,
916 int flags) {
917 if (!bitmap)
918 return;
919
920 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
921 if (!pPage)
922 return;
923
924 CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
925 pPage->SetRenderContext(pdfium::WrapUnique(pContext));
Tom Sepezf0799fe2017-03-28 09:31:32 -0700926
thestiga78ba602016-11-23 15:25:48 -0800927 CFX_FxgeDevice* pDevice = new CFX_FxgeDevice;
928 pContext->m_pDevice.reset(pDevice);
Tom Sepezf0799fe2017-03-28 09:31:32 -0700929
930 CFX_RetainPtr<CFX_DIBitmap> pBitmap(CFXBitmapFromFPDFBitmap(bitmap));
thestiga78ba602016-11-23 15:25:48 -0800931 pDevice->Attach(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER), nullptr, false);
932
933 CFX_Matrix transform_matrix = pPage->GetPageMatrix();
934 if (matrix) {
Dan Sinclairbba2a7c2017-02-07 16:36:39 -0500935 transform_matrix.Concat(CFX_Matrix(matrix->a, matrix->b, matrix->c,
936 matrix->d, matrix->e, matrix->f));
thestiga78ba602016-11-23 15:25:48 -0800937 }
938
939 CFX_FloatRect clipping_rect;
940 if (clipping) {
941 clipping_rect.left = clipping->left;
942 clipping_rect.bottom = clipping->bottom;
943 clipping_rect.right = clipping->right;
944 clipping_rect.top = clipping->top;
945 }
946 RenderPageImpl(pContext, pPage, transform_matrix, clipping_rect.ToFxRect(),
947 flags, true, nullptr);
948
949 pPage->SetRenderContext(nullptr);
950}
951
Cary Clark399be5b2016-03-14 16:51:29 -0400952#ifdef _SKIA_SUPPORT_
953DLLEXPORT FPDF_RECORDER STDCALL FPDF_RenderPageSkp(FPDF_PAGE page,
954 int size_x,
955 int size_y) {
956 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
957 if (!pPage)
958 return nullptr;
tsepez1e2c5572016-05-25 14:58:09 -0700959
weili9f515bc2016-07-24 08:08:24 -0700960 CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
tsepez36eb4bd2016-10-03 15:24:27 -0700961 pPage->SetRenderContext(pdfium::WrapUnique(pContext));
caryclarkd6e18872016-05-13 10:57:20 -0700962 CFX_FxgeDevice* skDevice = new CFX_FxgeDevice;
Cary Clark399be5b2016-03-14 16:51:29 -0400963 FPDF_RECORDER recorder = skDevice->CreateRecorder(size_x, size_y);
weili9f515bc2016-07-24 08:08:24 -0700964 pContext->m_pDevice.reset(skDevice);
tsepez4cf55152016-11-02 14:37:54 -0700965 FPDF_RenderPage_Retail(pContext, page, 0, 0, size_x, size_y, 0, 0, true,
tsepez1e2c5572016-05-25 14:58:09 -0700966 nullptr);
tsepeze5cb0b12016-10-26 15:06:11 -0700967 pPage->SetRenderContext(nullptr);
Cary Clark399be5b2016-03-14 16:51:29 -0400968 return recorder;
969}
970#endif
971
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700972DLLEXPORT void STDCALL FPDF_ClosePage(FPDF_PAGE page) {
tsepez1e2c5572016-05-25 14:58:09 -0700973 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700974 if (!page)
975 return;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800976#ifdef PDF_ENABLE_XFA
Tom Sepez40e9ff32015-11-30 12:39:54 -0800977 pPage->Release();
978#else // PDF_ENABLE_XFA
Tom Sepez51da0932015-11-25 16:05:49 -0800979 CPDFSDK_PageView* pPageView =
tsepez1e2c5572016-05-25 14:58:09 -0700980 static_cast<CPDFSDK_PageView*>(pPage->GetView());
dsinclair1df1efa2016-09-07 09:55:37 -0700981 if (pPageView) {
dsinclairbcf46232016-10-03 13:02:27 -0700982 // We're already destroying the pageview, so bail early.
983 if (pPageView->IsBeingDestroyed())
984 return;
985
dsinclair1df1efa2016-09-07 09:55:37 -0700986 if (pPageView->IsLocked()) {
987 pPageView->TakePageOwnership();
988 return;
989 }
990
991 bool owned = pPageView->OwnsPage();
992 // This will delete the |pPageView| object. We must cleanup the PageView
993 // first because it will attempt to reset the View on the |pPage| during
994 // destruction.
dsinclair7cbe68e2016-10-12 11:56:23 -0700995 pPageView->GetFormFillEnv()->RemovePageView(pPage);
dsinclair1df1efa2016-09-07 09:55:37 -0700996 // If the page was owned then the pageview will have deleted the page.
997 if (owned)
998 return;
Tom Sepez51da0932015-11-25 16:05:49 -0800999 }
tsepez1e2c5572016-05-25 14:58:09 -07001000 delete pPage;
Tom Sepez40e9ff32015-11-30 12:39:54 -08001001#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001002}
1003
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001004DLLEXPORT void STDCALL FPDF_CloseDocument(FPDF_DOCUMENT document) {
Jun Fangfc751362015-12-16 21:23:39 -08001005 delete UnderlyingFromFPDFDocument(document);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001006}
1007
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001008DLLEXPORT unsigned long STDCALL FPDF_GetLastError() {
1009 return GetLastError();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001010}
1011
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001012DLLEXPORT void STDCALL FPDF_DeviceToPage(FPDF_PAGE page,
1013 int start_x,
1014 int start_y,
1015 int size_x,
1016 int size_y,
1017 int rotate,
1018 int device_x,
1019 int device_y,
1020 double* page_x,
1021 double* page_y) {
Lei Zhang412e9082015-12-14 18:34:00 -08001022 if (!page || !page_x || !page_y)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001023 return;
Tom Sepez50d12ad2015-11-24 09:50:51 -08001024 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepez40e9ff32015-11-30 12:39:54 -08001025#ifdef PDF_ENABLE_XFA
1026 pPage->DeviceToPage(start_x, start_y, size_x, size_y, rotate, device_x,
1027 device_y, page_x, page_y);
1028#else // PDF_ENABLE_XFA
Dan Sinclair1b08df12017-02-09 09:17:20 -05001029 CFX_Matrix page2device =
1030 pPage->GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate);
Tom Sepez60d909e2015-12-10 15:34:55 -08001031 CFX_Matrix device2page;
Tom Sepez51da0932015-11-25 16:05:49 -08001032 device2page.SetReverse(page2device);
Dan Sinclair1b08df12017-02-09 09:17:20 -05001033
Dan Sinclair05df0752017-03-14 14:43:42 -04001034 CFX_PointF pos = device2page.Transform(
1035 CFX_PointF(static_cast<float>(device_x), static_cast<float>(device_y)));
Dan Sinclairafb44562017-02-09 13:07:43 -05001036
Dan Sinclaira0061af2017-02-23 09:25:17 -05001037 *page_x = pos.x;
1038 *page_y = pos.y;
Tom Sepez40e9ff32015-11-30 12:39:54 -08001039#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001040}
1041
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001042DLLEXPORT void STDCALL FPDF_PageToDevice(FPDF_PAGE page,
1043 int start_x,
1044 int start_y,
1045 int size_x,
1046 int size_y,
1047 int rotate,
1048 double page_x,
1049 double page_y,
1050 int* device_x,
1051 int* device_y) {
Tom Sepezdb0be962015-10-16 14:00:21 -07001052 if (!device_x || !device_y)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001053 return;
Tom Sepez50d12ad2015-11-24 09:50:51 -08001054 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezdb0be962015-10-16 14:00:21 -07001055 if (!pPage)
1056 return;
Tom Sepez40e9ff32015-11-30 12:39:54 -08001057#ifdef PDF_ENABLE_XFA
1058 pPage->PageToDevice(start_x, start_y, size_x, size_y, rotate, page_x, page_y,
1059 device_x, device_y);
1060#else // PDF_ENABLE_XFA
Dan Sinclair1b08df12017-02-09 09:17:20 -05001061 CFX_Matrix page2device =
1062 pPage->GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate);
Dan Sinclaira0061af2017-02-23 09:25:17 -05001063 CFX_PointF pos = page2device.Transform(
Dan Sinclair05df0752017-03-14 14:43:42 -04001064 CFX_PointF(static_cast<float>(page_x), static_cast<float>(page_y)));
Dan Sinclairafb44562017-02-09 13:07:43 -05001065
Dan Sinclaira0061af2017-02-23 09:25:17 -05001066 *device_x = FXSYS_round(pos.x);
1067 *device_y = FXSYS_round(pos.y);
Tom Sepez40e9ff32015-11-30 12:39:54 -08001068#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001069}
1070
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001071DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_Create(int width,
1072 int height,
1073 int alpha) {
Tom Sepezf0799fe2017-03-28 09:31:32 -07001074 auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
tsepez37b12ad2016-12-14 19:50:23 -08001075 if (!pBitmap->Create(width, height, alpha ? FXDIB_Argb : FXDIB_Rgb32))
thestig1cd352e2016-06-07 17:53:06 -07001076 return nullptr;
tsepez37b12ad2016-12-14 19:50:23 -08001077
Tom Sepezf0799fe2017-03-28 09:31:32 -07001078 return pBitmap.Leak();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001079}
1080
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001081DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_CreateEx(int width,
1082 int height,
1083 int format,
1084 void* first_scan,
1085 int stride) {
1086 FXDIB_Format fx_format;
1087 switch (format) {
1088 case FPDFBitmap_Gray:
1089 fx_format = FXDIB_8bppRgb;
1090 break;
1091 case FPDFBitmap_BGR:
1092 fx_format = FXDIB_Rgb;
1093 break;
1094 case FPDFBitmap_BGRx:
1095 fx_format = FXDIB_Rgb32;
1096 break;
1097 case FPDFBitmap_BGRA:
1098 fx_format = FXDIB_Argb;
1099 break;
1100 default:
thestig1cd352e2016-06-07 17:53:06 -07001101 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001102 }
Tom Sepezf0799fe2017-03-28 09:31:32 -07001103 auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001104 pBitmap->Create(width, height, fx_format, (uint8_t*)first_scan, stride);
Tom Sepezf0799fe2017-03-28 09:31:32 -07001105 return pBitmap.Leak();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001106}
1107
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001108DLLEXPORT void STDCALL FPDFBitmap_FillRect(FPDF_BITMAP bitmap,
1109 int left,
1110 int top,
1111 int width,
1112 int height,
1113 FPDF_DWORD color) {
Lei Zhang412e9082015-12-14 18:34:00 -08001114 if (!bitmap)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001115 return;
thestigbefa4502016-05-26 20:15:19 -07001116
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001117 CFX_FxgeDevice device;
Tom Sepezf0799fe2017-03-28 09:31:32 -07001118 CFX_RetainPtr<CFX_DIBitmap> pBitmap(CFXBitmapFromFPDFBitmap(bitmap));
thestigbefa4502016-05-26 20:15:19 -07001119 device.Attach(pBitmap, false, nullptr, false);
1120 if (!pBitmap->HasAlpha())
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001121 color |= 0xFF000000;
1122 FX_RECT rect(left, top, left + width, top + height);
1123 device.FillRect(&rect, color);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001124}
1125
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001126DLLEXPORT void* STDCALL FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap) {
thestigbefa4502016-05-26 20:15:19 -07001127 return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetBuffer() : nullptr;
Bo Xu9114e832014-07-14 13:22:47 -07001128}
1129
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001130DLLEXPORT int STDCALL FPDFBitmap_GetWidth(FPDF_BITMAP bitmap) {
thestigbefa4502016-05-26 20:15:19 -07001131 return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetWidth() : 0;
Bo Xu9114e832014-07-14 13:22:47 -07001132}
1133
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001134DLLEXPORT int STDCALL FPDFBitmap_GetHeight(FPDF_BITMAP bitmap) {
thestigbefa4502016-05-26 20:15:19 -07001135 return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetHeight() : 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001136}
1137
1138DLLEXPORT int STDCALL FPDFBitmap_GetStride(FPDF_BITMAP bitmap) {
thestigbefa4502016-05-26 20:15:19 -07001139 return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetPitch() : 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001140}
1141
1142DLLEXPORT void STDCALL FPDFBitmap_Destroy(FPDF_BITMAP bitmap) {
Tom Sepezf0799fe2017-03-28 09:31:32 -07001143 CFX_RetainPtr<CFX_DIBitmap> destroyer;
1144 destroyer.Unleak(CFXBitmapFromFPDFBitmap(bitmap));
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001145}
1146
weili9f515bc2016-07-24 08:08:24 -07001147void FPDF_RenderPage_Retail(CPDF_PageRenderContext* pContext,
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001148 FPDF_PAGE page,
1149 int start_x,
1150 int start_y,
1151 int size_x,
1152 int size_y,
1153 int rotate,
1154 int flags,
tsepez4cf55152016-11-02 14:37:54 -07001155 bool bNeedToRestore,
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001156 IFSDK_PAUSE_Adapter* pause) {
Tom Sepezdb0be962015-10-16 14:00:21 -07001157 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
1158 if (!pPage)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001159 return;
1160
Dan Sinclair1b08df12017-02-09 09:17:20 -05001161 RenderPageImpl(pContext, pPage, pPage->GetDisplayMatrix(
1162 start_x, start_y, size_x, size_y, rotate),
1163 FX_RECT(start_x, start_y, start_x + size_x, start_y + size_y),
1164 flags, bNeedToRestore, pause);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001165}
1166
1167DLLEXPORT int STDCALL FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document,
1168 int page_index,
1169 double* width,
1170 double* height) {
Tom Sepez540c4362015-11-24 13:33:57 -08001171 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
1172 if (!pDoc)
tsepez4cf55152016-11-02 14:37:54 -07001173 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001174
Tom Sepez40e9ff32015-11-30 12:39:54 -08001175#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001176 int count = pDoc->GetPageCount();
1177 if (page_index < 0 || page_index >= count)
tsepez4cf55152016-11-02 14:37:54 -07001178 return false;
dsinclair9f206f02016-09-20 12:17:42 -07001179 CPDFXFA_Page* pPage = pDoc->GetXFAPage(page_index);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001180 if (!pPage)
tsepez4cf55152016-11-02 14:37:54 -07001181 return false;
Tom Sepez40e9ff32015-11-30 12:39:54 -08001182 *width = pPage->GetPageWidth();
1183 *height = pPage->GetPageHeight();
1184#else // PDF_ENABLE_XFA
1185 CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
1186 if (!pDict)
tsepez4cf55152016-11-02 14:37:54 -07001187 return false;
thestig5cc24652016-04-26 11:46:02 -07001188
1189 CPDF_Page page(pDoc, pDict, true);
Tom Sepez51da0932015-11-25 16:05:49 -08001190 *width = page.GetPageWidth();
1191 *height = page.GetPageHeight();
Tom Sepez40e9ff32015-11-30 12:39:54 -08001192#endif // PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001193
tsepez4cf55152016-11-02 14:37:54 -07001194 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001195}
1196
1197DLLEXPORT FPDF_BOOL STDCALL
1198FPDF_VIEWERREF_GetPrintScaling(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001199 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001200 if (!pDoc)
tsepez4cf55152016-11-02 14:37:54 -07001201 return true;
Tom Sepez471a1032015-10-15 16:17:18 -07001202 CPDF_ViewerPreferences viewRef(pDoc);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001203 return viewRef.PrintScaling();
1204}
1205
1206DLLEXPORT int STDCALL FPDF_VIEWERREF_GetNumCopies(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001207 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001208 if (!pDoc)
1209 return 1;
1210 CPDF_ViewerPreferences viewRef(pDoc);
1211 return viewRef.NumCopies();
1212}
1213
1214DLLEXPORT FPDF_PAGERANGE STDCALL
1215FPDF_VIEWERREF_GetPrintPageRange(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001216 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001217 if (!pDoc)
thestig1cd352e2016-06-07 17:53:06 -07001218 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001219 CPDF_ViewerPreferences viewRef(pDoc);
1220 return viewRef.PrintPageRange();
1221}
1222
1223DLLEXPORT FPDF_DUPLEXTYPE STDCALL
1224FPDF_VIEWERREF_GetDuplex(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001225 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001226 if (!pDoc)
Bo Xu9114e832014-07-14 13:22:47 -07001227 return DuplexUndefined;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001228 CPDF_ViewerPreferences viewRef(pDoc);
1229 CFX_ByteString duplex = viewRef.Duplex();
Lei Zhangd983b092015-12-14 16:58:33 -08001230 if ("Simplex" == duplex)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001231 return Simplex;
Lei Zhangd983b092015-12-14 16:58:33 -08001232 if ("DuplexFlipShortEdge" == duplex)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001233 return DuplexFlipShortEdge;
Lei Zhangd983b092015-12-14 16:58:33 -08001234 if ("DuplexFlipLongEdge" == duplex)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001235 return DuplexFlipLongEdge;
1236 return DuplexUndefined;
Bo Xu9114e832014-07-14 13:22:47 -07001237}
1238
thestig04bebfe2016-11-04 16:07:25 -07001239DLLEXPORT unsigned long STDCALL FPDF_VIEWERREF_GetName(FPDF_DOCUMENT document,
1240 FPDF_BYTESTRING key,
1241 char* buffer,
1242 unsigned long length) {
1243 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1244 if (!pDoc)
1245 return 0;
1246
1247 CPDF_ViewerPreferences viewRef(pDoc);
1248 CFX_ByteString bsVal;
1249 if (!viewRef.GenericName(key, &bsVal))
1250 return 0;
1251
1252 unsigned long dwStringLen = bsVal.GetLength() + 1;
1253 if (buffer && length >= dwStringLen)
1254 memcpy(buffer, bsVal.c_str(), dwStringLen);
1255 return dwStringLen;
1256}
1257
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001258DLLEXPORT FPDF_DWORD STDCALL FPDF_CountNamedDests(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001259 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1260 if (!pDoc)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001261 return 0;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001262
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001263 CPDF_Dictionary* pRoot = pDoc->GetRoot();
1264 if (!pRoot)
1265 return 0;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001266
Lei Zhangd983b092015-12-14 16:58:33 -08001267 CPDF_NameTree nameTree(pDoc, "Dests");
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001268 pdfium::base::CheckedNumeric<FPDF_DWORD> count = nameTree.GetCount();
dsinclair38fd8442016-09-15 10:15:32 -07001269 CPDF_Dictionary* pDest = pRoot->GetDictFor("Dests");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001270 if (pDest)
1271 count += pDest->GetCount();
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001272
1273 if (!count.IsValid())
1274 return 0;
1275
1276 return count.ValueOrDie();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001277}
1278
1279DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDestByName(FPDF_DOCUMENT document,
1280 FPDF_BYTESTRING name) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001281 if (!name || name[0] == 0)
Tom Sepez471a1032015-10-15 16:17:18 -07001282 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001283
Tom Sepez471a1032015-10-15 16:17:18 -07001284 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1285 if (!pDoc)
1286 return nullptr;
1287
Lei Zhangd983b092015-12-14 16:58:33 -08001288 CPDF_NameTree name_tree(pDoc, "Dests");
Tom Sepez471a1032015-10-15 16:17:18 -07001289 return name_tree.LookupNamedDest(pDoc, name);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001290}
1291
Tom Sepez51da0932015-11-25 16:05:49 -08001292#ifdef PDF_ENABLE_XFA
thestig77d148d2016-04-06 06:28:31 -07001293DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Init(FPDF_BSTR* str) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001294 if (!str)
1295 return -1;
1296
Dan Sinclair1c5d0b42017-04-03 15:05:11 -04001297 memset(str, 0, sizeof(FPDF_BSTR));
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001298 return 0;
1299}
1300
thestig77d148d2016-04-06 06:28:31 -07001301DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Set(FPDF_BSTR* str,
1302 FPDF_LPCSTR bstr,
1303 int length) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001304 if (!str)
1305 return -1;
1306 if (!bstr || !length)
1307 return -1;
1308 if (length == -1)
1309 length = FXSYS_strlen(bstr);
1310
1311 if (length == 0) {
1312 if (str->str) {
1313 FX_Free(str->str);
thestig1cd352e2016-06-07 17:53:06 -07001314 str->str = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001315 }
1316 str->len = 0;
1317 return 0;
1318 }
1319
1320 if (str->str && str->len < length)
1321 str->str = FX_Realloc(char, str->str, length + 1);
1322 else if (!str->str)
1323 str->str = FX_Alloc(char, length + 1);
1324
1325 str->str[length] = 0;
Dan Sinclair1c5d0b42017-04-03 15:05:11 -04001326 memcpy(str->str, bstr, length);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001327 str->len = length;
1328
1329 return 0;
1330}
1331
thestig77d148d2016-04-06 06:28:31 -07001332DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Clear(FPDF_BSTR* str) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001333 if (!str)
1334 return -1;
1335
1336 if (str->str) {
1337 FX_Free(str->str);
thestig1cd352e2016-06-07 17:53:06 -07001338 str->str = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001339 }
1340 str->len = 0;
1341 return 0;
1342}
Tom Sepez40e9ff32015-11-30 12:39:54 -08001343#endif // PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001344
1345DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDest(FPDF_DOCUMENT document,
1346 int index,
1347 void* buffer,
1348 long* buflen) {
1349 if (!buffer)
1350 *buflen = 0;
Tom Sepez540c4362015-11-24 13:33:57 -08001351
1352 if (index < 0)
1353 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001354
Tom Sepezbf59a072015-10-21 14:07:23 -07001355 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Tom Sepez540c4362015-11-24 13:33:57 -08001356 if (!pDoc)
1357 return nullptr;
1358
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001359 CPDF_Dictionary* pRoot = pDoc->GetRoot();
1360 if (!pRoot)
Tom Sepez540c4362015-11-24 13:33:57 -08001361 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001362
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001363 CPDF_Object* pDestObj = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001364 CFX_ByteString bsName;
Lei Zhangd983b092015-12-14 16:58:33 -08001365 CPDF_NameTree nameTree(pDoc, "Dests");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001366 int count = nameTree.GetCount();
1367 if (index >= count) {
dsinclair38fd8442016-09-15 10:15:32 -07001368 CPDF_Dictionary* pDest = pRoot->GetDictFor("Dests");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001369 if (!pDest)
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001370 return nullptr;
1371
1372 pdfium::base::CheckedNumeric<int> checked_count = count;
1373 checked_count += pDest->GetCount();
1374 if (!checked_count.IsValid() || index >= checked_count.ValueOrDie())
1375 return nullptr;
1376
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001377 index -= count;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001378 int i = 0;
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001379 for (const auto& it : *pDest) {
1380 bsName = it.first;
tsepez0e606b52016-11-18 16:22:41 -08001381 pDestObj = it.second.get();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001382 if (!pDestObj)
1383 continue;
1384 if (i == index)
1385 break;
1386 i++;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001387 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001388 } else {
Tom Sepezc4a2b752017-04-07 13:56:13 -07001389 pDestObj = nameTree.LookupValueAndName(index, &bsName);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001390 }
1391 if (!pDestObj)
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001392 return nullptr;
Dan Sinclairf1251c12015-10-20 16:24:45 -04001393 if (CPDF_Dictionary* pDict = pDestObj->AsDictionary()) {
dsinclair38fd8442016-09-15 10:15:32 -07001394 pDestObj = pDict->GetArrayFor("D");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001395 if (!pDestObj)
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001396 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001397 }
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001398 if (!pDestObj->IsArray())
1399 return nullptr;
1400
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001401 CFX_WideString wsName = PDF_DecodeText(bsName);
1402 CFX_ByteString utf16Name = wsName.UTF16LE_Encode();
weili47ca6922016-03-31 15:08:27 -07001403 int len = utf16Name.GetLength();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001404 if (!buffer) {
1405 *buflen = len;
thestig9067fd62016-11-23 14:10:06 -08001406 } else if (len <= *buflen) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001407 memcpy(buffer, utf16Name.c_str(), len);
1408 *buflen = len;
1409 } else {
1410 *buflen = -1;
1411 }
1412 return (FPDF_DEST)pDestObj;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001413}