blob: 5d9bf4b2522f71198c655b999798b9ca540deb6c [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 Zhange5b0bd12015-06-19 17:15:41 -07007#include "../../core/include/fpdfapi/fpdf_module.h"
8#include "../../core/include/fxcodec/fx_codec.h"
Tom Sepeza4d1f402015-06-05 13:32:52 -07009#include "../../core/include/fxcrt/fx_safe_types.h"
Tom Sepez1ed8a212015-05-11 15:25:39 -070010#include "../../public/fpdf_ext.h"
11#include "../../public/fpdf_formfill.h"
12#include "../../public/fpdf_progressive.h"
13#include "../../public/fpdfview.h"
Tom Sepeza4d1f402015-06-05 13:32:52 -070014#include "../../third_party/base/nonstd_unique_ptr.h"
15#include "../../third_party/base/numerics/safe_conversions_impl.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070016#include "../include/fsdk_define.h"
Bo Xufacd0152014-09-24 10:49:52 -070017#include "../include/fsdk_mgr.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070018#include "../include/fsdk_rendercontext.h"
Bo Xufdc00a72014-10-28 23:03:33 -070019#include "../include/fpdfxfa/fpdfxfa_doc.h"
20#include "../include/fpdfxfa/fpdfxfa_app.h"
21#include "../include/fpdfxfa/fpdfxfa_page.h"
22#include "../include/fpdfxfa/fpdfxfa_util.h"
Tom Sepez452b4f32015-10-13 09:27:27 -070023#include "../include/javascript/IJavaScript.h"
Bo Xufdc00a72014-10-28 23:03:33 -070024
Tom Sepez471a1032015-10-15 16:17:18 -070025CPDF_Document* CPDFDocumentFromFPDFDocument(FPDF_DOCUMENT doc) {
26 return doc ? static_cast<CPDFXFA_Document*>(doc)->GetPDFDoc() : nullptr;
27}
28
Nico Weber9d8ec5a2015-08-04 13:00:21 -070029CFPDF_FileStream::CFPDF_FileStream(FPDF_FILEHANDLER* pFS) {
30 m_pFS = pFS;
31 m_nCurPos = 0;
Bo Xufdc00a72014-10-28 23:03:33 -070032}
33
Nico Weber9d8ec5a2015-08-04 13:00:21 -070034IFX_FileStream* CFPDF_FileStream::Retain() {
35 return this;
Bo Xufdc00a72014-10-28 23:03:33 -070036}
37
Nico Weber9d8ec5a2015-08-04 13:00:21 -070038void CFPDF_FileStream::Release() {
39 if (m_pFS && m_pFS->Release)
40 m_pFS->Release(m_pFS->clientData);
41 delete this;
Bo Xufdc00a72014-10-28 23:03:33 -070042}
43
Nico Weber9d8ec5a2015-08-04 13:00:21 -070044FX_FILESIZE CFPDF_FileStream::GetSize() {
45 if (m_pFS && m_pFS->GetSize)
46 return (FX_FILESIZE)m_pFS->GetSize(m_pFS->clientData);
47 return 0;
Bo Xufdc00a72014-10-28 23:03:33 -070048}
49
Nico Weber9d8ec5a2015-08-04 13:00:21 -070050FX_BOOL CFPDF_FileStream::IsEOF() {
51 return m_nCurPos >= GetSize();
Bo Xufdc00a72014-10-28 23:03:33 -070052}
53
Nico Weber9d8ec5a2015-08-04 13:00:21 -070054FX_BOOL CFPDF_FileStream::ReadBlock(void* buffer,
55 FX_FILESIZE offset,
56 size_t size) {
57 if (!buffer || !size || !m_pFS->ReadBlock)
58 return FALSE;
Bo Xufdc00a72014-10-28 23:03:33 -070059
Nico Weber9d8ec5a2015-08-04 13:00:21 -070060 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
61 (FPDF_DWORD)size) == 0) {
62 m_nCurPos = offset + size;
63 return TRUE;
64 }
65 return FALSE;
Bo Xufdc00a72014-10-28 23:03:33 -070066}
67
Nico Weber9d8ec5a2015-08-04 13:00:21 -070068size_t CFPDF_FileStream::ReadBlock(void* buffer, size_t size) {
69 if (!buffer || !size || !m_pFS->ReadBlock)
70 return 0;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -070071
Nico Weber9d8ec5a2015-08-04 13:00:21 -070072 FX_FILESIZE nSize = GetSize();
73 if (m_nCurPos >= nSize)
74 return 0;
75 FX_FILESIZE dwAvail = nSize - m_nCurPos;
76 if (dwAvail < (FX_FILESIZE)size)
77 size = (size_t)dwAvail;
78 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)m_nCurPos, buffer,
79 (FPDF_DWORD)size) == 0) {
80 m_nCurPos += size;
81 return size;
82 }
Bo Xufdc00a72014-10-28 23:03:33 -070083
Nico Weber9d8ec5a2015-08-04 13:00:21 -070084 return 0;
Bo Xufdc00a72014-10-28 23:03:33 -070085}
86
Nico Weber9d8ec5a2015-08-04 13:00:21 -070087FX_BOOL CFPDF_FileStream::WriteBlock(const void* buffer,
88 FX_FILESIZE offset,
89 size_t size) {
90 if (!m_pFS || !m_pFS->WriteBlock)
91 return FALSE;
Bo Xufdc00a72014-10-28 23:03:33 -070092
Nico Weber9d8ec5a2015-08-04 13:00:21 -070093 if (m_pFS->WriteBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
94 (FPDF_DWORD)size) == 0) {
95 m_nCurPos = offset + size;
96 return TRUE;
97 }
98 return FALSE;
Bo Xufdc00a72014-10-28 23:03:33 -070099}
100
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700101FX_BOOL CFPDF_FileStream::Flush() {
102 if (!m_pFS || !m_pFS->Flush)
103 return TRUE;
Bo Xufdc00a72014-10-28 23:03:33 -0700104
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700105 return m_pFS->Flush(m_pFS->clientData) == 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700106}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700107
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700108CPDF_CustomAccess::CPDF_CustomAccess(FPDF_FILEACCESS* pFileAccess) {
109 m_FileAccess = *pFileAccess;
110 m_BufferOffset = (FX_DWORD)-1;
Bo Xufdc00a72014-10-28 23:03:33 -0700111}
112
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700113FX_BOOL CPDF_CustomAccess::GetByte(FX_DWORD pos, uint8_t& ch) {
114 if (pos >= m_FileAccess.m_FileLen)
115 return FALSE;
116 if (m_BufferOffset == (FX_DWORD)-1 || pos < m_BufferOffset ||
117 pos >= m_BufferOffset + 512) {
118 // Need to read from file access
119 m_BufferOffset = pos;
120 int size = 512;
121 if (pos + 512 > m_FileAccess.m_FileLen)
122 size = m_FileAccess.m_FileLen - pos;
123 if (!m_FileAccess.m_GetBlock(m_FileAccess.m_Param, m_BufferOffset, m_Buffer,
124 size))
125 return FALSE;
126 }
127 ch = m_Buffer[pos - m_BufferOffset];
128 return TRUE;
Bo Xufdc00a72014-10-28 23:03:33 -0700129}
130
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700131FX_BOOL CPDF_CustomAccess::GetBlock(FX_DWORD pos,
132 uint8_t* pBuf,
133 FX_DWORD size) {
134 if (pos + size > m_FileAccess.m_FileLen)
135 return FALSE;
136 return m_FileAccess.m_GetBlock(m_FileAccess.m_Param, pos, pBuf, size);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700137}
138
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700139FX_BOOL CPDF_CustomAccess::ReadBlock(void* buffer,
140 FX_FILESIZE offset,
141 size_t size) {
142 if (offset < 0) {
143 return FALSE;
144 }
145 FX_SAFE_FILESIZE newPos =
146 pdfium::base::checked_cast<FX_FILESIZE, size_t>(size);
147 newPos += offset;
148 if (!newPos.IsValid() || newPos.ValueOrDie() > m_FileAccess.m_FileLen) {
149 return FALSE;
150 }
151 return m_FileAccess.m_GetBlock(m_FileAccess.m_Param, offset, (uint8_t*)buffer,
152 size);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700153}
154
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700155// 0 bit: FPDF_POLICY_MACHINETIME_ACCESS
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700156static FX_DWORD foxit_sandbox_policy = 0xFFFFFFFF;
157
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700158void FSDK_SetSandBoxPolicy(FPDF_DWORD policy, FPDF_BOOL enable) {
159 switch (policy) {
160 case FPDF_POLICY_MACHINETIME_ACCESS: {
161 if (enable)
162 foxit_sandbox_policy |= 0x01;
163 else
164 foxit_sandbox_policy &= 0xFFFFFFFE;
165 } break;
166 default:
167 break;
168 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700169}
170
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700171FPDF_BOOL FSDK_IsSandBoxPolicyEnabled(FPDF_DWORD policy) {
172 switch (policy) {
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700173 case FPDF_POLICY_MACHINETIME_ACCESS:
174 return (foxit_sandbox_policy & 0x01) ? TRUE : FALSE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700175 default:
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700176 return FALSE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700177 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700178}
179
Tom Sepez2c286192015-06-18 12:47:11 -0700180CCodec_ModuleMgr* g_pCodecModule = nullptr;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700181
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700182DLLEXPORT void STDCALL FPDF_InitLibrary() {
Lei Zhang6f62d532015-09-23 15:31:44 -0700183 FPDF_InitLibraryWithConfig(nullptr);
184}
185
186DLLEXPORT void STDCALL
187FPDF_InitLibraryWithConfig(const FPDF_LIBRARY_CONFIG* cfg) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700188 g_pCodecModule = new CCodec_ModuleMgr();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700189
Lei Zhang6f62d532015-09-23 15:31:44 -0700190 CFX_GEModule::Create(cfg ? cfg->m_pUserFontPaths : nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700191 CFX_GEModule::Get()->SetCodecModule(g_pCodecModule);
Tom Sepezbdeeb8a2015-05-27 12:25:00 -0700192
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700193 CPDF_ModuleMgr::Create();
194 CPDF_ModuleMgr::Get()->SetCodecModule(g_pCodecModule);
195 CPDF_ModuleMgr::Get()->InitPageModule();
196 CPDF_ModuleMgr::Get()->InitRenderModule();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700197 CPDFXFA_App::GetInstance()->Initialize();
Tom Sepez452b4f32015-10-13 09:27:27 -0700198 if (cfg && cfg->version >= 2)
199 IJS_Runtime::Initialize(cfg->m_v8EmbedderSlot, cfg->m_pIsolate);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700200}
201
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700202DLLEXPORT void STDCALL FPDF_DestroyLibrary() {
203 CPDFXFA_App::ReleaseInstance();
204 CPDF_ModuleMgr::Destroy();
205 CFX_GEModule::Destroy();
Tom Sepez2c286192015-06-18 12:47:11 -0700206
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700207 delete g_pCodecModule;
208 g_pCodecModule = nullptr;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700209}
210
211#ifndef _WIN32
212int g_LastError;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700213void SetLastError(int err) {
214 g_LastError = err;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700215}
216
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700217int GetLastError() {
218 return g_LastError;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700219}
220#endif
221
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700222void ProcessParseError(FX_DWORD err_code) {
223 // Translate FPDFAPI error code to FPDFVIEW error code
224 switch (err_code) {
225 case PDFPARSE_ERROR_FILE:
226 err_code = FPDF_ERR_FILE;
227 break;
228 case PDFPARSE_ERROR_FORMAT:
229 err_code = FPDF_ERR_FORMAT;
230 break;
231 case PDFPARSE_ERROR_PASSWORD:
232 err_code = FPDF_ERR_PASSWORD;
233 break;
234 case PDFPARSE_ERROR_HANDLER:
235 err_code = FPDF_ERR_SECURITY;
236 break;
237 }
238 SetLastError(err_code);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700239}
240
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700241DLLEXPORT void STDCALL FPDF_SetSandBoxPolicy(FPDF_DWORD policy,
242 FPDF_BOOL enable) {
243 return FSDK_SetSandBoxPolicy(policy, enable);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700244}
245
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700246DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadDocument(FPDF_STRING file_path,
247 FPDF_BYTESTRING password) {
Tom Sepeze3166a82015-08-05 10:50:32 -0700248 // NOTE: the creation of the file needs to be by the embedder on the
249 // other side of this API.
250 IFX_FileRead* pFileAccess = FX_CreateFileRead((const FX_CHAR*)file_path);
251 if (!pFileAccess) {
252 return nullptr;
253 }
254
255 CPDF_Parser* pParser = new CPDF_Parser;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700256 pParser->SetPassword(password);
Bo Xud4e406e2014-08-13 11:03:19 -0700257
Tom Sepeze3166a82015-08-05 10:50:32 -0700258 FX_DWORD err_code = pParser->StartParse(pFileAccess);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700259 if (err_code) {
260 delete pParser;
261 ProcessParseError(err_code);
262 return NULL;
263 }
264 CPDF_Document* pPDFDoc = pParser->GetDocument();
265 if (!pPDFDoc)
266 return NULL;
Bo Xufdc00a72014-10-28 23:03:33 -0700267
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700268 CPDFXFA_App* pProvider = CPDFXFA_App::GetInstance();
Lei Zhangcb78ef52015-10-02 10:10:49 -0700269 return new CPDFXFA_Document(pPDFDoc, pProvider);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700270}
Jun Fange118ce92015-02-17 06:50:08 -0800271
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700272DLLEXPORT FPDF_BOOL STDCALL FPDF_HasXFAField(FPDF_DOCUMENT document,
273 int* docType) {
274 if (!document)
275 return FALSE;
JUN FANG827a1722015-03-05 13:39:21 -0800276
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700277 CPDF_Document* pdfDoc =
278 (static_cast<CPDFXFA_Document*>(document))->GetPDFDoc();
279 if (!pdfDoc)
280 return FALSE;
JUN FANG827a1722015-03-05 13:39:21 -0800281
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700282 CPDF_Dictionary* pRoot = pdfDoc->GetRoot();
283 if (!pRoot)
284 return FALSE;
JUN FANG827a1722015-03-05 13:39:21 -0800285
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700286 CPDF_Dictionary* pAcroForm = pRoot->GetDict("AcroForm");
287 if (!pAcroForm)
288 return FALSE;
JUN FANG827a1722015-03-05 13:39:21 -0800289
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700290 CPDF_Object* pXFA = pAcroForm->GetElement("XFA");
291 if (!pXFA)
292 return FALSE;
JUN FANG827a1722015-03-05 13:39:21 -0800293
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700294 FX_BOOL bDynamicXFA = pRoot->GetBoolean("NeedsRendering", FALSE);
JUN FANG827a1722015-03-05 13:39:21 -0800295
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700296 if (bDynamicXFA)
297 *docType = DOCTYPE_DYNIMIC_XFA;
298 else
299 *docType = DOCTYPE_STATIC_XFA;
JUN FANG827a1722015-03-05 13:39:21 -0800300
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700301 return TRUE;
Jun Fange118ce92015-02-17 06:50:08 -0800302}
303
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700304DLLEXPORT FPDF_BOOL STDCALL FPDF_LoadXFA(FPDF_DOCUMENT document) {
305 return document && (static_cast<CPDFXFA_Document*>(document))->LoadXFADoc();
Bo Xufdc00a72014-10-28 23:03:33 -0700306}
307
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700308class CMemFile final : public IFX_FileRead {
309 public:
310 CMemFile(uint8_t* pBuf, FX_FILESIZE size) : m_pBuf(pBuf), m_size(size) {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700311
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700312 virtual void Release() { delete this; }
313 virtual FX_FILESIZE GetSize() { return m_size; }
314 virtual FX_BOOL ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) {
315 if (offset < 0) {
316 return FALSE;
317 }
318 FX_SAFE_FILESIZE newPos =
319 pdfium::base::checked_cast<FX_FILESIZE, size_t>(size);
320 newPos += offset;
321 if (!newPos.IsValid() || newPos.ValueOrDie() > (FX_DWORD)m_size) {
322 return FALSE;
323 }
324 FXSYS_memcpy(buffer, m_pBuf + offset, size);
325 return TRUE;
326 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700327
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700328 private:
Lei Zhang2b1a2d52015-08-14 22:16:22 -0700329 ~CMemFile() override {}
330
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700331 uint8_t* m_pBuf;
332 FX_FILESIZE m_size;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700333};
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700334DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadMemDocument(const void* data_buf,
335 int size,
336 FPDF_BYTESTRING password) {
Tom Sepezae51c812015-08-05 12:34:06 -0700337 CPDF_Parser* pParser = new CPDF_Parser;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700338 pParser->SetPassword(password);
339 CMemFile* pMemFile = new CMemFile((uint8_t*)data_buf, size);
340 FX_DWORD err_code = pParser->StartParse(pMemFile);
341 if (err_code) {
342 delete pParser;
343 ProcessParseError(err_code);
344 return NULL;
345 }
346 CPDF_Document* pDoc = NULL;
347 pDoc = pParser ? pParser->GetDocument() : NULL;
348 CheckUnSupportError(pDoc, err_code);
349 CPDF_Document* pPDFDoc = pParser->GetDocument();
350 if (!pPDFDoc)
351 return NULL;
Bo Xufdc00a72014-10-28 23:03:33 -0700352
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700353 CPDFXFA_App* pProvider = CPDFXFA_App::GetInstance();
Lei Zhangcb78ef52015-10-02 10:10:49 -0700354 return new CPDFXFA_Document(pPDFDoc, pProvider);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700355}
356
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700357DLLEXPORT FPDF_DOCUMENT STDCALL
358FPDF_LoadCustomDocument(FPDF_FILEACCESS* pFileAccess,
359 FPDF_BYTESTRING password) {
Tom Sepezae51c812015-08-05 12:34:06 -0700360 CPDF_Parser* pParser = new CPDF_Parser;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700361 pParser->SetPassword(password);
Tom Sepezae51c812015-08-05 12:34:06 -0700362 CPDF_CustomAccess* pFile = new CPDF_CustomAccess(pFileAccess);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700363 FX_DWORD err_code = pParser->StartParse(pFile);
364 if (err_code) {
365 delete pParser;
366 ProcessParseError(err_code);
367 return NULL;
368 }
369 CPDF_Document* pDoc = NULL;
370 pDoc = pParser ? pParser->GetDocument() : NULL;
371 CheckUnSupportError(pDoc, err_code);
372 CPDF_Document* pPDFDoc = pParser->GetDocument();
373 if (!pPDFDoc)
374 return NULL;
Bo Xufdc00a72014-10-28 23:03:33 -0700375
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700376 CPDFXFA_App* pProvider = CPDFXFA_App::GetInstance();
Lei Zhangcb78ef52015-10-02 10:10:49 -0700377 return new CPDFXFA_Document(pPDFDoc, pProvider);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700378}
379
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700380DLLEXPORT FPDF_BOOL STDCALL FPDF_GetFileVersion(FPDF_DOCUMENT doc,
381 int* fileVersion) {
Tom Sepez471a1032015-10-15 16:17:18 -0700382 if (!fileVersion)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700383 return FALSE;
Bo Xufdc00a72014-10-28 23:03:33 -0700384
Tom Sepez471a1032015-10-15 16:17:18 -0700385 *fileVersion = 0;
386 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(doc);
387 if (!pDoc)
388 return FALSE;
389
390 CPDF_Parser* pParser = pDoc->GetParser();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700391 if (!pParser)
392 return FALSE;
Tom Sepez471a1032015-10-15 16:17:18 -0700393
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700394 *fileVersion = pParser->GetFileVersion();
395 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700396}
397
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700398// jabdelmalek: changed return type from FX_DWORD to build on Linux (and match
399// header).
400DLLEXPORT unsigned long STDCALL FPDF_GetDocPermissions(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700401 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
402 if (!pDoc)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700403 return (FX_DWORD)-1;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700404
Tom Sepez471a1032015-10-15 16:17:18 -0700405 CPDF_Dictionary* pDict = pDoc->GetParser()->GetEncryptDict();
406 return pDict ? pDict->GetInteger("P") : (FX_DWORD)-1;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700407}
408
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700409DLLEXPORT int STDCALL FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700410 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
411 if (!pDoc)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700412 return -1;
Bo Xuc5cab022014-09-19 19:16:31 -0700413
Tom Sepez471a1032015-10-15 16:17:18 -0700414 CPDF_Dictionary* pDict = pDoc->GetParser()->GetEncryptDict();
415 return pDict ? pDict->GetInteger("R") : -1;
Bo Xuc5cab022014-09-19 19:16:31 -0700416}
417
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700418DLLEXPORT int STDCALL FPDF_GetPageCount(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700419 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
420 return pDoc ? pDoc->GetPageCount() : 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700421}
422
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700423DLLEXPORT FPDF_PAGE STDCALL FPDF_LoadPage(FPDF_DOCUMENT document,
424 int page_index) {
Tom Sepez471a1032015-10-15 16:17:18 -0700425 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
426 if (!pDoc)
427 return nullptr;
428
429 if (page_index < 0 || page_index >= FPDF_GetPageCount(document))
430 return nullptr;
431
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700432 return pDoc->GetPage(page_index);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700433}
434
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700435DLLEXPORT double STDCALL FPDF_GetPageWidth(FPDF_PAGE page) {
436 if (!page)
437 return 0.0;
438 return ((CPDFXFA_Page*)page)->GetPageWidth();
439 // return ((CPDF_Page*)page)->GetPageWidth();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700440}
441
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700442DLLEXPORT double STDCALL FPDF_GetPageHeight(FPDF_PAGE page) {
443 if (!page)
444 return 0.0;
445 // return ((CPDF_Page*)page)->GetPageHeight();
446 return ((CPDFXFA_Page*)page)->GetPageHeight();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700447}
448
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700449void DropContext(void* data) {
450 delete (CRenderContext*)data;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700451}
452
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700453#if defined(_DEBUG) || defined(DEBUG)
454#define DEBUG_TRACE
455#endif
456
457#if defined(_WIN32)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700458DLLEXPORT void STDCALL FPDF_RenderPage(HDC dc,
459 FPDF_PAGE page,
460 int start_x,
461 int start_y,
462 int size_x,
463 int size_y,
464 int rotate,
465 int flags) {
466 if (page == NULL)
467 return;
468 CPDF_Page* pPage = ((CPDFXFA_Page*)page)->GetPDFPage();
469 if (!pPage)
470 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700471
Tom Sepezae51c812015-08-05 12:34:06 -0700472 CRenderContext* pContext = new CRenderContext;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700473 pPage->SetPrivateData((void*)1, pContext, DropContext);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700474
475#ifndef _WIN32_WCE
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700476 CFX_DIBitmap* pBitmap = NULL;
477 FX_BOOL bBackgroundAlphaNeeded = FALSE;
478 bBackgroundAlphaNeeded = pPage->BackgroundAlphaNeeded();
479 if (bBackgroundAlphaNeeded) {
Tom Sepezae51c812015-08-05 12:34:06 -0700480 pBitmap = new CFX_DIBitmap;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700481 pBitmap->Create(size_x, size_y, FXDIB_Argb);
482 pBitmap->Clear(0x00ffffff);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700483#ifdef _SKIA_SUPPORT_
Tom Sepezae51c812015-08-05 12:34:06 -0700484 pContext->m_pDevice = new CFX_SkiaDevice;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700485 ((CFX_SkiaDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)pBitmap);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700486#else
Tom Sepezae51c812015-08-05 12:34:06 -0700487 pContext->m_pDevice = new CFX_FxgeDevice;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700488 ((CFX_FxgeDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)pBitmap);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700489#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700490 } else
Tom Sepezae51c812015-08-05 12:34:06 -0700491 pContext->m_pDevice = new CFX_WindowsDevice(dc);
Bo Xud4e406e2014-08-13 11:03:19 -0700492
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700493 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
494 rotate, flags, TRUE, NULL);
Bo Xud4e406e2014-08-13 11:03:19 -0700495
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700496 if (bBackgroundAlphaNeeded) {
497 if (pBitmap) {
498 CFX_WindowsDevice WinDC(dc);
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700499
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700500 if (WinDC.GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
Tom Sepezae51c812015-08-05 12:34:06 -0700501 CFX_DIBitmap* pDst = new CFX_DIBitmap;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700502 int pitch = pBitmap->GetPitch();
503 pDst->Create(size_x, size_y, FXDIB_Rgb32);
504 FXSYS_memset(pDst->GetBuffer(), -1, pitch * size_y);
505 pDst->CompositeBitmap(0, 0, size_x, size_y, pBitmap, 0, 0,
506 FXDIB_BLEND_NORMAL, NULL, FALSE, NULL);
507 WinDC.StretchDIBits(pDst, 0, 0, size_x, size_y);
508 delete pDst;
509 } else
510 WinDC.SetDIBits(pBitmap, 0, 0);
Lei Zhang6d8b1c22015-06-19 17:26:17 -0700511 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700512 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700513#else
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700514 // get clip region
515 RECT rect, cliprect;
516 rect.left = start_x;
517 rect.top = start_y;
518 rect.right = start_x + size_x;
519 rect.bottom = start_y + size_y;
520 GetClipBox(dc, &cliprect);
521 IntersectRect(&rect, &rect, &cliprect);
522 int width = rect.right - rect.left;
523 int height = rect.bottom - rect.top;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700524
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700525#ifdef DEBUG_TRACE
526 {
527 char str[128];
528 memset(str, 0, sizeof(str));
529 FXSYS_snprintf(str, sizeof(str) - 1, "Rendering DIB %d x %d", width,
530 height);
531 CPDF_ModuleMgr::Get()->ReportError(999, str);
532 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700533#endif
Bo Xud4e406e2014-08-13 11:03:19 -0700534
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700535 // Create a DIB section
536 LPVOID pBuffer;
537 BITMAPINFOHEADER bmih;
538 FXSYS_memset(&bmih, 0, sizeof bmih);
539 bmih.biSize = sizeof bmih;
540 bmih.biBitCount = 24;
541 bmih.biHeight = -height;
542 bmih.biPlanes = 1;
543 bmih.biWidth = width;
544 pContext->m_hBitmap = CreateDIBSection(dc, (BITMAPINFO*)&bmih, DIB_RGB_COLORS,
545 &pBuffer, NULL, 0);
546 if (pContext->m_hBitmap == NULL) {
547#if defined(DEBUG) || defined(_DEBUG)
548 char str[128];
549 memset(str, 0, sizeof(str));
550 FXSYS_snprintf(str, sizeof(str) - 1,
551 "Error CreateDIBSection: %d x %d, error code = %d", width,
552 height, GetLastError());
553 CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, str);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700554#else
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700555 CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700556#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700557 }
558 FXSYS_memset(pBuffer, 0xff, height * ((width * 3 + 3) / 4 * 4));
559
560#ifdef DEBUG_TRACE
561 { CPDF_ModuleMgr::Get()->ReportError(999, "DIBSection created"); }
562#endif
563
564 // Create a device with this external buffer
565 pContext->m_pBitmap = new CFX_DIBitmap;
566 pContext->m_pBitmap->Create(width, height, FXDIB_Rgb, (uint8_t*)pBuffer);
567 pContext->m_pDevice = new CPDF_FxgeDevice;
568 ((CPDF_FxgeDevice*)pContext->m_pDevice)->Attach(pContext->m_pBitmap);
569
570#ifdef DEBUG_TRACE
571 CPDF_ModuleMgr::Get()->ReportError(999, "Ready for PDF rendering");
572#endif
573
574 // output to bitmap device
575 FPDF_RenderPage_Retail(pContext, page, start_x - rect.left,
576 start_y - rect.top, size_x, size_y, rotate, flags);
577
578#ifdef DEBUG_TRACE
579 CPDF_ModuleMgr::Get()->ReportError(999, "Finished PDF rendering");
580#endif
581
582 // Now output to real device
583 HDC hMemDC = CreateCompatibleDC(dc);
584 if (hMemDC == NULL) {
585#if defined(DEBUG) || defined(_DEBUG)
586 char str[128];
587 memset(str, 0, sizeof(str));
588 FXSYS_snprintf(str, sizeof(str) - 1,
589 "Error CreateCompatibleDC. Error code = %d", GetLastError());
590 CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, str);
591#else
592 CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, NULL);
593#endif
594 }
595
596 HGDIOBJ hOldBitmap = SelectObject(hMemDC, pContext->m_hBitmap);
597
598#ifdef DEBUG_TRACE
599 CPDF_ModuleMgr::Get()->ReportError(999, "Ready for screen rendering");
600#endif
601
602 BitBlt(dc, rect.left, rect.top, width, height, hMemDC, 0, 0, SRCCOPY);
603 SelectObject(hMemDC, hOldBitmap);
604 DeleteDC(hMemDC);
605
606#ifdef DEBUG_TRACE
607 CPDF_ModuleMgr::Get()->ReportError(999, "Finished screen rendering");
608#endif
609
610#endif
611 if (bBackgroundAlphaNeeded) {
612 delete pBitmap;
613 pBitmap = NULL;
614 }
615 delete pContext;
616 pPage->RemovePrivateData((void*)1);
617}
618#endif
619
620DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap,
621 FPDF_PAGE page,
622 int start_x,
623 int start_y,
624 int size_x,
625 int size_y,
626 int rotate,
627 int flags) {
628 if (bitmap == NULL || page == NULL)
629 return;
630 CPDF_Page* pPage = ((CPDFXFA_Page*)page)->GetPDFPage();
631 if (!pPage)
632 return;
633
Tom Sepezae51c812015-08-05 12:34:06 -0700634 CRenderContext* pContext = new CRenderContext;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700635 pPage->SetPrivateData((void*)1, pContext, DropContext);
636#ifdef _SKIA_SUPPORT_
Tom Sepezae51c812015-08-05 12:34:06 -0700637 pContext->m_pDevice = new CFX_SkiaDevice;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700638
639 if (flags & FPDF_REVERSE_BYTE_ORDER)
640 ((CFX_SkiaDevice*)pContext->m_pDevice)
641 ->Attach((CFX_DIBitmap*)bitmap, 0, TRUE);
642 else
643 ((CFX_SkiaDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)bitmap);
644#else
Tom Sepezae51c812015-08-05 12:34:06 -0700645 pContext->m_pDevice = new CFX_FxgeDevice;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700646
647 if (flags & FPDF_REVERSE_BYTE_ORDER)
648 ((CFX_FxgeDevice*)pContext->m_pDevice)
649 ->Attach((CFX_DIBitmap*)bitmap, 0, TRUE);
650 else
651 ((CFX_FxgeDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)bitmap);
652#endif
653
654 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
655 rotate, flags, TRUE, NULL);
656
657 delete pContext;
658 pPage->RemovePrivateData((void*)1);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700659}
660
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700661DLLEXPORT void STDCALL FPDF_ClosePage(FPDF_PAGE page) {
662 if (!page)
663 return;
664
665 CPDFXFA_Page* pPage = (CPDFXFA_Page*)page;
666 pPage->Release();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700667}
668
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700669DLLEXPORT void STDCALL FPDF_CloseDocument(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700670 delete CPDFDocumentFromFPDFDocument(document);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700671}
672
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700673DLLEXPORT unsigned long STDCALL FPDF_GetLastError() {
674 return GetLastError();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700675}
676
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700677DLLEXPORT void STDCALL FPDF_DeviceToPage(FPDF_PAGE page,
678 int start_x,
679 int start_y,
680 int size_x,
681 int size_y,
682 int rotate,
683 int device_x,
684 int device_y,
685 double* page_x,
686 double* page_y) {
687 if (page == NULL || page_x == NULL || page_y == NULL)
688 return;
689 CPDFXFA_Page* pPage = (CPDFXFA_Page*)page;
690
691 pPage->DeviceToPage(start_x, start_y, size_x, size_y, rotate, device_x,
692 device_y, page_x, page_y);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700693}
694
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700695DLLEXPORT void STDCALL FPDF_PageToDevice(FPDF_PAGE page,
696 int start_x,
697 int start_y,
698 int size_x,
699 int size_y,
700 int rotate,
701 double page_x,
702 double page_y,
703 int* device_x,
704 int* device_y) {
705 if (page == NULL || device_x == NULL || device_y == NULL)
706 return;
707 CPDFXFA_Page* pPage = (CPDFXFA_Page*)page;
708 pPage->PageToDevice(start_x, start_y, size_x, size_y, rotate, page_x, page_y,
709 device_x, device_y);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700710}
711
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700712DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_Create(int width,
713 int height,
714 int alpha) {
715 nonstd::unique_ptr<CFX_DIBitmap> pBitmap(new CFX_DIBitmap);
716 if (!pBitmap->Create(width, height, alpha ? FXDIB_Argb : FXDIB_Rgb32)) {
717 return NULL;
718 }
719 return pBitmap.release();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700720}
721
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700722DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_CreateEx(int width,
723 int height,
724 int format,
725 void* first_scan,
726 int stride) {
727 FXDIB_Format fx_format;
728 switch (format) {
729 case FPDFBitmap_Gray:
730 fx_format = FXDIB_8bppRgb;
731 break;
732 case FPDFBitmap_BGR:
733 fx_format = FXDIB_Rgb;
734 break;
735 case FPDFBitmap_BGRx:
736 fx_format = FXDIB_Rgb32;
737 break;
738 case FPDFBitmap_BGRA:
739 fx_format = FXDIB_Argb;
740 break;
741 default:
742 return NULL;
743 }
744 CFX_DIBitmap* pBitmap = new CFX_DIBitmap;
745 pBitmap->Create(width, height, fx_format, (uint8_t*)first_scan, stride);
746 return pBitmap;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700747}
748
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700749DLLEXPORT void STDCALL FPDFBitmap_FillRect(FPDF_BITMAP bitmap,
750 int left,
751 int top,
752 int width,
753 int height,
754 FPDF_DWORD color) {
755 if (bitmap == NULL)
756 return;
757#ifdef _SKIA_SUPPORT_
758 CFX_SkiaDevice device;
759#else
760 CFX_FxgeDevice device;
761#endif
762 device.Attach((CFX_DIBitmap*)bitmap);
763 if (!((CFX_DIBitmap*)bitmap)->HasAlpha())
764 color |= 0xFF000000;
765 FX_RECT rect(left, top, left + width, top + height);
766 device.FillRect(&rect, color);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700767}
768
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700769DLLEXPORT void* STDCALL FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap) {
770 if (bitmap == NULL)
771 return NULL;
772 return ((CFX_DIBitmap*)bitmap)->GetBuffer();
Bo Xu9114e832014-07-14 13:22:47 -0700773}
774
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700775DLLEXPORT int STDCALL FPDFBitmap_GetWidth(FPDF_BITMAP bitmap) {
776 if (bitmap == NULL)
777 return 0;
778 return ((CFX_DIBitmap*)bitmap)->GetWidth();
Bo Xu9114e832014-07-14 13:22:47 -0700779}
780
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700781DLLEXPORT int STDCALL FPDFBitmap_GetHeight(FPDF_BITMAP bitmap) {
782 if (bitmap == NULL)
783 return 0;
784 return ((CFX_DIBitmap*)bitmap)->GetHeight();
785}
786
787DLLEXPORT int STDCALL FPDFBitmap_GetStride(FPDF_BITMAP bitmap) {
788 if (bitmap == NULL)
789 return 0;
790 return ((CFX_DIBitmap*)bitmap)->GetPitch();
791}
792
793DLLEXPORT void STDCALL FPDFBitmap_Destroy(FPDF_BITMAP bitmap) {
794 delete (CFX_DIBitmap*)bitmap;
795}
796
797void FPDF_RenderPage_Retail(CRenderContext* pContext,
798 FPDF_PAGE page,
799 int start_x,
800 int start_y,
801 int size_x,
802 int size_y,
803 int rotate,
804 int flags,
805 FX_BOOL bNeedToRestore,
806 IFSDK_PAUSE_Adapter* pause) {
807 CPDF_Page* pPage = ((CPDFXFA_Page*)page)->GetPDFPage();
808 if (pPage == NULL)
809 return;
810
811 if (!pContext->m_pOptions)
812 pContext->m_pOptions = new CPDF_RenderOptions;
813
814 if (flags & FPDF_LCD_TEXT)
815 pContext->m_pOptions->m_Flags |= RENDER_CLEARTYPE;
816 else
817 pContext->m_pOptions->m_Flags &= ~RENDER_CLEARTYPE;
818 if (flags & FPDF_NO_NATIVETEXT)
819 pContext->m_pOptions->m_Flags |= RENDER_NO_NATIVETEXT;
820 if (flags & FPDF_RENDER_LIMITEDIMAGECACHE)
821 pContext->m_pOptions->m_Flags |= RENDER_LIMITEDIMAGECACHE;
822 if (flags & FPDF_RENDER_FORCEHALFTONE)
823 pContext->m_pOptions->m_Flags |= RENDER_FORCE_HALFTONE;
824 // Grayscale output
825 if (flags & FPDF_GRAYSCALE) {
826 pContext->m_pOptions->m_ColorMode = RENDER_COLOR_GRAY;
827 pContext->m_pOptions->m_ForeColor = 0;
828 pContext->m_pOptions->m_BackColor = 0xffffff;
829 }
830 const CPDF_OCContext::UsageType usage =
831 (flags & FPDF_PRINTING) ? CPDF_OCContext::Print : CPDF_OCContext::View;
832 pContext->m_pOptions->m_AddFlags = flags >> 8;
833 pContext->m_pOptions->m_pOCContext =
834 new CPDF_OCContext(pPage->m_pDocument, usage);
835
836 CFX_AffineMatrix matrix;
837 pPage->GetDisplayMatrix(matrix, start_x, start_y, size_x, size_y, rotate);
838
839 FX_RECT clip;
840 clip.left = start_x;
841 clip.right = start_x + size_x;
842 clip.top = start_y;
843 clip.bottom = start_y + size_y;
844 pContext->m_pDevice->SaveState();
845 pContext->m_pDevice->SetClip_Rect(&clip);
846
Tom Sepezae51c812015-08-05 12:34:06 -0700847 pContext->m_pContext = new CPDF_RenderContext;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700848 pContext->m_pContext->Create(pPage);
849 pContext->m_pContext->AppendObjectList(pPage, &matrix);
850
851 if (flags & FPDF_ANNOT) {
Tom Sepezae51c812015-08-05 12:34:06 -0700852 pContext->m_pAnnots = new CPDF_AnnotList(pPage);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700853 FX_BOOL bPrinting = pContext->m_pDevice->GetDeviceClass() != FXDC_DISPLAY;
854 pContext->m_pAnnots->DisplayAnnots(pPage, pContext->m_pContext, bPrinting,
855 &matrix, TRUE, NULL);
856 }
857
Tom Sepezae51c812015-08-05 12:34:06 -0700858 pContext->m_pRenderer = new CPDF_ProgressiveRenderer;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700859 pContext->m_pRenderer->Start(pContext->m_pContext, pContext->m_pDevice,
860 pContext->m_pOptions, pause);
861 if (bNeedToRestore) {
862 pContext->m_pDevice->RestoreState();
863 }
864
865 //#endif
866}
867
868DLLEXPORT int STDCALL FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document,
869 int page_index,
870 double* width,
871 double* height) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700872 CPDFXFA_Document* pDoc = (CPDFXFA_Document*)document;
873 if (pDoc == NULL)
874 return FALSE;
875
876 int count = pDoc->GetPageCount();
877 if (page_index < 0 || page_index >= count)
878 return FALSE;
879
880 CPDFXFA_Page* pPage = pDoc->GetPage(page_index);
881 if (!pPage)
882 return FALSE;
883
884 *width = pPage->GetPageWidth();
885 *height = pPage->GetPageHeight();
886
887 return TRUE;
888}
889
890DLLEXPORT FPDF_BOOL STDCALL
891FPDF_VIEWERREF_GetPrintScaling(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700892 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700893 if (!pDoc)
894 return TRUE;
Tom Sepez471a1032015-10-15 16:17:18 -0700895 CPDF_ViewerPreferences viewRef(pDoc);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700896 return viewRef.PrintScaling();
897}
898
899DLLEXPORT int STDCALL FPDF_VIEWERREF_GetNumCopies(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700900 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700901 if (!pDoc)
902 return 1;
903 CPDF_ViewerPreferences viewRef(pDoc);
904 return viewRef.NumCopies();
905}
906
907DLLEXPORT FPDF_PAGERANGE STDCALL
908FPDF_VIEWERREF_GetPrintPageRange(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700909 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700910 if (!pDoc)
911 return NULL;
912 CPDF_ViewerPreferences viewRef(pDoc);
913 return viewRef.PrintPageRange();
914}
915
916DLLEXPORT FPDF_DUPLEXTYPE STDCALL
917FPDF_VIEWERREF_GetDuplex(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700918 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700919 if (!pDoc)
Bo Xu9114e832014-07-14 13:22:47 -0700920 return DuplexUndefined;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700921 CPDF_ViewerPreferences viewRef(pDoc);
922 CFX_ByteString duplex = viewRef.Duplex();
923 if (FX_BSTRC("Simplex") == duplex)
924 return Simplex;
925 if (FX_BSTRC("DuplexFlipShortEdge") == duplex)
926 return DuplexFlipShortEdge;
927 if (FX_BSTRC("DuplexFlipLongEdge") == duplex)
928 return DuplexFlipLongEdge;
929 return DuplexUndefined;
Bo Xu9114e832014-07-14 13:22:47 -0700930}
931
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700932DLLEXPORT FPDF_DWORD STDCALL FPDF_CountNamedDests(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700933 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
934 if (!pDoc)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700935 return 0;
Bo Xu4d62b6b2015-01-10 22:52:59 -0800936
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700937 CPDF_Dictionary* pRoot = pDoc->GetRoot();
938 if (!pRoot)
939 return 0;
Bo Xu4d62b6b2015-01-10 22:52:59 -0800940
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700941 CPDF_NameTree nameTree(pDoc, FX_BSTRC("Dests"));
942 int count = nameTree.GetCount();
943 CPDF_Dictionary* pDest = pRoot->GetDict(FX_BSTRC("Dests"));
944 if (pDest)
945 count += pDest->GetCount();
946 return count;
947}
948
949DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDestByName(FPDF_DOCUMENT document,
950 FPDF_BYTESTRING name) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700951 if (!name || name[0] == 0)
Tom Sepez471a1032015-10-15 16:17:18 -0700952 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700953
Tom Sepez471a1032015-10-15 16:17:18 -0700954 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
955 if (!pDoc)
956 return nullptr;
957
958 CPDF_NameTree name_tree(pDoc, FX_BSTRC("Dests"));
959 return name_tree.LookupNamedDest(pDoc, name);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700960}
961
962FPDF_RESULT FPDF_BStr_Init(FPDF_BSTR* str) {
963 if (!str)
964 return -1;
965
966 FXSYS_memset(str, 0, sizeof(FPDF_BSTR));
967 return 0;
968}
969
970FPDF_RESULT FPDF_BStr_Set(FPDF_BSTR* str, FPDF_LPCSTR bstr, int length) {
971 if (!str)
972 return -1;
973 if (!bstr || !length)
974 return -1;
975 if (length == -1)
976 length = FXSYS_strlen(bstr);
977
978 if (length == 0) {
979 if (str->str) {
980 FX_Free(str->str);
981 str->str = NULL;
982 }
983 str->len = 0;
984 return 0;
985 }
986
987 if (str->str && str->len < length)
988 str->str = FX_Realloc(char, str->str, length + 1);
989 else if (!str->str)
990 str->str = FX_Alloc(char, length + 1);
991
992 str->str[length] = 0;
993 if (str->str == NULL)
994 return -1;
995
996 FXSYS_memcpy(str->str, bstr, length);
997 str->len = length;
998
999 return 0;
1000}
1001
1002FPDF_RESULT FPDF_BStr_Clear(FPDF_BSTR* str) {
1003 if (!str)
1004 return -1;
1005
1006 if (str->str) {
1007 FX_Free(str->str);
1008 str->str = NULL;
1009 }
1010 str->len = 0;
1011 return 0;
1012}
1013
1014DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDest(FPDF_DOCUMENT document,
1015 int index,
1016 void* buffer,
1017 long* buflen) {
1018 if (!buffer)
1019 *buflen = 0;
1020 if (!document || index < 0)
1021 return NULL;
1022 CPDF_Document* pDoc = ((CPDFXFA_Document*)document)->GetPDFDoc();
1023
1024 CPDF_Dictionary* pRoot = pDoc->GetRoot();
1025 if (!pRoot)
1026 return NULL;
1027
1028 CPDF_Object* pDestObj = NULL;
1029 CFX_ByteString bsName;
1030 CPDF_NameTree nameTree(pDoc, FX_BSTRC("Dests"));
1031 int count = nameTree.GetCount();
1032 if (index >= count) {
Bo Xu4d62b6b2015-01-10 22:52:59 -08001033 CPDF_Dictionary* pDest = pRoot->GetDict(FX_BSTRC("Dests"));
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001034 if (!pDest)
1035 return NULL;
1036 if (index >= count + pDest->GetCount())
1037 return NULL;
1038 index -= count;
1039 FX_POSITION pos = pDest->GetStartPos();
1040 int i = 0;
1041 while (pos) {
1042 pDestObj = pDest->GetNextElement(pos, bsName);
1043 if (!pDestObj)
1044 continue;
1045 if (i == index)
1046 break;
1047 i++;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001048 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001049 } else {
1050 pDestObj = nameTree.LookupValue(index, bsName);
1051 }
1052 if (!pDestObj)
1053 return NULL;
1054 if (pDestObj->GetType() == PDFOBJ_DICTIONARY) {
1055 pDestObj = ((CPDF_Dictionary*)pDestObj)->GetArray(FX_BSTRC("D"));
1056 if (!pDestObj)
1057 return NULL;
1058 }
1059 if (pDestObj->GetType() != PDFOBJ_ARRAY)
1060 return NULL;
1061 CFX_WideString wsName = PDF_DecodeText(bsName);
1062 CFX_ByteString utf16Name = wsName.UTF16LE_Encode();
1063 unsigned int len = utf16Name.GetLength();
1064 if (!buffer) {
1065 *buflen = len;
1066 } else if (*buflen >= len) {
1067 memcpy(buffer, utf16Name.c_str(), len);
1068 *buflen = len;
1069 } else {
1070 *buflen = -1;
1071 }
1072 return (FPDF_DEST)pDestObj;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001073}