blob: d47e2b02da539ebbf00800c74d4ca3fad2dd3958 [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
Tom Sepez51da0932015-11-25 16:05:49 -08009#ifdef PDF_ENABLE_XFA
Lei Zhanga688a042015-11-09 13:57:49 -080010#include "../include/fpdfxfa/fpdfxfa_app.h"
11#include "../include/fpdfxfa/fpdfxfa_doc.h"
12#include "../include/fpdfxfa/fpdfxfa_page.h"
13#include "../include/fpdfxfa/fpdfxfa_util.h"
Lei Zhanga688a042015-11-09 13:57:49 -080014#include "core/include/fpdfapi/fpdf_module.h"
Tom Sepez51da0932015-11-25 16:05:49 -080015#endif
Lei Zhanga688a042015-11-09 13:57:49 -080016#include "core/include/fxcodec/fx_codec.h"
17#include "core/include/fxcrt/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"
21#include "fpdfsdk/include/javascript/IJavaScript.h"
Lei Zhangb4e7f302015-11-06 15:52:32 -080022#include "public/fpdf_ext.h"
Tom Sepez51da0932015-11-25 16:05:49 -080023#ifdef PDF_ENABLE_XFA
Lei Zhangb4e7f302015-11-06 15:52:32 -080024#include "public/fpdf_formfill.h"
Tom Sepez51da0932015-11-25 16:05:49 -080025#endif
Lei Zhangb4e7f302015-11-06 15:52:32 -080026#include "public/fpdf_progressive.h"
Lei Zhang8241df72015-11-06 14:38:48 -080027#include "third_party/base/nonstd_unique_ptr.h"
28#include "third_party/base/numerics/safe_conversions_impl.h"
Bo Xufdc00a72014-10-28 23:03:33 -070029
Tom Sepez50d12ad2015-11-24 09:50:51 -080030UnderlyingDocumentType* UnderlyingFromFPDFDocument(FPDF_DOCUMENT doc) {
31 return static_cast<UnderlyingDocumentType*>(doc);
32}
33
34FPDF_DOCUMENT FPDFDocumentFromUnderlying(UnderlyingDocumentType* doc) {
35 return static_cast<FPDF_DOCUMENT>(doc);
36}
37
38UnderlyingPageType* UnderlyingFromFPDFPage(FPDF_PAGE page) {
39 return static_cast<UnderlyingPageType*>(page);
40}
41
Tom Sepez471a1032015-10-15 16:17:18 -070042CPDF_Document* CPDFDocumentFromFPDFDocument(FPDF_DOCUMENT doc) {
Tom Sepez51da0932015-11-25 16:05:49 -080043#ifndef PDF_ENABLE_XFA
44 return UnderlyingFromFPDFDocument(doc);
45#else
Tom Sepez50d12ad2015-11-24 09:50:51 -080046 return doc ? UnderlyingFromFPDFDocument(doc)->GetPDFDoc() : nullptr;
Tom Sepez51da0932015-11-25 16:05:49 -080047#endif
Tom Sepez471a1032015-10-15 16:17:18 -070048}
49
Tom Sepezbf59a072015-10-21 14:07:23 -070050FPDF_DOCUMENT FPDFDocumentFromCPDFDocument(CPDF_Document* doc) {
Tom Sepez51da0932015-11-25 16:05:49 -080051#ifndef PDF_ENABLE_XFA
52 return FPDFDocumentFromUnderlying(doc);
53#else
Tom Sepez50d12ad2015-11-24 09:50:51 -080054 return doc ? FPDFDocumentFromUnderlying(
55 new CPDFXFA_Document(doc, CPDFXFA_App::GetInstance()))
56 : nullptr;
Tom Sepez51da0932015-11-25 16:05:49 -080057#endif
Tom Sepezbf59a072015-10-21 14:07:23 -070058}
59
Tom Sepezdb0be962015-10-16 14:00:21 -070060CPDF_Page* CPDFPageFromFPDFPage(FPDF_PAGE page) {
Tom Sepez51da0932015-11-25 16:05:49 -080061#ifndef PDF_ENABLE_XFA
62 return UnderlyingFromFPDFPage(page);
63#else
Tom Sepez50d12ad2015-11-24 09:50:51 -080064 return page ? UnderlyingFromFPDFPage(page)->GetPDFPage() : nullptr;
Tom Sepezdb0be962015-10-16 14:00:21 -070065}
66
Nico Weber9d8ec5a2015-08-04 13:00:21 -070067CFPDF_FileStream::CFPDF_FileStream(FPDF_FILEHANDLER* pFS) {
68 m_pFS = pFS;
69 m_nCurPos = 0;
Bo Xufdc00a72014-10-28 23:03:33 -070070}
71
Nico Weber9d8ec5a2015-08-04 13:00:21 -070072IFX_FileStream* CFPDF_FileStream::Retain() {
73 return this;
Bo Xufdc00a72014-10-28 23:03:33 -070074}
75
Nico Weber9d8ec5a2015-08-04 13:00:21 -070076void CFPDF_FileStream::Release() {
77 if (m_pFS && m_pFS->Release)
78 m_pFS->Release(m_pFS->clientData);
79 delete this;
Bo Xufdc00a72014-10-28 23:03:33 -070080}
81
Nico Weber9d8ec5a2015-08-04 13:00:21 -070082FX_FILESIZE CFPDF_FileStream::GetSize() {
83 if (m_pFS && m_pFS->GetSize)
84 return (FX_FILESIZE)m_pFS->GetSize(m_pFS->clientData);
85 return 0;
Bo Xufdc00a72014-10-28 23:03:33 -070086}
87
Nico Weber9d8ec5a2015-08-04 13:00:21 -070088FX_BOOL CFPDF_FileStream::IsEOF() {
89 return m_nCurPos >= GetSize();
Bo Xufdc00a72014-10-28 23:03:33 -070090}
91
Nico Weber9d8ec5a2015-08-04 13:00:21 -070092FX_BOOL CFPDF_FileStream::ReadBlock(void* buffer,
93 FX_FILESIZE offset,
94 size_t size) {
95 if (!buffer || !size || !m_pFS->ReadBlock)
96 return FALSE;
Bo Xufdc00a72014-10-28 23:03:33 -070097
Nico Weber9d8ec5a2015-08-04 13:00:21 -070098 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
99 (FPDF_DWORD)size) == 0) {
100 m_nCurPos = offset + size;
101 return TRUE;
102 }
103 return FALSE;
Bo Xufdc00a72014-10-28 23:03:33 -0700104}
105
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700106size_t CFPDF_FileStream::ReadBlock(void* buffer, size_t size) {
107 if (!buffer || !size || !m_pFS->ReadBlock)
108 return 0;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700109
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700110 FX_FILESIZE nSize = GetSize();
111 if (m_nCurPos >= nSize)
112 return 0;
113 FX_FILESIZE dwAvail = nSize - m_nCurPos;
114 if (dwAvail < (FX_FILESIZE)size)
115 size = (size_t)dwAvail;
116 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)m_nCurPos, buffer,
117 (FPDF_DWORD)size) == 0) {
118 m_nCurPos += size;
119 return size;
120 }
Bo Xufdc00a72014-10-28 23:03:33 -0700121
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700122 return 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700123}
124
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700125FX_BOOL CFPDF_FileStream::WriteBlock(const void* buffer,
126 FX_FILESIZE offset,
127 size_t size) {
128 if (!m_pFS || !m_pFS->WriteBlock)
129 return FALSE;
Bo Xufdc00a72014-10-28 23:03:33 -0700130
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700131 if (m_pFS->WriteBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
132 (FPDF_DWORD)size) == 0) {
133 m_nCurPos = offset + size;
134 return TRUE;
135 }
136 return FALSE;
Bo Xufdc00a72014-10-28 23:03:33 -0700137}
138
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700139FX_BOOL CFPDF_FileStream::Flush() {
140 if (!m_pFS || !m_pFS->Flush)
141 return TRUE;
Bo Xufdc00a72014-10-28 23:03:33 -0700142
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700143 return m_pFS->Flush(m_pFS->clientData) == 0;
Tom Sepez51da0932015-11-25 16:05:49 -0800144#endif
Bo Xufdc00a72014-10-28 23:03:33 -0700145}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700146
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700147CPDF_CustomAccess::CPDF_CustomAccess(FPDF_FILEACCESS* pFileAccess) {
148 m_FileAccess = *pFileAccess;
Tom Sepez51da0932015-11-25 16:05:49 -0800149#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700150 m_BufferOffset = (FX_DWORD)-1;
Bo Xufdc00a72014-10-28 23:03:33 -0700151}
152
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700153FX_BOOL CPDF_CustomAccess::GetByte(FX_DWORD pos, uint8_t& ch) {
154 if (pos >= m_FileAccess.m_FileLen)
155 return FALSE;
156 if (m_BufferOffset == (FX_DWORD)-1 || pos < m_BufferOffset ||
157 pos >= m_BufferOffset + 512) {
158 // Need to read from file access
159 m_BufferOffset = pos;
160 int size = 512;
161 if (pos + 512 > m_FileAccess.m_FileLen)
162 size = m_FileAccess.m_FileLen - pos;
163 if (!m_FileAccess.m_GetBlock(m_FileAccess.m_Param, m_BufferOffset, m_Buffer,
164 size))
165 return FALSE;
166 }
167 ch = m_Buffer[pos - m_BufferOffset];
168 return TRUE;
Bo Xufdc00a72014-10-28 23:03:33 -0700169}
170
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700171FX_BOOL CPDF_CustomAccess::GetBlock(FX_DWORD pos,
172 uint8_t* pBuf,
173 FX_DWORD size) {
174 if (pos + size > m_FileAccess.m_FileLen)
175 return FALSE;
176 return m_FileAccess.m_GetBlock(m_FileAccess.m_Param, pos, pBuf, size);
Tom Sepez51da0932015-11-25 16:05:49 -0800177#endif
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700178}
179
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700180FX_BOOL CPDF_CustomAccess::ReadBlock(void* buffer,
181 FX_FILESIZE offset,
182 size_t size) {
183 if (offset < 0) {
184 return FALSE;
185 }
186 FX_SAFE_FILESIZE newPos =
187 pdfium::base::checked_cast<FX_FILESIZE, size_t>(size);
188 newPos += offset;
189 if (!newPos.IsValid() || newPos.ValueOrDie() > m_FileAccess.m_FileLen) {
190 return FALSE;
191 }
192 return m_FileAccess.m_GetBlock(m_FileAccess.m_Param, offset, (uint8_t*)buffer,
193 size);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700194}
195
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700196// 0 bit: FPDF_POLICY_MACHINETIME_ACCESS
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700197static FX_DWORD foxit_sandbox_policy = 0xFFFFFFFF;
198
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700199void FSDK_SetSandBoxPolicy(FPDF_DWORD policy, FPDF_BOOL enable) {
200 switch (policy) {
201 case FPDF_POLICY_MACHINETIME_ACCESS: {
202 if (enable)
203 foxit_sandbox_policy |= 0x01;
204 else
205 foxit_sandbox_policy &= 0xFFFFFFFE;
206 } break;
207 default:
208 break;
209 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700210}
211
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700212FPDF_BOOL FSDK_IsSandBoxPolicyEnabled(FPDF_DWORD policy) {
213 switch (policy) {
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700214 case FPDF_POLICY_MACHINETIME_ACCESS:
Lei Zhangb0748bb2015-10-19 12:11:49 -0700215 return !!(foxit_sandbox_policy & 0x01);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700216 default:
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700217 return FALSE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700218 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700219}
220
Tom Sepez2c286192015-06-18 12:47:11 -0700221CCodec_ModuleMgr* g_pCodecModule = nullptr;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700222
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700223DLLEXPORT void STDCALL FPDF_InitLibrary() {
Lei Zhang6f62d532015-09-23 15:31:44 -0700224 FPDF_InitLibraryWithConfig(nullptr);
225}
226
Tom Sepezc7e4c4f2015-11-20 09:45:24 -0800227DLLEXPORT void STDCALL FPDF_InitLibraryWithConfig(
228 const FPDF_LIBRARY_CONFIG* cfg) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700229 g_pCodecModule = new CCodec_ModuleMgr();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700230
Lei Zhang6f62d532015-09-23 15:31:44 -0700231 CFX_GEModule::Create(cfg ? cfg->m_pUserFontPaths : nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700232 CFX_GEModule::Get()->SetCodecModule(g_pCodecModule);
Tom Sepezbdeeb8a2015-05-27 12:25:00 -0700233
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700234 CPDF_ModuleMgr::Create();
Tom Sepez1b246282015-11-25 15:15:31 -0800235 CPDF_ModuleMgr* pModuleMgr = CPDF_ModuleMgr::Get();
236 pModuleMgr->SetCodecModule(g_pCodecModule);
237 pModuleMgr->InitPageModule();
238 pModuleMgr->InitRenderModule();
Tom Sepez51da0932015-11-25 16:05:49 -0800239#ifndef PDF_ENABLE_XFA
240 pModuleMgr->LoadEmbeddedGB1CMaps();
241 pModuleMgr->LoadEmbeddedJapan1CMaps();
242 pModuleMgr->LoadEmbeddedCNS1CMaps();
243 pModuleMgr->LoadEmbeddedKorea1CMaps();
244#else
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700245 CPDFXFA_App::GetInstance()->Initialize();
Tom Sepez51da0932015-11-25 16:05:49 -0800246#endif
Tom Sepez452b4f32015-10-13 09:27:27 -0700247 if (cfg && cfg->version >= 2)
248 IJS_Runtime::Initialize(cfg->m_v8EmbedderSlot, cfg->m_pIsolate);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700249}
250
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700251DLLEXPORT void STDCALL FPDF_DestroyLibrary() {
Tom Sepez51da0932015-11-25 16:05:49 -0800252#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700253 CPDFXFA_App::ReleaseInstance();
Tom Sepez51da0932015-11-25 16:05:49 -0800254#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700255 CPDF_ModuleMgr::Destroy();
256 CFX_GEModule::Destroy();
Tom Sepez2c286192015-06-18 12:47:11 -0700257
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700258 delete g_pCodecModule;
259 g_pCodecModule = nullptr;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700260}
261
262#ifndef _WIN32
263int g_LastError;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700264void SetLastError(int err) {
265 g_LastError = err;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700266}
267
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700268int GetLastError() {
269 return g_LastError;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700270}
271#endif
272
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700273void ProcessParseError(FX_DWORD err_code) {
274 // Translate FPDFAPI error code to FPDFVIEW error code
275 switch (err_code) {
276 case PDFPARSE_ERROR_FILE:
277 err_code = FPDF_ERR_FILE;
278 break;
279 case PDFPARSE_ERROR_FORMAT:
280 err_code = FPDF_ERR_FORMAT;
281 break;
282 case PDFPARSE_ERROR_PASSWORD:
283 err_code = FPDF_ERR_PASSWORD;
284 break;
285 case PDFPARSE_ERROR_HANDLER:
286 err_code = FPDF_ERR_SECURITY;
287 break;
288 }
289 SetLastError(err_code);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700290}
291
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700292DLLEXPORT void STDCALL FPDF_SetSandBoxPolicy(FPDF_DWORD policy,
293 FPDF_BOOL enable) {
294 return FSDK_SetSandBoxPolicy(policy, enable);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700295}
296
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700297DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadDocument(FPDF_STRING file_path,
298 FPDF_BYTESTRING password) {
Tom Sepeze3166a82015-08-05 10:50:32 -0700299 // NOTE: the creation of the file needs to be by the embedder on the
300 // other side of this API.
301 IFX_FileRead* pFileAccess = FX_CreateFileRead((const FX_CHAR*)file_path);
302 if (!pFileAccess) {
303 return nullptr;
304 }
305
306 CPDF_Parser* pParser = new CPDF_Parser;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700307 pParser->SetPassword(password);
Bo Xud4e406e2014-08-13 11:03:19 -0700308
Tom Sepeze3166a82015-08-05 10:50:32 -0700309 FX_DWORD err_code = pParser->StartParse(pFileAccess);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700310 if (err_code) {
311 delete pParser;
312 ProcessParseError(err_code);
313 return NULL;
314 }
Tom Sepez51da0932015-11-25 16:05:49 -0800315#ifndef PDF_ENABLE_XFA
316 return pParser->GetDocument();
317#else
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700318 CPDF_Document* pPDFDoc = pParser->GetDocument();
319 if (!pPDFDoc)
320 return NULL;
Bo Xufdc00a72014-10-28 23:03:33 -0700321
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700322 CPDFXFA_App* pProvider = CPDFXFA_App::GetInstance();
Lei Zhangcb78ef52015-10-02 10:10:49 -0700323 return new CPDFXFA_Document(pPDFDoc, pProvider);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700324}
Jun Fange118ce92015-02-17 06:50:08 -0800325
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700326DLLEXPORT FPDF_BOOL STDCALL FPDF_HasXFAField(FPDF_DOCUMENT document,
327 int* docType) {
328 if (!document)
329 return FALSE;
JUN FANG827a1722015-03-05 13:39:21 -0800330
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700331 CPDF_Document* pdfDoc =
332 (static_cast<CPDFXFA_Document*>(document))->GetPDFDoc();
333 if (!pdfDoc)
334 return FALSE;
JUN FANG827a1722015-03-05 13:39:21 -0800335
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700336 CPDF_Dictionary* pRoot = pdfDoc->GetRoot();
337 if (!pRoot)
338 return FALSE;
JUN FANG827a1722015-03-05 13:39:21 -0800339
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700340 CPDF_Dictionary* pAcroForm = pRoot->GetDict("AcroForm");
341 if (!pAcroForm)
342 return FALSE;
JUN FANG827a1722015-03-05 13:39:21 -0800343
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700344 CPDF_Object* pXFA = pAcroForm->GetElement("XFA");
345 if (!pXFA)
346 return FALSE;
JUN FANG827a1722015-03-05 13:39:21 -0800347
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700348 FX_BOOL bDynamicXFA = pRoot->GetBoolean("NeedsRendering", FALSE);
JUN FANG827a1722015-03-05 13:39:21 -0800349
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700350 if (bDynamicXFA)
Tom Sepezd3116dc2015-11-24 15:58:06 -0800351 *docType = DOCTYPE_DYNAMIC_XFA;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700352 else
353 *docType = DOCTYPE_STATIC_XFA;
JUN FANG827a1722015-03-05 13:39:21 -0800354
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700355 return TRUE;
Jun Fange118ce92015-02-17 06:50:08 -0800356}
357
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700358DLLEXPORT FPDF_BOOL STDCALL FPDF_LoadXFA(FPDF_DOCUMENT document) {
359 return document && (static_cast<CPDFXFA_Document*>(document))->LoadXFADoc();
Tom Sepez51da0932015-11-25 16:05:49 -0800360#endif
Bo Xufdc00a72014-10-28 23:03:33 -0700361}
362
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700363class CMemFile final : public IFX_FileRead {
364 public:
365 CMemFile(uint8_t* pBuf, FX_FILESIZE size) : m_pBuf(pBuf), m_size(size) {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700366
Lei Zhang3884dba2015-10-19 17:27:53 -0700367 void Release() override { delete this; }
368 FX_FILESIZE GetSize() override { return m_size; }
369 FX_BOOL ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700370 if (offset < 0) {
371 return FALSE;
372 }
373 FX_SAFE_FILESIZE newPos =
374 pdfium::base::checked_cast<FX_FILESIZE, size_t>(size);
375 newPos += offset;
376 if (!newPos.IsValid() || newPos.ValueOrDie() > (FX_DWORD)m_size) {
377 return FALSE;
378 }
379 FXSYS_memcpy(buffer, m_pBuf + offset, size);
380 return TRUE;
381 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700382
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700383 private:
Lei Zhang2b1a2d52015-08-14 22:16:22 -0700384 ~CMemFile() override {}
385
Lei Zhang3884dba2015-10-19 17:27:53 -0700386 uint8_t* const m_pBuf;
387 const FX_FILESIZE m_size;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700388};
Lei Zhang3884dba2015-10-19 17:27:53 -0700389
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700390DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadMemDocument(const void* data_buf,
391 int size,
392 FPDF_BYTESTRING password) {
Tom Sepezae51c812015-08-05 12:34:06 -0700393 CPDF_Parser* pParser = new CPDF_Parser;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700394 pParser->SetPassword(password);
395 CMemFile* pMemFile = new CMemFile((uint8_t*)data_buf, size);
396 FX_DWORD err_code = pParser->StartParse(pMemFile);
397 if (err_code) {
398 delete pParser;
399 ProcessParseError(err_code);
400 return NULL;
401 }
402 CPDF_Document* pDoc = NULL;
403 pDoc = pParser ? pParser->GetDocument() : NULL;
404 CheckUnSupportError(pDoc, err_code);
Tom Sepezbf59a072015-10-21 14:07:23 -0700405 return FPDFDocumentFromCPDFDocument(pParser->GetDocument());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700406}
407
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700408DLLEXPORT FPDF_DOCUMENT STDCALL
409FPDF_LoadCustomDocument(FPDF_FILEACCESS* pFileAccess,
410 FPDF_BYTESTRING password) {
Tom Sepezae51c812015-08-05 12:34:06 -0700411 CPDF_Parser* pParser = new CPDF_Parser;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700412 pParser->SetPassword(password);
Tom Sepezae51c812015-08-05 12:34:06 -0700413 CPDF_CustomAccess* pFile = new CPDF_CustomAccess(pFileAccess);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700414 FX_DWORD err_code = pParser->StartParse(pFile);
415 if (err_code) {
416 delete pParser;
417 ProcessParseError(err_code);
418 return NULL;
419 }
420 CPDF_Document* pDoc = NULL;
421 pDoc = pParser ? pParser->GetDocument() : NULL;
422 CheckUnSupportError(pDoc, err_code);
Tom Sepezbf59a072015-10-21 14:07:23 -0700423 return FPDFDocumentFromCPDFDocument(pParser->GetDocument());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700424}
425
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700426DLLEXPORT FPDF_BOOL STDCALL FPDF_GetFileVersion(FPDF_DOCUMENT doc,
427 int* fileVersion) {
Tom Sepez471a1032015-10-15 16:17:18 -0700428 if (!fileVersion)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700429 return FALSE;
Bo Xufdc00a72014-10-28 23:03:33 -0700430
Tom Sepez471a1032015-10-15 16:17:18 -0700431 *fileVersion = 0;
432 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(doc);
433 if (!pDoc)
434 return FALSE;
435
436 CPDF_Parser* pParser = pDoc->GetParser();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700437 if (!pParser)
438 return FALSE;
Tom Sepez471a1032015-10-15 16:17:18 -0700439
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700440 *fileVersion = pParser->GetFileVersion();
441 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700442}
443
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700444// jabdelmalek: changed return type from FX_DWORD to build on Linux (and match
445// header).
446DLLEXPORT unsigned long STDCALL FPDF_GetDocPermissions(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700447 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
448 if (!pDoc)
Tom Sepez51da0932015-11-25 16:05:49 -0800449#ifndef PDF_ENABLE_XFA
450 return 0;
451#else
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700452 return (FX_DWORD)-1;
Tom Sepez51da0932015-11-25 16:05:49 -0800453#endif
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700454
Tom Sepez471a1032015-10-15 16:17:18 -0700455 CPDF_Dictionary* pDict = pDoc->GetParser()->GetEncryptDict();
456 return pDict ? pDict->GetInteger("P") : (FX_DWORD)-1;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700457}
458
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700459DLLEXPORT int STDCALL FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700460 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
461 if (!pDoc)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700462 return -1;
Bo Xuc5cab022014-09-19 19:16:31 -0700463
Tom Sepez471a1032015-10-15 16:17:18 -0700464 CPDF_Dictionary* pDict = pDoc->GetParser()->GetEncryptDict();
465 return pDict ? pDict->GetInteger("R") : -1;
Bo Xuc5cab022014-09-19 19:16:31 -0700466}
467
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700468DLLEXPORT int STDCALL FPDF_GetPageCount(FPDF_DOCUMENT document) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800469 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
Tom Sepez471a1032015-10-15 16:17:18 -0700470 return pDoc ? pDoc->GetPageCount() : 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700471}
472
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700473DLLEXPORT FPDF_PAGE STDCALL FPDF_LoadPage(FPDF_DOCUMENT document,
474 int page_index) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800475 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
476 if (!pDoc)
Tom Sepez471a1032015-10-15 16:17:18 -0700477 return nullptr;
Tom Sepez1b246282015-11-25 15:15:31 -0800478
Tom Sepezbbe0e4d2015-10-20 15:41:40 -0700479 if (page_index < 0 || page_index >= pDoc->GetPageCount())
Tom Sepez471a1032015-10-15 16:17:18 -0700480 return nullptr;
481
Tom Sepez51da0932015-11-25 16:05:49 -0800482#ifndef PDF_ENABLE_XFA
483 CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
484 if (pDict == NULL)
485 return NULL;
486 CPDF_Page* pPage = new CPDF_Page;
487 pPage->Load(pDoc, pDict);
488 pPage->ParseContent();
489 return pPage;
490#else
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700491 return pDoc->GetPage(page_index);
Tom Sepez51da0932015-11-25 16:05:49 -0800492#endif
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700493}
494
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700495DLLEXPORT double STDCALL FPDF_GetPageWidth(FPDF_PAGE page) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800496 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezbf59a072015-10-21 14:07:23 -0700497 return pPage ? pPage->GetPageWidth() : 0.0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700498}
499
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700500DLLEXPORT double STDCALL FPDF_GetPageHeight(FPDF_PAGE page) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800501 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezbf59a072015-10-21 14:07:23 -0700502 return pPage ? pPage->GetPageHeight() : 0.0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700503}
504
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700505void DropContext(void* data) {
506 delete (CRenderContext*)data;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700507}
508
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700509#if defined(_DEBUG) || defined(DEBUG)
510#define DEBUG_TRACE
511#endif
512
513#if defined(_WIN32)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700514DLLEXPORT void STDCALL FPDF_RenderPage(HDC dc,
515 FPDF_PAGE page,
516 int start_x,
517 int start_y,
518 int size_x,
519 int size_y,
520 int rotate,
521 int flags) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700522 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700523 if (!pPage)
524 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700525
Tom Sepezae51c812015-08-05 12:34:06 -0700526 CRenderContext* pContext = new CRenderContext;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700527 pPage->SetPrivateData((void*)1, pContext, DropContext);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700528
529#ifndef _WIN32_WCE
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700530 CFX_DIBitmap* pBitmap = NULL;
531 FX_BOOL bBackgroundAlphaNeeded = FALSE;
532 bBackgroundAlphaNeeded = pPage->BackgroundAlphaNeeded();
533 if (bBackgroundAlphaNeeded) {
Tom Sepezae51c812015-08-05 12:34:06 -0700534 pBitmap = new CFX_DIBitmap;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700535 pBitmap->Create(size_x, size_y, FXDIB_Argb);
536 pBitmap->Clear(0x00ffffff);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700537#ifdef _SKIA_SUPPORT_
Tom Sepezae51c812015-08-05 12:34:06 -0700538 pContext->m_pDevice = new CFX_SkiaDevice;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700539 ((CFX_SkiaDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)pBitmap);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700540#else
Tom Sepezae51c812015-08-05 12:34:06 -0700541 pContext->m_pDevice = new CFX_FxgeDevice;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700542 ((CFX_FxgeDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)pBitmap);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700543#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700544 } else
Tom Sepezae51c812015-08-05 12:34:06 -0700545 pContext->m_pDevice = new CFX_WindowsDevice(dc);
Bo Xud4e406e2014-08-13 11:03:19 -0700546
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700547 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
548 rotate, flags, TRUE, NULL);
Bo Xud4e406e2014-08-13 11:03:19 -0700549
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700550 if (bBackgroundAlphaNeeded) {
551 if (pBitmap) {
552 CFX_WindowsDevice WinDC(dc);
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700553
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700554 if (WinDC.GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
Tom Sepezae51c812015-08-05 12:34:06 -0700555 CFX_DIBitmap* pDst = new CFX_DIBitmap;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700556 int pitch = pBitmap->GetPitch();
557 pDst->Create(size_x, size_y, FXDIB_Rgb32);
558 FXSYS_memset(pDst->GetBuffer(), -1, pitch * size_y);
559 pDst->CompositeBitmap(0, 0, size_x, size_y, pBitmap, 0, 0,
560 FXDIB_BLEND_NORMAL, NULL, FALSE, NULL);
561 WinDC.StretchDIBits(pDst, 0, 0, size_x, size_y);
562 delete pDst;
563 } else
564 WinDC.SetDIBits(pBitmap, 0, 0);
Lei Zhang6d8b1c22015-06-19 17:26:17 -0700565 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700566 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700567#else
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700568 // get clip region
569 RECT rect, cliprect;
570 rect.left = start_x;
571 rect.top = start_y;
572 rect.right = start_x + size_x;
573 rect.bottom = start_y + size_y;
574 GetClipBox(dc, &cliprect);
575 IntersectRect(&rect, &rect, &cliprect);
576 int width = rect.right - rect.left;
577 int height = rect.bottom - rect.top;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700578
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700579#ifdef DEBUG_TRACE
580 {
581 char str[128];
582 memset(str, 0, sizeof(str));
583 FXSYS_snprintf(str, sizeof(str) - 1, "Rendering DIB %d x %d", width,
584 height);
585 CPDF_ModuleMgr::Get()->ReportError(999, str);
586 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700587#endif
Bo Xud4e406e2014-08-13 11:03:19 -0700588
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700589 // Create a DIB section
590 LPVOID pBuffer;
591 BITMAPINFOHEADER bmih;
592 FXSYS_memset(&bmih, 0, sizeof bmih);
593 bmih.biSize = sizeof bmih;
594 bmih.biBitCount = 24;
595 bmih.biHeight = -height;
596 bmih.biPlanes = 1;
597 bmih.biWidth = width;
598 pContext->m_hBitmap = CreateDIBSection(dc, (BITMAPINFO*)&bmih, DIB_RGB_COLORS,
599 &pBuffer, NULL, 0);
600 if (pContext->m_hBitmap == NULL) {
601#if defined(DEBUG) || defined(_DEBUG)
602 char str[128];
603 memset(str, 0, sizeof(str));
604 FXSYS_snprintf(str, sizeof(str) - 1,
605 "Error CreateDIBSection: %d x %d, error code = %d", width,
606 height, GetLastError());
607 CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, str);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700608#else
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700609 CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700610#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700611 }
612 FXSYS_memset(pBuffer, 0xff, height * ((width * 3 + 3) / 4 * 4));
613
614#ifdef DEBUG_TRACE
615 { CPDF_ModuleMgr::Get()->ReportError(999, "DIBSection created"); }
616#endif
617
618 // Create a device with this external buffer
619 pContext->m_pBitmap = new CFX_DIBitmap;
620 pContext->m_pBitmap->Create(width, height, FXDIB_Rgb, (uint8_t*)pBuffer);
621 pContext->m_pDevice = new CPDF_FxgeDevice;
622 ((CPDF_FxgeDevice*)pContext->m_pDevice)->Attach(pContext->m_pBitmap);
623
624#ifdef DEBUG_TRACE
625 CPDF_ModuleMgr::Get()->ReportError(999, "Ready for PDF rendering");
626#endif
627
628 // output to bitmap device
629 FPDF_RenderPage_Retail(pContext, page, start_x - rect.left,
630 start_y - rect.top, size_x, size_y, rotate, flags);
631
632#ifdef DEBUG_TRACE
633 CPDF_ModuleMgr::Get()->ReportError(999, "Finished PDF rendering");
634#endif
635
636 // Now output to real device
637 HDC hMemDC = CreateCompatibleDC(dc);
638 if (hMemDC == NULL) {
639#if defined(DEBUG) || defined(_DEBUG)
640 char str[128];
641 memset(str, 0, sizeof(str));
642 FXSYS_snprintf(str, sizeof(str) - 1,
643 "Error CreateCompatibleDC. Error code = %d", GetLastError());
644 CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, str);
645#else
646 CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, NULL);
647#endif
648 }
649
650 HGDIOBJ hOldBitmap = SelectObject(hMemDC, pContext->m_hBitmap);
651
652#ifdef DEBUG_TRACE
653 CPDF_ModuleMgr::Get()->ReportError(999, "Ready for screen rendering");
654#endif
655
656 BitBlt(dc, rect.left, rect.top, width, height, hMemDC, 0, 0, SRCCOPY);
657 SelectObject(hMemDC, hOldBitmap);
658 DeleteDC(hMemDC);
659
660#ifdef DEBUG_TRACE
661 CPDF_ModuleMgr::Get()->ReportError(999, "Finished screen rendering");
662#endif
663
664#endif
665 if (bBackgroundAlphaNeeded) {
666 delete pBitmap;
667 pBitmap = NULL;
668 }
669 delete pContext;
670 pPage->RemovePrivateData((void*)1);
671}
672#endif
673
674DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap,
675 FPDF_PAGE page,
676 int start_x,
677 int start_y,
678 int size_x,
679 int size_y,
680 int rotate,
681 int flags) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700682 if (!bitmap)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700683 return;
Tom Sepezdb0be962015-10-16 14:00:21 -0700684 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700685 if (!pPage)
686 return;
Tom Sepezae51c812015-08-05 12:34:06 -0700687 CRenderContext* pContext = new CRenderContext;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700688 pPage->SetPrivateData((void*)1, pContext, DropContext);
689#ifdef _SKIA_SUPPORT_
Tom Sepezae51c812015-08-05 12:34:06 -0700690 pContext->m_pDevice = new CFX_SkiaDevice;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700691
692 if (flags & FPDF_REVERSE_BYTE_ORDER)
693 ((CFX_SkiaDevice*)pContext->m_pDevice)
694 ->Attach((CFX_DIBitmap*)bitmap, 0, TRUE);
695 else
696 ((CFX_SkiaDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)bitmap);
697#else
Tom Sepezae51c812015-08-05 12:34:06 -0700698 pContext->m_pDevice = new CFX_FxgeDevice;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700699
700 if (flags & FPDF_REVERSE_BYTE_ORDER)
701 ((CFX_FxgeDevice*)pContext->m_pDevice)
702 ->Attach((CFX_DIBitmap*)bitmap, 0, TRUE);
703 else
704 ((CFX_FxgeDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)bitmap);
705#endif
706
707 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
708 rotate, flags, TRUE, NULL);
709
710 delete pContext;
711 pPage->RemovePrivateData((void*)1);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700712}
713
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700714DLLEXPORT void STDCALL FPDF_ClosePage(FPDF_PAGE page) {
715 if (!page)
716 return;
Tom Sepez51da0932015-11-25 16:05:49 -0800717#ifndef PDF_ENABLE_XFA
718 CPDFSDK_PageView* pPageView =
719 (CPDFSDK_PageView*)(((CPDF_Page*)page))->GetPrivateData((void*)page);
720 if (pPageView && pPageView->IsLocked()) {
721 pPageView->TakeOverPage();
722 return;
723 }
724 delete (CPDF_Page*)page;
725#else
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700726
727 CPDFXFA_Page* pPage = (CPDFXFA_Page*)page;
728 pPage->Release();
Tom Sepez51da0932015-11-25 16:05:49 -0800729#endif
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700730}
731
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700732DLLEXPORT void STDCALL FPDF_CloseDocument(FPDF_DOCUMENT document) {
Tom Sepez51da0932015-11-25 16:05:49 -0800733#ifndef PDF_ENABLE_XFA
734 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
735 if (!pDoc)
736 return;
737
738 CPDF_Parser* pParser = (CPDF_Parser*)pDoc->GetParser();
739 if (!pParser) {
740 delete pDoc;
741 return;
742 }
743 delete pParser;
744#else
Tom Sepez471a1032015-10-15 16:17:18 -0700745 delete CPDFDocumentFromFPDFDocument(document);
Tom Sepez51da0932015-11-25 16:05:49 -0800746#endif
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700747}
748
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700749DLLEXPORT unsigned long STDCALL FPDF_GetLastError() {
750 return GetLastError();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700751}
752
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700753DLLEXPORT void STDCALL FPDF_DeviceToPage(FPDF_PAGE page,
754 int start_x,
755 int start_y,
756 int size_x,
757 int size_y,
758 int rotate,
759 int device_x,
760 int device_y,
761 double* page_x,
762 double* page_y) {
763 if (page == NULL || page_x == NULL || page_y == NULL)
764 return;
Tom Sepez50d12ad2015-11-24 09:50:51 -0800765 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepez51da0932015-11-25 16:05:49 -0800766#ifndef PDF_ENABLE_XFA
767
768 CPDF_Matrix page2device;
769 pPage->GetDisplayMatrix(page2device, start_x, start_y, size_x, size_y,
770 rotate);
771 CPDF_Matrix device2page;
772 device2page.SetReverse(page2device);
773
774 FX_FLOAT page_x_f, page_y_f;
775 device2page.Transform((FX_FLOAT)(device_x), (FX_FLOAT)(device_y), page_x_f,
776 page_y_f);
777
778 *page_x = (page_x_f);
779 *page_y = (page_y_f);
780#else
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700781 pPage->DeviceToPage(start_x, start_y, size_x, size_y, rotate, device_x,
782 device_y, page_x, page_y);
Tom Sepez51da0932015-11-25 16:05:49 -0800783#endif
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700784}
785
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700786DLLEXPORT void STDCALL FPDF_PageToDevice(FPDF_PAGE page,
787 int start_x,
788 int start_y,
789 int size_x,
790 int size_y,
791 int rotate,
792 double page_x,
793 double page_y,
794 int* device_x,
795 int* device_y) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700796 if (!device_x || !device_y)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700797 return;
Tom Sepez50d12ad2015-11-24 09:50:51 -0800798 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezdb0be962015-10-16 14:00:21 -0700799 if (!pPage)
800 return;
Tom Sepez51da0932015-11-25 16:05:49 -0800801#ifndef PDF_ENABLE_XFA
802 CPDF_Matrix page2device;
803 pPage->GetDisplayMatrix(page2device, start_x, start_y, size_x, size_y,
804 rotate);
805
806 FX_FLOAT device_x_f, device_y_f;
807 page2device.Transform(((FX_FLOAT)page_x), ((FX_FLOAT)page_y), device_x_f,
808 device_y_f);
809
810 *device_x = FXSYS_round(device_x_f);
811 *device_y = FXSYS_round(device_y_f);
812#else
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700813 pPage->PageToDevice(start_x, start_y, size_x, size_y, rotate, page_x, page_y,
814 device_x, device_y);
Tom Sepez51da0932015-11-25 16:05:49 -0800815#endif
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700816}
817
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700818DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_Create(int width,
819 int height,
820 int alpha) {
821 nonstd::unique_ptr<CFX_DIBitmap> pBitmap(new CFX_DIBitmap);
822 if (!pBitmap->Create(width, height, alpha ? FXDIB_Argb : FXDIB_Rgb32)) {
823 return NULL;
824 }
825 return pBitmap.release();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700826}
827
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700828DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_CreateEx(int width,
829 int height,
830 int format,
831 void* first_scan,
832 int stride) {
833 FXDIB_Format fx_format;
834 switch (format) {
835 case FPDFBitmap_Gray:
836 fx_format = FXDIB_8bppRgb;
837 break;
838 case FPDFBitmap_BGR:
839 fx_format = FXDIB_Rgb;
840 break;
841 case FPDFBitmap_BGRx:
842 fx_format = FXDIB_Rgb32;
843 break;
844 case FPDFBitmap_BGRA:
845 fx_format = FXDIB_Argb;
846 break;
847 default:
848 return NULL;
849 }
850 CFX_DIBitmap* pBitmap = new CFX_DIBitmap;
851 pBitmap->Create(width, height, fx_format, (uint8_t*)first_scan, stride);
852 return pBitmap;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700853}
854
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700855DLLEXPORT void STDCALL FPDFBitmap_FillRect(FPDF_BITMAP bitmap,
856 int left,
857 int top,
858 int width,
859 int height,
860 FPDF_DWORD color) {
861 if (bitmap == NULL)
862 return;
863#ifdef _SKIA_SUPPORT_
864 CFX_SkiaDevice device;
865#else
866 CFX_FxgeDevice device;
867#endif
868 device.Attach((CFX_DIBitmap*)bitmap);
869 if (!((CFX_DIBitmap*)bitmap)->HasAlpha())
870 color |= 0xFF000000;
871 FX_RECT rect(left, top, left + width, top + height);
872 device.FillRect(&rect, color);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700873}
874
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700875DLLEXPORT void* STDCALL FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap) {
876 if (bitmap == NULL)
877 return NULL;
878 return ((CFX_DIBitmap*)bitmap)->GetBuffer();
Bo Xu9114e832014-07-14 13:22:47 -0700879}
880
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700881DLLEXPORT int STDCALL FPDFBitmap_GetWidth(FPDF_BITMAP bitmap) {
882 if (bitmap == NULL)
883 return 0;
884 return ((CFX_DIBitmap*)bitmap)->GetWidth();
Bo Xu9114e832014-07-14 13:22:47 -0700885}
886
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700887DLLEXPORT int STDCALL FPDFBitmap_GetHeight(FPDF_BITMAP bitmap) {
888 if (bitmap == NULL)
889 return 0;
890 return ((CFX_DIBitmap*)bitmap)->GetHeight();
891}
892
893DLLEXPORT int STDCALL FPDFBitmap_GetStride(FPDF_BITMAP bitmap) {
894 if (bitmap == NULL)
895 return 0;
896 return ((CFX_DIBitmap*)bitmap)->GetPitch();
897}
898
899DLLEXPORT void STDCALL FPDFBitmap_Destroy(FPDF_BITMAP bitmap) {
900 delete (CFX_DIBitmap*)bitmap;
901}
902
903void FPDF_RenderPage_Retail(CRenderContext* pContext,
904 FPDF_PAGE page,
905 int start_x,
906 int start_y,
907 int size_x,
908 int size_y,
909 int rotate,
910 int flags,
911 FX_BOOL bNeedToRestore,
912 IFSDK_PAUSE_Adapter* pause) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700913 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
914 if (!pPage)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700915 return;
916
917 if (!pContext->m_pOptions)
918 pContext->m_pOptions = new CPDF_RenderOptions;
919
920 if (flags & FPDF_LCD_TEXT)
921 pContext->m_pOptions->m_Flags |= RENDER_CLEARTYPE;
922 else
923 pContext->m_pOptions->m_Flags &= ~RENDER_CLEARTYPE;
924 if (flags & FPDF_NO_NATIVETEXT)
925 pContext->m_pOptions->m_Flags |= RENDER_NO_NATIVETEXT;
926 if (flags & FPDF_RENDER_LIMITEDIMAGECACHE)
927 pContext->m_pOptions->m_Flags |= RENDER_LIMITEDIMAGECACHE;
928 if (flags & FPDF_RENDER_FORCEHALFTONE)
929 pContext->m_pOptions->m_Flags |= RENDER_FORCE_HALFTONE;
Tom Sepez51da0932015-11-25 16:05:49 -0800930#ifndef PDF_ENABLE_XFA
931 if (flags & FPDF_RENDER_NO_SMOOTHTEXT)
932 pContext->m_pOptions->m_Flags |= RENDER_NOTEXTSMOOTH;
933 if (flags & FPDF_RENDER_NO_SMOOTHIMAGE)
934 pContext->m_pOptions->m_Flags |= RENDER_NOIMAGESMOOTH;
935 if (flags & FPDF_RENDER_NO_SMOOTHPATH)
936 pContext->m_pOptions->m_Flags |= RENDER_NOPATHSMOOTH;
937#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700938 // Grayscale output
939 if (flags & FPDF_GRAYSCALE) {
940 pContext->m_pOptions->m_ColorMode = RENDER_COLOR_GRAY;
941 pContext->m_pOptions->m_ForeColor = 0;
942 pContext->m_pOptions->m_BackColor = 0xffffff;
943 }
944 const CPDF_OCContext::UsageType usage =
945 (flags & FPDF_PRINTING) ? CPDF_OCContext::Print : CPDF_OCContext::View;
946 pContext->m_pOptions->m_AddFlags = flags >> 8;
947 pContext->m_pOptions->m_pOCContext =
948 new CPDF_OCContext(pPage->m_pDocument, usage);
949
950 CFX_AffineMatrix matrix;
951 pPage->GetDisplayMatrix(matrix, start_x, start_y, size_x, size_y, rotate);
952
953 FX_RECT clip;
954 clip.left = start_x;
955 clip.right = start_x + size_x;
956 clip.top = start_y;
957 clip.bottom = start_y + size_y;
958 pContext->m_pDevice->SaveState();
959 pContext->m_pDevice->SetClip_Rect(&clip);
960
Tom Sepezae51c812015-08-05 12:34:06 -0700961 pContext->m_pContext = new CPDF_RenderContext;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700962 pContext->m_pContext->Create(pPage);
963 pContext->m_pContext->AppendObjectList(pPage, &matrix);
964
965 if (flags & FPDF_ANNOT) {
Tom Sepezae51c812015-08-05 12:34:06 -0700966 pContext->m_pAnnots = new CPDF_AnnotList(pPage);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700967 FX_BOOL bPrinting = pContext->m_pDevice->GetDeviceClass() != FXDC_DISPLAY;
968 pContext->m_pAnnots->DisplayAnnots(pPage, pContext->m_pContext, bPrinting,
969 &matrix, TRUE, NULL);
970 }
971
Tom Sepezb3b67622015-10-19 16:20:03 -0700972 pContext->m_pRenderer = new CPDF_ProgressiveRenderer(
973 pContext->m_pContext, pContext->m_pDevice, pContext->m_pOptions);
974 pContext->m_pRenderer->Start(pause);
Tom Sepezc7e4c4f2015-11-20 09:45:24 -0800975 if (bNeedToRestore)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700976 pContext->m_pDevice->RestoreState();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700977}
978
979DLLEXPORT int STDCALL FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document,
980 int page_index,
981 double* width,
982 double* height) {
Tom Sepez540c4362015-11-24 13:33:57 -0800983 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
984 if (!pDoc)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700985 return FALSE;
986
Tom Sepez51da0932015-11-25 16:05:49 -0800987#ifndef PDF_ENABLE_XFA
988 CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
989 if (!pDict)
990#else
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700991 int count = pDoc->GetPageCount();
992 if (page_index < 0 || page_index >= count)
993 return FALSE;
994
995 CPDFXFA_Page* pPage = pDoc->GetPage(page_index);
996 if (!pPage)
Tom Sepez51da0932015-11-25 16:05:49 -0800997#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700998 return FALSE;
999
Tom Sepez51da0932015-11-25 16:05:49 -08001000#ifndef PDF_ENABLE_XFA
1001 CPDF_Page page;
1002 page.Load(pDoc, pDict);
1003 *width = page.GetPageWidth();
1004 *height = page.GetPageHeight();
1005#else
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001006 *width = pPage->GetPageWidth();
1007 *height = pPage->GetPageHeight();
Tom Sepez51da0932015-11-25 16:05:49 -08001008#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001009
1010 return TRUE;
1011}
1012
1013DLLEXPORT FPDF_BOOL STDCALL
1014FPDF_VIEWERREF_GetPrintScaling(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001015 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001016 if (!pDoc)
1017 return TRUE;
Tom Sepez471a1032015-10-15 16:17:18 -07001018 CPDF_ViewerPreferences viewRef(pDoc);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001019 return viewRef.PrintScaling();
1020}
1021
1022DLLEXPORT int STDCALL FPDF_VIEWERREF_GetNumCopies(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001023 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001024 if (!pDoc)
1025 return 1;
1026 CPDF_ViewerPreferences viewRef(pDoc);
1027 return viewRef.NumCopies();
1028}
1029
1030DLLEXPORT FPDF_PAGERANGE STDCALL
1031FPDF_VIEWERREF_GetPrintPageRange(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001032 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001033 if (!pDoc)
1034 return NULL;
1035 CPDF_ViewerPreferences viewRef(pDoc);
1036 return viewRef.PrintPageRange();
1037}
1038
1039DLLEXPORT FPDF_DUPLEXTYPE STDCALL
1040FPDF_VIEWERREF_GetDuplex(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001041 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001042 if (!pDoc)
Bo Xu9114e832014-07-14 13:22:47 -07001043 return DuplexUndefined;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001044 CPDF_ViewerPreferences viewRef(pDoc);
1045 CFX_ByteString duplex = viewRef.Duplex();
1046 if (FX_BSTRC("Simplex") == duplex)
1047 return Simplex;
1048 if (FX_BSTRC("DuplexFlipShortEdge") == duplex)
1049 return DuplexFlipShortEdge;
1050 if (FX_BSTRC("DuplexFlipLongEdge") == duplex)
1051 return DuplexFlipLongEdge;
1052 return DuplexUndefined;
Bo Xu9114e832014-07-14 13:22:47 -07001053}
1054
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001055DLLEXPORT FPDF_DWORD STDCALL FPDF_CountNamedDests(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001056 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1057 if (!pDoc)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001058 return 0;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001059
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001060 CPDF_Dictionary* pRoot = pDoc->GetRoot();
1061 if (!pRoot)
1062 return 0;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001063
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001064 CPDF_NameTree nameTree(pDoc, FX_BSTRC("Dests"));
1065 int count = nameTree.GetCount();
1066 CPDF_Dictionary* pDest = pRoot->GetDict(FX_BSTRC("Dests"));
1067 if (pDest)
1068 count += pDest->GetCount();
1069 return count;
1070}
1071
1072DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDestByName(FPDF_DOCUMENT document,
1073 FPDF_BYTESTRING name) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001074 if (!name || name[0] == 0)
Tom Sepez471a1032015-10-15 16:17:18 -07001075 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001076
Tom Sepez471a1032015-10-15 16:17:18 -07001077 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1078 if (!pDoc)
1079 return nullptr;
1080
1081 CPDF_NameTree name_tree(pDoc, FX_BSTRC("Dests"));
1082 return name_tree.LookupNamedDest(pDoc, name);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001083}
1084
Tom Sepez51da0932015-11-25 16:05:49 -08001085#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001086FPDF_RESULT FPDF_BStr_Init(FPDF_BSTR* str) {
1087 if (!str)
1088 return -1;
1089
1090 FXSYS_memset(str, 0, sizeof(FPDF_BSTR));
1091 return 0;
1092}
1093
1094FPDF_RESULT FPDF_BStr_Set(FPDF_BSTR* str, FPDF_LPCSTR bstr, int length) {
1095 if (!str)
1096 return -1;
1097 if (!bstr || !length)
1098 return -1;
1099 if (length == -1)
1100 length = FXSYS_strlen(bstr);
1101
1102 if (length == 0) {
1103 if (str->str) {
1104 FX_Free(str->str);
1105 str->str = NULL;
1106 }
1107 str->len = 0;
1108 return 0;
1109 }
1110
1111 if (str->str && str->len < length)
1112 str->str = FX_Realloc(char, str->str, length + 1);
1113 else if (!str->str)
1114 str->str = FX_Alloc(char, length + 1);
1115
1116 str->str[length] = 0;
1117 if (str->str == NULL)
1118 return -1;
1119
1120 FXSYS_memcpy(str->str, bstr, length);
1121 str->len = length;
1122
1123 return 0;
1124}
1125
1126FPDF_RESULT FPDF_BStr_Clear(FPDF_BSTR* str) {
1127 if (!str)
1128 return -1;
1129
1130 if (str->str) {
1131 FX_Free(str->str);
1132 str->str = NULL;
1133 }
1134 str->len = 0;
1135 return 0;
1136}
1137
Tom Sepez51da0932015-11-25 16:05:49 -08001138#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001139DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDest(FPDF_DOCUMENT document,
1140 int index,
1141 void* buffer,
1142 long* buflen) {
1143 if (!buffer)
1144 *buflen = 0;
Tom Sepez540c4362015-11-24 13:33:57 -08001145
1146 if (index < 0)
1147 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001148
Tom Sepezbf59a072015-10-21 14:07:23 -07001149 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Tom Sepez540c4362015-11-24 13:33:57 -08001150 if (!pDoc)
1151 return nullptr;
1152
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001153 CPDF_Dictionary* pRoot = pDoc->GetRoot();
1154 if (!pRoot)
Tom Sepez540c4362015-11-24 13:33:57 -08001155 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001156
1157 CPDF_Object* pDestObj = NULL;
1158 CFX_ByteString bsName;
1159 CPDF_NameTree nameTree(pDoc, FX_BSTRC("Dests"));
1160 int count = nameTree.GetCount();
1161 if (index >= count) {
Bo Xu4d62b6b2015-01-10 22:52:59 -08001162 CPDF_Dictionary* pDest = pRoot->GetDict(FX_BSTRC("Dests"));
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001163 if (!pDest)
1164 return NULL;
1165 if (index >= count + pDest->GetCount())
1166 return NULL;
1167 index -= count;
1168 FX_POSITION pos = pDest->GetStartPos();
1169 int i = 0;
1170 while (pos) {
1171 pDestObj = pDest->GetNextElement(pos, bsName);
1172 if (!pDestObj)
1173 continue;
1174 if (i == index)
1175 break;
1176 i++;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001177 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001178 } else {
1179 pDestObj = nameTree.LookupValue(index, bsName);
1180 }
1181 if (!pDestObj)
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001182 return nullptr;
Dan Sinclairf1251c12015-10-20 16:24:45 -04001183 if (CPDF_Dictionary* pDict = pDestObj->AsDictionary()) {
1184 pDestObj = pDict->GetArray(FX_BSTRC("D"));
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001185 if (!pDestObj)
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001186 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001187 }
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001188 if (!pDestObj->IsArray())
1189 return nullptr;
1190
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001191 CFX_WideString wsName = PDF_DecodeText(bsName);
1192 CFX_ByteString utf16Name = wsName.UTF16LE_Encode();
1193 unsigned int len = utf16Name.GetLength();
1194 if (!buffer) {
1195 *buflen = len;
1196 } else if (*buflen >= len) {
1197 memcpy(buffer, utf16Name.c_str(), len);
1198 *buflen = len;
1199 } else {
1200 *buflen = -1;
1201 }
1202 return (FPDF_DEST)pDestObj;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001203}