blob: 8aebb550ff0b34227d4a34d5f3a837ff79e0f40a [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>
10
Dan Sinclair455a4192016-03-16 09:48:56 -040011#include "core/fpdfapi/fpdf_page/include/cpdf_page.h"
Dan Sinclairaa403d32016-03-15 14:57:22 -040012#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
13#include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
dsinclaircac704d2016-07-28 12:59:09 -070014#include "core/fpdfapi/fpdf_parser/include/fpdf_parser_decode.h"
weili9f515bc2016-07-24 08:08:24 -070015#include "core/fpdfapi/fpdf_render/include/cpdf_progressiverenderer.h"
Dan Sinclairaa403d32016-03-15 14:57:22 -040016#include "core/fpdfapi/fpdf_render/include/cpdf_renderoptions.h"
17#include "core/fpdfapi/include/cpdf_modulemgr.h"
weili9f515bc2016-07-24 08:08:24 -070018#include "core/fpdfapi/include/cpdf_pagerendercontext.h"
dsinclaircac704d2016-07-28 12:59:09 -070019#include "core/fpdfdoc/include/cpdf_annotlist.h"
20#include "core/fpdfdoc/include/cpdf_nametree.h"
21#include "core/fpdfdoc/include/cpdf_viewerpreferences.h"
dsinclair86e54742016-04-06 12:30:31 -070022#include "core/fxcodec/include/fx_codec.h"
weili9f515bc2016-07-24 08:08:24 -070023#include "core/fxcrt/include/fx_memory.h"
Dan Sinclaira8a28e02016-03-23 15:41:39 -040024#include "core/fxcrt/include/fx_safe_types.h"
npm9ada2d82016-08-10 07:51:38 -070025#include "core/fxge/include/cfx_fxgedevice.h"
npm26b86e62016-08-04 17:22:14 -070026#include "core/fxge/include/cfx_gemodule.h"
Lei Zhangbde53d22015-11-12 22:21:30 -080027#include "fpdfsdk/include/fsdk_define.h"
28#include "fpdfsdk/include/fsdk_mgr.h"
weili9f515bc2016-07-24 08:08:24 -070029#include "fpdfsdk/include/fsdk_pauseadapter.h"
dsinclair64376be2016-03-31 20:03:24 -070030#include "fpdfsdk/javascript/ijs_runtime.h"
Lei Zhangb4e7f302015-11-06 15:52:32 -080031#include "public/fpdf_ext.h"
Lei Zhangb4e7f302015-11-06 15:52:32 -080032#include "public/fpdf_progressive.h"
Lei Zhang8241df72015-11-06 14:38:48 -080033#include "third_party/base/numerics/safe_conversions_impl.h"
Bo Xufdc00a72014-10-28 23:03:33 -070034
Tom Sepez40e9ff32015-11-30 12:39:54 -080035#ifdef PDF_ENABLE_XFA
dsinclair89bdd082016-04-06 10:47:54 -070036#include "fpdfsdk/fpdfxfa/include/fpdfxfa_app.h"
37#include "fpdfsdk/fpdfxfa/include/fpdfxfa_doc.h"
38#include "fpdfsdk/fpdfxfa/include/fpdfxfa_page.h"
39#include "fpdfsdk/fpdfxfa/include/fpdfxfa_util.h"
Tom Sepez40e9ff32015-11-30 12:39:54 -080040#include "public/fpdf_formfill.h"
41#endif // PDF_ENABLE_XFA
42
thestig25fa42f2016-05-25 21:39:46 -070043#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
npm74847622016-07-29 15:20:25 -070044#include "core/fxge/include/cfx_windowsdevice.h"
thestig25fa42f2016-05-25 21:39:46 -070045#endif
46
Tom Sepez50d12ad2015-11-24 09:50:51 -080047UnderlyingDocumentType* UnderlyingFromFPDFDocument(FPDF_DOCUMENT doc) {
48 return static_cast<UnderlyingDocumentType*>(doc);
49}
50
51FPDF_DOCUMENT FPDFDocumentFromUnderlying(UnderlyingDocumentType* doc) {
52 return static_cast<FPDF_DOCUMENT>(doc);
53}
54
55UnderlyingPageType* UnderlyingFromFPDFPage(FPDF_PAGE page) {
56 return static_cast<UnderlyingPageType*>(page);
57}
58
Tom Sepez471a1032015-10-15 16:17:18 -070059CPDF_Document* CPDFDocumentFromFPDFDocument(FPDF_DOCUMENT doc) {
Tom Sepez40e9ff32015-11-30 12:39:54 -080060#ifdef PDF_ENABLE_XFA
Tom Sepez50d12ad2015-11-24 09:50:51 -080061 return doc ? UnderlyingFromFPDFDocument(doc)->GetPDFDoc() : nullptr;
Tom Sepez40e9ff32015-11-30 12:39:54 -080062#else // PDF_ENABLE_XFA
63 return UnderlyingFromFPDFDocument(doc);
64#endif // PDF_ENABLE_XFA
Tom Sepez471a1032015-10-15 16:17:18 -070065}
66
Tom Sepezbf59a072015-10-21 14:07:23 -070067FPDF_DOCUMENT FPDFDocumentFromCPDFDocument(CPDF_Document* doc) {
Tom Sepez40e9ff32015-11-30 12:39:54 -080068#ifdef PDF_ENABLE_XFA
Tom Sepez50d12ad2015-11-24 09:50:51 -080069 return doc ? FPDFDocumentFromUnderlying(
70 new CPDFXFA_Document(doc, CPDFXFA_App::GetInstance()))
71 : nullptr;
Tom Sepez40e9ff32015-11-30 12:39:54 -080072#else // PDF_ENABLE_XFA
73 return FPDFDocumentFromUnderlying(doc);
74#endif // PDF_ENABLE_XFA
Tom Sepezbf59a072015-10-21 14:07:23 -070075}
76
Tom Sepezdb0be962015-10-16 14:00:21 -070077CPDF_Page* CPDFPageFromFPDFPage(FPDF_PAGE page) {
Tom Sepez40e9ff32015-11-30 12:39:54 -080078#ifdef PDF_ENABLE_XFA
Tom Sepez50d12ad2015-11-24 09:50:51 -080079 return page ? UnderlyingFromFPDFPage(page)->GetPDFPage() : nullptr;
Tom Sepez40e9ff32015-11-30 12:39:54 -080080#else // PDF_ENABLE_XFA
81 return UnderlyingFromFPDFPage(page);
82#endif // PDF_ENABLE_XFA
Tom Sepezdb0be962015-10-16 14:00:21 -070083}
84
thestigbefa4502016-05-26 20:15:19 -070085CFX_DIBitmap* CFXBitmapFromFPDFBitmap(FPDF_BITMAP bitmap) {
86 return static_cast<CFX_DIBitmap*>(bitmap);
87}
88
Tom Sepez40e9ff32015-11-30 12:39:54 -080089#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -070090CFPDF_FileStream::CFPDF_FileStream(FPDF_FILEHANDLER* pFS) {
91 m_pFS = pFS;
92 m_nCurPos = 0;
Bo Xufdc00a72014-10-28 23:03:33 -070093}
94
Nico Weber9d8ec5a2015-08-04 13:00:21 -070095IFX_FileStream* CFPDF_FileStream::Retain() {
96 return this;
Bo Xufdc00a72014-10-28 23:03:33 -070097}
98
Nico Weber9d8ec5a2015-08-04 13:00:21 -070099void CFPDF_FileStream::Release() {
100 if (m_pFS && m_pFS->Release)
101 m_pFS->Release(m_pFS->clientData);
102 delete this;
Bo Xufdc00a72014-10-28 23:03:33 -0700103}
104
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700105FX_FILESIZE CFPDF_FileStream::GetSize() {
106 if (m_pFS && m_pFS->GetSize)
107 return (FX_FILESIZE)m_pFS->GetSize(m_pFS->clientData);
108 return 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700109}
110
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700111FX_BOOL CFPDF_FileStream::IsEOF() {
112 return m_nCurPos >= GetSize();
Bo Xufdc00a72014-10-28 23:03:33 -0700113}
114
weili625ad662016-06-15 11:21:33 -0700115FX_FILESIZE CFPDF_FileStream::GetPosition() {
116 return m_nCurPos;
117}
118
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700119FX_BOOL CFPDF_FileStream::ReadBlock(void* buffer,
120 FX_FILESIZE offset,
121 size_t size) {
122 if (!buffer || !size || !m_pFS->ReadBlock)
123 return FALSE;
Bo Xufdc00a72014-10-28 23:03:33 -0700124
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700125 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
126 (FPDF_DWORD)size) == 0) {
127 m_nCurPos = offset + size;
128 return TRUE;
129 }
130 return FALSE;
Bo Xufdc00a72014-10-28 23:03:33 -0700131}
132
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700133size_t CFPDF_FileStream::ReadBlock(void* buffer, size_t size) {
134 if (!buffer || !size || !m_pFS->ReadBlock)
135 return 0;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700136
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700137 FX_FILESIZE nSize = GetSize();
138 if (m_nCurPos >= nSize)
139 return 0;
140 FX_FILESIZE dwAvail = nSize - m_nCurPos;
141 if (dwAvail < (FX_FILESIZE)size)
142 size = (size_t)dwAvail;
143 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)m_nCurPos, buffer,
144 (FPDF_DWORD)size) == 0) {
145 m_nCurPos += size;
146 return size;
147 }
Bo Xufdc00a72014-10-28 23:03:33 -0700148
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700149 return 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700150}
151
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700152FX_BOOL CFPDF_FileStream::WriteBlock(const void* buffer,
153 FX_FILESIZE offset,
154 size_t size) {
155 if (!m_pFS || !m_pFS->WriteBlock)
156 return FALSE;
Bo Xufdc00a72014-10-28 23:03:33 -0700157
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700158 if (m_pFS->WriteBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
159 (FPDF_DWORD)size) == 0) {
160 m_nCurPos = offset + size;
161 return TRUE;
162 }
163 return FALSE;
Bo Xufdc00a72014-10-28 23:03:33 -0700164}
165
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700166FX_BOOL CFPDF_FileStream::Flush() {
167 if (!m_pFS || !m_pFS->Flush)
168 return TRUE;
Bo Xufdc00a72014-10-28 23:03:33 -0700169
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700170 return m_pFS->Flush(m_pFS->clientData) == 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700171}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800172#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700173
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700174CPDF_CustomAccess::CPDF_CustomAccess(FPDF_FILEACCESS* pFileAccess) {
175 m_FileAccess = *pFileAccess;
Tom Sepez51da0932015-11-25 16:05:49 -0800176#ifdef PDF_ENABLE_XFA
tsepezc3255f52016-03-25 14:52:27 -0700177 m_BufferOffset = (uint32_t)-1;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800178#endif // PDF_ENABLE_XFA
Bo Xufdc00a72014-10-28 23:03:33 -0700179}
180
Tom Sepez40e9ff32015-11-30 12:39:54 -0800181#ifdef PDF_ENABLE_XFA
weili625ad662016-06-15 11:21:33 -0700182CFX_ByteString CPDF_CustomAccess::GetFullPath() {
183 return "";
184}
185
tsepezc3255f52016-03-25 14:52:27 -0700186FX_BOOL CPDF_CustomAccess::GetByte(uint32_t pos, uint8_t& ch) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700187 if (pos >= m_FileAccess.m_FileLen)
188 return FALSE;
tsepezc3255f52016-03-25 14:52:27 -0700189 if (m_BufferOffset == (uint32_t)-1 || pos < m_BufferOffset ||
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700190 pos >= m_BufferOffset + 512) {
191 // Need to read from file access
192 m_BufferOffset = pos;
193 int size = 512;
194 if (pos + 512 > m_FileAccess.m_FileLen)
195 size = m_FileAccess.m_FileLen - pos;
196 if (!m_FileAccess.m_GetBlock(m_FileAccess.m_Param, m_BufferOffset, m_Buffer,
197 size))
198 return FALSE;
199 }
200 ch = m_Buffer[pos - m_BufferOffset];
201 return TRUE;
Bo Xufdc00a72014-10-28 23:03:33 -0700202}
203
tsepezc3255f52016-03-25 14:52:27 -0700204FX_BOOL CPDF_CustomAccess::GetBlock(uint32_t pos,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700205 uint8_t* pBuf,
tsepezc3255f52016-03-25 14:52:27 -0700206 uint32_t size) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700207 if (pos + size > m_FileAccess.m_FileLen)
208 return FALSE;
209 return m_FileAccess.m_GetBlock(m_FileAccess.m_Param, pos, pBuf, size);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700210}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800211#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700212
weili625ad662016-06-15 11:21:33 -0700213FX_FILESIZE CPDF_CustomAccess::GetSize() {
214 return m_FileAccess.m_FileLen;
215}
216
217void CPDF_CustomAccess::Release() {
218 delete this;
219}
220
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700221FX_BOOL CPDF_CustomAccess::ReadBlock(void* buffer,
222 FX_FILESIZE offset,
223 size_t size) {
224 if (offset < 0) {
225 return FALSE;
226 }
227 FX_SAFE_FILESIZE newPos =
228 pdfium::base::checked_cast<FX_FILESIZE, size_t>(size);
229 newPos += offset;
Wei Li05d53f02016-03-29 16:42:53 -0700230 if (!newPos.IsValid() ||
231 newPos.ValueOrDie() > static_cast<FX_FILESIZE>(m_FileAccess.m_FileLen)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700232 return FALSE;
233 }
234 return m_FileAccess.m_GetBlock(m_FileAccess.m_Param, offset, (uint8_t*)buffer,
235 size);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700236}
237
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700238// 0 bit: FPDF_POLICY_MACHINETIME_ACCESS
tsepezc3255f52016-03-25 14:52:27 -0700239static uint32_t foxit_sandbox_policy = 0xFFFFFFFF;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700240
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700241void FSDK_SetSandBoxPolicy(FPDF_DWORD policy, FPDF_BOOL enable) {
242 switch (policy) {
243 case FPDF_POLICY_MACHINETIME_ACCESS: {
244 if (enable)
245 foxit_sandbox_policy |= 0x01;
246 else
247 foxit_sandbox_policy &= 0xFFFFFFFE;
248 } break;
249 default:
250 break;
251 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700252}
253
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700254FPDF_BOOL FSDK_IsSandBoxPolicyEnabled(FPDF_DWORD policy) {
255 switch (policy) {
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700256 case FPDF_POLICY_MACHINETIME_ACCESS:
Lei Zhangb0748bb2015-10-19 12:11:49 -0700257 return !!(foxit_sandbox_policy & 0x01);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700258 default:
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700259 return FALSE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700260 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700261}
262
Tom Sepez2c286192015-06-18 12:47:11 -0700263CCodec_ModuleMgr* g_pCodecModule = nullptr;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700264
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700265DLLEXPORT void STDCALL FPDF_InitLibrary() {
Lei Zhang6f62d532015-09-23 15:31:44 -0700266 FPDF_InitLibraryWithConfig(nullptr);
267}
268
Dan Sinclairf766ad22016-03-14 13:51:24 -0400269DLLEXPORT void STDCALL
270FPDF_InitLibraryWithConfig(const FPDF_LIBRARY_CONFIG* cfg) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700271 g_pCodecModule = new CCodec_ModuleMgr();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700272
weili47228ac2016-07-20 10:35:31 -0700273 CFX_GEModule* pModule = CFX_GEModule::Get();
274 pModule->Init(cfg ? cfg->m_pUserFontPaths : nullptr, g_pCodecModule);
Tom Sepez1b246282015-11-25 15:15:31 -0800275 CPDF_ModuleMgr* pModuleMgr = CPDF_ModuleMgr::Get();
276 pModuleMgr->SetCodecModule(g_pCodecModule);
277 pModuleMgr->InitPageModule();
dsinclairab5b60e2016-06-23 08:18:36 -0700278 pModuleMgr->LoadEmbeddedGB1CMaps();
279 pModuleMgr->LoadEmbeddedJapan1CMaps();
280 pModuleMgr->LoadEmbeddedCNS1CMaps();
281 pModuleMgr->LoadEmbeddedKorea1CMaps();
dsinclaird647a6b2016-04-26 13:13:20 -0700282
Tom Sepez40e9ff32015-11-30 12:39:54 -0800283#ifdef PDF_ENABLE_XFA
jinming_wang48661582016-02-04 09:41:56 +0800284 CPDFXFA_App::GetInstance()->Initialize(
dsinclairec3da5b2016-05-25 16:42:05 -0700285 (cfg && cfg->version >= 2) ? static_cast<v8::Isolate*>(cfg->m_pIsolate)
286 : nullptr);
Tom Sepez40e9ff32015-11-30 12:39:54 -0800287#endif // PDF_ENABLE_XFA
dsinclaird647a6b2016-04-26 13:13:20 -0700288
Tom Sepez452b4f32015-10-13 09:27:27 -0700289 if (cfg && cfg->version >= 2)
290 IJS_Runtime::Initialize(cfg->m_v8EmbedderSlot, cfg->m_pIsolate);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700291}
292
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700293DLLEXPORT void STDCALL FPDF_DestroyLibrary() {
Tom Sepez51da0932015-11-25 16:05:49 -0800294#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700295 CPDFXFA_App::ReleaseInstance();
Tom Sepez40e9ff32015-11-30 12:39:54 -0800296#endif // PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700297 CPDF_ModuleMgr::Destroy();
298 CFX_GEModule::Destroy();
Tom Sepez2c286192015-06-18 12:47:11 -0700299
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700300 delete g_pCodecModule;
301 g_pCodecModule = nullptr;
thestig2d6dda12016-06-28 07:39:09 -0700302
303 IJS_Runtime::Destroy();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700304}
305
306#ifndef _WIN32
307int g_LastError;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700308void SetLastError(int err) {
309 g_LastError = err;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700310}
311
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700312int GetLastError() {
313 return g_LastError;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700314}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800315#endif // _WIN32
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700316
Tom Sepezf10ae632016-01-26 14:19:52 -0800317void ProcessParseError(CPDF_Parser::Error err) {
tsepezc3255f52016-03-25 14:52:27 -0700318 uint32_t err_code = FPDF_ERR_SUCCESS;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700319 // Translate FPDFAPI error code to FPDFVIEW error code
Tom Sepezf10ae632016-01-26 14:19:52 -0800320 switch (err) {
321 case CPDF_Parser::SUCCESS:
322 err_code = FPDF_ERR_SUCCESS;
323 break;
324 case CPDF_Parser::FILE_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700325 err_code = FPDF_ERR_FILE;
326 break;
Tom Sepezf10ae632016-01-26 14:19:52 -0800327 case CPDF_Parser::FORMAT_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700328 err_code = FPDF_ERR_FORMAT;
329 break;
Tom Sepezf10ae632016-01-26 14:19:52 -0800330 case CPDF_Parser::PASSWORD_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700331 err_code = FPDF_ERR_PASSWORD;
332 break;
Tom Sepezf10ae632016-01-26 14:19:52 -0800333 case CPDF_Parser::HANDLER_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700334 err_code = FPDF_ERR_SECURITY;
335 break;
336 }
337 SetLastError(err_code);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700338}
339
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700340DLLEXPORT void STDCALL FPDF_SetSandBoxPolicy(FPDF_DWORD policy,
341 FPDF_BOOL enable) {
342 return FSDK_SetSandBoxPolicy(policy, enable);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700343}
344
thestigfdb35ff2016-07-18 13:45:44 -0700345#if defined(_WIN32) && defined(PDFIUM_PRINT_TEXT_WITH_GDI)
346DLLEXPORT void STDCALL
347FPDF_SetTypefaceAccessibleFunc(PDFiumEnsureTypefaceCharactersAccessible func) {
348 g_pdfium_typeface_accessible_func = func;
349}
350
351DLLEXPORT void STDCALL FPDF_SetPrintTextWithGDI(FPDF_BOOL use_gdi) {
352 g_pdfium_print_text_with_gdi = !!use_gdi;
353}
354#endif
355
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700356DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadDocument(FPDF_STRING file_path,
357 FPDF_BYTESTRING password) {
Tom Sepeze3166a82015-08-05 10:50:32 -0700358 // NOTE: the creation of the file needs to be by the embedder on the
359 // other side of this API.
360 IFX_FileRead* pFileAccess = FX_CreateFileRead((const FX_CHAR*)file_path);
361 if (!pFileAccess) {
362 return nullptr;
363 }
364
365 CPDF_Parser* pParser = new CPDF_Parser;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700366 pParser->SetPassword(password);
Bo Xud4e406e2014-08-13 11:03:19 -0700367
Tom Sepezf10ae632016-01-26 14:19:52 -0800368 CPDF_Parser::Error error = pParser->StartParse(pFileAccess);
369 if (error != CPDF_Parser::SUCCESS) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700370 delete pParser;
Tom Sepezf10ae632016-01-26 14:19:52 -0800371 ProcessParseError(error);
thestig1cd352e2016-06-07 17:53:06 -0700372 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700373 }
Tom Sepez40e9ff32015-11-30 12:39:54 -0800374#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700375 CPDF_Document* pPDFDoc = pParser->GetDocument();
376 if (!pPDFDoc)
thestig1cd352e2016-06-07 17:53:06 -0700377 return nullptr;
Bo Xufdc00a72014-10-28 23:03:33 -0700378
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700379 CPDFXFA_App* pProvider = CPDFXFA_App::GetInstance();
Lei Zhangcb78ef52015-10-02 10:10:49 -0700380 return new CPDFXFA_Document(pPDFDoc, pProvider);
Tom Sepez40e9ff32015-11-30 12:39:54 -0800381#else // PDF_ENABLE_XFA
382 return pParser->GetDocument();
383#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700384}
Jun Fange118ce92015-02-17 06:50:08 -0800385
Tom Sepez40e9ff32015-11-30 12:39:54 -0800386#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700387DLLEXPORT FPDF_BOOL STDCALL FPDF_HasXFAField(FPDF_DOCUMENT document,
388 int* docType) {
389 if (!document)
390 return FALSE;
JUN FANG827a1722015-03-05 13:39:21 -0800391
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700392 CPDF_Document* pdfDoc =
393 (static_cast<CPDFXFA_Document*>(document))->GetPDFDoc();
394 if (!pdfDoc)
395 return FALSE;
JUN FANG827a1722015-03-05 13:39:21 -0800396
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700397 CPDF_Dictionary* pRoot = pdfDoc->GetRoot();
398 if (!pRoot)
399 return FALSE;
JUN FANG827a1722015-03-05 13:39:21 -0800400
Wei Li9b761132016-01-29 15:44:20 -0800401 CPDF_Dictionary* pAcroForm = pRoot->GetDictBy("AcroForm");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700402 if (!pAcroForm)
403 return FALSE;
JUN FANG827a1722015-03-05 13:39:21 -0800404
tsepezbd567552016-03-29 14:51:50 -0700405 CPDF_Object* pXFA = pAcroForm->GetObjectBy("XFA");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700406 if (!pXFA)
407 return FALSE;
JUN FANG827a1722015-03-05 13:39:21 -0800408
thestigded36342016-05-23 17:54:02 -0700409 bool bDynamicXFA = pRoot->GetBooleanBy("NeedsRendering", false);
410 *docType = bDynamicXFA ? DOCTYPE_DYNAMIC_XFA : DOCTYPE_STATIC_XFA;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700411 return TRUE;
Jun Fange118ce92015-02-17 06:50:08 -0800412}
413
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700414DLLEXPORT FPDF_BOOL STDCALL FPDF_LoadXFA(FPDF_DOCUMENT document) {
415 return document && (static_cast<CPDFXFA_Document*>(document))->LoadXFADoc();
Bo Xufdc00a72014-10-28 23:03:33 -0700416}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800417#endif // PDF_ENABLE_XFA
Bo Xufdc00a72014-10-28 23:03:33 -0700418
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700419class CMemFile final : public IFX_FileRead {
420 public:
421 CMemFile(uint8_t* pBuf, FX_FILESIZE size) : m_pBuf(pBuf), m_size(size) {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700422
Lei Zhang3884dba2015-10-19 17:27:53 -0700423 void Release() override { delete this; }
424 FX_FILESIZE GetSize() override { return m_size; }
425 FX_BOOL ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700426 if (offset < 0) {
427 return FALSE;
428 }
429 FX_SAFE_FILESIZE newPos =
430 pdfium::base::checked_cast<FX_FILESIZE, size_t>(size);
431 newPos += offset;
weili47ca6922016-03-31 15:08:27 -0700432 if (!newPos.IsValid() || newPos.ValueOrDie() > m_size) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700433 return FALSE;
434 }
435 FXSYS_memcpy(buffer, m_pBuf + offset, size);
436 return TRUE;
437 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700438
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700439 private:
Lei Zhang2b1a2d52015-08-14 22:16:22 -0700440 ~CMemFile() override {}
441
Lei Zhang3884dba2015-10-19 17:27:53 -0700442 uint8_t* const m_pBuf;
443 const FX_FILESIZE m_size;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700444};
Lei Zhang3884dba2015-10-19 17:27:53 -0700445
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700446DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadMemDocument(const void* data_buf,
447 int size,
448 FPDF_BYTESTRING password) {
Tom Sepezae51c812015-08-05 12:34:06 -0700449 CPDF_Parser* pParser = new CPDF_Parser;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700450 pParser->SetPassword(password);
451 CMemFile* pMemFile = new CMemFile((uint8_t*)data_buf, size);
Tom Sepezf10ae632016-01-26 14:19:52 -0800452 CPDF_Parser::Error error = pParser->StartParse(pMemFile);
453 if (error != CPDF_Parser::SUCCESS) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700454 delete pParser;
Tom Sepezf10ae632016-01-26 14:19:52 -0800455 ProcessParseError(error);
thestig1cd352e2016-06-07 17:53:06 -0700456 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700457 }
thestig1cd352e2016-06-07 17:53:06 -0700458 CPDF_Document* pDoc = pParser ? pParser->GetDocument() : nullptr;
Tom Sepezf10ae632016-01-26 14:19:52 -0800459 CheckUnSupportError(pDoc, error);
Tom Sepezbf59a072015-10-21 14:07:23 -0700460 return FPDFDocumentFromCPDFDocument(pParser->GetDocument());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700461}
462
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700463DLLEXPORT FPDF_DOCUMENT STDCALL
464FPDF_LoadCustomDocument(FPDF_FILEACCESS* pFileAccess,
465 FPDF_BYTESTRING password) {
Tom Sepezae51c812015-08-05 12:34:06 -0700466 CPDF_Parser* pParser = new CPDF_Parser;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700467 pParser->SetPassword(password);
Tom Sepezae51c812015-08-05 12:34:06 -0700468 CPDF_CustomAccess* pFile = new CPDF_CustomAccess(pFileAccess);
Tom Sepezf10ae632016-01-26 14:19:52 -0800469 CPDF_Parser::Error error = pParser->StartParse(pFile);
470 if (error != CPDF_Parser::SUCCESS) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700471 delete pParser;
Tom Sepezf10ae632016-01-26 14:19:52 -0800472 ProcessParseError(error);
thestig1cd352e2016-06-07 17:53:06 -0700473 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700474 }
thestig1cd352e2016-06-07 17:53:06 -0700475 CPDF_Document* pDoc = pParser ? pParser->GetDocument() : nullptr;
Tom Sepezf10ae632016-01-26 14:19:52 -0800476 CheckUnSupportError(pDoc, error);
Tom Sepezbf59a072015-10-21 14:07:23 -0700477 return FPDFDocumentFromCPDFDocument(pParser->GetDocument());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700478}
479
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700480DLLEXPORT FPDF_BOOL STDCALL FPDF_GetFileVersion(FPDF_DOCUMENT doc,
481 int* fileVersion) {
Tom Sepez471a1032015-10-15 16:17:18 -0700482 if (!fileVersion)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700483 return FALSE;
Bo Xufdc00a72014-10-28 23:03:33 -0700484
Tom Sepez471a1032015-10-15 16:17:18 -0700485 *fileVersion = 0;
486 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(doc);
487 if (!pDoc)
488 return FALSE;
489
490 CPDF_Parser* pParser = pDoc->GetParser();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700491 if (!pParser)
492 return FALSE;
Tom Sepez471a1032015-10-15 16:17:18 -0700493
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700494 *fileVersion = pParser->GetFileVersion();
495 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700496}
497
tsepezc3255f52016-03-25 14:52:27 -0700498// jabdelmalek: changed return type from uint32_t to build on Linux (and match
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700499// header).
500DLLEXPORT unsigned long STDCALL FPDF_GetDocPermissions(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700501 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
thestig27ddf162016-05-23 15:06:59 -0700502 // https://bugs.chromium.org/p/pdfium/issues/detail?id=499
503 if (!pDoc) {
Tom Sepez51da0932015-11-25 16:05:49 -0800504#ifndef PDF_ENABLE_XFA
505 return 0;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800506#else // PDF_ENABLE_XFA
thestig27ddf162016-05-23 15:06:59 -0700507 return 0xFFFFFFFF;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800508#endif // PDF_ENABLE_XFA
thestig27ddf162016-05-23 15:06:59 -0700509 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700510
thestig27ddf162016-05-23 15:06:59 -0700511 return pDoc->GetUserPermissions();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700512}
513
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700514DLLEXPORT int STDCALL FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700515 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
thestigb8db5112016-04-06 12:12:52 -0700516 if (!pDoc || !pDoc->GetParser())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700517 return -1;
Bo Xuc5cab022014-09-19 19:16:31 -0700518
Tom Sepez471a1032015-10-15 16:17:18 -0700519 CPDF_Dictionary* pDict = pDoc->GetParser()->GetEncryptDict();
Wei Li9b761132016-01-29 15:44:20 -0800520 return pDict ? pDict->GetIntegerBy("R") : -1;
Bo Xuc5cab022014-09-19 19:16:31 -0700521}
522
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700523DLLEXPORT int STDCALL FPDF_GetPageCount(FPDF_DOCUMENT document) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800524 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
Tom Sepez471a1032015-10-15 16:17:18 -0700525 return pDoc ? pDoc->GetPageCount() : 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700526}
527
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700528DLLEXPORT FPDF_PAGE STDCALL FPDF_LoadPage(FPDF_DOCUMENT document,
529 int page_index) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800530 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
531 if (!pDoc)
Tom Sepez471a1032015-10-15 16:17:18 -0700532 return nullptr;
Tom Sepez1b246282015-11-25 15:15:31 -0800533
Tom Sepezbbe0e4d2015-10-20 15:41:40 -0700534 if (page_index < 0 || page_index >= pDoc->GetPageCount())
Tom Sepez471a1032015-10-15 16:17:18 -0700535 return nullptr;
536
Tom Sepez40e9ff32015-11-30 12:39:54 -0800537#ifdef PDF_ENABLE_XFA
538 return pDoc->GetPage(page_index);
539#else // PDF_ENABLE_XFA
Tom Sepez51da0932015-11-25 16:05:49 -0800540 CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
Lei Zhang412e9082015-12-14 18:34:00 -0800541 if (!pDict)
thestig5cc24652016-04-26 11:46:02 -0700542 return nullptr;
543
544 CPDF_Page* pPage = new CPDF_Page(pDoc, pDict, true);
545 pPage->ParseContent();
Tom Sepez51da0932015-11-25 16:05:49 -0800546 return pPage;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800547#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700548}
549
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700550DLLEXPORT double STDCALL FPDF_GetPageWidth(FPDF_PAGE page) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800551 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezbf59a072015-10-21 14:07:23 -0700552 return pPage ? pPage->GetPageWidth() : 0.0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700553}
554
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700555DLLEXPORT double STDCALL FPDF_GetPageHeight(FPDF_PAGE page) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800556 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezbf59a072015-10-21 14:07:23 -0700557 return pPage ? pPage->GetPageHeight() : 0.0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700558}
559
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700560#if defined(_WIN32)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700561DLLEXPORT void STDCALL FPDF_RenderPage(HDC dc,
562 FPDF_PAGE page,
563 int start_x,
564 int start_y,
565 int size_x,
566 int size_y,
567 int rotate,
568 int flags) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700569 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700570 if (!pPage)
571 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700572
weili9f515bc2016-07-24 08:08:24 -0700573 CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
574 pPage->SetRenderContext(WrapUnique(pContext));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700575
Jun Fang1aeeceb2015-12-29 10:27:44 +0800576 CFX_DIBitmap* pBitmap = nullptr;
577 FX_BOOL bBackgroundAlphaNeeded = pPage->BackgroundAlphaNeeded();
578 FX_BOOL bHasImageMask = pPage->HasImageMask();
579 if (bBackgroundAlphaNeeded || bHasImageMask) {
Tom Sepezae51c812015-08-05 12:34:06 -0700580 pBitmap = new CFX_DIBitmap;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700581 pBitmap->Create(size_x, size_y, FXDIB_Argb);
582 pBitmap->Clear(0x00ffffff);
thestigbefa4502016-05-26 20:15:19 -0700583 CFX_FxgeDevice* pDevice = new CFX_FxgeDevice;
weili9f515bc2016-07-24 08:08:24 -0700584 pContext->m_pDevice.reset(pDevice);
thestigbefa4502016-05-26 20:15:19 -0700585 pDevice->Attach(pBitmap, false, nullptr, false);
Jun Fang1aeeceb2015-12-29 10:27:44 +0800586 } else {
weili9f515bc2016-07-24 08:08:24 -0700587 pContext->m_pDevice.reset(new CFX_WindowsDevice(dc));
Jun Fang1aeeceb2015-12-29 10:27:44 +0800588 }
Bo Xud4e406e2014-08-13 11:03:19 -0700589
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700590 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
thestigbefa4502016-05-26 20:15:19 -0700591 rotate, flags, TRUE, nullptr);
Bo Xud4e406e2014-08-13 11:03:19 -0700592
Jun Fang1aeeceb2015-12-29 10:27:44 +0800593 if (bBackgroundAlphaNeeded || bHasImageMask) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700594 if (pBitmap) {
595 CFX_WindowsDevice WinDC(dc);
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700596
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700597 if (WinDC.GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
Tom Sepezae51c812015-08-05 12:34:06 -0700598 CFX_DIBitmap* pDst = new CFX_DIBitmap;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700599 int pitch = pBitmap->GetPitch();
600 pDst->Create(size_x, size_y, FXDIB_Rgb32);
601 FXSYS_memset(pDst->GetBuffer(), -1, pitch * size_y);
602 pDst->CompositeBitmap(0, 0, size_x, size_y, pBitmap, 0, 0,
thestig1cd352e2016-06-07 17:53:06 -0700603 FXDIB_BLEND_NORMAL, nullptr, FALSE, nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700604 WinDC.StretchDIBits(pDst, 0, 0, size_x, size_y);
605 delete pDst;
Jun Fang1aeeceb2015-12-29 10:27:44 +0800606 } else {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700607 WinDC.SetDIBits(pBitmap, 0, 0);
Jun Fang1aeeceb2015-12-29 10:27:44 +0800608 }
Lei Zhang6d8b1c22015-06-19 17:26:17 -0700609 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700610 }
Jun Fang1aeeceb2015-12-29 10:27:44 +0800611 if (bBackgroundAlphaNeeded || bHasImageMask)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700612 delete pBitmap;
Jun Fang1aeeceb2015-12-29 10:27:44 +0800613
weili9f515bc2016-07-24 08:08:24 -0700614 pPage->SetRenderContext(std::unique_ptr<CPDF_PageRenderContext>());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700615}
Lei Zhangae85f872016-02-19 14:57:07 -0800616#endif // defined(_WIN32)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700617
618DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap,
619 FPDF_PAGE page,
620 int start_x,
621 int start_y,
622 int size_x,
623 int size_y,
624 int rotate,
625 int flags) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700626 if (!bitmap)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700627 return;
tsepez1e2c5572016-05-25 14:58:09 -0700628
Tom Sepezdb0be962015-10-16 14:00:21 -0700629 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700630 if (!pPage)
631 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700632
weili9f515bc2016-07-24 08:08:24 -0700633 CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
634 pPage->SetRenderContext(WrapUnique(pContext));
thestigbefa4502016-05-26 20:15:19 -0700635 CFX_FxgeDevice* pDevice = new CFX_FxgeDevice;
weili9f515bc2016-07-24 08:08:24 -0700636 pContext->m_pDevice.reset(pDevice);
thestigbefa4502016-05-26 20:15:19 -0700637 CFX_DIBitmap* pBitmap = CFXBitmapFromFPDFBitmap(bitmap);
638 pDevice->Attach(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER), nullptr, false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700639
640 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
tsepez1e2c5572016-05-25 14:58:09 -0700641 rotate, flags, TRUE, nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700642
weili9f515bc2016-07-24 08:08:24 -0700643 pPage->SetRenderContext(std::unique_ptr<CPDF_PageRenderContext>());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700644}
645
Cary Clark399be5b2016-03-14 16:51:29 -0400646#ifdef _SKIA_SUPPORT_
647DLLEXPORT FPDF_RECORDER STDCALL FPDF_RenderPageSkp(FPDF_PAGE page,
648 int size_x,
649 int size_y) {
650 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
651 if (!pPage)
652 return nullptr;
tsepez1e2c5572016-05-25 14:58:09 -0700653
weili9f515bc2016-07-24 08:08:24 -0700654 CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
655 pPage->SetRenderContext(WrapUnique(pContext));
caryclarkd6e18872016-05-13 10:57:20 -0700656 CFX_FxgeDevice* skDevice = new CFX_FxgeDevice;
Cary Clark399be5b2016-03-14 16:51:29 -0400657 FPDF_RECORDER recorder = skDevice->CreateRecorder(size_x, size_y);
weili9f515bc2016-07-24 08:08:24 -0700658 pContext->m_pDevice.reset(skDevice);
thestig4d1311b2016-05-25 18:31:25 -0700659 FPDF_RenderPage_Retail(pContext, page, 0, 0, size_x, size_y, 0, 0, TRUE,
tsepez1e2c5572016-05-25 14:58:09 -0700660 nullptr);
weili9f515bc2016-07-24 08:08:24 -0700661 pPage->SetRenderContext(std::unique_ptr<CPDF_PageRenderContext>());
Cary Clark399be5b2016-03-14 16:51:29 -0400662 return recorder;
663}
664#endif
665
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700666DLLEXPORT void STDCALL FPDF_ClosePage(FPDF_PAGE page) {
tsepez1e2c5572016-05-25 14:58:09 -0700667 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700668 if (!page)
669 return;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800670#ifdef PDF_ENABLE_XFA
Tom Sepez40e9ff32015-11-30 12:39:54 -0800671 pPage->Release();
672#else // PDF_ENABLE_XFA
Tom Sepez51da0932015-11-25 16:05:49 -0800673 CPDFSDK_PageView* pPageView =
tsepez1e2c5572016-05-25 14:58:09 -0700674 static_cast<CPDFSDK_PageView*>(pPage->GetView());
Tom Sepez51da0932015-11-25 16:05:49 -0800675 if (pPageView && pPageView->IsLocked()) {
676 pPageView->TakeOverPage();
677 return;
678 }
tsepez1e2c5572016-05-25 14:58:09 -0700679 delete pPage;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800680#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700681}
682
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700683DLLEXPORT void STDCALL FPDF_CloseDocument(FPDF_DOCUMENT document) {
Tom Sepez40e9ff32015-11-30 12:39:54 -0800684#ifdef PDF_ENABLE_XFA
Jun Fangfc751362015-12-16 21:23:39 -0800685 delete UnderlyingFromFPDFDocument(document);
Tom Sepez40e9ff32015-11-30 12:39:54 -0800686#else // PDF_ENABLE_XFA
Tom Sepez51da0932015-11-25 16:05:49 -0800687 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
688 if (!pDoc)
689 return;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800690 CPDF_Parser* pParser = pDoc->GetParser();
Tom Sepez51da0932015-11-25 16:05:49 -0800691 if (!pParser) {
692 delete pDoc;
693 return;
694 }
695 delete pParser;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800696#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700697}
698
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700699DLLEXPORT unsigned long STDCALL FPDF_GetLastError() {
700 return GetLastError();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700701}
702
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700703DLLEXPORT void STDCALL FPDF_DeviceToPage(FPDF_PAGE page,
704 int start_x,
705 int start_y,
706 int size_x,
707 int size_y,
708 int rotate,
709 int device_x,
710 int device_y,
711 double* page_x,
712 double* page_y) {
Lei Zhang412e9082015-12-14 18:34:00 -0800713 if (!page || !page_x || !page_y)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700714 return;
Tom Sepez50d12ad2015-11-24 09:50:51 -0800715 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepez40e9ff32015-11-30 12:39:54 -0800716#ifdef PDF_ENABLE_XFA
717 pPage->DeviceToPage(start_x, start_y, size_x, size_y, rotate, device_x,
718 device_y, page_x, page_y);
719#else // PDF_ENABLE_XFA
Tom Sepez60d909e2015-12-10 15:34:55 -0800720 CFX_Matrix page2device;
Tom Sepez51da0932015-11-25 16:05:49 -0800721 pPage->GetDisplayMatrix(page2device, start_x, start_y, size_x, size_y,
722 rotate);
Tom Sepez60d909e2015-12-10 15:34:55 -0800723 CFX_Matrix device2page;
Tom Sepez51da0932015-11-25 16:05:49 -0800724 device2page.SetReverse(page2device);
Tom Sepez51da0932015-11-25 16:05:49 -0800725 FX_FLOAT page_x_f, page_y_f;
726 device2page.Transform((FX_FLOAT)(device_x), (FX_FLOAT)(device_y), page_x_f,
727 page_y_f);
Tom Sepez51da0932015-11-25 16:05:49 -0800728 *page_x = (page_x_f);
729 *page_y = (page_y_f);
Tom Sepez40e9ff32015-11-30 12:39:54 -0800730#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700731}
732
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700733DLLEXPORT void STDCALL FPDF_PageToDevice(FPDF_PAGE page,
734 int start_x,
735 int start_y,
736 int size_x,
737 int size_y,
738 int rotate,
739 double page_x,
740 double page_y,
741 int* device_x,
742 int* device_y) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700743 if (!device_x || !device_y)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700744 return;
Tom Sepez50d12ad2015-11-24 09:50:51 -0800745 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezdb0be962015-10-16 14:00:21 -0700746 if (!pPage)
747 return;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800748#ifdef PDF_ENABLE_XFA
749 pPage->PageToDevice(start_x, start_y, size_x, size_y, rotate, page_x, page_y,
750 device_x, device_y);
751#else // PDF_ENABLE_XFA
Tom Sepez60d909e2015-12-10 15:34:55 -0800752 CFX_Matrix page2device;
Tom Sepez51da0932015-11-25 16:05:49 -0800753 pPage->GetDisplayMatrix(page2device, start_x, start_y, size_x, size_y,
754 rotate);
Tom Sepez51da0932015-11-25 16:05:49 -0800755 FX_FLOAT device_x_f, device_y_f;
756 page2device.Transform(((FX_FLOAT)page_x), ((FX_FLOAT)page_y), device_x_f,
757 device_y_f);
Tom Sepez51da0932015-11-25 16:05:49 -0800758 *device_x = FXSYS_round(device_x_f);
759 *device_y = FXSYS_round(device_y_f);
Tom Sepez40e9ff32015-11-30 12:39:54 -0800760#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700761}
762
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700763DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_Create(int width,
764 int height,
765 int alpha) {
Lei Zhangaa8bf7e2015-12-24 19:13:32 -0800766 std::unique_ptr<CFX_DIBitmap> pBitmap(new CFX_DIBitmap);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700767 if (!pBitmap->Create(width, height, alpha ? FXDIB_Argb : FXDIB_Rgb32)) {
thestig1cd352e2016-06-07 17:53:06 -0700768 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700769 }
770 return pBitmap.release();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700771}
772
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700773DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_CreateEx(int width,
774 int height,
775 int format,
776 void* first_scan,
777 int stride) {
778 FXDIB_Format fx_format;
779 switch (format) {
780 case FPDFBitmap_Gray:
781 fx_format = FXDIB_8bppRgb;
782 break;
783 case FPDFBitmap_BGR:
784 fx_format = FXDIB_Rgb;
785 break;
786 case FPDFBitmap_BGRx:
787 fx_format = FXDIB_Rgb32;
788 break;
789 case FPDFBitmap_BGRA:
790 fx_format = FXDIB_Argb;
791 break;
792 default:
thestig1cd352e2016-06-07 17:53:06 -0700793 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700794 }
795 CFX_DIBitmap* pBitmap = new CFX_DIBitmap;
796 pBitmap->Create(width, height, fx_format, (uint8_t*)first_scan, stride);
797 return pBitmap;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700798}
799
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700800DLLEXPORT void STDCALL FPDFBitmap_FillRect(FPDF_BITMAP bitmap,
801 int left,
802 int top,
803 int width,
804 int height,
805 FPDF_DWORD color) {
Lei Zhang412e9082015-12-14 18:34:00 -0800806 if (!bitmap)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700807 return;
thestigbefa4502016-05-26 20:15:19 -0700808
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700809 CFX_FxgeDevice device;
thestigbefa4502016-05-26 20:15:19 -0700810 CFX_DIBitmap* pBitmap = CFXBitmapFromFPDFBitmap(bitmap);
811 device.Attach(pBitmap, false, nullptr, false);
812 if (!pBitmap->HasAlpha())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700813 color |= 0xFF000000;
814 FX_RECT rect(left, top, left + width, top + height);
815 device.FillRect(&rect, color);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700816}
817
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700818DLLEXPORT void* STDCALL FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap) {
thestigbefa4502016-05-26 20:15:19 -0700819 return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetBuffer() : nullptr;
Bo Xu9114e832014-07-14 13:22:47 -0700820}
821
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700822DLLEXPORT int STDCALL FPDFBitmap_GetWidth(FPDF_BITMAP bitmap) {
thestigbefa4502016-05-26 20:15:19 -0700823 return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetWidth() : 0;
Bo Xu9114e832014-07-14 13:22:47 -0700824}
825
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700826DLLEXPORT int STDCALL FPDFBitmap_GetHeight(FPDF_BITMAP bitmap) {
thestigbefa4502016-05-26 20:15:19 -0700827 return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetHeight() : 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700828}
829
830DLLEXPORT int STDCALL FPDFBitmap_GetStride(FPDF_BITMAP bitmap) {
thestigbefa4502016-05-26 20:15:19 -0700831 return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetPitch() : 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700832}
833
834DLLEXPORT void STDCALL FPDFBitmap_Destroy(FPDF_BITMAP bitmap) {
thestigbefa4502016-05-26 20:15:19 -0700835 delete CFXBitmapFromFPDFBitmap(bitmap);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700836}
837
weili9f515bc2016-07-24 08:08:24 -0700838void FPDF_RenderPage_Retail(CPDF_PageRenderContext* pContext,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700839 FPDF_PAGE page,
840 int start_x,
841 int start_y,
842 int size_x,
843 int size_y,
844 int rotate,
845 int flags,
846 FX_BOOL bNeedToRestore,
847 IFSDK_PAUSE_Adapter* pause) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700848 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
849 if (!pPage)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700850 return;
851
852 if (!pContext->m_pOptions)
weili9f515bc2016-07-24 08:08:24 -0700853 pContext->m_pOptions.reset(new CPDF_RenderOptions);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700854
855 if (flags & FPDF_LCD_TEXT)
856 pContext->m_pOptions->m_Flags |= RENDER_CLEARTYPE;
857 else
858 pContext->m_pOptions->m_Flags &= ~RENDER_CLEARTYPE;
859 if (flags & FPDF_NO_NATIVETEXT)
860 pContext->m_pOptions->m_Flags |= RENDER_NO_NATIVETEXT;
861 if (flags & FPDF_RENDER_LIMITEDIMAGECACHE)
862 pContext->m_pOptions->m_Flags |= RENDER_LIMITEDIMAGECACHE;
863 if (flags & FPDF_RENDER_FORCEHALFTONE)
864 pContext->m_pOptions->m_Flags |= RENDER_FORCE_HALFTONE;
Tom Sepez51da0932015-11-25 16:05:49 -0800865#ifndef PDF_ENABLE_XFA
866 if (flags & FPDF_RENDER_NO_SMOOTHTEXT)
867 pContext->m_pOptions->m_Flags |= RENDER_NOTEXTSMOOTH;
868 if (flags & FPDF_RENDER_NO_SMOOTHIMAGE)
869 pContext->m_pOptions->m_Flags |= RENDER_NOIMAGESMOOTH;
870 if (flags & FPDF_RENDER_NO_SMOOTHPATH)
871 pContext->m_pOptions->m_Flags |= RENDER_NOPATHSMOOTH;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800872#endif // PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700873 // Grayscale output
874 if (flags & FPDF_GRAYSCALE) {
875 pContext->m_pOptions->m_ColorMode = RENDER_COLOR_GRAY;
876 pContext->m_pOptions->m_ForeColor = 0;
877 pContext->m_pOptions->m_BackColor = 0xffffff;
878 }
879 const CPDF_OCContext::UsageType usage =
880 (flags & FPDF_PRINTING) ? CPDF_OCContext::Print : CPDF_OCContext::View;
881 pContext->m_pOptions->m_AddFlags = flags >> 8;
882 pContext->m_pOptions->m_pOCContext =
883 new CPDF_OCContext(pPage->m_pDocument, usage);
884
Tom Sepez60d909e2015-12-10 15:34:55 -0800885 CFX_Matrix matrix;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700886 pPage->GetDisplayMatrix(matrix, start_x, start_y, size_x, size_y, rotate);
887
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700888 pContext->m_pDevice->SaveState();
Tom Sepezbec4ea12016-02-29 13:23:13 -0800889 pContext->m_pDevice->SetClip_Rect(
890 FX_RECT(start_x, start_y, start_x + size_x, start_y + size_y));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700891
weili9f515bc2016-07-24 08:08:24 -0700892 pContext->m_pContext.reset(new CPDF_RenderContext(pPage));
Tom Sepez71fdc342016-01-22 12:06:32 -0800893 pContext->m_pContext->AppendLayer(pPage, &matrix);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700894
895 if (flags & FPDF_ANNOT) {
weili9f515bc2016-07-24 08:08:24 -0700896 pContext->m_pAnnots.reset(new CPDF_AnnotList(pPage));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700897 FX_BOOL bPrinting = pContext->m_pDevice->GetDeviceClass() != FXDC_DISPLAY;
weili9f515bc2016-07-24 08:08:24 -0700898 pContext->m_pAnnots->DisplayAnnots(pPage, pContext->m_pContext.get(),
899 bPrinting, &matrix, TRUE, nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700900 }
901
weili9f515bc2016-07-24 08:08:24 -0700902 pContext->m_pRenderer.reset(new CPDF_ProgressiveRenderer(
903 pContext->m_pContext.get(), pContext->m_pDevice.get(),
904 pContext->m_pOptions.get()));
Tom Sepezb3b67622015-10-19 16:20:03 -0700905 pContext->m_pRenderer->Start(pause);
Tom Sepezc7e4c4f2015-11-20 09:45:24 -0800906 if (bNeedToRestore)
thestig41846a02016-05-26 10:45:30 -0700907 pContext->m_pDevice->RestoreState(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700908}
909
910DLLEXPORT int STDCALL FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document,
911 int page_index,
912 double* width,
913 double* height) {
Tom Sepez540c4362015-11-24 13:33:57 -0800914 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
915 if (!pDoc)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700916 return FALSE;
917
Tom Sepez40e9ff32015-11-30 12:39:54 -0800918#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700919 int count = pDoc->GetPageCount();
920 if (page_index < 0 || page_index >= count)
921 return FALSE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700922 CPDFXFA_Page* pPage = pDoc->GetPage(page_index);
923 if (!pPage)
924 return FALSE;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800925 *width = pPage->GetPageWidth();
926 *height = pPage->GetPageHeight();
927#else // PDF_ENABLE_XFA
928 CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
929 if (!pDict)
930 return FALSE;
thestig5cc24652016-04-26 11:46:02 -0700931
932 CPDF_Page page(pDoc, pDict, true);
Tom Sepez51da0932015-11-25 16:05:49 -0800933 *width = page.GetPageWidth();
934 *height = page.GetPageHeight();
Tom Sepez40e9ff32015-11-30 12:39:54 -0800935#endif // PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700936
937 return TRUE;
938}
939
940DLLEXPORT FPDF_BOOL STDCALL
941FPDF_VIEWERREF_GetPrintScaling(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700942 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700943 if (!pDoc)
944 return TRUE;
Tom Sepez471a1032015-10-15 16:17:18 -0700945 CPDF_ViewerPreferences viewRef(pDoc);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700946 return viewRef.PrintScaling();
947}
948
949DLLEXPORT int STDCALL FPDF_VIEWERREF_GetNumCopies(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700950 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700951 if (!pDoc)
952 return 1;
953 CPDF_ViewerPreferences viewRef(pDoc);
954 return viewRef.NumCopies();
955}
956
957DLLEXPORT FPDF_PAGERANGE STDCALL
958FPDF_VIEWERREF_GetPrintPageRange(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700959 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700960 if (!pDoc)
thestig1cd352e2016-06-07 17:53:06 -0700961 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700962 CPDF_ViewerPreferences viewRef(pDoc);
963 return viewRef.PrintPageRange();
964}
965
966DLLEXPORT FPDF_DUPLEXTYPE STDCALL
967FPDF_VIEWERREF_GetDuplex(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700968 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700969 if (!pDoc)
Bo Xu9114e832014-07-14 13:22:47 -0700970 return DuplexUndefined;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700971 CPDF_ViewerPreferences viewRef(pDoc);
972 CFX_ByteString duplex = viewRef.Duplex();
Lei Zhangd983b092015-12-14 16:58:33 -0800973 if ("Simplex" == duplex)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700974 return Simplex;
Lei Zhangd983b092015-12-14 16:58:33 -0800975 if ("DuplexFlipShortEdge" == duplex)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700976 return DuplexFlipShortEdge;
Lei Zhangd983b092015-12-14 16:58:33 -0800977 if ("DuplexFlipLongEdge" == duplex)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700978 return DuplexFlipLongEdge;
979 return DuplexUndefined;
Bo Xu9114e832014-07-14 13:22:47 -0700980}
981
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700982DLLEXPORT FPDF_DWORD STDCALL FPDF_CountNamedDests(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700983 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
984 if (!pDoc)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700985 return 0;
Bo Xu4d62b6b2015-01-10 22:52:59 -0800986
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700987 CPDF_Dictionary* pRoot = pDoc->GetRoot();
988 if (!pRoot)
989 return 0;
Bo Xu4d62b6b2015-01-10 22:52:59 -0800990
Lei Zhangd983b092015-12-14 16:58:33 -0800991 CPDF_NameTree nameTree(pDoc, "Dests");
Oliver Chang3f1c71f2016-01-11 08:45:31 -0800992 pdfium::base::CheckedNumeric<FPDF_DWORD> count = nameTree.GetCount();
Wei Li9b761132016-01-29 15:44:20 -0800993 CPDF_Dictionary* pDest = pRoot->GetDictBy("Dests");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700994 if (pDest)
995 count += pDest->GetCount();
Oliver Chang3f1c71f2016-01-11 08:45:31 -0800996
997 if (!count.IsValid())
998 return 0;
999
1000 return count.ValueOrDie();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001001}
1002
1003DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDestByName(FPDF_DOCUMENT document,
1004 FPDF_BYTESTRING name) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001005 if (!name || name[0] == 0)
Tom Sepez471a1032015-10-15 16:17:18 -07001006 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001007
Tom Sepez471a1032015-10-15 16:17:18 -07001008 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1009 if (!pDoc)
1010 return nullptr;
1011
Lei Zhangd983b092015-12-14 16:58:33 -08001012 CPDF_NameTree name_tree(pDoc, "Dests");
Tom Sepez471a1032015-10-15 16:17:18 -07001013 return name_tree.LookupNamedDest(pDoc, name);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001014}
1015
Tom Sepez51da0932015-11-25 16:05:49 -08001016#ifdef PDF_ENABLE_XFA
thestig77d148d2016-04-06 06:28:31 -07001017DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Init(FPDF_BSTR* str) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001018 if (!str)
1019 return -1;
1020
1021 FXSYS_memset(str, 0, sizeof(FPDF_BSTR));
1022 return 0;
1023}
1024
thestig77d148d2016-04-06 06:28:31 -07001025DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Set(FPDF_BSTR* str,
1026 FPDF_LPCSTR bstr,
1027 int length) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001028 if (!str)
1029 return -1;
1030 if (!bstr || !length)
1031 return -1;
1032 if (length == -1)
1033 length = FXSYS_strlen(bstr);
1034
1035 if (length == 0) {
1036 if (str->str) {
1037 FX_Free(str->str);
thestig1cd352e2016-06-07 17:53:06 -07001038 str->str = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001039 }
1040 str->len = 0;
1041 return 0;
1042 }
1043
1044 if (str->str && str->len < length)
1045 str->str = FX_Realloc(char, str->str, length + 1);
1046 else if (!str->str)
1047 str->str = FX_Alloc(char, length + 1);
1048
1049 str->str[length] = 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001050 FXSYS_memcpy(str->str, bstr, length);
1051 str->len = length;
1052
1053 return 0;
1054}
1055
thestig77d148d2016-04-06 06:28:31 -07001056DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Clear(FPDF_BSTR* str) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001057 if (!str)
1058 return -1;
1059
1060 if (str->str) {
1061 FX_Free(str->str);
thestig1cd352e2016-06-07 17:53:06 -07001062 str->str = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001063 }
1064 str->len = 0;
1065 return 0;
1066}
Tom Sepez40e9ff32015-11-30 12:39:54 -08001067#endif // PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001068
1069DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDest(FPDF_DOCUMENT document,
1070 int index,
1071 void* buffer,
1072 long* buflen) {
1073 if (!buffer)
1074 *buflen = 0;
Tom Sepez540c4362015-11-24 13:33:57 -08001075
1076 if (index < 0)
1077 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001078
Tom Sepezbf59a072015-10-21 14:07:23 -07001079 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Tom Sepez540c4362015-11-24 13:33:57 -08001080 if (!pDoc)
1081 return nullptr;
1082
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001083 CPDF_Dictionary* pRoot = pDoc->GetRoot();
1084 if (!pRoot)
Tom Sepez540c4362015-11-24 13:33:57 -08001085 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001086
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001087 CPDF_Object* pDestObj = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001088 CFX_ByteString bsName;
Lei Zhangd983b092015-12-14 16:58:33 -08001089 CPDF_NameTree nameTree(pDoc, "Dests");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001090 int count = nameTree.GetCount();
1091 if (index >= count) {
Wei Li9b761132016-01-29 15:44:20 -08001092 CPDF_Dictionary* pDest = pRoot->GetDictBy("Dests");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001093 if (!pDest)
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001094 return nullptr;
1095
1096 pdfium::base::CheckedNumeric<int> checked_count = count;
1097 checked_count += pDest->GetCount();
1098 if (!checked_count.IsValid() || index >= checked_count.ValueOrDie())
1099 return nullptr;
1100
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001101 index -= count;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001102 int i = 0;
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001103 for (const auto& it : *pDest) {
1104 bsName = it.first;
1105 pDestObj = it.second;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001106 if (!pDestObj)
1107 continue;
1108 if (i == index)
1109 break;
1110 i++;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001111 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001112 } else {
1113 pDestObj = nameTree.LookupValue(index, bsName);
1114 }
1115 if (!pDestObj)
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001116 return nullptr;
Dan Sinclairf1251c12015-10-20 16:24:45 -04001117 if (CPDF_Dictionary* pDict = pDestObj->AsDictionary()) {
Wei Li9b761132016-01-29 15:44:20 -08001118 pDestObj = pDict->GetArrayBy("D");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001119 if (!pDestObj)
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001120 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001121 }
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001122 if (!pDestObj->IsArray())
1123 return nullptr;
1124
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001125 CFX_WideString wsName = PDF_DecodeText(bsName);
1126 CFX_ByteString utf16Name = wsName.UTF16LE_Encode();
weili47ca6922016-03-31 15:08:27 -07001127 int len = utf16Name.GetLength();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001128 if (!buffer) {
1129 *buflen = len;
1130 } else if (*buflen >= len) {
1131 memcpy(buffer, utf16Name.c_str(), len);
1132 *buflen = len;
1133 } else {
1134 *buflen = -1;
1135 }
1136 return (FPDF_DEST)pDestObj;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001137}