blob: 5bcc643ac179f66a4f26cf359b6b85a06ce7f9f7 [file] [log] [blame]
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001// Copyright 2014 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
Lei Zhangb4e7f302015-11-06 15:52:32 -08007#include "public/fpdfview.h"
8
Lei Zhangaa8bf7e2015-12-24 19:13:32 -08009#include <memory>
thestigd4c34f22016-09-28 17:04:51 -070010#include <utility>
rbpottercec01802017-04-17 09:10:21 -070011#include <vector>
Lei Zhangaa8bf7e2015-12-24 19:13:32 -080012
dsinclair39c62fd2016-09-29 12:49:17 -070013#include "core/fpdfapi/cpdf_modulemgr.h"
14#include "core/fpdfapi/cpdf_pagerendercontext.h"
rbpottercec01802017-04-17 09:10:21 -070015#include "core/fpdfapi/page/cpdf_image.h"
16#include "core/fpdfapi/page/cpdf_imageobject.h"
dsinclair41872fa2016-10-04 11:29:35 -070017#include "core/fpdfapi/page/cpdf_page.h"
rbpottercec01802017-04-17 09:10:21 -070018#include "core/fpdfapi/page/cpdf_pageobject.h"
Jane Liu3b057432017-06-19 10:44:01 -040019#include "core/fpdfapi/page/cpdf_pathobject.h"
dsinclair488b7ad2016-10-04 11:55:50 -070020#include "core/fpdfapi/parser/cpdf_array.h"
Jane Liu4fd9a472017-06-01 18:56:09 -040021#include "core/fpdfapi/parser/cpdf_dictionary.h"
dsinclair488b7ad2016-10-04 11:55:50 -070022#include "core/fpdfapi/parser/cpdf_document.h"
23#include "core/fpdfapi/parser/fpdf_parser_decode.h"
dsinclair69d9c682016-10-04 12:18:35 -070024#include "core/fpdfapi/render/cpdf_progressiverenderer.h"
25#include "core/fpdfapi/render/cpdf_renderoptions.h"
dsinclair1727aee2016-09-29 13:12:56 -070026#include "core/fpdfdoc/cpdf_annotlist.h"
27#include "core/fpdfdoc/cpdf_nametree.h"
28#include "core/fpdfdoc/cpdf_occontext.h"
29#include "core/fpdfdoc/cpdf_viewerpreferences.h"
dsinclair8a4e2862016-09-29 13:43:30 -070030#include "core/fxcodec/fx_codec.h"
dsinclaira52ab742016-09-29 13:59:29 -070031#include "core/fxcrt/fx_memory.h"
32#include "core/fxcrt/fx_safe_types.h"
Dan Sinclairbcd1e702017-08-31 13:19:18 -040033#include "core/fxcrt/fx_stream.h"
Dan Sinclaira5085d42017-05-11 16:26:50 -040034#include "core/fxge/cfx_defaultrenderdevice.h"
dsinclair74a34fc2016-09-29 16:41:42 -070035#include "core/fxge/cfx_gemodule.h"
dsinclairb402b172016-10-11 09:26:32 -070036#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
dsinclair114e46a2016-09-29 17:18:21 -070037#include "fpdfsdk/cpdfsdk_pageview.h"
38#include "fpdfsdk/fsdk_define.h"
39#include "fpdfsdk/fsdk_pauseadapter.h"
dsinclair64376be2016-03-31 20:03:24 -070040#include "fpdfsdk/javascript/ijs_runtime.h"
rbpottere8468c42017-07-11 10:04:29 -070041#include "public/fpdf_edit.h"
Lei Zhangb4e7f302015-11-06 15:52:32 -080042#include "public/fpdf_ext.h"
Lei Zhangb4e7f302015-11-06 15:52:32 -080043#include "public/fpdf_progressive.h"
Chris Palmere4b035b2017-03-26 15:48:34 -070044#include "third_party/base/allocator/partition_allocator/partition_alloc.h"
Lei Zhang8241df72015-11-06 14:38:48 -080045#include "third_party/base/numerics/safe_conversions_impl.h"
tsepez36eb4bd2016-10-03 15:24:27 -070046#include "third_party/base/ptr_util.h"
Bo Xufdc00a72014-10-28 23:03:33 -070047
Tom Sepez40e9ff32015-11-30 12:39:54 -080048#ifdef PDF_ENABLE_XFA
dsinclair521b7502016-11-02 13:02:28 -070049#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
dsinclair4d29e782016-10-04 14:02:47 -070050#include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
51#include "fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h"
Dan Sinclaire7786682017-03-29 15:18:41 -040052#include "fxbarcode/BC_Library.h"
Tom Sepez40e9ff32015-11-30 12:39:54 -080053#include "public/fpdf_formfill.h"
54#endif // PDF_ENABLE_XFA
55
thestig25fa42f2016-05-25 21:39:46 -070056#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
Dan Sinclaira5085d42017-05-11 16:26:50 -040057#include "core/fxge/cfx_windowsrenderdevice.h"
rbpottere8468c42017-07-11 10:04:29 -070058
59// These checks are here because core/ and public/ cannot depend on each other.
60static_assert(WindowsPrintMode::kModeEmf == FPDF_PRINTMODE_EMF,
61 "WindowsPrintMode::kModeEmf value mismatch");
62static_assert(WindowsPrintMode::kModeTextOnly == FPDF_PRINTMODE_TEXTONLY,
63 "WindowsPrintMode::kModeTextOnly value mismatch");
64static_assert(WindowsPrintMode::kModePostScript2 == FPDF_PRINTMODE_POSTSCRIPT2,
65 "WindowsPrintMode::kModePostScript2 value mismatch");
66static_assert(WindowsPrintMode::kModePostScript3 == FPDF_PRINTMODE_POSTSCRIPT3,
67 "WindowsPrintMode::kModePostScript3 value mismatch");
thestig25fa42f2016-05-25 21:39:46 -070068#endif
69
thestiga78ba602016-11-23 15:25:48 -080070namespace {
71
Dan Sinclair830897a2017-05-11 14:36:10 -040072bool g_bLibraryInitialized = false;
tsepez02759102016-12-01 08:29:25 -080073
thestiga78ba602016-11-23 15:25:48 -080074void RenderPageImpl(CPDF_PageRenderContext* pContext,
75 CPDF_Page* pPage,
76 const CFX_Matrix& matrix,
77 const FX_RECT& clipping_rect,
78 int flags,
79 bool bNeedToRestore,
80 IFSDK_PAUSE_Adapter* pause) {
81 if (!pContext->m_pOptions)
82 pContext->m_pOptions = pdfium::MakeUnique<CPDF_RenderOptions>();
83
84 if (flags & FPDF_LCD_TEXT)
85 pContext->m_pOptions->m_Flags |= RENDER_CLEARTYPE;
86 else
87 pContext->m_pOptions->m_Flags &= ~RENDER_CLEARTYPE;
88
89 if (flags & FPDF_NO_NATIVETEXT)
90 pContext->m_pOptions->m_Flags |= RENDER_NO_NATIVETEXT;
91 if (flags & FPDF_RENDER_LIMITEDIMAGECACHE)
92 pContext->m_pOptions->m_Flags |= RENDER_LIMITEDIMAGECACHE;
93 if (flags & FPDF_RENDER_FORCEHALFTONE)
94 pContext->m_pOptions->m_Flags |= RENDER_FORCE_HALFTONE;
95#ifndef PDF_ENABLE_XFA
96 if (flags & FPDF_RENDER_NO_SMOOTHTEXT)
97 pContext->m_pOptions->m_Flags |= RENDER_NOTEXTSMOOTH;
98 if (flags & FPDF_RENDER_NO_SMOOTHIMAGE)
99 pContext->m_pOptions->m_Flags |= RENDER_NOIMAGESMOOTH;
100 if (flags & FPDF_RENDER_NO_SMOOTHPATH)
101 pContext->m_pOptions->m_Flags |= RENDER_NOPATHSMOOTH;
102#endif // PDF_ENABLE_XFA
103
104 // Grayscale output
Dan Sinclairf55e72e2017-07-13 14:53:28 -0400105 if (flags & FPDF_GRAYSCALE)
106 pContext->m_pOptions->m_ColorMode = CPDF_RenderOptions::kGray;
thestiga78ba602016-11-23 15:25:48 -0800107
108 const CPDF_OCContext::UsageType usage =
109 (flags & FPDF_PRINTING) ? CPDF_OCContext::Print : CPDF_OCContext::View;
thestiga78ba602016-11-23 15:25:48 -0800110 pContext->m_pOptions->m_pOCContext =
Tom Sepez4cb82ee2017-05-22 15:15:30 -0700111 pdfium::MakeRetain<CPDF_OCContext>(pPage->m_pDocument.Get(), usage);
thestiga78ba602016-11-23 15:25:48 -0800112
113 pContext->m_pDevice->SaveState();
114 pContext->m_pDevice->SetClip_Rect(clipping_rect);
thestiga78ba602016-11-23 15:25:48 -0800115 pContext->m_pContext = pdfium::MakeUnique<CPDF_RenderContext>(pPage);
116 pContext->m_pContext->AppendLayer(pPage, &matrix);
117
118 if (flags & FPDF_ANNOT) {
119 pContext->m_pAnnots = pdfium::MakeUnique<CPDF_AnnotList>(pPage);
120 bool bPrinting = pContext->m_pDevice->GetDeviceClass() != FXDC_DISPLAY;
121 pContext->m_pAnnots->DisplayAnnots(pPage, pContext->m_pContext.get(),
122 bPrinting, &matrix, false, nullptr);
123 }
124
125 pContext->m_pRenderer = pdfium::MakeUnique<CPDF_ProgressiveRenderer>(
126 pContext->m_pContext.get(), pContext->m_pDevice.get(),
127 pContext->m_pOptions.get());
128 pContext->m_pRenderer->Start(pause);
129 if (bNeedToRestore)
130 pContext->m_pDevice->RestoreState(false);
131}
132
tsepezbea04972016-12-01 13:54:42 -0800133class CPDF_CustomAccess final : public IFX_SeekableReadStream {
134 public:
Tom Sepez40badde2017-05-01 13:21:39 -0700135 template <typename T, typename... Args>
136 friend CFX_RetainPtr<T> pdfium::MakeRetain(Args&&... args);
tsepezbea04972016-12-01 13:54:42 -0800137
138 // IFX_SeekableReadStream
139 FX_FILESIZE GetSize() override;
tsepezbea04972016-12-01 13:54:42 -0800140 bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override;
141
142 private:
tsepez833619b2016-12-07 09:21:17 -0800143 explicit CPDF_CustomAccess(FPDF_FILEACCESS* pFileAccess);
144
tsepezbea04972016-12-01 13:54:42 -0800145 FPDF_FILEACCESS m_FileAccess;
146};
147
148CPDF_CustomAccess::CPDF_CustomAccess(FPDF_FILEACCESS* pFileAccess)
149 : m_FileAccess(*pFileAccess) {}
150
151FX_FILESIZE CPDF_CustomAccess::GetSize() {
152 return m_FileAccess.m_FileLen;
153}
154
tsepezbea04972016-12-01 13:54:42 -0800155bool CPDF_CustomAccess::ReadBlock(void* buffer,
156 FX_FILESIZE offset,
157 size_t size) {
158 if (offset < 0)
159 return false;
160
161 FX_SAFE_FILESIZE newPos = pdfium::base::checked_cast<FX_FILESIZE>(size);
162 newPos += offset;
163 if (!newPos.IsValid() ||
164 newPos.ValueOrDie() > static_cast<FX_FILESIZE>(m_FileAccess.m_FileLen)) {
165 return false;
166 }
167 return !!m_FileAccess.m_GetBlock(m_FileAccess.m_Param, offset,
Nicolas Pena46abb662017-05-17 17:23:22 -0400168 static_cast<uint8_t*>(buffer), size);
tsepezbea04972016-12-01 13:54:42 -0800169}
170
Tom Sepez40e9ff32015-11-30 12:39:54 -0800171#ifdef PDF_ENABLE_XFA
tsepezfa89a202016-12-02 09:48:30 -0800172class CFPDF_FileStream : public IFX_SeekableStream {
173 public:
Tom Sepez40badde2017-05-01 13:21:39 -0700174 template <typename T, typename... Args>
175 friend CFX_RetainPtr<T> pdfium::MakeRetain(Args&&... args);
176
tsepez833619b2016-12-07 09:21:17 -0800177 ~CFPDF_FileStream() override;
Tom Sepez471a1032015-10-15 16:17:18 -0700178
tsepezfa89a202016-12-02 09:48:30 -0800179 // IFX_SeekableStream:
tsepezfa89a202016-12-02 09:48:30 -0800180 FX_FILESIZE GetSize() override;
181 bool IsEOF() override;
182 FX_FILESIZE GetPosition() override;
183 bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override;
184 size_t ReadBlock(void* buffer, size_t size) override;
185 bool WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size) override;
186 bool Flush() override;
Tom Sepezbf59a072015-10-21 14:07:23 -0700187
tsepezfa89a202016-12-02 09:48:30 -0800188 void SetPosition(FX_FILESIZE pos) { m_nCurPos = pos; }
Tom Sepezdb0be962015-10-16 14:00:21 -0700189
tsepezfa89a202016-12-02 09:48:30 -0800190 protected:
tsepez833619b2016-12-07 09:21:17 -0800191 explicit CFPDF_FileStream(FPDF_FILEHANDLER* pFS);
192
tsepezfa89a202016-12-02 09:48:30 -0800193 FPDF_FILEHANDLER* m_pFS;
194 FX_FILESIZE m_nCurPos;
195};
thestigbefa4502016-05-26 20:15:19 -0700196
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700197CFPDF_FileStream::CFPDF_FileStream(FPDF_FILEHANDLER* pFS) {
198 m_pFS = pFS;
199 m_nCurPos = 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700200}
201
tsepez833619b2016-12-07 09:21:17 -0800202CFPDF_FileStream::~CFPDF_FileStream() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700203 if (m_pFS && m_pFS->Release)
204 m_pFS->Release(m_pFS->clientData);
Bo Xufdc00a72014-10-28 23:03:33 -0700205}
206
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700207FX_FILESIZE CFPDF_FileStream::GetSize() {
208 if (m_pFS && m_pFS->GetSize)
209 return (FX_FILESIZE)m_pFS->GetSize(m_pFS->clientData);
210 return 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700211}
212
tsepezf39074c2016-10-26 15:33:58 -0700213bool CFPDF_FileStream::IsEOF() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700214 return m_nCurPos >= GetSize();
Bo Xufdc00a72014-10-28 23:03:33 -0700215}
216
weili625ad662016-06-15 11:21:33 -0700217FX_FILESIZE CFPDF_FileStream::GetPosition() {
218 return m_nCurPos;
219}
220
tsepezf39074c2016-10-26 15:33:58 -0700221bool CFPDF_FileStream::ReadBlock(void* buffer,
222 FX_FILESIZE offset,
223 size_t size) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700224 if (!buffer || !size || !m_pFS->ReadBlock)
tsepezf39074c2016-10-26 15:33:58 -0700225 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700226
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700227 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
228 (FPDF_DWORD)size) == 0) {
229 m_nCurPos = offset + size;
tsepezf39074c2016-10-26 15:33:58 -0700230 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700231 }
tsepezf39074c2016-10-26 15:33:58 -0700232 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700233}
234
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700235size_t CFPDF_FileStream::ReadBlock(void* buffer, size_t size) {
236 if (!buffer || !size || !m_pFS->ReadBlock)
237 return 0;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700238
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700239 FX_FILESIZE nSize = GetSize();
240 if (m_nCurPos >= nSize)
241 return 0;
242 FX_FILESIZE dwAvail = nSize - m_nCurPos;
243 if (dwAvail < (FX_FILESIZE)size)
244 size = (size_t)dwAvail;
245 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)m_nCurPos, buffer,
246 (FPDF_DWORD)size) == 0) {
247 m_nCurPos += size;
248 return size;
249 }
Bo Xufdc00a72014-10-28 23:03:33 -0700250
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700251 return 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700252}
253
tsepezf39074c2016-10-26 15:33:58 -0700254bool CFPDF_FileStream::WriteBlock(const void* buffer,
255 FX_FILESIZE offset,
256 size_t size) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700257 if (!m_pFS || !m_pFS->WriteBlock)
tsepezf39074c2016-10-26 15:33:58 -0700258 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700259
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700260 if (m_pFS->WriteBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
261 (FPDF_DWORD)size) == 0) {
262 m_nCurPos = offset + size;
tsepezf39074c2016-10-26 15:33:58 -0700263 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700264 }
tsepezf39074c2016-10-26 15:33:58 -0700265 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700266}
267
tsepezf39074c2016-10-26 15:33:58 -0700268bool CFPDF_FileStream::Flush() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700269 if (!m_pFS || !m_pFS->Flush)
tsepezf39074c2016-10-26 15:33:58 -0700270 return true;
Bo Xufdc00a72014-10-28 23:03:33 -0700271
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700272 return m_pFS->Flush(m_pFS->clientData) == 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700273}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800274#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700275
Artem Strygin3f7ff052017-07-27 22:16:13 +0300276FPDF_DOCUMENT LoadDocumentImpl(
277 const CFX_RetainPtr<IFX_SeekableReadStream>& pFileAccess,
278 FPDF_BYTESTRING password) {
Jane Liu8a1081f2017-08-22 16:28:05 -0400279 if (!pFileAccess) {
280 ProcessParseError(CPDF_Parser::FILE_ERROR);
Artem Strygin3f7ff052017-07-27 22:16:13 +0300281 return nullptr;
Jane Liu8a1081f2017-08-22 16:28:05 -0400282 }
Artem Strygin3f7ff052017-07-27 22:16:13 +0300283
284 auto pParser = pdfium::MakeUnique<CPDF_Parser>();
285 pParser->SetPassword(password);
286
287 auto pDocument = pdfium::MakeUnique<CPDF_Document>(std::move(pParser));
288 CPDF_Parser::Error error =
289 pDocument->GetParser()->StartParse(pFileAccess, pDocument.get());
290 if (error != CPDF_Parser::SUCCESS) {
291 ProcessParseError(error);
292 return nullptr;
293 }
294 CheckUnSupportError(pDocument.get(), error);
295 return FPDFDocumentFromCPDFDocument(pDocument.release());
296}
297
tsepezfa89a202016-12-02 09:48:30 -0800298} // namespace
299
300UnderlyingDocumentType* UnderlyingFromFPDFDocument(FPDF_DOCUMENT doc) {
301 return static_cast<UnderlyingDocumentType*>(doc);
302}
303
304FPDF_DOCUMENT FPDFDocumentFromUnderlying(UnderlyingDocumentType* doc) {
305 return static_cast<FPDF_DOCUMENT>(doc);
306}
307
308UnderlyingPageType* UnderlyingFromFPDFPage(FPDF_PAGE page) {
309 return static_cast<UnderlyingPageType*>(page);
310}
311
312CPDF_Document* CPDFDocumentFromFPDFDocument(FPDF_DOCUMENT doc) {
313#ifdef PDF_ENABLE_XFA
314 return doc ? UnderlyingFromFPDFDocument(doc)->GetPDFDoc() : nullptr;
315#else // PDF_ENABLE_XFA
316 return UnderlyingFromFPDFDocument(doc);
317#endif // PDF_ENABLE_XFA
318}
319
320FPDF_DOCUMENT FPDFDocumentFromCPDFDocument(CPDF_Document* doc) {
321#ifdef PDF_ENABLE_XFA
322 return doc ? FPDFDocumentFromUnderlying(
323 new CPDFXFA_Context(pdfium::WrapUnique(doc)))
324 : nullptr;
325#else // PDF_ENABLE_XFA
326 return FPDFDocumentFromUnderlying(doc);
327#endif // PDF_ENABLE_XFA
328}
329
330CPDF_Page* CPDFPageFromFPDFPage(FPDF_PAGE page) {
331#ifdef PDF_ENABLE_XFA
332 return page ? UnderlyingFromFPDFPage(page)->GetPDFPage() : nullptr;
333#else // PDF_ENABLE_XFA
334 return UnderlyingFromFPDFPage(page);
335#endif // PDF_ENABLE_XFA
336}
337
Jane Liu3b057432017-06-19 10:44:01 -0400338CPDF_PathObject* CPDFPathObjectFromFPDFPageObject(FPDF_PAGEOBJECT page_object) {
339 return static_cast<CPDF_PathObject*>(page_object);
340}
341
Jane Liubaa7ff42017-06-29 19:18:23 -0400342CPDF_PageObject* CPDFPageObjectFromFPDFPageObject(FPDF_PAGEOBJECT page_object) {
343 return static_cast<CPDF_PageObject*>(page_object);
344}
345
Jane Liu18ae06d2017-07-18 10:15:16 -0400346CPDF_Object* CPDFObjectFromFPDFAttachment(FPDF_ATTACHMENT attachment) {
347 return static_cast<CPDF_Object*>(attachment);
348}
349
350CFX_ByteString CFXByteStringFromFPDFWideString(FPDF_WIDESTRING wide_string) {
351 return CFX_WideString::FromUTF16LE(wide_string,
352 CFX_WideString::WStringLength(wide_string))
353 .UTF8Encode();
354}
355
tsepezfa89a202016-12-02 09:48:30 -0800356CFX_DIBitmap* CFXBitmapFromFPDFBitmap(FPDF_BITMAP bitmap) {
357 return static_cast<CFX_DIBitmap*>(bitmap);
358}
359
Jane Liu18ae06d2017-07-18 10:15:16 -0400360unsigned long Utf16EncodeMaybeCopyAndReturnLength(const CFX_WideString& text,
361 void* buffer,
362 unsigned long buflen) {
Jane Liu548334e2017-08-03 16:33:40 -0400363 CFX_ByteString encoded_text = text.UTF16LE_Encode();
364 unsigned long len = encoded_text.GetLength();
Jane Liu18ae06d2017-07-18 10:15:16 -0400365 if (buffer && len <= buflen)
Jane Liu548334e2017-08-03 16:33:40 -0400366 memcpy(buffer, encoded_text.c_str(), len);
367 return len;
368}
369
370unsigned long DecodeStreamMaybeCopyAndReturnLength(const CPDF_Stream* stream,
371 void* buffer,
372 unsigned long buflen) {
373 ASSERT(stream);
374 uint8_t* data = stream->GetRawData();
375 uint32_t len = stream->GetRawSize();
376 CPDF_Dictionary* dict = stream->GetDict();
377 CPDF_Object* decoder = dict ? dict->GetDirectObjectFor("Filter") : nullptr;
378 if (decoder && (decoder->IsArray() || decoder->IsName())) {
379 // Decode the stream if one or more stream filters are specified.
380 uint8_t* decoded_data = nullptr;
381 uint32_t decoded_len = 0;
382 CFX_ByteString dummy_last_decoder;
383 CPDF_Dictionary* dummy_last_param;
384 if (PDF_DataDecode(data, len, dict, dict->GetIntegerFor("DL"), false,
385 &decoded_data, &decoded_len, &dummy_last_decoder,
386 &dummy_last_param)) {
387 if (buffer && buflen >= decoded_len)
388 memcpy(buffer, decoded_data, decoded_len);
389
390 // Free the buffer for the decoded data if it was allocated by
391 // PDF_DataDecode(). Note that for images with a single image-specific
392 // filter, |decoded_data| is directly assigned to be |data|, so
393 // |decoded_data| does not need to be freed.
394 if (decoded_data != data)
395 FX_Free(decoded_data);
396
397 return decoded_len;
398 }
399 }
400 // Copy the raw data and return its length if there is no valid filter
401 // specified or if decoding failed.
402 if (buffer && buflen >= len)
403 memcpy(buffer, data, len);
404
Jane Liu18ae06d2017-07-18 10:15:16 -0400405 return len;
406}
407
tsepez833619b2016-12-07 09:21:17 -0800408CFX_RetainPtr<IFX_SeekableReadStream> MakeSeekableReadStream(
409 FPDF_FILEACCESS* pFileAccess) {
Tom Sepez40badde2017-05-01 13:21:39 -0700410 return pdfium::MakeRetain<CPDF_CustomAccess>(pFileAccess);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700411}
412
tsepezfa89a202016-12-02 09:48:30 -0800413#ifdef PDF_ENABLE_XFA
tsepez833619b2016-12-07 09:21:17 -0800414CFX_RetainPtr<IFX_SeekableStream> MakeSeekableStream(
415 FPDF_FILEHANDLER* pFilehandler) {
Tom Sepez40badde2017-05-01 13:21:39 -0700416 return pdfium::MakeRetain<CFPDF_FileStream>(pFilehandler);
tsepezfa89a202016-12-02 09:48:30 -0800417}
418#endif // PDF_ENABLE_XFA
419
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700420// 0 bit: FPDF_POLICY_MACHINETIME_ACCESS
tsepezc3255f52016-03-25 14:52:27 -0700421static uint32_t foxit_sandbox_policy = 0xFFFFFFFF;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700422
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700423void FSDK_SetSandBoxPolicy(FPDF_DWORD policy, FPDF_BOOL enable) {
424 switch (policy) {
425 case FPDF_POLICY_MACHINETIME_ACCESS: {
426 if (enable)
427 foxit_sandbox_policy |= 0x01;
428 else
429 foxit_sandbox_policy &= 0xFFFFFFFE;
430 } break;
431 default:
432 break;
433 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700434}
435
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700436FPDF_BOOL FSDK_IsSandBoxPolicyEnabled(FPDF_DWORD policy) {
437 switch (policy) {
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700438 case FPDF_POLICY_MACHINETIME_ACCESS:
Lei Zhangb0748bb2015-10-19 12:11:49 -0700439 return !!(foxit_sandbox_policy & 0x01);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700440 default:
tsepez4cf55152016-11-02 14:37:54 -0700441 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700442 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700443}
444
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400445FPDF_EXPORT void FPDF_CALLCONV FPDF_InitLibrary() {
Lei Zhang6f62d532015-09-23 15:31:44 -0700446 FPDF_InitLibraryWithConfig(nullptr);
447}
448
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400449FPDF_EXPORT void FPDF_CALLCONV
Dan Sinclairf766ad22016-03-14 13:51:24 -0400450FPDF_InitLibraryWithConfig(const FPDF_LIBRARY_CONFIG* cfg) {
Dan Sinclair830897a2017-05-11 14:36:10 -0400451 if (g_bLibraryInitialized)
tsepez02759102016-12-01 08:29:25 -0800452 return;
453
Dan Sinclairdbc3d3e2017-05-11 13:41:38 -0400454 FXMEM_InitializePartitionAlloc();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700455
weili47228ac2016-07-20 10:35:31 -0700456 CFX_GEModule* pModule = CFX_GEModule::Get();
Dan Sinclair830897a2017-05-11 14:36:10 -0400457 pModule->Init(cfg ? cfg->m_pUserFontPaths : nullptr);
tsepez02759102016-12-01 08:29:25 -0800458
Tom Sepez1b246282015-11-25 15:15:31 -0800459 CPDF_ModuleMgr* pModuleMgr = CPDF_ModuleMgr::Get();
Lei Zhang76020fc2017-05-18 15:51:20 -0700460 pModuleMgr->Init();
Tom Sepezb4a26182017-03-01 12:15:00 -0800461
Tom Sepez40e9ff32015-11-30 12:39:54 -0800462#ifdef PDF_ENABLE_XFA
dsinclair8837c912016-11-01 11:22:37 -0700463 FXJSE_Initialize();
464 BC_Library_Init();
Tom Sepez40e9ff32015-11-30 12:39:54 -0800465#endif // PDF_ENABLE_XFA
Tom Sepez452b4f32015-10-13 09:27:27 -0700466 if (cfg && cfg->version >= 2)
467 IJS_Runtime::Initialize(cfg->m_v8EmbedderSlot, cfg->m_pIsolate);
Dan Sinclair830897a2017-05-11 14:36:10 -0400468
469 g_bLibraryInitialized = true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700470}
471
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400472FPDF_EXPORT void FPDF_CALLCONV FPDF_DestroyLibrary() {
Dan Sinclair830897a2017-05-11 14:36:10 -0400473 if (!g_bLibraryInitialized)
tsepez02759102016-12-01 08:29:25 -0800474 return;
475
Tom Sepez51da0932015-11-25 16:05:49 -0800476#ifdef PDF_ENABLE_XFA
Tom Sepez5628fd72017-04-27 14:58:53 -0700477 BC_Library_Destroy();
dsinclair8837c912016-11-01 11:22:37 -0700478 FXJSE_Finalize();
Tom Sepez40e9ff32015-11-30 12:39:54 -0800479#endif // PDF_ENABLE_XFA
dsinclair8837c912016-11-01 11:22:37 -0700480
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700481 CPDF_ModuleMgr::Destroy();
482 CFX_GEModule::Destroy();
Tom Sepez2c286192015-06-18 12:47:11 -0700483
thestig2d6dda12016-06-28 07:39:09 -0700484 IJS_Runtime::Destroy();
Dan Sinclair830897a2017-05-11 14:36:10 -0400485
486 g_bLibraryInitialized = false;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700487}
488
489#ifndef _WIN32
490int g_LastError;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700491void SetLastError(int err) {
492 g_LastError = err;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700493}
494
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700495int GetLastError() {
496 return g_LastError;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700497}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800498#endif // _WIN32
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700499
Tom Sepezf10ae632016-01-26 14:19:52 -0800500void ProcessParseError(CPDF_Parser::Error err) {
tsepezc3255f52016-03-25 14:52:27 -0700501 uint32_t err_code = FPDF_ERR_SUCCESS;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700502 // Translate FPDFAPI error code to FPDFVIEW error code
Tom Sepezf10ae632016-01-26 14:19:52 -0800503 switch (err) {
504 case CPDF_Parser::SUCCESS:
505 err_code = FPDF_ERR_SUCCESS;
506 break;
507 case CPDF_Parser::FILE_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700508 err_code = FPDF_ERR_FILE;
509 break;
Tom Sepezf10ae632016-01-26 14:19:52 -0800510 case CPDF_Parser::FORMAT_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700511 err_code = FPDF_ERR_FORMAT;
512 break;
Tom Sepezf10ae632016-01-26 14:19:52 -0800513 case CPDF_Parser::PASSWORD_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700514 err_code = FPDF_ERR_PASSWORD;
515 break;
Tom Sepezf10ae632016-01-26 14:19:52 -0800516 case CPDF_Parser::HANDLER_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700517 err_code = FPDF_ERR_SECURITY;
518 break;
519 }
520 SetLastError(err_code);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700521}
522
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400523FPDF_EXPORT void FPDF_CALLCONV FPDF_SetSandBoxPolicy(FPDF_DWORD policy,
524 FPDF_BOOL enable) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700525 return FSDK_SetSandBoxPolicy(policy, enable);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700526}
527
rbpotterdb764702017-01-12 10:31:43 -0800528#if defined(_WIN32)
529#if defined(PDFIUM_PRINT_TEXT_WITH_GDI)
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400530FPDF_EXPORT void FPDF_CALLCONV
thestigfdb35ff2016-07-18 13:45:44 -0700531FPDF_SetTypefaceAccessibleFunc(PDFiumEnsureTypefaceCharactersAccessible func) {
532 g_pdfium_typeface_accessible_func = func;
533}
534
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400535FPDF_EXPORT void FPDF_CALLCONV FPDF_SetPrintTextWithGDI(FPDF_BOOL use_gdi) {
thestigfdb35ff2016-07-18 13:45:44 -0700536 g_pdfium_print_text_with_gdi = !!use_gdi;
537}
rbpotterdb764702017-01-12 10:31:43 -0800538#endif // PDFIUM_PRINT_TEXT_WITH_GDI
539
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400540FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
541FPDF_SetPrintPostscriptLevel(int postscript_level) {
rbpotter38a01b92017-07-13 11:58:01 -0700542 return postscript_level != 1 && FPDF_SetPrintMode(postscript_level);
543}
544
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400545FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_SetPrintMode(int mode) {
rbpottere8468c42017-07-11 10:04:29 -0700546 if (mode < FPDF_PRINTMODE_EMF || mode > FPDF_PRINTMODE_POSTSCRIPT3)
rbpotterdb764702017-01-12 10:31:43 -0800547 return FALSE;
rbpottere8468c42017-07-11 10:04:29 -0700548 g_pdfium_print_mode = mode;
rbpotterdb764702017-01-12 10:31:43 -0800549 return TRUE;
550}
551#endif // defined(_WIN32)
thestigfdb35ff2016-07-18 13:45:44 -0700552
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400553FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV
554FPDF_LoadDocument(FPDF_STRING file_path, FPDF_BYTESTRING password) {
Tom Sepeze3166a82015-08-05 10:50:32 -0700555 // NOTE: the creation of the file needs to be by the embedder on the
556 // other side of this API.
Artem Strygin3f7ff052017-07-27 22:16:13 +0300557 return LoadDocumentImpl(
558 IFX_SeekableReadStream::CreateFromFilename((const char*)file_path),
559 password);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700560}
Jun Fange118ce92015-02-17 06:50:08 -0800561
Tom Sepez40e9ff32015-11-30 12:39:54 -0800562#ifdef PDF_ENABLE_XFA
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400563FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_HasXFAField(FPDF_DOCUMENT document,
564 int* docType) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700565 if (!document)
tsepez4cf55152016-11-02 14:37:54 -0700566 return false;
JUN FANG827a1722015-03-05 13:39:21 -0800567
Lei Zhang01581062017-08-30 14:19:26 -0700568 const CPDF_Document* pDoc =
569 static_cast<CPDFXFA_Context*>(document)->GetPDFDoc();
570 if (!pDoc)
tsepez4cf55152016-11-02 14:37:54 -0700571 return false;
JUN FANG827a1722015-03-05 13:39:21 -0800572
Lei Zhang01581062017-08-30 14:19:26 -0700573 const CPDF_Dictionary* pRoot = pDoc->GetRoot();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700574 if (!pRoot)
tsepez4cf55152016-11-02 14:37:54 -0700575 return false;
JUN FANG827a1722015-03-05 13:39:21 -0800576
dsinclair38fd8442016-09-15 10:15:32 -0700577 CPDF_Dictionary* pAcroForm = pRoot->GetDictFor("AcroForm");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700578 if (!pAcroForm)
tsepez4cf55152016-11-02 14:37:54 -0700579 return false;
JUN FANG827a1722015-03-05 13:39:21 -0800580
dsinclair38fd8442016-09-15 10:15:32 -0700581 CPDF_Object* pXFA = pAcroForm->GetObjectFor("XFA");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700582 if (!pXFA)
tsepez4cf55152016-11-02 14:37:54 -0700583 return false;
JUN FANG827a1722015-03-05 13:39:21 -0800584
dsinclair38fd8442016-09-15 10:15:32 -0700585 bool bDynamicXFA = pRoot->GetBooleanFor("NeedsRendering", false);
thestigded36342016-05-23 17:54:02 -0700586 *docType = bDynamicXFA ? DOCTYPE_DYNAMIC_XFA : DOCTYPE_STATIC_XFA;
tsepez4cf55152016-11-02 14:37:54 -0700587 return true;
Jun Fange118ce92015-02-17 06:50:08 -0800588}
589
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400590FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_LoadXFA(FPDF_DOCUMENT document) {
Lei Zhang01581062017-08-30 14:19:26 -0700591 return document && static_cast<CPDFXFA_Context*>(document)->LoadXFADoc();
Bo Xufdc00a72014-10-28 23:03:33 -0700592}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800593#endif // PDF_ENABLE_XFA
Bo Xufdc00a72014-10-28 23:03:33 -0700594
tsepezad2441e2016-10-24 10:19:11 -0700595class CMemFile final : public IFX_SeekableReadStream {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700596 public:
tsepez833619b2016-12-07 09:21:17 -0800597 static CFX_RetainPtr<CMemFile> Create(uint8_t* pBuf, FX_FILESIZE size) {
598 return CFX_RetainPtr<CMemFile>(new CMemFile(pBuf, size));
599 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700600
Lei Zhang3884dba2015-10-19 17:27:53 -0700601 FX_FILESIZE GetSize() override { return m_size; }
tsepezf39074c2016-10-26 15:33:58 -0700602 bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override {
tsepez833619b2016-12-07 09:21:17 -0800603 if (offset < 0)
tsepezf39074c2016-10-26 15:33:58 -0700604 return false;
tsepez833619b2016-12-07 09:21:17 -0800605
tsepez4e597c82016-11-07 15:16:01 -0800606 FX_SAFE_FILESIZE newPos = pdfium::base::checked_cast<FX_FILESIZE>(size);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700607 newPos += offset;
tsepez833619b2016-12-07 09:21:17 -0800608 if (!newPos.IsValid() || newPos.ValueOrDie() > m_size)
tsepezf39074c2016-10-26 15:33:58 -0700609 return false;
tsepez833619b2016-12-07 09:21:17 -0800610
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400611 memcpy(buffer, m_pBuf + offset, size);
tsepezf39074c2016-10-26 15:33:58 -0700612 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700613 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700614
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700615 private:
tsepez833619b2016-12-07 09:21:17 -0800616 CMemFile(uint8_t* pBuf, FX_FILESIZE size) : m_pBuf(pBuf), m_size(size) {}
Lei Zhang2b1a2d52015-08-14 22:16:22 -0700617
Lei Zhang3884dba2015-10-19 17:27:53 -0700618 uint8_t* const m_pBuf;
619 const FX_FILESIZE m_size;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700620};
Lei Zhang3884dba2015-10-19 17:27:53 -0700621
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400622FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV
623FPDF_LoadMemDocument(const void* data_buf, int size, FPDF_BYTESTRING password) {
Artem Strygin3f7ff052017-07-27 22:16:13 +0300624 return LoadDocumentImpl(CMemFile::Create((uint8_t*)data_buf, size), password);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700625}
626
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400627FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700628FPDF_LoadCustomDocument(FPDF_FILEACCESS* pFileAccess,
629 FPDF_BYTESTRING password) {
Artem Strygin3f7ff052017-07-27 22:16:13 +0300630 return LoadDocumentImpl(pdfium::MakeRetain<CPDF_CustomAccess>(pFileAccess),
631 password);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700632}
633
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400634FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_GetFileVersion(FPDF_DOCUMENT doc,
635 int* fileVersion) {
Tom Sepez471a1032015-10-15 16:17:18 -0700636 if (!fileVersion)
tsepez4cf55152016-11-02 14:37:54 -0700637 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700638
Tom Sepez471a1032015-10-15 16:17:18 -0700639 *fileVersion = 0;
640 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(doc);
641 if (!pDoc)
tsepez4cf55152016-11-02 14:37:54 -0700642 return false;
Tom Sepez471a1032015-10-15 16:17:18 -0700643
Lei Zhang01581062017-08-30 14:19:26 -0700644 const CPDF_Parser* pParser = pDoc->GetParser();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700645 if (!pParser)
tsepez4cf55152016-11-02 14:37:54 -0700646 return false;
Tom Sepez471a1032015-10-15 16:17:18 -0700647
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700648 *fileVersion = pParser->GetFileVersion();
tsepez4cf55152016-11-02 14:37:54 -0700649 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700650}
651
tsepezc3255f52016-03-25 14:52:27 -0700652// jabdelmalek: changed return type from uint32_t to build on Linux (and match
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700653// header).
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400654FPDF_EXPORT unsigned long FPDF_CALLCONV
655FPDF_GetDocPermissions(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700656 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
thestig27ddf162016-05-23 15:06:59 -0700657 // https://bugs.chromium.org/p/pdfium/issues/detail?id=499
658 if (!pDoc) {
Tom Sepez51da0932015-11-25 16:05:49 -0800659#ifndef PDF_ENABLE_XFA
660 return 0;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800661#else // PDF_ENABLE_XFA
thestig27ddf162016-05-23 15:06:59 -0700662 return 0xFFFFFFFF;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800663#endif // PDF_ENABLE_XFA
thestig27ddf162016-05-23 15:06:59 -0700664 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700665
thestig27ddf162016-05-23 15:06:59 -0700666 return pDoc->GetUserPermissions();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700667}
668
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400669FPDF_EXPORT int FPDF_CALLCONV
670FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700671 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
thestigb8db5112016-04-06 12:12:52 -0700672 if (!pDoc || !pDoc->GetParser())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700673 return -1;
Bo Xuc5cab022014-09-19 19:16:31 -0700674
Tom Sepez471a1032015-10-15 16:17:18 -0700675 CPDF_Dictionary* pDict = pDoc->GetParser()->GetEncryptDict();
dsinclair38fd8442016-09-15 10:15:32 -0700676 return pDict ? pDict->GetIntegerFor("R") : -1;
Bo Xuc5cab022014-09-19 19:16:31 -0700677}
678
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400679FPDF_EXPORT int FPDF_CALLCONV FPDF_GetPageCount(FPDF_DOCUMENT document) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800680 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
Tom Sepez471a1032015-10-15 16:17:18 -0700681 return pDoc ? pDoc->GetPageCount() : 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700682}
683
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400684FPDF_EXPORT FPDF_PAGE FPDF_CALLCONV FPDF_LoadPage(FPDF_DOCUMENT document,
685 int page_index) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800686 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
687 if (!pDoc)
Tom Sepez471a1032015-10-15 16:17:18 -0700688 return nullptr;
Tom Sepez1b246282015-11-25 15:15:31 -0800689
Tom Sepezbbe0e4d2015-10-20 15:41:40 -0700690 if (page_index < 0 || page_index >= pDoc->GetPageCount())
Tom Sepez471a1032015-10-15 16:17:18 -0700691 return nullptr;
692
Tom Sepez40e9ff32015-11-30 12:39:54 -0800693#ifdef PDF_ENABLE_XFA
Tom Sepez9792f162017-05-16 14:11:30 -0700694 return pDoc->GetXFAPage(page_index).Leak();
Tom Sepez40e9ff32015-11-30 12:39:54 -0800695#else // PDF_ENABLE_XFA
Tom Sepez51da0932015-11-25 16:05:49 -0800696 CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
Lei Zhang412e9082015-12-14 18:34:00 -0800697 if (!pDict)
thestig5cc24652016-04-26 11:46:02 -0700698 return nullptr;
699
700 CPDF_Page* pPage = new CPDF_Page(pDoc, pDict, true);
701 pPage->ParseContent();
Tom Sepez51da0932015-11-25 16:05:49 -0800702 return pPage;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800703#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700704}
705
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400706FPDF_EXPORT double FPDF_CALLCONV FPDF_GetPageWidth(FPDF_PAGE page) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800707 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezbf59a072015-10-21 14:07:23 -0700708 return pPage ? pPage->GetPageWidth() : 0.0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700709}
710
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400711FPDF_EXPORT double FPDF_CALLCONV FPDF_GetPageHeight(FPDF_PAGE page) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800712 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezbf59a072015-10-21 14:07:23 -0700713 return pPage ? pPage->GetPageHeight() : 0.0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700714}
715
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700716#if defined(_WIN32)
rbpottercec01802017-04-17 09:10:21 -0700717namespace {
718
719const double kEpsilonSize = 0.01f;
720
721void GetScaling(CPDF_Page* pPage,
722 int size_x,
723 int size_y,
724 int rotate,
725 double* scale_x,
726 double* scale_y) {
727 ASSERT(pPage);
728 ASSERT(scale_x);
729 ASSERT(scale_y);
730 double page_width = pPage->GetPageWidth();
731 double page_height = pPage->GetPageHeight();
732 if (page_width < kEpsilonSize || page_height < kEpsilonSize)
733 return;
734
735 if (rotate % 2 == 0) {
736 *scale_x = size_x / page_width;
737 *scale_y = size_y / page_height;
738 } else {
739 *scale_x = size_y / page_width;
740 *scale_y = size_x / page_height;
741 }
742}
743
744FX_RECT GetMaskDimensionsAndOffsets(CPDF_Page* pPage,
745 int start_x,
746 int start_y,
747 int size_x,
748 int size_y,
749 int rotate,
750 const CFX_FloatRect& mask_box) {
751 double scale_x = 0.0f;
752 double scale_y = 0.0f;
753 GetScaling(pPage, size_x, size_y, rotate, &scale_x, &scale_y);
754 if (scale_x < kEpsilonSize || scale_y < kEpsilonSize)
755 return FX_RECT();
756
757 // Compute sizes in page points. Round down to catch the entire bitmap.
758 int start_x_bm = static_cast<int>(mask_box.left * scale_x);
759 int start_y_bm = static_cast<int>(mask_box.bottom * scale_y);
760 int size_x_bm = static_cast<int>(mask_box.right * scale_x + 1.0f) -
761 static_cast<int>(mask_box.left * scale_x);
762 int size_y_bm = static_cast<int>(mask_box.top * scale_y + 1.0f) -
763 static_cast<int>(mask_box.bottom * scale_y);
764
765 // Get page rotation
rbpotterce8e51e2017-04-28 12:42:47 -0700766 int page_rotation = pPage->GetPageRotation();
rbpottercec01802017-04-17 09:10:21 -0700767
768 // Compute offsets
769 int offset_x = 0;
770 int offset_y = 0;
rbpotter8d7672e2017-08-16 16:45:44 -0700771 if (size_x > size_y)
772 std::swap(size_x_bm, size_y_bm);
773
rbpottercec01802017-04-17 09:10:21 -0700774 switch ((rotate + page_rotation) % 4) {
775 case 0:
776 offset_x = start_x_bm + start_x;
777 offset_y = start_y + size_y - size_y_bm - start_y_bm;
778 break;
779 case 1:
780 offset_x = start_y_bm + start_x;
781 offset_y = start_x_bm + start_y;
782 break;
783 case 2:
784 offset_x = start_x + size_x - size_x_bm - start_x_bm;
785 offset_y = start_y_bm + start_y;
786 break;
787 case 3:
788 offset_x = start_x + size_x - size_x_bm - start_y_bm;
789 offset_y = start_y + size_y - size_y_bm - start_x_bm;
790 break;
791 }
792 return FX_RECT(offset_x, offset_y, offset_x + size_x_bm,
793 offset_y + size_y_bm);
794}
795
796// Get a bitmap of just the mask section defined by |mask_box| from a full page
797// bitmap |pBitmap|.
798CFX_RetainPtr<CFX_DIBitmap> GetMaskBitmap(CPDF_Page* pPage,
799 int start_x,
800 int start_y,
801 int size_x,
802 int size_y,
803 int rotate,
804 CFX_RetainPtr<CFX_DIBitmap>& pSrc,
805 const CFX_FloatRect& mask_box,
806 FX_RECT* bitmap_area) {
807 ASSERT(bitmap_area);
808 *bitmap_area = GetMaskDimensionsAndOffsets(pPage, start_x, start_y, size_x,
809 size_y, rotate, mask_box);
810 if (bitmap_area->IsEmpty())
811 return nullptr;
812
813 // Create a new bitmap to transfer part of the page bitmap to.
814 CFX_RetainPtr<CFX_DIBitmap> pDst = pdfium::MakeRetain<CFX_DIBitmap>();
815 pDst->Create(bitmap_area->Width(), bitmap_area->Height(), FXDIB_Argb);
816 pDst->Clear(0x00ffffff);
817 pDst->TransferBitmap(0, 0, bitmap_area->Width(), bitmap_area->Height(), pSrc,
818 bitmap_area->left, bitmap_area->top);
819 return pDst;
820}
821
822void RenderBitmap(CFX_RenderDevice* device,
823 const CFX_RetainPtr<CFX_DIBitmap>& pSrc,
824 const FX_RECT& mask_area) {
825 int size_x_bm = mask_area.Width();
826 int size_y_bm = mask_area.Height();
827 if (size_x_bm == 0 || size_y_bm == 0)
828 return;
829
830 // Create a new bitmap from the old one
831 CFX_RetainPtr<CFX_DIBitmap> pDst = pdfium::MakeRetain<CFX_DIBitmap>();
832 pDst->Create(size_x_bm, size_y_bm, FXDIB_Rgb32);
833 pDst->Clear(0xffffffff);
834 pDst->CompositeBitmap(0, 0, size_x_bm, size_y_bm, pSrc, 0, 0,
835 FXDIB_BLEND_NORMAL, nullptr, false);
836
837 if (device->GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
rbpotter8d7672e2017-08-16 16:45:44 -0700838 device->StretchDIBits(pDst, mask_area.left, mask_area.top, size_x_bm,
839 size_y_bm);
rbpottercec01802017-04-17 09:10:21 -0700840 } else {
841 device->SetDIBits(pDst, mask_area.left, mask_area.top);
842 }
843}
844
845} // namespace
846
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400847FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPage(HDC dc,
848 FPDF_PAGE page,
849 int start_x,
850 int start_y,
851 int size_x,
852 int size_y,
853 int rotate,
854 int flags) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700855 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700856 if (!pPage)
857 return;
rbpottercec01802017-04-17 09:10:21 -0700858 pPage->SetRenderContext(pdfium::MakeUnique<CPDF_PageRenderContext>());
859 CPDF_PageRenderContext* pContext = pPage->GetRenderContext();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700860
Tom Sepezf0799fe2017-03-28 09:31:32 -0700861 CFX_RetainPtr<CFX_DIBitmap> pBitmap;
rbpottercec01802017-04-17 09:10:21 -0700862 // Don't render the full page to bitmap for a mask unless there are a lot
863 // of masks. Full page bitmaps result in large spool sizes, so they should
864 // only be used when necessary. For large numbers of masks, rendering each
865 // individually is inefficient and unlikely to significantly improve spool
rbpotter8d7672e2017-08-16 16:45:44 -0700866 // size.
thestig84144e82016-09-27 15:06:01 -0700867 const bool bNewBitmap =
rbpotter8d7672e2017-08-16 16:45:44 -0700868 pPage->BackgroundAlphaNeeded() ||
869 (pPage->HasImageMask() && pPage->GetMaskBoundingBoxes().size() > 100);
rbpottercec01802017-04-17 09:10:21 -0700870 const bool bHasMask = pPage->HasImageMask() && !bNewBitmap;
871 if (bNewBitmap || bHasMask) {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700872 pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700873 pBitmap->Create(size_x, size_y, FXDIB_Argb);
874 pBitmap->Clear(0x00ffffff);
Dan Sinclaira5085d42017-05-11 16:26:50 -0400875 CFX_DefaultRenderDevice* pDevice = new CFX_DefaultRenderDevice;
tsepez36eb4bd2016-10-03 15:24:27 -0700876 pContext->m_pDevice = pdfium::WrapUnique(pDevice);
Tom Sepezf0799fe2017-03-28 09:31:32 -0700877 pDevice->Attach(pBitmap, false, nullptr, false);
rbpottercec01802017-04-17 09:10:21 -0700878 if (bHasMask) {
879 pContext->m_pOptions = pdfium::MakeUnique<CPDF_RenderOptions>();
880 pContext->m_pOptions->m_Flags |= RENDER_BREAKFORMASKS;
881 }
Jun Fang1aeeceb2015-12-29 10:27:44 +0800882 } else {
Dan Sinclaira5085d42017-05-11 16:26:50 -0400883 pContext->m_pDevice = pdfium::MakeUnique<CFX_WindowsRenderDevice>(dc);
Jun Fang1aeeceb2015-12-29 10:27:44 +0800884 }
rbpottercec01802017-04-17 09:10:21 -0700885
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700886 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
tsepez4cf55152016-11-02 14:37:54 -0700887 rotate, flags, true, nullptr);
Bo Xud4e406e2014-08-13 11:03:19 -0700888
rbpottercec01802017-04-17 09:10:21 -0700889 if (bHasMask) {
890 // Finish rendering the page to bitmap and copy the correct segments
891 // of the page to individual image mask bitmaps.
892 const std::vector<CFX_FloatRect>& mask_boxes =
893 pPage->GetMaskBoundingBoxes();
894 std::vector<FX_RECT> bitmap_areas(mask_boxes.size());
895 std::vector<CFX_RetainPtr<CFX_DIBitmap>> bitmaps(mask_boxes.size());
896 for (size_t i = 0; i < mask_boxes.size(); i++) {
897 bitmaps[i] =
898 GetMaskBitmap(pPage, start_x, start_y, size_x, size_y, rotate,
899 pBitmap, mask_boxes[i], &bitmap_areas[i]);
900 pContext->m_pRenderer->Continue(nullptr);
901 }
902
903 // Reset rendering context
904 pPage->SetRenderContext(nullptr);
905
906 // Begin rendering to the printer. Add flag to indicate the renderer should
907 // pause after each image mask.
908 pPage->SetRenderContext(pdfium::MakeUnique<CPDF_PageRenderContext>());
909 pContext = pPage->GetRenderContext();
Dan Sinclaira5085d42017-05-11 16:26:50 -0400910 pContext->m_pDevice = pdfium::MakeUnique<CFX_WindowsRenderDevice>(dc);
rbpottercec01802017-04-17 09:10:21 -0700911 pContext->m_pOptions = pdfium::MakeUnique<CPDF_RenderOptions>();
912 pContext->m_pOptions->m_Flags |= RENDER_BREAKFORMASKS;
913 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
914 rotate, flags, true, nullptr);
915
916 // Render masks
917 for (size_t i = 0; i < mask_boxes.size(); i++) {
918 // Render the bitmap for the mask and free the bitmap.
919 if (bitmaps[i]) { // will be null if mask has zero area
920 RenderBitmap(pContext->m_pDevice.get(), bitmaps[i], bitmap_areas[i]);
921 }
922 // Render the next portion of page.
923 pContext->m_pRenderer->Continue(nullptr);
924 }
925 } else if (bNewBitmap) {
Dan Sinclaira5085d42017-05-11 16:26:50 -0400926 CFX_WindowsRenderDevice WinDC(dc);
thestig84144e82016-09-27 15:06:01 -0700927 if (WinDC.GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700928 auto pDst = pdfium::MakeRetain<CFX_DIBitmap>();
thestig84144e82016-09-27 15:06:01 -0700929 int pitch = pBitmap->GetPitch();
930 pDst->Create(size_x, size_y, FXDIB_Rgb32);
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400931 memset(pDst->GetBuffer(), -1, pitch * size_y);
Tom Sepezf0799fe2017-03-28 09:31:32 -0700932 pDst->CompositeBitmap(0, 0, size_x, size_y, pBitmap, 0, 0,
Nicolas Pena6a5c20c2017-04-07 14:12:31 -0400933 FXDIB_BLEND_NORMAL, nullptr, false);
Tom Sepezf0799fe2017-03-28 09:31:32 -0700934 WinDC.StretchDIBits(pDst, 0, 0, size_x, size_y);
thestig84144e82016-09-27 15:06:01 -0700935 } else {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700936 WinDC.SetDIBits(pBitmap, 0, 0);
Lei Zhang6d8b1c22015-06-19 17:26:17 -0700937 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700938 }
rbpottercec01802017-04-17 09:10:21 -0700939
tsepeze5cb0b12016-10-26 15:06:11 -0700940 pPage->SetRenderContext(nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700941}
Lei Zhangae85f872016-02-19 14:57:07 -0800942#endif // defined(_WIN32)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700943
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400944FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPageBitmap(FPDF_BITMAP bitmap,
945 FPDF_PAGE page,
946 int start_x,
947 int start_y,
948 int size_x,
949 int size_y,
950 int rotate,
951 int flags) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700952 if (!bitmap)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700953 return;
tsepez1e2c5572016-05-25 14:58:09 -0700954
Tom Sepezdb0be962015-10-16 14:00:21 -0700955 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700956 if (!pPage)
957 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700958
weili9f515bc2016-07-24 08:08:24 -0700959 CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
tsepez36eb4bd2016-10-03 15:24:27 -0700960 pPage->SetRenderContext(pdfium::WrapUnique(pContext));
Tom Sepezf0799fe2017-03-28 09:31:32 -0700961
Dan Sinclaira5085d42017-05-11 16:26:50 -0400962 CFX_DefaultRenderDevice* pDevice = new CFX_DefaultRenderDevice;
weili9f515bc2016-07-24 08:08:24 -0700963 pContext->m_pDevice.reset(pDevice);
dsinclair31b08d42017-03-28 15:47:47 +0000964
Tom Sepezf0799fe2017-03-28 09:31:32 -0700965 CFX_RetainPtr<CFX_DIBitmap> pBitmap(CFXBitmapFromFPDFBitmap(bitmap));
966 pDevice->Attach(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER), nullptr, false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700967 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
tsepez4cf55152016-11-02 14:37:54 -0700968 rotate, flags, true, nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700969
caryclark687fbde2016-11-22 12:44:25 -0800970#ifdef _SKIA_SUPPORT_PATHS_
Cary Clark364d18b2017-07-25 10:39:10 -0400971 pDevice->Flush(true);
caryclark687fbde2016-11-22 12:44:25 -0800972 pBitmap->UnPreMultiply();
973#endif
tsepeze5cb0b12016-10-26 15:06:11 -0700974 pPage->SetRenderContext(nullptr);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700975}
976
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400977FPDF_EXPORT void FPDF_CALLCONV
978FPDF_RenderPageBitmapWithMatrix(FPDF_BITMAP bitmap,
979 FPDF_PAGE page,
980 const FS_MATRIX* matrix,
981 const FS_RECTF* clipping,
982 int flags) {
thestiga78ba602016-11-23 15:25:48 -0800983 if (!bitmap)
984 return;
985
986 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
987 if (!pPage)
988 return;
989
990 CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
991 pPage->SetRenderContext(pdfium::WrapUnique(pContext));
Tom Sepezf0799fe2017-03-28 09:31:32 -0700992
Dan Sinclaira5085d42017-05-11 16:26:50 -0400993 CFX_DefaultRenderDevice* pDevice = new CFX_DefaultRenderDevice;
thestiga78ba602016-11-23 15:25:48 -0800994 pContext->m_pDevice.reset(pDevice);
Tom Sepezf0799fe2017-03-28 09:31:32 -0700995
996 CFX_RetainPtr<CFX_DIBitmap> pBitmap(CFXBitmapFromFPDFBitmap(bitmap));
thestiga78ba602016-11-23 15:25:48 -0800997 pDevice->Attach(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER), nullptr, false);
998
thestiga78ba602016-11-23 15:25:48 -0800999 CFX_FloatRect clipping_rect;
1000 if (clipping) {
1001 clipping_rect.left = clipping->left;
1002 clipping_rect.bottom = clipping->bottom;
1003 clipping_rect.right = clipping->right;
1004 clipping_rect.top = clipping->top;
1005 }
Nicolas Pena60bde102017-07-26 13:50:12 -04001006 FX_RECT clip_rect = clipping_rect.ToFxRect();
Nicolas Pena24b07332017-09-13 18:02:11 -04001007 RenderPageImpl(
1008 pContext, pPage,
1009 pPage->GetDisplayMatrixWithTransformation(
1010 clip_rect.left, clip_rect.top, clip_rect.Width(), clip_rect.Height(),
1011 CFX_Matrix(matrix->a, matrix->b, matrix->c, matrix->d, matrix->e,
1012 matrix->f)),
1013 clip_rect, flags, true, nullptr);
thestiga78ba602016-11-23 15:25:48 -08001014
1015 pPage->SetRenderContext(nullptr);
1016}
1017
Cary Clark399be5b2016-03-14 16:51:29 -04001018#ifdef _SKIA_SUPPORT_
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001019FPDF_EXPORT FPDF_RECORDER FPDF_CALLCONV FPDF_RenderPageSkp(FPDF_PAGE page,
1020 int size_x,
1021 int size_y) {
Cary Clark399be5b2016-03-14 16:51:29 -04001022 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
1023 if (!pPage)
1024 return nullptr;
tsepez1e2c5572016-05-25 14:58:09 -07001025
weili9f515bc2016-07-24 08:08:24 -07001026 CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
tsepez36eb4bd2016-10-03 15:24:27 -07001027 pPage->SetRenderContext(pdfium::WrapUnique(pContext));
Dan Sinclaira5085d42017-05-11 16:26:50 -04001028 CFX_DefaultRenderDevice* skDevice = new CFX_DefaultRenderDevice;
Cary Clark399be5b2016-03-14 16:51:29 -04001029 FPDF_RECORDER recorder = skDevice->CreateRecorder(size_x, size_y);
weili9f515bc2016-07-24 08:08:24 -07001030 pContext->m_pDevice.reset(skDevice);
tsepez4cf55152016-11-02 14:37:54 -07001031 FPDF_RenderPage_Retail(pContext, page, 0, 0, size_x, size_y, 0, 0, true,
tsepez1e2c5572016-05-25 14:58:09 -07001032 nullptr);
tsepeze5cb0b12016-10-26 15:06:11 -07001033 pPage->SetRenderContext(nullptr);
Cary Clark399be5b2016-03-14 16:51:29 -04001034 return recorder;
1035}
1036#endif
1037
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001038FPDF_EXPORT void FPDF_CALLCONV FPDF_ClosePage(FPDF_PAGE page) {
tsepez1e2c5572016-05-25 14:58:09 -07001039 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001040 if (!page)
1041 return;
Tom Sepez40e9ff32015-11-30 12:39:54 -08001042#ifdef PDF_ENABLE_XFA
Tom Sepez9792f162017-05-16 14:11:30 -07001043 // Take it back across the API and throw it away.
1044 CFX_RetainPtr<CPDFXFA_Page>().Unleak(pPage);
Tom Sepez40e9ff32015-11-30 12:39:54 -08001045#else // PDF_ENABLE_XFA
Tom Sepez51da0932015-11-25 16:05:49 -08001046 CPDFSDK_PageView* pPageView =
tsepez1e2c5572016-05-25 14:58:09 -07001047 static_cast<CPDFSDK_PageView*>(pPage->GetView());
dsinclair1df1efa2016-09-07 09:55:37 -07001048 if (pPageView) {
dsinclairbcf46232016-10-03 13:02:27 -07001049 // We're already destroying the pageview, so bail early.
1050 if (pPageView->IsBeingDestroyed())
1051 return;
1052
dsinclair1df1efa2016-09-07 09:55:37 -07001053 if (pPageView->IsLocked()) {
1054 pPageView->TakePageOwnership();
1055 return;
1056 }
1057
1058 bool owned = pPageView->OwnsPage();
1059 // This will delete the |pPageView| object. We must cleanup the PageView
1060 // first because it will attempt to reset the View on the |pPage| during
1061 // destruction.
dsinclair7cbe68e2016-10-12 11:56:23 -07001062 pPageView->GetFormFillEnv()->RemovePageView(pPage);
dsinclair1df1efa2016-09-07 09:55:37 -07001063 // If the page was owned then the pageview will have deleted the page.
1064 if (owned)
1065 return;
Tom Sepez51da0932015-11-25 16:05:49 -08001066 }
tsepez1e2c5572016-05-25 14:58:09 -07001067 delete pPage;
Tom Sepez40e9ff32015-11-30 12:39:54 -08001068#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001069}
1070
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001071FPDF_EXPORT void FPDF_CALLCONV FPDF_CloseDocument(FPDF_DOCUMENT document) {
Jun Fangfc751362015-12-16 21:23:39 -08001072 delete UnderlyingFromFPDFDocument(document);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001073}
1074
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001075FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_GetLastError() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001076 return GetLastError();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001077}
1078
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001079FPDF_EXPORT void FPDF_CALLCONV FPDF_DeviceToPage(FPDF_PAGE page,
1080 int start_x,
1081 int start_y,
1082 int size_x,
1083 int size_y,
1084 int rotate,
1085 int device_x,
1086 int device_y,
1087 double* page_x,
1088 double* page_y) {
Lei Zhang412e9082015-12-14 18:34:00 -08001089 if (!page || !page_x || !page_y)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001090 return;
Tom Sepez50d12ad2015-11-24 09:50:51 -08001091 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepez40e9ff32015-11-30 12:39:54 -08001092#ifdef PDF_ENABLE_XFA
1093 pPage->DeviceToPage(start_x, start_y, size_x, size_y, rotate, device_x,
1094 device_y, page_x, page_y);
1095#else // PDF_ENABLE_XFA
Dan Sinclair1b08df12017-02-09 09:17:20 -05001096 CFX_Matrix page2device =
1097 pPage->GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate);
Dan Sinclair1b08df12017-02-09 09:17:20 -05001098
Nicolas Penab21f1742017-06-29 12:02:06 -04001099 CFX_PointF pos = page2device.GetInverse().Transform(
Dan Sinclair05df0752017-03-14 14:43:42 -04001100 CFX_PointF(static_cast<float>(device_x), static_cast<float>(device_y)));
Dan Sinclairafb44562017-02-09 13:07:43 -05001101
Dan Sinclaira0061af2017-02-23 09:25:17 -05001102 *page_x = pos.x;
1103 *page_y = pos.y;
Tom Sepez40e9ff32015-11-30 12:39:54 -08001104#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001105}
1106
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001107FPDF_EXPORT void FPDF_CALLCONV FPDF_PageToDevice(FPDF_PAGE page,
1108 int start_x,
1109 int start_y,
1110 int size_x,
1111 int size_y,
1112 int rotate,
1113 double page_x,
1114 double page_y,
1115 int* device_x,
1116 int* device_y) {
Tom Sepezdb0be962015-10-16 14:00:21 -07001117 if (!device_x || !device_y)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001118 return;
Tom Sepez50d12ad2015-11-24 09:50:51 -08001119 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezdb0be962015-10-16 14:00:21 -07001120 if (!pPage)
1121 return;
Tom Sepez40e9ff32015-11-30 12:39:54 -08001122#ifdef PDF_ENABLE_XFA
1123 pPage->PageToDevice(start_x, start_y, size_x, size_y, rotate, page_x, page_y,
1124 device_x, device_y);
1125#else // PDF_ENABLE_XFA
Dan Sinclair1b08df12017-02-09 09:17:20 -05001126 CFX_Matrix page2device =
1127 pPage->GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate);
Dan Sinclaira0061af2017-02-23 09:25:17 -05001128 CFX_PointF pos = page2device.Transform(
Dan Sinclair05df0752017-03-14 14:43:42 -04001129 CFX_PointF(static_cast<float>(page_x), static_cast<float>(page_y)));
Dan Sinclairafb44562017-02-09 13:07:43 -05001130
Dan Sinclaira0061af2017-02-23 09:25:17 -05001131 *device_x = FXSYS_round(pos.x);
1132 *device_y = FXSYS_round(pos.y);
Tom Sepez40e9ff32015-11-30 12:39:54 -08001133#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001134}
1135
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001136FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV FPDFBitmap_Create(int width,
1137 int height,
1138 int alpha) {
Tom Sepezf0799fe2017-03-28 09:31:32 -07001139 auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
tsepez37b12ad2016-12-14 19:50:23 -08001140 if (!pBitmap->Create(width, height, alpha ? FXDIB_Argb : FXDIB_Rgb32))
thestig1cd352e2016-06-07 17:53:06 -07001141 return nullptr;
tsepez37b12ad2016-12-14 19:50:23 -08001142
Tom Sepezf0799fe2017-03-28 09:31:32 -07001143 return pBitmap.Leak();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001144}
1145
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001146FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV FPDFBitmap_CreateEx(int width,
1147 int height,
1148 int format,
1149 void* first_scan,
1150 int stride) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001151 FXDIB_Format fx_format;
1152 switch (format) {
1153 case FPDFBitmap_Gray:
1154 fx_format = FXDIB_8bppRgb;
1155 break;
1156 case FPDFBitmap_BGR:
1157 fx_format = FXDIB_Rgb;
1158 break;
1159 case FPDFBitmap_BGRx:
1160 fx_format = FXDIB_Rgb32;
1161 break;
1162 case FPDFBitmap_BGRA:
1163 fx_format = FXDIB_Argb;
1164 break;
1165 default:
thestig1cd352e2016-06-07 17:53:06 -07001166 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001167 }
Tom Sepezf0799fe2017-03-28 09:31:32 -07001168 auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001169 pBitmap->Create(width, height, fx_format, (uint8_t*)first_scan, stride);
Tom Sepezf0799fe2017-03-28 09:31:32 -07001170 return pBitmap.Leak();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001171}
1172
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001173FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetFormat(FPDF_BITMAP bitmap) {
Jane Liu28fb7ba2017-08-02 21:45:57 -04001174 if (!bitmap)
1175 return FPDFBitmap_Unknown;
1176
1177 FXDIB_Format format = CFXBitmapFromFPDFBitmap(bitmap)->GetFormat();
1178 switch (format) {
1179 case FXDIB_8bppRgb:
1180 case FXDIB_8bppMask:
1181 return FPDFBitmap_Gray;
1182 case FXDIB_Rgb:
1183 return FPDFBitmap_BGR;
1184 case FXDIB_Rgb32:
1185 return FPDFBitmap_BGRx;
1186 case FXDIB_Argb:
1187 return FPDFBitmap_BGRA;
1188 default:
1189 return FPDFBitmap_Unknown;
1190 }
1191}
1192
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001193FPDF_EXPORT void FPDF_CALLCONV FPDFBitmap_FillRect(FPDF_BITMAP bitmap,
1194 int left,
1195 int top,
1196 int width,
1197 int height,
1198 FPDF_DWORD color) {
Lei Zhang412e9082015-12-14 18:34:00 -08001199 if (!bitmap)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001200 return;
thestigbefa4502016-05-26 20:15:19 -07001201
Dan Sinclaira5085d42017-05-11 16:26:50 -04001202 CFX_DefaultRenderDevice device;
Tom Sepezf0799fe2017-03-28 09:31:32 -07001203 CFX_RetainPtr<CFX_DIBitmap> pBitmap(CFXBitmapFromFPDFBitmap(bitmap));
thestigbefa4502016-05-26 20:15:19 -07001204 device.Attach(pBitmap, false, nullptr, false);
1205 if (!pBitmap->HasAlpha())
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001206 color |= 0xFF000000;
1207 FX_RECT rect(left, top, left + width, top + height);
1208 device.FillRect(&rect, color);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001209}
1210
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001211FPDF_EXPORT void* FPDF_CALLCONV FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap) {
thestigbefa4502016-05-26 20:15:19 -07001212 return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetBuffer() : nullptr;
Bo Xu9114e832014-07-14 13:22:47 -07001213}
1214
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001215FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetWidth(FPDF_BITMAP bitmap) {
thestigbefa4502016-05-26 20:15:19 -07001216 return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetWidth() : 0;
Bo Xu9114e832014-07-14 13:22:47 -07001217}
1218
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001219FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetHeight(FPDF_BITMAP bitmap) {
thestigbefa4502016-05-26 20:15:19 -07001220 return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetHeight() : 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001221}
1222
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001223FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetStride(FPDF_BITMAP bitmap) {
thestigbefa4502016-05-26 20:15:19 -07001224 return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetPitch() : 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001225}
1226
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001227FPDF_EXPORT void FPDF_CALLCONV FPDFBitmap_Destroy(FPDF_BITMAP bitmap) {
Tom Sepezf0799fe2017-03-28 09:31:32 -07001228 CFX_RetainPtr<CFX_DIBitmap> destroyer;
1229 destroyer.Unleak(CFXBitmapFromFPDFBitmap(bitmap));
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001230}
1231
weili9f515bc2016-07-24 08:08:24 -07001232void FPDF_RenderPage_Retail(CPDF_PageRenderContext* pContext,
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001233 FPDF_PAGE page,
1234 int start_x,
1235 int start_y,
1236 int size_x,
1237 int size_y,
1238 int rotate,
1239 int flags,
tsepez4cf55152016-11-02 14:37:54 -07001240 bool bNeedToRestore,
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001241 IFSDK_PAUSE_Adapter* pause) {
Tom Sepezdb0be962015-10-16 14:00:21 -07001242 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
1243 if (!pPage)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001244 return;
1245
Dan Sinclair1b08df12017-02-09 09:17:20 -05001246 RenderPageImpl(pContext, pPage, pPage->GetDisplayMatrix(
1247 start_x, start_y, size_x, size_y, rotate),
1248 FX_RECT(start_x, start_y, start_x + size_x, start_y + size_y),
1249 flags, bNeedToRestore, pause);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001250}
1251
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001252FPDF_EXPORT int FPDF_CALLCONV FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document,
1253 int page_index,
1254 double* width,
1255 double* height) {
Tom Sepez540c4362015-11-24 13:33:57 -08001256 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
1257 if (!pDoc)
tsepez4cf55152016-11-02 14:37:54 -07001258 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001259
Tom Sepez40e9ff32015-11-30 12:39:54 -08001260#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001261 int count = pDoc->GetPageCount();
1262 if (page_index < 0 || page_index >= count)
tsepez4cf55152016-11-02 14:37:54 -07001263 return false;
Tom Sepez9792f162017-05-16 14:11:30 -07001264 CFX_RetainPtr<CPDFXFA_Page> pPage = pDoc->GetXFAPage(page_index);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001265 if (!pPage)
tsepez4cf55152016-11-02 14:37:54 -07001266 return false;
Tom Sepez40e9ff32015-11-30 12:39:54 -08001267 *width = pPage->GetPageWidth();
1268 *height = pPage->GetPageHeight();
1269#else // PDF_ENABLE_XFA
1270 CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
1271 if (!pDict)
tsepez4cf55152016-11-02 14:37:54 -07001272 return false;
thestig5cc24652016-04-26 11:46:02 -07001273
1274 CPDF_Page page(pDoc, pDict, true);
Tom Sepez51da0932015-11-25 16:05:49 -08001275 *width = page.GetPageWidth();
1276 *height = page.GetPageHeight();
Tom Sepez40e9ff32015-11-30 12:39:54 -08001277#endif // PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001278
tsepez4cf55152016-11-02 14:37:54 -07001279 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001280}
1281
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001282FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001283FPDF_VIEWERREF_GetPrintScaling(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001284 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001285 if (!pDoc)
tsepez4cf55152016-11-02 14:37:54 -07001286 return true;
Tom Sepez471a1032015-10-15 16:17:18 -07001287 CPDF_ViewerPreferences viewRef(pDoc);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001288 return viewRef.PrintScaling();
1289}
1290
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001291FPDF_EXPORT int FPDF_CALLCONV
1292FPDF_VIEWERREF_GetNumCopies(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001293 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001294 if (!pDoc)
1295 return 1;
1296 CPDF_ViewerPreferences viewRef(pDoc);
1297 return viewRef.NumCopies();
1298}
1299
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001300FPDF_EXPORT FPDF_PAGERANGE FPDF_CALLCONV
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001301FPDF_VIEWERREF_GetPrintPageRange(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001302 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001303 if (!pDoc)
thestig1cd352e2016-06-07 17:53:06 -07001304 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001305 CPDF_ViewerPreferences viewRef(pDoc);
1306 return viewRef.PrintPageRange();
1307}
1308
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001309FPDF_EXPORT FPDF_DUPLEXTYPE FPDF_CALLCONV
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001310FPDF_VIEWERREF_GetDuplex(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001311 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001312 if (!pDoc)
Bo Xu9114e832014-07-14 13:22:47 -07001313 return DuplexUndefined;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001314 CPDF_ViewerPreferences viewRef(pDoc);
1315 CFX_ByteString duplex = viewRef.Duplex();
Lei Zhangd983b092015-12-14 16:58:33 -08001316 if ("Simplex" == duplex)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001317 return Simplex;
Lei Zhangd983b092015-12-14 16:58:33 -08001318 if ("DuplexFlipShortEdge" == duplex)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001319 return DuplexFlipShortEdge;
Lei Zhangd983b092015-12-14 16:58:33 -08001320 if ("DuplexFlipLongEdge" == duplex)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001321 return DuplexFlipLongEdge;
1322 return DuplexUndefined;
Bo Xu9114e832014-07-14 13:22:47 -07001323}
1324
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001325FPDF_EXPORT unsigned long FPDF_CALLCONV
1326FPDF_VIEWERREF_GetName(FPDF_DOCUMENT document,
1327 FPDF_BYTESTRING key,
1328 char* buffer,
1329 unsigned long length) {
thestig04bebfe2016-11-04 16:07:25 -07001330 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1331 if (!pDoc)
1332 return 0;
1333
1334 CPDF_ViewerPreferences viewRef(pDoc);
1335 CFX_ByteString bsVal;
1336 if (!viewRef.GenericName(key, &bsVal))
1337 return 0;
1338
1339 unsigned long dwStringLen = bsVal.GetLength() + 1;
1340 if (buffer && length >= dwStringLen)
1341 memcpy(buffer, bsVal.c_str(), dwStringLen);
1342 return dwStringLen;
1343}
1344
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001345FPDF_EXPORT FPDF_DWORD FPDF_CALLCONV
1346FPDF_CountNamedDests(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001347 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1348 if (!pDoc)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001349 return 0;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001350
Lei Zhang01581062017-08-30 14:19:26 -07001351 const CPDF_Dictionary* pRoot = pDoc->GetRoot();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001352 if (!pRoot)
1353 return 0;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001354
Lei Zhangd983b092015-12-14 16:58:33 -08001355 CPDF_NameTree nameTree(pDoc, "Dests");
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001356 pdfium::base::CheckedNumeric<FPDF_DWORD> count = nameTree.GetCount();
dsinclair38fd8442016-09-15 10:15:32 -07001357 CPDF_Dictionary* pDest = pRoot->GetDictFor("Dests");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001358 if (pDest)
1359 count += pDest->GetCount();
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001360
1361 if (!count.IsValid())
1362 return 0;
1363
1364 return count.ValueOrDie();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001365}
1366
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001367FPDF_EXPORT FPDF_DEST FPDF_CALLCONV
1368FPDF_GetNamedDestByName(FPDF_DOCUMENT document, FPDF_BYTESTRING name) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001369 if (!name || name[0] == 0)
Tom Sepez471a1032015-10-15 16:17:18 -07001370 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001371
Tom Sepez471a1032015-10-15 16:17:18 -07001372 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1373 if (!pDoc)
1374 return nullptr;
1375
Lei Zhangd983b092015-12-14 16:58:33 -08001376 CPDF_NameTree name_tree(pDoc, "Dests");
Jane Liu67ccef72017-07-19 13:10:50 -04001377 return name_tree.LookupNamedDest(pDoc, PDF_DecodeText(CFX_ByteString(name)));
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001378}
1379
Tom Sepez51da0932015-11-25 16:05:49 -08001380#ifdef PDF_ENABLE_XFA
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001381FPDF_EXPORT FPDF_RESULT FPDF_CALLCONV FPDF_BStr_Init(FPDF_BSTR* str) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001382 if (!str)
1383 return -1;
1384
Dan Sinclair1c5d0b42017-04-03 15:05:11 -04001385 memset(str, 0, sizeof(FPDF_BSTR));
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001386 return 0;
1387}
1388
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001389FPDF_EXPORT FPDF_RESULT FPDF_CALLCONV FPDF_BStr_Set(FPDF_BSTR* str,
1390 FPDF_LPCSTR bstr,
1391 int length) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001392 if (!str)
1393 return -1;
1394 if (!bstr || !length)
1395 return -1;
1396 if (length == -1)
1397 length = FXSYS_strlen(bstr);
1398
1399 if (length == 0) {
1400 if (str->str) {
1401 FX_Free(str->str);
thestig1cd352e2016-06-07 17:53:06 -07001402 str->str = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001403 }
1404 str->len = 0;
1405 return 0;
1406 }
1407
1408 if (str->str && str->len < length)
1409 str->str = FX_Realloc(char, str->str, length + 1);
1410 else if (!str->str)
1411 str->str = FX_Alloc(char, length + 1);
1412
1413 str->str[length] = 0;
Dan Sinclair1c5d0b42017-04-03 15:05:11 -04001414 memcpy(str->str, bstr, length);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001415 str->len = length;
1416
1417 return 0;
1418}
1419
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001420FPDF_EXPORT FPDF_RESULT FPDF_CALLCONV FPDF_BStr_Clear(FPDF_BSTR* str) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001421 if (!str)
1422 return -1;
1423
1424 if (str->str) {
1425 FX_Free(str->str);
thestig1cd352e2016-06-07 17:53:06 -07001426 str->str = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001427 }
1428 str->len = 0;
1429 return 0;
1430}
Tom Sepez40e9ff32015-11-30 12:39:54 -08001431#endif // PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001432
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001433FPDF_EXPORT FPDF_DEST FPDF_CALLCONV FPDF_GetNamedDest(FPDF_DOCUMENT document,
1434 int index,
1435 void* buffer,
1436 long* buflen) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001437 if (!buffer)
1438 *buflen = 0;
Tom Sepez540c4362015-11-24 13:33:57 -08001439
1440 if (index < 0)
1441 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001442
Tom Sepezbf59a072015-10-21 14:07:23 -07001443 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Tom Sepez540c4362015-11-24 13:33:57 -08001444 if (!pDoc)
1445 return nullptr;
1446
Lei Zhang01581062017-08-30 14:19:26 -07001447 const CPDF_Dictionary* pRoot = pDoc->GetRoot();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001448 if (!pRoot)
Tom Sepez540c4362015-11-24 13:33:57 -08001449 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001450
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001451 CPDF_Object* pDestObj = nullptr;
Jane Liu67ccef72017-07-19 13:10:50 -04001452 CFX_WideString wsName;
Lei Zhangd983b092015-12-14 16:58:33 -08001453 CPDF_NameTree nameTree(pDoc, "Dests");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001454 int count = nameTree.GetCount();
1455 if (index >= count) {
dsinclair38fd8442016-09-15 10:15:32 -07001456 CPDF_Dictionary* pDest = pRoot->GetDictFor("Dests");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001457 if (!pDest)
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001458 return nullptr;
1459
1460 pdfium::base::CheckedNumeric<int> checked_count = count;
1461 checked_count += pDest->GetCount();
1462 if (!checked_count.IsValid() || index >= checked_count.ValueOrDie())
1463 return nullptr;
1464
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001465 index -= count;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001466 int i = 0;
Lei Zhangd0856ba2017-07-20 23:41:26 -07001467 CFX_ByteString bsName;
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001468 for (const auto& it : *pDest) {
1469 bsName = it.first;
tsepez0e606b52016-11-18 16:22:41 -08001470 pDestObj = it.second.get();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001471 if (!pDestObj)
1472 continue;
1473 if (i == index)
1474 break;
1475 i++;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001476 }
Jane Liu67ccef72017-07-19 13:10:50 -04001477 wsName = PDF_DecodeText(bsName);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001478 } else {
Jane Liu67ccef72017-07-19 13:10:50 -04001479 pDestObj = nameTree.LookupValueAndName(index, &wsName);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001480 }
1481 if (!pDestObj)
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001482 return nullptr;
Dan Sinclairf1251c12015-10-20 16:24:45 -04001483 if (CPDF_Dictionary* pDict = pDestObj->AsDictionary()) {
dsinclair38fd8442016-09-15 10:15:32 -07001484 pDestObj = pDict->GetArrayFor("D");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001485 if (!pDestObj)
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001486 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001487 }
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001488 if (!pDestObj->IsArray())
1489 return nullptr;
1490
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001491 CFX_ByteString utf16Name = wsName.UTF16LE_Encode();
weili47ca6922016-03-31 15:08:27 -07001492 int len = utf16Name.GetLength();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001493 if (!buffer) {
1494 *buflen = len;
thestig9067fd62016-11-23 14:10:06 -08001495 } else if (len <= *buflen) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001496 memcpy(buffer, utf16Name.c_str(), len);
1497 *buflen = len;
1498 } else {
1499 *buflen = -1;
1500 }
1501 return (FPDF_DEST)pDestObj;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001502}