blob: e7b3a96b0b3cbcaa38a39da74b1c3317b107c13f [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"
14#include "core/fpdfapi/fpdf_render/include/cpdf_renderoptions.h"
15#include "core/fpdfapi/include/cpdf_modulemgr.h"
dsinclair86e54742016-04-06 12:30:31 -070016#include "core/fxcodec/include/fx_codec.h"
Dan Sinclaira8a28e02016-03-23 15:41:39 -040017#include "core/fxcrt/include/fx_safe_types.h"
Lei Zhangbde53d22015-11-12 22:21:30 -080018#include "fpdfsdk/include/fsdk_define.h"
19#include "fpdfsdk/include/fsdk_mgr.h"
20#include "fpdfsdk/include/fsdk_rendercontext.h"
dsinclair64376be2016-03-31 20:03:24 -070021#include "fpdfsdk/javascript/ijs_runtime.h"
Lei Zhangb4e7f302015-11-06 15:52:32 -080022#include "public/fpdf_ext.h"
Lei Zhangb4e7f302015-11-06 15:52:32 -080023#include "public/fpdf_progressive.h"
Lei Zhang8241df72015-11-06 14:38:48 -080024#include "third_party/base/numerics/safe_conversions_impl.h"
Bo Xufdc00a72014-10-28 23:03:33 -070025
Tom Sepez40e9ff32015-11-30 12:39:54 -080026#ifdef PDF_ENABLE_XFA
dsinclair89bdd082016-04-06 10:47:54 -070027#include "fpdfsdk/fpdfxfa/include/fpdfxfa_app.h"
28#include "fpdfsdk/fpdfxfa/include/fpdfxfa_doc.h"
29#include "fpdfsdk/fpdfxfa/include/fpdfxfa_page.h"
30#include "fpdfsdk/fpdfxfa/include/fpdfxfa_util.h"
Tom Sepez40e9ff32015-11-30 12:39:54 -080031#include "public/fpdf_formfill.h"
32#endif // PDF_ENABLE_XFA
33
Tom Sepez50d12ad2015-11-24 09:50:51 -080034UnderlyingDocumentType* UnderlyingFromFPDFDocument(FPDF_DOCUMENT doc) {
35 return static_cast<UnderlyingDocumentType*>(doc);
36}
37
38FPDF_DOCUMENT FPDFDocumentFromUnderlying(UnderlyingDocumentType* doc) {
39 return static_cast<FPDF_DOCUMENT>(doc);
40}
41
42UnderlyingPageType* UnderlyingFromFPDFPage(FPDF_PAGE page) {
43 return static_cast<UnderlyingPageType*>(page);
44}
45
Tom Sepez471a1032015-10-15 16:17:18 -070046CPDF_Document* CPDFDocumentFromFPDFDocument(FPDF_DOCUMENT doc) {
Tom Sepez40e9ff32015-11-30 12:39:54 -080047#ifdef PDF_ENABLE_XFA
Tom Sepez50d12ad2015-11-24 09:50:51 -080048 return doc ? UnderlyingFromFPDFDocument(doc)->GetPDFDoc() : nullptr;
Tom Sepez40e9ff32015-11-30 12:39:54 -080049#else // PDF_ENABLE_XFA
50 return UnderlyingFromFPDFDocument(doc);
51#endif // PDF_ENABLE_XFA
Tom Sepez471a1032015-10-15 16:17:18 -070052}
53
Tom Sepezbf59a072015-10-21 14:07:23 -070054FPDF_DOCUMENT FPDFDocumentFromCPDFDocument(CPDF_Document* doc) {
Tom Sepez40e9ff32015-11-30 12:39:54 -080055#ifdef PDF_ENABLE_XFA
Tom Sepez50d12ad2015-11-24 09:50:51 -080056 return doc ? FPDFDocumentFromUnderlying(
57 new CPDFXFA_Document(doc, CPDFXFA_App::GetInstance()))
58 : nullptr;
Tom Sepez40e9ff32015-11-30 12:39:54 -080059#else // PDF_ENABLE_XFA
60 return FPDFDocumentFromUnderlying(doc);
61#endif // PDF_ENABLE_XFA
Tom Sepezbf59a072015-10-21 14:07:23 -070062}
63
Tom Sepezdb0be962015-10-16 14:00:21 -070064CPDF_Page* CPDFPageFromFPDFPage(FPDF_PAGE page) {
Tom Sepez40e9ff32015-11-30 12:39:54 -080065#ifdef PDF_ENABLE_XFA
Tom Sepez50d12ad2015-11-24 09:50:51 -080066 return page ? UnderlyingFromFPDFPage(page)->GetPDFPage() : nullptr;
Tom Sepez40e9ff32015-11-30 12:39:54 -080067#else // PDF_ENABLE_XFA
68 return UnderlyingFromFPDFPage(page);
69#endif // PDF_ENABLE_XFA
Tom Sepezdb0be962015-10-16 14:00:21 -070070}
71
Tom Sepez40e9ff32015-11-30 12:39:54 -080072#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -070073CFPDF_FileStream::CFPDF_FileStream(FPDF_FILEHANDLER* pFS) {
74 m_pFS = pFS;
75 m_nCurPos = 0;
Bo Xufdc00a72014-10-28 23:03:33 -070076}
77
Nico Weber9d8ec5a2015-08-04 13:00:21 -070078IFX_FileStream* CFPDF_FileStream::Retain() {
79 return this;
Bo Xufdc00a72014-10-28 23:03:33 -070080}
81
Nico Weber9d8ec5a2015-08-04 13:00:21 -070082void CFPDF_FileStream::Release() {
83 if (m_pFS && m_pFS->Release)
84 m_pFS->Release(m_pFS->clientData);
85 delete this;
Bo Xufdc00a72014-10-28 23:03:33 -070086}
87
Nico Weber9d8ec5a2015-08-04 13:00:21 -070088FX_FILESIZE CFPDF_FileStream::GetSize() {
89 if (m_pFS && m_pFS->GetSize)
90 return (FX_FILESIZE)m_pFS->GetSize(m_pFS->clientData);
91 return 0;
Bo Xufdc00a72014-10-28 23:03:33 -070092}
93
Nico Weber9d8ec5a2015-08-04 13:00:21 -070094FX_BOOL CFPDF_FileStream::IsEOF() {
95 return m_nCurPos >= GetSize();
Bo Xufdc00a72014-10-28 23:03:33 -070096}
97
Nico Weber9d8ec5a2015-08-04 13:00:21 -070098FX_BOOL CFPDF_FileStream::ReadBlock(void* buffer,
99 FX_FILESIZE offset,
100 size_t size) {
101 if (!buffer || !size || !m_pFS->ReadBlock)
102 return FALSE;
Bo Xufdc00a72014-10-28 23:03:33 -0700103
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700104 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
105 (FPDF_DWORD)size) == 0) {
106 m_nCurPos = offset + size;
107 return TRUE;
108 }
109 return FALSE;
Bo Xufdc00a72014-10-28 23:03:33 -0700110}
111
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700112size_t CFPDF_FileStream::ReadBlock(void* buffer, size_t size) {
113 if (!buffer || !size || !m_pFS->ReadBlock)
114 return 0;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700115
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700116 FX_FILESIZE nSize = GetSize();
117 if (m_nCurPos >= nSize)
118 return 0;
119 FX_FILESIZE dwAvail = nSize - m_nCurPos;
120 if (dwAvail < (FX_FILESIZE)size)
121 size = (size_t)dwAvail;
122 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)m_nCurPos, buffer,
123 (FPDF_DWORD)size) == 0) {
124 m_nCurPos += size;
125 return size;
126 }
Bo Xufdc00a72014-10-28 23:03:33 -0700127
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700128 return 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700129}
130
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700131FX_BOOL CFPDF_FileStream::WriteBlock(const void* buffer,
132 FX_FILESIZE offset,
133 size_t size) {
134 if (!m_pFS || !m_pFS->WriteBlock)
135 return FALSE;
Bo Xufdc00a72014-10-28 23:03:33 -0700136
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700137 if (m_pFS->WriteBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
138 (FPDF_DWORD)size) == 0) {
139 m_nCurPos = offset + size;
140 return TRUE;
141 }
142 return FALSE;
Bo Xufdc00a72014-10-28 23:03:33 -0700143}
144
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700145FX_BOOL CFPDF_FileStream::Flush() {
146 if (!m_pFS || !m_pFS->Flush)
147 return TRUE;
Bo Xufdc00a72014-10-28 23:03:33 -0700148
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700149 return m_pFS->Flush(m_pFS->clientData) == 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700150}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800151#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700152
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700153CPDF_CustomAccess::CPDF_CustomAccess(FPDF_FILEACCESS* pFileAccess) {
154 m_FileAccess = *pFileAccess;
Tom Sepez51da0932015-11-25 16:05:49 -0800155#ifdef PDF_ENABLE_XFA
tsepezc3255f52016-03-25 14:52:27 -0700156 m_BufferOffset = (uint32_t)-1;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800157#endif // PDF_ENABLE_XFA
Bo Xufdc00a72014-10-28 23:03:33 -0700158}
159
Tom Sepez40e9ff32015-11-30 12:39:54 -0800160#ifdef PDF_ENABLE_XFA
tsepezc3255f52016-03-25 14:52:27 -0700161FX_BOOL CPDF_CustomAccess::GetByte(uint32_t pos, uint8_t& ch) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700162 if (pos >= m_FileAccess.m_FileLen)
163 return FALSE;
tsepezc3255f52016-03-25 14:52:27 -0700164 if (m_BufferOffset == (uint32_t)-1 || pos < m_BufferOffset ||
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700165 pos >= m_BufferOffset + 512) {
166 // Need to read from file access
167 m_BufferOffset = pos;
168 int size = 512;
169 if (pos + 512 > m_FileAccess.m_FileLen)
170 size = m_FileAccess.m_FileLen - pos;
171 if (!m_FileAccess.m_GetBlock(m_FileAccess.m_Param, m_BufferOffset, m_Buffer,
172 size))
173 return FALSE;
174 }
175 ch = m_Buffer[pos - m_BufferOffset];
176 return TRUE;
Bo Xufdc00a72014-10-28 23:03:33 -0700177}
178
tsepezc3255f52016-03-25 14:52:27 -0700179FX_BOOL CPDF_CustomAccess::GetBlock(uint32_t pos,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700180 uint8_t* pBuf,
tsepezc3255f52016-03-25 14:52:27 -0700181 uint32_t size) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700182 if (pos + size > m_FileAccess.m_FileLen)
183 return FALSE;
184 return m_FileAccess.m_GetBlock(m_FileAccess.m_Param, pos, pBuf, size);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700185}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800186#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700187
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700188FX_BOOL CPDF_CustomAccess::ReadBlock(void* buffer,
189 FX_FILESIZE offset,
190 size_t size) {
191 if (offset < 0) {
192 return FALSE;
193 }
194 FX_SAFE_FILESIZE newPos =
195 pdfium::base::checked_cast<FX_FILESIZE, size_t>(size);
196 newPos += offset;
Wei Li05d53f02016-03-29 16:42:53 -0700197 if (!newPos.IsValid() ||
198 newPos.ValueOrDie() > static_cast<FX_FILESIZE>(m_FileAccess.m_FileLen)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700199 return FALSE;
200 }
201 return m_FileAccess.m_GetBlock(m_FileAccess.m_Param, offset, (uint8_t*)buffer,
202 size);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700203}
204
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700205// 0 bit: FPDF_POLICY_MACHINETIME_ACCESS
tsepezc3255f52016-03-25 14:52:27 -0700206static uint32_t foxit_sandbox_policy = 0xFFFFFFFF;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700207
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700208void FSDK_SetSandBoxPolicy(FPDF_DWORD policy, FPDF_BOOL enable) {
209 switch (policy) {
210 case FPDF_POLICY_MACHINETIME_ACCESS: {
211 if (enable)
212 foxit_sandbox_policy |= 0x01;
213 else
214 foxit_sandbox_policy &= 0xFFFFFFFE;
215 } break;
216 default:
217 break;
218 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700219}
220
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700221FPDF_BOOL FSDK_IsSandBoxPolicyEnabled(FPDF_DWORD policy) {
222 switch (policy) {
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700223 case FPDF_POLICY_MACHINETIME_ACCESS:
Lei Zhangb0748bb2015-10-19 12:11:49 -0700224 return !!(foxit_sandbox_policy & 0x01);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700225 default:
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700226 return FALSE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700227 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700228}
229
Tom Sepez2c286192015-06-18 12:47:11 -0700230CCodec_ModuleMgr* g_pCodecModule = nullptr;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700231
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700232DLLEXPORT void STDCALL FPDF_InitLibrary() {
Lei Zhang6f62d532015-09-23 15:31:44 -0700233 FPDF_InitLibraryWithConfig(nullptr);
234}
235
Dan Sinclairf766ad22016-03-14 13:51:24 -0400236DLLEXPORT void STDCALL
237FPDF_InitLibraryWithConfig(const FPDF_LIBRARY_CONFIG* cfg) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700238 g_pCodecModule = new CCodec_ModuleMgr();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700239
Lei Zhang6f62d532015-09-23 15:31:44 -0700240 CFX_GEModule::Create(cfg ? cfg->m_pUserFontPaths : nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700241 CFX_GEModule::Get()->SetCodecModule(g_pCodecModule);
Tom Sepezbdeeb8a2015-05-27 12:25:00 -0700242
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700243 CPDF_ModuleMgr::Create();
Tom Sepez1b246282015-11-25 15:15:31 -0800244 CPDF_ModuleMgr* pModuleMgr = CPDF_ModuleMgr::Get();
245 pModuleMgr->SetCodecModule(g_pCodecModule);
246 pModuleMgr->InitPageModule();
dsinclaird647a6b2016-04-26 13:13:20 -0700247
Tom Sepez40e9ff32015-11-30 12:39:54 -0800248#ifdef PDF_ENABLE_XFA
jinming_wang48661582016-02-04 09:41:56 +0800249 CPDFXFA_App::GetInstance()->Initialize(
250 (cfg && cfg->version >= 2)
251 ? reinterpret_cast<FXJSE_HRUNTIME>(cfg->m_pIsolate)
252 : nullptr);
Tom Sepez40e9ff32015-11-30 12:39:54 -0800253#else // PDF_ENABLE_XFA
Tom Sepez51da0932015-11-25 16:05:49 -0800254 pModuleMgr->LoadEmbeddedGB1CMaps();
255 pModuleMgr->LoadEmbeddedJapan1CMaps();
256 pModuleMgr->LoadEmbeddedCNS1CMaps();
257 pModuleMgr->LoadEmbeddedKorea1CMaps();
Tom Sepez40e9ff32015-11-30 12:39:54 -0800258#endif // PDF_ENABLE_XFA
dsinclaird647a6b2016-04-26 13:13:20 -0700259
Tom Sepez452b4f32015-10-13 09:27:27 -0700260 if (cfg && cfg->version >= 2)
261 IJS_Runtime::Initialize(cfg->m_v8EmbedderSlot, cfg->m_pIsolate);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700262}
263
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700264DLLEXPORT void STDCALL FPDF_DestroyLibrary() {
Tom Sepez51da0932015-11-25 16:05:49 -0800265#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700266 CPDFXFA_App::ReleaseInstance();
Tom Sepez40e9ff32015-11-30 12:39:54 -0800267#endif // PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700268 CPDF_ModuleMgr::Destroy();
269 CFX_GEModule::Destroy();
Tom Sepez2c286192015-06-18 12:47:11 -0700270
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700271 delete g_pCodecModule;
272 g_pCodecModule = nullptr;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700273}
274
275#ifndef _WIN32
276int g_LastError;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700277void SetLastError(int err) {
278 g_LastError = err;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700279}
280
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700281int GetLastError() {
282 return g_LastError;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700283}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800284#endif // _WIN32
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700285
Tom Sepezf10ae632016-01-26 14:19:52 -0800286void ProcessParseError(CPDF_Parser::Error err) {
tsepezc3255f52016-03-25 14:52:27 -0700287 uint32_t err_code = FPDF_ERR_SUCCESS;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700288 // Translate FPDFAPI error code to FPDFVIEW error code
Tom Sepezf10ae632016-01-26 14:19:52 -0800289 switch (err) {
290 case CPDF_Parser::SUCCESS:
291 err_code = FPDF_ERR_SUCCESS;
292 break;
293 case CPDF_Parser::FILE_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700294 err_code = FPDF_ERR_FILE;
295 break;
Tom Sepezf10ae632016-01-26 14:19:52 -0800296 case CPDF_Parser::FORMAT_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700297 err_code = FPDF_ERR_FORMAT;
298 break;
Tom Sepezf10ae632016-01-26 14:19:52 -0800299 case CPDF_Parser::PASSWORD_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700300 err_code = FPDF_ERR_PASSWORD;
301 break;
Tom Sepezf10ae632016-01-26 14:19:52 -0800302 case CPDF_Parser::HANDLER_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700303 err_code = FPDF_ERR_SECURITY;
304 break;
305 }
306 SetLastError(err_code);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700307}
308
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700309DLLEXPORT void STDCALL FPDF_SetSandBoxPolicy(FPDF_DWORD policy,
310 FPDF_BOOL enable) {
311 return FSDK_SetSandBoxPolicy(policy, enable);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700312}
313
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700314DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadDocument(FPDF_STRING file_path,
315 FPDF_BYTESTRING password) {
Tom Sepeze3166a82015-08-05 10:50:32 -0700316 // NOTE: the creation of the file needs to be by the embedder on the
317 // other side of this API.
318 IFX_FileRead* pFileAccess = FX_CreateFileRead((const FX_CHAR*)file_path);
319 if (!pFileAccess) {
320 return nullptr;
321 }
322
323 CPDF_Parser* pParser = new CPDF_Parser;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700324 pParser->SetPassword(password);
Bo Xud4e406e2014-08-13 11:03:19 -0700325
Tom Sepezf10ae632016-01-26 14:19:52 -0800326 CPDF_Parser::Error error = pParser->StartParse(pFileAccess);
327 if (error != CPDF_Parser::SUCCESS) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700328 delete pParser;
Tom Sepezf10ae632016-01-26 14:19:52 -0800329 ProcessParseError(error);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700330 return NULL;
331 }
Tom Sepez40e9ff32015-11-30 12:39:54 -0800332#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700333 CPDF_Document* pPDFDoc = pParser->GetDocument();
334 if (!pPDFDoc)
335 return NULL;
Bo Xufdc00a72014-10-28 23:03:33 -0700336
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700337 CPDFXFA_App* pProvider = CPDFXFA_App::GetInstance();
Lei Zhangcb78ef52015-10-02 10:10:49 -0700338 return new CPDFXFA_Document(pPDFDoc, pProvider);
Tom Sepez40e9ff32015-11-30 12:39:54 -0800339#else // PDF_ENABLE_XFA
340 return pParser->GetDocument();
341#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700342}
Jun Fange118ce92015-02-17 06:50:08 -0800343
Tom Sepez40e9ff32015-11-30 12:39:54 -0800344#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700345DLLEXPORT FPDF_BOOL STDCALL FPDF_HasXFAField(FPDF_DOCUMENT document,
346 int* docType) {
347 if (!document)
348 return FALSE;
JUN FANG827a1722015-03-05 13:39:21 -0800349
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700350 CPDF_Document* pdfDoc =
351 (static_cast<CPDFXFA_Document*>(document))->GetPDFDoc();
352 if (!pdfDoc)
353 return FALSE;
JUN FANG827a1722015-03-05 13:39:21 -0800354
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700355 CPDF_Dictionary* pRoot = pdfDoc->GetRoot();
356 if (!pRoot)
357 return FALSE;
JUN FANG827a1722015-03-05 13:39:21 -0800358
Wei Li9b761132016-01-29 15:44:20 -0800359 CPDF_Dictionary* pAcroForm = pRoot->GetDictBy("AcroForm");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700360 if (!pAcroForm)
361 return FALSE;
JUN FANG827a1722015-03-05 13:39:21 -0800362
tsepezbd567552016-03-29 14:51:50 -0700363 CPDF_Object* pXFA = pAcroForm->GetObjectBy("XFA");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700364 if (!pXFA)
365 return FALSE;
JUN FANG827a1722015-03-05 13:39:21 -0800366
Wei Li9b761132016-01-29 15:44:20 -0800367 FX_BOOL bDynamicXFA = pRoot->GetBooleanBy("NeedsRendering", FALSE);
JUN FANG827a1722015-03-05 13:39:21 -0800368
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700369 if (bDynamicXFA)
Tom Sepezd3116dc2015-11-24 15:58:06 -0800370 *docType = DOCTYPE_DYNAMIC_XFA;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700371 else
372 *docType = DOCTYPE_STATIC_XFA;
JUN FANG827a1722015-03-05 13:39:21 -0800373
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700374 return TRUE;
Jun Fange118ce92015-02-17 06:50:08 -0800375}
376
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700377DLLEXPORT FPDF_BOOL STDCALL FPDF_LoadXFA(FPDF_DOCUMENT document) {
378 return document && (static_cast<CPDFXFA_Document*>(document))->LoadXFADoc();
Bo Xufdc00a72014-10-28 23:03:33 -0700379}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800380#endif // PDF_ENABLE_XFA
Bo Xufdc00a72014-10-28 23:03:33 -0700381
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700382class CMemFile final : public IFX_FileRead {
383 public:
384 CMemFile(uint8_t* pBuf, FX_FILESIZE size) : m_pBuf(pBuf), m_size(size) {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700385
Lei Zhang3884dba2015-10-19 17:27:53 -0700386 void Release() override { delete this; }
387 FX_FILESIZE GetSize() override { return m_size; }
388 FX_BOOL ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700389 if (offset < 0) {
390 return FALSE;
391 }
392 FX_SAFE_FILESIZE newPos =
393 pdfium::base::checked_cast<FX_FILESIZE, size_t>(size);
394 newPos += offset;
weili47ca6922016-03-31 15:08:27 -0700395 if (!newPos.IsValid() || newPos.ValueOrDie() > m_size) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700396 return FALSE;
397 }
398 FXSYS_memcpy(buffer, m_pBuf + offset, size);
399 return TRUE;
400 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700401
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700402 private:
Lei Zhang2b1a2d52015-08-14 22:16:22 -0700403 ~CMemFile() override {}
404
Lei Zhang3884dba2015-10-19 17:27:53 -0700405 uint8_t* const m_pBuf;
406 const FX_FILESIZE m_size;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700407};
Lei Zhang3884dba2015-10-19 17:27:53 -0700408
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700409DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadMemDocument(const void* data_buf,
410 int size,
411 FPDF_BYTESTRING password) {
Tom Sepezae51c812015-08-05 12:34:06 -0700412 CPDF_Parser* pParser = new CPDF_Parser;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700413 pParser->SetPassword(password);
414 CMemFile* pMemFile = new CMemFile((uint8_t*)data_buf, size);
Tom Sepezf10ae632016-01-26 14:19:52 -0800415 CPDF_Parser::Error error = pParser->StartParse(pMemFile);
416 if (error != CPDF_Parser::SUCCESS) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700417 delete pParser;
Tom Sepezf10ae632016-01-26 14:19:52 -0800418 ProcessParseError(error);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700419 return NULL;
420 }
421 CPDF_Document* pDoc = NULL;
422 pDoc = pParser ? pParser->GetDocument() : NULL;
Tom Sepezf10ae632016-01-26 14:19:52 -0800423 CheckUnSupportError(pDoc, error);
Tom Sepezbf59a072015-10-21 14:07:23 -0700424 return FPDFDocumentFromCPDFDocument(pParser->GetDocument());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700425}
426
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700427DLLEXPORT FPDF_DOCUMENT STDCALL
428FPDF_LoadCustomDocument(FPDF_FILEACCESS* pFileAccess,
429 FPDF_BYTESTRING password) {
Tom Sepezae51c812015-08-05 12:34:06 -0700430 CPDF_Parser* pParser = new CPDF_Parser;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700431 pParser->SetPassword(password);
Tom Sepezae51c812015-08-05 12:34:06 -0700432 CPDF_CustomAccess* pFile = new CPDF_CustomAccess(pFileAccess);
Tom Sepezf10ae632016-01-26 14:19:52 -0800433 CPDF_Parser::Error error = pParser->StartParse(pFile);
434 if (error != CPDF_Parser::SUCCESS) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700435 delete pParser;
Tom Sepezf10ae632016-01-26 14:19:52 -0800436 ProcessParseError(error);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700437 return NULL;
438 }
439 CPDF_Document* pDoc = NULL;
440 pDoc = pParser ? pParser->GetDocument() : NULL;
Tom Sepezf10ae632016-01-26 14:19:52 -0800441 CheckUnSupportError(pDoc, error);
Tom Sepezbf59a072015-10-21 14:07:23 -0700442 return FPDFDocumentFromCPDFDocument(pParser->GetDocument());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700443}
444
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700445DLLEXPORT FPDF_BOOL STDCALL FPDF_GetFileVersion(FPDF_DOCUMENT doc,
446 int* fileVersion) {
Tom Sepez471a1032015-10-15 16:17:18 -0700447 if (!fileVersion)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700448 return FALSE;
Bo Xufdc00a72014-10-28 23:03:33 -0700449
Tom Sepez471a1032015-10-15 16:17:18 -0700450 *fileVersion = 0;
451 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(doc);
452 if (!pDoc)
453 return FALSE;
454
455 CPDF_Parser* pParser = pDoc->GetParser();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700456 if (!pParser)
457 return FALSE;
Tom Sepez471a1032015-10-15 16:17:18 -0700458
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700459 *fileVersion = pParser->GetFileVersion();
460 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700461}
462
tsepezc3255f52016-03-25 14:52:27 -0700463// jabdelmalek: changed return type from uint32_t to build on Linux (and match
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700464// header).
465DLLEXPORT unsigned long STDCALL FPDF_GetDocPermissions(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700466 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
thestig27ddf162016-05-23 15:06:59 -0700467 // https://bugs.chromium.org/p/pdfium/issues/detail?id=499
468 if (!pDoc) {
Tom Sepez51da0932015-11-25 16:05:49 -0800469#ifndef PDF_ENABLE_XFA
470 return 0;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800471#else // PDF_ENABLE_XFA
thestig27ddf162016-05-23 15:06:59 -0700472 return 0xFFFFFFFF;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800473#endif // PDF_ENABLE_XFA
thestig27ddf162016-05-23 15:06:59 -0700474 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700475
thestig27ddf162016-05-23 15:06:59 -0700476 return pDoc->GetUserPermissions();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700477}
478
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700479DLLEXPORT int STDCALL FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700480 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
thestigb8db5112016-04-06 12:12:52 -0700481 if (!pDoc || !pDoc->GetParser())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700482 return -1;
Bo Xuc5cab022014-09-19 19:16:31 -0700483
Tom Sepez471a1032015-10-15 16:17:18 -0700484 CPDF_Dictionary* pDict = pDoc->GetParser()->GetEncryptDict();
Wei Li9b761132016-01-29 15:44:20 -0800485 return pDict ? pDict->GetIntegerBy("R") : -1;
Bo Xuc5cab022014-09-19 19:16:31 -0700486}
487
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700488DLLEXPORT int STDCALL FPDF_GetPageCount(FPDF_DOCUMENT document) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800489 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
Tom Sepez471a1032015-10-15 16:17:18 -0700490 return pDoc ? pDoc->GetPageCount() : 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700491}
492
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700493DLLEXPORT FPDF_PAGE STDCALL FPDF_LoadPage(FPDF_DOCUMENT document,
494 int page_index) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800495 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
496 if (!pDoc)
Tom Sepez471a1032015-10-15 16:17:18 -0700497 return nullptr;
Tom Sepez1b246282015-11-25 15:15:31 -0800498
Tom Sepezbbe0e4d2015-10-20 15:41:40 -0700499 if (page_index < 0 || page_index >= pDoc->GetPageCount())
Tom Sepez471a1032015-10-15 16:17:18 -0700500 return nullptr;
501
Tom Sepez40e9ff32015-11-30 12:39:54 -0800502#ifdef PDF_ENABLE_XFA
503 return pDoc->GetPage(page_index);
504#else // PDF_ENABLE_XFA
Tom Sepez51da0932015-11-25 16:05:49 -0800505 CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
Lei Zhang412e9082015-12-14 18:34:00 -0800506 if (!pDict)
thestig5cc24652016-04-26 11:46:02 -0700507 return nullptr;
508
509 CPDF_Page* pPage = new CPDF_Page(pDoc, pDict, true);
510 pPage->ParseContent();
Tom Sepez51da0932015-11-25 16:05:49 -0800511 return pPage;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800512#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700513}
514
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700515DLLEXPORT double STDCALL FPDF_GetPageWidth(FPDF_PAGE page) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800516 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezbf59a072015-10-21 14:07:23 -0700517 return pPage ? pPage->GetPageWidth() : 0.0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700518}
519
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700520DLLEXPORT double STDCALL FPDF_GetPageHeight(FPDF_PAGE page) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800521 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezbf59a072015-10-21 14:07:23 -0700522 return pPage ? pPage->GetPageHeight() : 0.0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700523}
524
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700525void DropContext(void* data) {
526 delete (CRenderContext*)data;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700527}
528
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700529#if defined(_WIN32)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700530DLLEXPORT void STDCALL FPDF_RenderPage(HDC dc,
531 FPDF_PAGE page,
532 int start_x,
533 int start_y,
534 int size_x,
535 int size_y,
536 int rotate,
537 int flags) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700538 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700539 if (!pPage)
540 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700541
Tom Sepezae51c812015-08-05 12:34:06 -0700542 CRenderContext* pContext = new CRenderContext;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700543 pPage->SetPrivateData((void*)1, pContext, DropContext);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700544
Lei Zhangae85f872016-02-19 14:57:07 -0800545#if !defined(_WIN32_WCE)
Jun Fang1aeeceb2015-12-29 10:27:44 +0800546 CFX_DIBitmap* pBitmap = nullptr;
547 FX_BOOL bBackgroundAlphaNeeded = pPage->BackgroundAlphaNeeded();
548 FX_BOOL bHasImageMask = pPage->HasImageMask();
549 if (bBackgroundAlphaNeeded || bHasImageMask) {
Tom Sepezae51c812015-08-05 12:34:06 -0700550 pBitmap = new CFX_DIBitmap;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700551 pBitmap->Create(size_x, size_y, FXDIB_Argb);
552 pBitmap->Clear(0x00ffffff);
Tom Sepezae51c812015-08-05 12:34:06 -0700553 pContext->m_pDevice = new CFX_FxgeDevice;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700554 ((CFX_FxgeDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)pBitmap);
Jun Fang1aeeceb2015-12-29 10:27:44 +0800555 } else {
Tom Sepezae51c812015-08-05 12:34:06 -0700556 pContext->m_pDevice = new CFX_WindowsDevice(dc);
Jun Fang1aeeceb2015-12-29 10:27:44 +0800557 }
Bo Xud4e406e2014-08-13 11:03:19 -0700558
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700559 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
560 rotate, flags, TRUE, NULL);
Bo Xud4e406e2014-08-13 11:03:19 -0700561
Jun Fang1aeeceb2015-12-29 10:27:44 +0800562 if (bBackgroundAlphaNeeded || bHasImageMask) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700563 if (pBitmap) {
564 CFX_WindowsDevice WinDC(dc);
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700565
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700566 if (WinDC.GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
Tom Sepezae51c812015-08-05 12:34:06 -0700567 CFX_DIBitmap* pDst = new CFX_DIBitmap;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700568 int pitch = pBitmap->GetPitch();
569 pDst->Create(size_x, size_y, FXDIB_Rgb32);
570 FXSYS_memset(pDst->GetBuffer(), -1, pitch * size_y);
571 pDst->CompositeBitmap(0, 0, size_x, size_y, pBitmap, 0, 0,
572 FXDIB_BLEND_NORMAL, NULL, FALSE, NULL);
573 WinDC.StretchDIBits(pDst, 0, 0, size_x, size_y);
574 delete pDst;
Jun Fang1aeeceb2015-12-29 10:27:44 +0800575 } else {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700576 WinDC.SetDIBits(pBitmap, 0, 0);
Jun Fang1aeeceb2015-12-29 10:27:44 +0800577 }
Lei Zhang6d8b1c22015-06-19 17:26:17 -0700578 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700579 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700580#else
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700581 // get clip region
582 RECT rect, cliprect;
583 rect.left = start_x;
584 rect.top = start_y;
585 rect.right = start_x + size_x;
586 rect.bottom = start_y + size_y;
587 GetClipBox(dc, &cliprect);
588 IntersectRect(&rect, &rect, &cliprect);
589 int width = rect.right - rect.left;
590 int height = rect.bottom - rect.top;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700591
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700592 // Create a DIB section
593 LPVOID pBuffer;
594 BITMAPINFOHEADER bmih;
595 FXSYS_memset(&bmih, 0, sizeof bmih);
596 bmih.biSize = sizeof bmih;
597 bmih.biBitCount = 24;
598 bmih.biHeight = -height;
599 bmih.biPlanes = 1;
600 bmih.biWidth = width;
601 pContext->m_hBitmap = CreateDIBSection(dc, (BITMAPINFO*)&bmih, DIB_RGB_COLORS,
602 &pBuffer, NULL, 0);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700603 FXSYS_memset(pBuffer, 0xff, height * ((width * 3 + 3) / 4 * 4));
604
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700605 // Create a device with this external buffer
606 pContext->m_pBitmap = new CFX_DIBitmap;
607 pContext->m_pBitmap->Create(width, height, FXDIB_Rgb, (uint8_t*)pBuffer);
608 pContext->m_pDevice = new CPDF_FxgeDevice;
609 ((CPDF_FxgeDevice*)pContext->m_pDevice)->Attach(pContext->m_pBitmap);
610
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700611 // output to bitmap device
612 FPDF_RenderPage_Retail(pContext, page, start_x - rect.left,
613 start_y - rect.top, size_x, size_y, rotate, flags);
614
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700615 // Now output to real device
616 HDC hMemDC = CreateCompatibleDC(dc);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700617 HGDIOBJ hOldBitmap = SelectObject(hMemDC, pContext->m_hBitmap);
618
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700619 BitBlt(dc, rect.left, rect.top, width, height, hMemDC, 0, 0, SRCCOPY);
620 SelectObject(hMemDC, hOldBitmap);
621 DeleteDC(hMemDC);
622
Lei Zhangae85f872016-02-19 14:57:07 -0800623#endif // !defined(_WIN32_WCE)
Jun Fang1aeeceb2015-12-29 10:27:44 +0800624 if (bBackgroundAlphaNeeded || bHasImageMask)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700625 delete pBitmap;
Jun Fang1aeeceb2015-12-29 10:27:44 +0800626
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700627 delete pContext;
628 pPage->RemovePrivateData((void*)1);
629}
Lei Zhangae85f872016-02-19 14:57:07 -0800630#endif // defined(_WIN32)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700631
632DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap,
633 FPDF_PAGE page,
634 int start_x,
635 int start_y,
636 int size_x,
637 int size_y,
638 int rotate,
639 int flags) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700640 if (!bitmap)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700641 return;
Tom Sepezdb0be962015-10-16 14:00:21 -0700642 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700643 if (!pPage)
644 return;
Tom Sepezae51c812015-08-05 12:34:06 -0700645 CRenderContext* pContext = new CRenderContext;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700646 pPage->SetPrivateData((void*)1, pContext, DropContext);
Tom Sepezae51c812015-08-05 12:34:06 -0700647 pContext->m_pDevice = new CFX_FxgeDevice;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700648
649 if (flags & FPDF_REVERSE_BYTE_ORDER)
650 ((CFX_FxgeDevice*)pContext->m_pDevice)
651 ->Attach((CFX_DIBitmap*)bitmap, 0, TRUE);
652 else
653 ((CFX_FxgeDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)bitmap);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700654
655 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
656 rotate, flags, TRUE, NULL);
657
658 delete pContext;
659 pPage->RemovePrivateData((void*)1);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700660}
661
Cary Clark399be5b2016-03-14 16:51:29 -0400662#ifdef _SKIA_SUPPORT_
663DLLEXPORT FPDF_RECORDER STDCALL FPDF_RenderPageSkp(FPDF_PAGE page,
664 int size_x,
665 int size_y) {
666 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
667 if (!pPage)
668 return nullptr;
669 std::unique_ptr<CRenderContext> pContext(new CRenderContext);
670 pPage->SetPrivateData((void*)1, pContext.get(), DropContext);
caryclarkd6e18872016-05-13 10:57:20 -0700671 CFX_FxgeDevice* skDevice = new CFX_FxgeDevice;
Cary Clark399be5b2016-03-14 16:51:29 -0400672 FPDF_RECORDER recorder = skDevice->CreateRecorder(size_x, size_y);
673 pContext->m_pDevice = skDevice;
674
675 FPDF_RenderPage_Retail(pContext.get(), page, 0, 0, size_x, size_y, 0, 0, TRUE,
676 NULL);
677 pPage->RemovePrivateData((void*)1);
678 return recorder;
679}
680#endif
681
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700682DLLEXPORT void STDCALL FPDF_ClosePage(FPDF_PAGE page) {
683 if (!page)
684 return;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800685#ifdef PDF_ENABLE_XFA
686 CPDFXFA_Page* pPage = (CPDFXFA_Page*)page;
687 pPage->Release();
688#else // PDF_ENABLE_XFA
Tom Sepez51da0932015-11-25 16:05:49 -0800689 CPDFSDK_PageView* pPageView =
690 (CPDFSDK_PageView*)(((CPDF_Page*)page))->GetPrivateData((void*)page);
691 if (pPageView && pPageView->IsLocked()) {
692 pPageView->TakeOverPage();
693 return;
694 }
695 delete (CPDF_Page*)page;
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 void STDCALL FPDF_CloseDocument(FPDF_DOCUMENT document) {
Tom Sepez40e9ff32015-11-30 12:39:54 -0800700#ifdef PDF_ENABLE_XFA
Jun Fangfc751362015-12-16 21:23:39 -0800701 delete UnderlyingFromFPDFDocument(document);
Tom Sepez40e9ff32015-11-30 12:39:54 -0800702#else // PDF_ENABLE_XFA
Tom Sepez51da0932015-11-25 16:05:49 -0800703 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
704 if (!pDoc)
705 return;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800706 CPDF_Parser* pParser = pDoc->GetParser();
Tom Sepez51da0932015-11-25 16:05:49 -0800707 if (!pParser) {
708 delete pDoc;
709 return;
710 }
711 delete pParser;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800712#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700713}
714
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700715DLLEXPORT unsigned long STDCALL FPDF_GetLastError() {
716 return GetLastError();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700717}
718
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700719DLLEXPORT void STDCALL FPDF_DeviceToPage(FPDF_PAGE page,
720 int start_x,
721 int start_y,
722 int size_x,
723 int size_y,
724 int rotate,
725 int device_x,
726 int device_y,
727 double* page_x,
728 double* page_y) {
Lei Zhang412e9082015-12-14 18:34:00 -0800729 if (!page || !page_x || !page_y)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700730 return;
Tom Sepez50d12ad2015-11-24 09:50:51 -0800731 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepez40e9ff32015-11-30 12:39:54 -0800732#ifdef PDF_ENABLE_XFA
733 pPage->DeviceToPage(start_x, start_y, size_x, size_y, rotate, device_x,
734 device_y, page_x, page_y);
735#else // PDF_ENABLE_XFA
Tom Sepez60d909e2015-12-10 15:34:55 -0800736 CFX_Matrix page2device;
Tom Sepez51da0932015-11-25 16:05:49 -0800737 pPage->GetDisplayMatrix(page2device, start_x, start_y, size_x, size_y,
738 rotate);
Tom Sepez60d909e2015-12-10 15:34:55 -0800739 CFX_Matrix device2page;
Tom Sepez51da0932015-11-25 16:05:49 -0800740 device2page.SetReverse(page2device);
Tom Sepez51da0932015-11-25 16:05:49 -0800741 FX_FLOAT page_x_f, page_y_f;
742 device2page.Transform((FX_FLOAT)(device_x), (FX_FLOAT)(device_y), page_x_f,
743 page_y_f);
Tom Sepez51da0932015-11-25 16:05:49 -0800744 *page_x = (page_x_f);
745 *page_y = (page_y_f);
Tom Sepez40e9ff32015-11-30 12:39:54 -0800746#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700747}
748
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700749DLLEXPORT void STDCALL FPDF_PageToDevice(FPDF_PAGE page,
750 int start_x,
751 int start_y,
752 int size_x,
753 int size_y,
754 int rotate,
755 double page_x,
756 double page_y,
757 int* device_x,
758 int* device_y) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700759 if (!device_x || !device_y)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700760 return;
Tom Sepez50d12ad2015-11-24 09:50:51 -0800761 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezdb0be962015-10-16 14:00:21 -0700762 if (!pPage)
763 return;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800764#ifdef PDF_ENABLE_XFA
765 pPage->PageToDevice(start_x, start_y, size_x, size_y, rotate, page_x, page_y,
766 device_x, device_y);
767#else // PDF_ENABLE_XFA
Tom Sepez60d909e2015-12-10 15:34:55 -0800768 CFX_Matrix page2device;
Tom Sepez51da0932015-11-25 16:05:49 -0800769 pPage->GetDisplayMatrix(page2device, start_x, start_y, size_x, size_y,
770 rotate);
Tom Sepez51da0932015-11-25 16:05:49 -0800771 FX_FLOAT device_x_f, device_y_f;
772 page2device.Transform(((FX_FLOAT)page_x), ((FX_FLOAT)page_y), device_x_f,
773 device_y_f);
Tom Sepez51da0932015-11-25 16:05:49 -0800774 *device_x = FXSYS_round(device_x_f);
775 *device_y = FXSYS_round(device_y_f);
Tom Sepez40e9ff32015-11-30 12:39:54 -0800776#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700777}
778
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700779DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_Create(int width,
780 int height,
781 int alpha) {
Lei Zhangaa8bf7e2015-12-24 19:13:32 -0800782 std::unique_ptr<CFX_DIBitmap> pBitmap(new CFX_DIBitmap);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700783 if (!pBitmap->Create(width, height, alpha ? FXDIB_Argb : FXDIB_Rgb32)) {
784 return NULL;
785 }
786 return pBitmap.release();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700787}
788
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700789DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_CreateEx(int width,
790 int height,
791 int format,
792 void* first_scan,
793 int stride) {
794 FXDIB_Format fx_format;
795 switch (format) {
796 case FPDFBitmap_Gray:
797 fx_format = FXDIB_8bppRgb;
798 break;
799 case FPDFBitmap_BGR:
800 fx_format = FXDIB_Rgb;
801 break;
802 case FPDFBitmap_BGRx:
803 fx_format = FXDIB_Rgb32;
804 break;
805 case FPDFBitmap_BGRA:
806 fx_format = FXDIB_Argb;
807 break;
808 default:
809 return NULL;
810 }
811 CFX_DIBitmap* pBitmap = new CFX_DIBitmap;
812 pBitmap->Create(width, height, fx_format, (uint8_t*)first_scan, stride);
813 return pBitmap;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700814}
815
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700816DLLEXPORT void STDCALL FPDFBitmap_FillRect(FPDF_BITMAP bitmap,
817 int left,
818 int top,
819 int width,
820 int height,
821 FPDF_DWORD color) {
Lei Zhang412e9082015-12-14 18:34:00 -0800822 if (!bitmap)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700823 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700824 CFX_FxgeDevice device;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700825 device.Attach((CFX_DIBitmap*)bitmap);
826 if (!((CFX_DIBitmap*)bitmap)->HasAlpha())
827 color |= 0xFF000000;
828 FX_RECT rect(left, top, left + width, top + height);
829 device.FillRect(&rect, color);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700830}
831
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700832DLLEXPORT void* STDCALL FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap) {
Lei Zhang412e9082015-12-14 18:34:00 -0800833 return bitmap ? ((CFX_DIBitmap*)bitmap)->GetBuffer() : nullptr;
Bo Xu9114e832014-07-14 13:22:47 -0700834}
835
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700836DLLEXPORT int STDCALL FPDFBitmap_GetWidth(FPDF_BITMAP bitmap) {
Lei Zhang412e9082015-12-14 18:34:00 -0800837 return bitmap ? ((CFX_DIBitmap*)bitmap)->GetWidth() : 0;
Bo Xu9114e832014-07-14 13:22:47 -0700838}
839
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700840DLLEXPORT int STDCALL FPDFBitmap_GetHeight(FPDF_BITMAP bitmap) {
Lei Zhang412e9082015-12-14 18:34:00 -0800841 return bitmap ? ((CFX_DIBitmap*)bitmap)->GetHeight() : 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700842}
843
844DLLEXPORT int STDCALL FPDFBitmap_GetStride(FPDF_BITMAP bitmap) {
Lei Zhang412e9082015-12-14 18:34:00 -0800845 return bitmap ? ((CFX_DIBitmap*)bitmap)->GetPitch() : 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700846}
847
848DLLEXPORT void STDCALL FPDFBitmap_Destroy(FPDF_BITMAP bitmap) {
849 delete (CFX_DIBitmap*)bitmap;
850}
851
852void FPDF_RenderPage_Retail(CRenderContext* pContext,
853 FPDF_PAGE page,
854 int start_x,
855 int start_y,
856 int size_x,
857 int size_y,
858 int rotate,
859 int flags,
860 FX_BOOL bNeedToRestore,
861 IFSDK_PAUSE_Adapter* pause) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700862 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
863 if (!pPage)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700864 return;
865
866 if (!pContext->m_pOptions)
867 pContext->m_pOptions = new CPDF_RenderOptions;
868
869 if (flags & FPDF_LCD_TEXT)
870 pContext->m_pOptions->m_Flags |= RENDER_CLEARTYPE;
871 else
872 pContext->m_pOptions->m_Flags &= ~RENDER_CLEARTYPE;
873 if (flags & FPDF_NO_NATIVETEXT)
874 pContext->m_pOptions->m_Flags |= RENDER_NO_NATIVETEXT;
875 if (flags & FPDF_RENDER_LIMITEDIMAGECACHE)
876 pContext->m_pOptions->m_Flags |= RENDER_LIMITEDIMAGECACHE;
877 if (flags & FPDF_RENDER_FORCEHALFTONE)
878 pContext->m_pOptions->m_Flags |= RENDER_FORCE_HALFTONE;
Tom Sepez51da0932015-11-25 16:05:49 -0800879#ifndef PDF_ENABLE_XFA
880 if (flags & FPDF_RENDER_NO_SMOOTHTEXT)
881 pContext->m_pOptions->m_Flags |= RENDER_NOTEXTSMOOTH;
882 if (flags & FPDF_RENDER_NO_SMOOTHIMAGE)
883 pContext->m_pOptions->m_Flags |= RENDER_NOIMAGESMOOTH;
884 if (flags & FPDF_RENDER_NO_SMOOTHPATH)
885 pContext->m_pOptions->m_Flags |= RENDER_NOPATHSMOOTH;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800886#endif // PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700887 // Grayscale output
888 if (flags & FPDF_GRAYSCALE) {
889 pContext->m_pOptions->m_ColorMode = RENDER_COLOR_GRAY;
890 pContext->m_pOptions->m_ForeColor = 0;
891 pContext->m_pOptions->m_BackColor = 0xffffff;
892 }
893 const CPDF_OCContext::UsageType usage =
894 (flags & FPDF_PRINTING) ? CPDF_OCContext::Print : CPDF_OCContext::View;
895 pContext->m_pOptions->m_AddFlags = flags >> 8;
896 pContext->m_pOptions->m_pOCContext =
897 new CPDF_OCContext(pPage->m_pDocument, usage);
898
Tom Sepez60d909e2015-12-10 15:34:55 -0800899 CFX_Matrix matrix;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700900 pPage->GetDisplayMatrix(matrix, start_x, start_y, size_x, size_y, rotate);
901
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700902 pContext->m_pDevice->SaveState();
Tom Sepezbec4ea12016-02-29 13:23:13 -0800903 pContext->m_pDevice->SetClip_Rect(
904 FX_RECT(start_x, start_y, start_x + size_x, start_y + size_y));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700905
Tom Sepez979ddd82015-12-17 13:41:13 -0800906 pContext->m_pContext = new CPDF_RenderContext(pPage);
Tom Sepez71fdc342016-01-22 12:06:32 -0800907 pContext->m_pContext->AppendLayer(pPage, &matrix);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700908
909 if (flags & FPDF_ANNOT) {
Tom Sepezae51c812015-08-05 12:34:06 -0700910 pContext->m_pAnnots = new CPDF_AnnotList(pPage);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700911 FX_BOOL bPrinting = pContext->m_pDevice->GetDeviceClass() != FXDC_DISPLAY;
912 pContext->m_pAnnots->DisplayAnnots(pPage, pContext->m_pContext, bPrinting,
913 &matrix, TRUE, NULL);
914 }
915
Tom Sepezb3b67622015-10-19 16:20:03 -0700916 pContext->m_pRenderer = new CPDF_ProgressiveRenderer(
917 pContext->m_pContext, pContext->m_pDevice, pContext->m_pOptions);
918 pContext->m_pRenderer->Start(pause);
Tom Sepezc7e4c4f2015-11-20 09:45:24 -0800919 if (bNeedToRestore)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700920 pContext->m_pDevice->RestoreState();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700921}
922
923DLLEXPORT int STDCALL FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document,
924 int page_index,
925 double* width,
926 double* height) {
Tom Sepez540c4362015-11-24 13:33:57 -0800927 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
928 if (!pDoc)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700929 return FALSE;
930
Tom Sepez40e9ff32015-11-30 12:39:54 -0800931#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700932 int count = pDoc->GetPageCount();
933 if (page_index < 0 || page_index >= count)
934 return FALSE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700935 CPDFXFA_Page* pPage = pDoc->GetPage(page_index);
936 if (!pPage)
937 return FALSE;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800938 *width = pPage->GetPageWidth();
939 *height = pPage->GetPageHeight();
940#else // PDF_ENABLE_XFA
941 CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
942 if (!pDict)
943 return FALSE;
thestig5cc24652016-04-26 11:46:02 -0700944
945 CPDF_Page page(pDoc, pDict, true);
Tom Sepez51da0932015-11-25 16:05:49 -0800946 *width = page.GetPageWidth();
947 *height = page.GetPageHeight();
Tom Sepez40e9ff32015-11-30 12:39:54 -0800948#endif // PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700949
950 return TRUE;
951}
952
953DLLEXPORT FPDF_BOOL STDCALL
954FPDF_VIEWERREF_GetPrintScaling(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700955 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700956 if (!pDoc)
957 return TRUE;
Tom Sepez471a1032015-10-15 16:17:18 -0700958 CPDF_ViewerPreferences viewRef(pDoc);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700959 return viewRef.PrintScaling();
960}
961
962DLLEXPORT int STDCALL FPDF_VIEWERREF_GetNumCopies(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700963 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700964 if (!pDoc)
965 return 1;
966 CPDF_ViewerPreferences viewRef(pDoc);
967 return viewRef.NumCopies();
968}
969
970DLLEXPORT FPDF_PAGERANGE STDCALL
971FPDF_VIEWERREF_GetPrintPageRange(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700972 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700973 if (!pDoc)
974 return NULL;
975 CPDF_ViewerPreferences viewRef(pDoc);
976 return viewRef.PrintPageRange();
977}
978
979DLLEXPORT FPDF_DUPLEXTYPE STDCALL
980FPDF_VIEWERREF_GetDuplex(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700981 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700982 if (!pDoc)
Bo Xu9114e832014-07-14 13:22:47 -0700983 return DuplexUndefined;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700984 CPDF_ViewerPreferences viewRef(pDoc);
985 CFX_ByteString duplex = viewRef.Duplex();
Lei Zhangd983b092015-12-14 16:58:33 -0800986 if ("Simplex" == duplex)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700987 return Simplex;
Lei Zhangd983b092015-12-14 16:58:33 -0800988 if ("DuplexFlipShortEdge" == duplex)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700989 return DuplexFlipShortEdge;
Lei Zhangd983b092015-12-14 16:58:33 -0800990 if ("DuplexFlipLongEdge" == duplex)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700991 return DuplexFlipLongEdge;
992 return DuplexUndefined;
Bo Xu9114e832014-07-14 13:22:47 -0700993}
994
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700995DLLEXPORT FPDF_DWORD STDCALL FPDF_CountNamedDests(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700996 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
997 if (!pDoc)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700998 return 0;
Bo Xu4d62b6b2015-01-10 22:52:59 -0800999
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001000 CPDF_Dictionary* pRoot = pDoc->GetRoot();
1001 if (!pRoot)
1002 return 0;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001003
Lei Zhangd983b092015-12-14 16:58:33 -08001004 CPDF_NameTree nameTree(pDoc, "Dests");
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001005 pdfium::base::CheckedNumeric<FPDF_DWORD> count = nameTree.GetCount();
Wei Li9b761132016-01-29 15:44:20 -08001006 CPDF_Dictionary* pDest = pRoot->GetDictBy("Dests");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001007 if (pDest)
1008 count += pDest->GetCount();
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001009
1010 if (!count.IsValid())
1011 return 0;
1012
1013 return count.ValueOrDie();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001014}
1015
1016DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDestByName(FPDF_DOCUMENT document,
1017 FPDF_BYTESTRING name) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001018 if (!name || name[0] == 0)
Tom Sepez471a1032015-10-15 16:17:18 -07001019 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001020
Tom Sepez471a1032015-10-15 16:17:18 -07001021 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1022 if (!pDoc)
1023 return nullptr;
1024
Lei Zhangd983b092015-12-14 16:58:33 -08001025 CPDF_NameTree name_tree(pDoc, "Dests");
Tom Sepez471a1032015-10-15 16:17:18 -07001026 return name_tree.LookupNamedDest(pDoc, name);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001027}
1028
Tom Sepez51da0932015-11-25 16:05:49 -08001029#ifdef PDF_ENABLE_XFA
thestig77d148d2016-04-06 06:28:31 -07001030DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Init(FPDF_BSTR* str) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001031 if (!str)
1032 return -1;
1033
1034 FXSYS_memset(str, 0, sizeof(FPDF_BSTR));
1035 return 0;
1036}
1037
thestig77d148d2016-04-06 06:28:31 -07001038DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Set(FPDF_BSTR* str,
1039 FPDF_LPCSTR bstr,
1040 int length) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001041 if (!str)
1042 return -1;
1043 if (!bstr || !length)
1044 return -1;
1045 if (length == -1)
1046 length = FXSYS_strlen(bstr);
1047
1048 if (length == 0) {
1049 if (str->str) {
1050 FX_Free(str->str);
1051 str->str = NULL;
1052 }
1053 str->len = 0;
1054 return 0;
1055 }
1056
1057 if (str->str && str->len < length)
1058 str->str = FX_Realloc(char, str->str, length + 1);
1059 else if (!str->str)
1060 str->str = FX_Alloc(char, length + 1);
1061
1062 str->str[length] = 0;
1063 if (str->str == NULL)
1064 return -1;
1065
1066 FXSYS_memcpy(str->str, bstr, length);
1067 str->len = length;
1068
1069 return 0;
1070}
1071
thestig77d148d2016-04-06 06:28:31 -07001072DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Clear(FPDF_BSTR* str) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001073 if (!str)
1074 return -1;
1075
1076 if (str->str) {
1077 FX_Free(str->str);
1078 str->str = NULL;
1079 }
1080 str->len = 0;
1081 return 0;
1082}
Tom Sepez40e9ff32015-11-30 12:39:54 -08001083#endif // PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001084
1085DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDest(FPDF_DOCUMENT document,
1086 int index,
1087 void* buffer,
1088 long* buflen) {
1089 if (!buffer)
1090 *buflen = 0;
Tom Sepez540c4362015-11-24 13:33:57 -08001091
1092 if (index < 0)
1093 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001094
Tom Sepezbf59a072015-10-21 14:07:23 -07001095 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Tom Sepez540c4362015-11-24 13:33:57 -08001096 if (!pDoc)
1097 return nullptr;
1098
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001099 CPDF_Dictionary* pRoot = pDoc->GetRoot();
1100 if (!pRoot)
Tom Sepez540c4362015-11-24 13:33:57 -08001101 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001102
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001103 CPDF_Object* pDestObj = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001104 CFX_ByteString bsName;
Lei Zhangd983b092015-12-14 16:58:33 -08001105 CPDF_NameTree nameTree(pDoc, "Dests");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001106 int count = nameTree.GetCount();
1107 if (index >= count) {
Wei Li9b761132016-01-29 15:44:20 -08001108 CPDF_Dictionary* pDest = pRoot->GetDictBy("Dests");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001109 if (!pDest)
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001110 return nullptr;
1111
1112 pdfium::base::CheckedNumeric<int> checked_count = count;
1113 checked_count += pDest->GetCount();
1114 if (!checked_count.IsValid() || index >= checked_count.ValueOrDie())
1115 return nullptr;
1116
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001117 index -= count;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001118 int i = 0;
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001119 for (const auto& it : *pDest) {
1120 bsName = it.first;
1121 pDestObj = it.second;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001122 if (!pDestObj)
1123 continue;
1124 if (i == index)
1125 break;
1126 i++;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001127 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001128 } else {
1129 pDestObj = nameTree.LookupValue(index, bsName);
1130 }
1131 if (!pDestObj)
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001132 return nullptr;
Dan Sinclairf1251c12015-10-20 16:24:45 -04001133 if (CPDF_Dictionary* pDict = pDestObj->AsDictionary()) {
Wei Li9b761132016-01-29 15:44:20 -08001134 pDestObj = pDict->GetArrayBy("D");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001135 if (!pDestObj)
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001136 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001137 }
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001138 if (!pDestObj->IsArray())
1139 return nullptr;
1140
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001141 CFX_WideString wsName = PDF_DecodeText(bsName);
1142 CFX_ByteString utf16Name = wsName.UTF16LE_Encode();
weili47ca6922016-03-31 15:08:27 -07001143 int len = utf16Name.GetLength();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001144 if (!buffer) {
1145 *buflen = len;
1146 } else if (*buflen >= len) {
1147 memcpy(buffer, utf16Name.c_str(), len);
1148 *buflen = len;
1149 } else {
1150 *buflen = -1;
1151 }
1152 return (FPDF_DEST)pDestObj;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001153}