blob: 80a9fa52a3bc9876bab6c5c07639478f7c6d0bfe [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"
23
24CFPDF_FileStream::CFPDF_FileStream(FPDF_FILEHANDLER* pFS)
25{
26 m_pFS = pFS;
27 m_nCurPos = 0;
28}
29
30IFX_FileStream* CFPDF_FileStream::Retain()
31{
32 return this;
33}
34
35void CFPDF_FileStream::Release()
36{
37 if (m_pFS && m_pFS->Release)
38 m_pFS->Release(m_pFS->clientData);
39 delete this;
40}
41
42FX_FILESIZE CFPDF_FileStream::GetSize()
43{
44 if (m_pFS && m_pFS->GetSize)
45 return (FX_FILESIZE)m_pFS->GetSize(m_pFS->clientData);
46 return 0;
47}
48
49FX_BOOL CFPDF_FileStream::IsEOF()
50{
51 return m_nCurPos >= GetSize();
52}
53
54FX_BOOL CFPDF_FileStream::ReadBlock(void* buffer, FX_FILESIZE offset, size_t size)
55{
56 if (!buffer || !size || !m_pFS->ReadBlock) return FALSE;
57
58 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer, (FPDF_DWORD)size) == 0)
59 {
60 m_nCurPos = offset + size;
61 return TRUE;
62 }
63 return FALSE;
64}
65
66size_t CFPDF_FileStream::ReadBlock(void* buffer, size_t size)
67{
68 if (!buffer || !size || !m_pFS->ReadBlock) return 0;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -070069
Bo Xufdc00a72014-10-28 23:03:33 -070070 FX_FILESIZE nSize = GetSize();
71 if (m_nCurPos >= nSize) return 0;
72 FX_FILESIZE dwAvail = nSize - m_nCurPos;
73 if (dwAvail < (FX_FILESIZE)size) size = (size_t)dwAvail;
74 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)m_nCurPos, buffer, (FPDF_DWORD)size) == 0)
75 {
76 m_nCurPos += size;
77 return size;
78 }
79
80 return 0;
81}
82
83FX_BOOL CFPDF_FileStream::WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size)
84{
85 if (!m_pFS || !m_pFS->WriteBlock) return FALSE;
86
87 if(m_pFS->WriteBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer, (FPDF_DWORD)size) == 0)
88 {
89 m_nCurPos = offset + size;
90 return TRUE;
91 }
92 return FALSE;
93}
94
95FX_BOOL CFPDF_FileStream::Flush()
96{
97 if (!m_pFS || !m_pFS->Flush) return TRUE;
98
99 return m_pFS->Flush(m_pFS->clientData) == 0;
100}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700101
102CPDF_CustomAccess::CPDF_CustomAccess(FPDF_FILEACCESS* pFileAccess)
103{
Bo Xufdc00a72014-10-28 23:03:33 -0700104 m_FileAccess = *pFileAccess;
105 m_BufferOffset = (FX_DWORD)-1;
106}
107
Tom Sepezbfa9a822015-06-09 13:24:12 -0700108FX_BOOL CPDF_CustomAccess::GetByte(FX_DWORD pos, uint8_t& ch)
Bo Xufdc00a72014-10-28 23:03:33 -0700109{
110 if (pos >= m_FileAccess.m_FileLen) return FALSE;
111 if (m_BufferOffset == (FX_DWORD)-1 || pos < m_BufferOffset || pos >= m_BufferOffset + 512) {
112 // Need to read from file access
113 m_BufferOffset = pos;
114 int size = 512;
115 if (pos + 512 > m_FileAccess.m_FileLen)
116 size = m_FileAccess.m_FileLen - pos;
117 if (!m_FileAccess.m_GetBlock(m_FileAccess.m_Param, m_BufferOffset, m_Buffer, size))
118 return FALSE;
119 }
120 ch = m_Buffer[pos - m_BufferOffset];
121 return TRUE;
122}
123
Tom Sepezd7e5cc72015-06-10 14:33:37 -0700124FX_BOOL CPDF_CustomAccess::GetBlock(FX_DWORD pos, uint8_t* pBuf, FX_DWORD size)
Bo Xufdc00a72014-10-28 23:03:33 -0700125{
126 if (pos + size > m_FileAccess.m_FileLen) return FALSE;
127 return m_FileAccess.m_GetBlock(m_FileAccess.m_Param, pos, pBuf, size);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700128}
129
130FX_BOOL CPDF_CustomAccess::ReadBlock(void* buffer, FX_FILESIZE offset, size_t size)
131{
Bo Xu465c2a82014-08-02 15:13:46 -0700132 if (offset < 0) {
133 return FALSE;
134 }
Tom Sepez35425892015-02-05 10:03:18 -0800135 FX_SAFE_FILESIZE newPos = pdfium::base::checked_cast<FX_FILESIZE, size_t>(size);
Bo Xu465c2a82014-08-02 15:13:46 -0700136 newPos += offset;
137 if (!newPos.IsValid() || newPos.ValueOrDie() > m_FileAccess.m_FileLen) {
138 return FALSE;
139 }
Tom Sepezd7e5cc72015-06-10 14:33:37 -0700140 return m_FileAccess.m_GetBlock(m_FileAccess.m_Param, offset,(uint8_t*) buffer, size);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700141}
142
143//0 bit: FPDF_POLICY_MACHINETIME_ACCESS
144static FX_DWORD foxit_sandbox_policy = 0xFFFFFFFF;
145
146void FSDK_SetSandBoxPolicy(FPDF_DWORD policy, FPDF_BOOL enable)
147{
148 switch(policy)
149 {
150 case FPDF_POLICY_MACHINETIME_ACCESS:
151 {
152 if(enable)
153 foxit_sandbox_policy |= 0x01;
154 else
155 foxit_sandbox_policy &= 0xFFFFFFFE;
156 }
157 break;
158 default:
159 break;
160 }
161}
162
163FPDF_BOOL FSDK_IsSandBoxPolicyEnabled(FPDF_DWORD policy)
164{
165 switch(policy)
166 {
167 case FPDF_POLICY_MACHINETIME_ACCESS:
168 {
169 if(foxit_sandbox_policy&0x01)
170 return TRUE;
171 else
172 return FALSE;
173 }
174 break;
175 default:
176 break;
177 }
178 return FALSE;
179}
180
Tom Sepez2c286192015-06-18 12:47:11 -0700181CCodec_ModuleMgr* g_pCodecModule = nullptr;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700182
John Abd-El-Malek207299b2014-12-15 12:13:45 -0800183DLLEXPORT void STDCALL FPDF_InitLibrary()
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700184{
Tom Sepez2c286192015-06-18 12:47:11 -0700185 g_pCodecModule = new CCodec_ModuleMgr();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700186
Tom Sepezbdeeb8a2015-05-27 12:25:00 -0700187 CFX_GEModule::Create();
188 CFX_GEModule::Get()->SetCodecModule(g_pCodecModule);
189
190 CPDF_ModuleMgr::Create();
191 CPDF_ModuleMgr::Get()->SetCodecModule(g_pCodecModule);
192 CPDF_ModuleMgr::Get()->InitPageModule();
193 CPDF_ModuleMgr::Get()->InitRenderModule();
194
195 CPDFXFA_App::GetInstance()->Initialize();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700196}
197
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700198DLLEXPORT void STDCALL FPDF_DestroyLibrary()
199{
Tom Sepezbdeeb8a2015-05-27 12:25:00 -0700200 CPDFXFA_App::ReleaseInstance();
201 CPDF_ModuleMgr::Destroy();
202 CFX_GEModule::Destroy();
Tom Sepez2c286192015-06-18 12:47:11 -0700203
204 delete g_pCodecModule;
205 g_pCodecModule = nullptr;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700206}
207
208#ifndef _WIN32
209int g_LastError;
210void SetLastError(int err)
211{
212 g_LastError = err;
213}
214
215int GetLastError()
216{
217 return g_LastError;
218}
219#endif
220
221void ProcessParseError(FX_DWORD err_code)
222{
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);
239}
240
241DLLEXPORT void STDCALL FPDF_SetSandBoxPolicy(FPDF_DWORD policy, FPDF_BOOL enable)
242{
243 return FSDK_SetSandBoxPolicy(policy, enable);
244}
245
246DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadDocument(FPDF_STRING file_path, FPDF_BYTESTRING password)
247{
248 CPDF_Parser* pParser = FX_NEW CPDF_Parser;
249 pParser->SetPassword(password);
Bo Xud4e406e2014-08-13 11:03:19 -0700250
Tom Sepezd7e5cc72015-06-10 14:33:37 -0700251 FX_DWORD err_code = pParser->StartParse((const FX_CHAR*)file_path);
Bo Xud4e406e2014-08-13 11:03:19 -0700252 if (err_code) {
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700253 delete pParser;
Bo Xud4e406e2014-08-13 11:03:19 -0700254 ProcessParseError(err_code);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700255 return NULL;
256 }
Bo Xufdc00a72014-10-28 23:03:33 -0700257 CPDF_Document* pPDFDoc = pParser->GetDocument();
258 if (!pPDFDoc)
259 return NULL;
260
Tom Sepezbdeeb8a2015-05-27 12:25:00 -0700261 CPDFXFA_App* pProvider = CPDFXFA_App::GetInstance();
Bo Xufdc00a72014-10-28 23:03:33 -0700262 CPDFXFA_Document* pDocument = FX_NEW CPDFXFA_Document(pPDFDoc, pProvider);
263 return pDocument;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700264}
Jun Fange118ce92015-02-17 06:50:08 -0800265
Tom Sepezcf22eb82015-05-12 17:28:08 -0700266DLLEXPORT FX_BOOL STDCALL FPDF_HasXFAField(FPDF_DOCUMENT document, int* docType)
JUN FANG827a1722015-03-05 13:39:21 -0800267{
268 if (!document)
269 return FALSE;
270
271 CPDF_Document *pdfDoc = (static_cast<CPDFXFA_Document *>(document))->GetPDFDoc();
272 if (!pdfDoc)
273 return FALSE;
274
275 CPDF_Dictionary* pRoot = pdfDoc->GetRoot();
276 if (!pRoot)
277 return FALSE;
278
279 CPDF_Dictionary* pAcroForm = pRoot->GetDict("AcroForm");
280 if (!pAcroForm)
281 return FALSE;
282
283 CPDF_Object* pXFA = pAcroForm->GetElement("XFA");
284 if (!pXFA)
285 return FALSE;
286
287 FX_BOOL bDynamicXFA = pRoot->GetBoolean("NeedsRendering", FALSE);
288
289 if (bDynamicXFA)
Tom Sepezcf22eb82015-05-12 17:28:08 -0700290 *docType = DOCTYPE_DYNIMIC_XFA;
JUN FANG827a1722015-03-05 13:39:21 -0800291 else
Tom Sepezcf22eb82015-05-12 17:28:08 -0700292 *docType = DOCTYPE_STATIC_XFA;
JUN FANG827a1722015-03-05 13:39:21 -0800293
294 return TRUE;
Jun Fange118ce92015-02-17 06:50:08 -0800295}
296
Bo Xufdc00a72014-10-28 23:03:33 -0700297DLLEXPORT FPDF_BOOL STDCALL FPDF_LoadXFA(FPDF_DOCUMENT document)
298{
JUN FANG827a1722015-03-05 13:39:21 -0800299 return document && (static_cast<CPDFXFA_Document *>(document))->LoadXFADoc();
Bo Xufdc00a72014-10-28 23:03:33 -0700300}
301
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700302
303extern void CheckUnSupportError(CPDF_Document * pDoc, FX_DWORD err_code);
304
Tom Sepezb1161362015-06-09 11:29:12 -0700305class CMemFile final : public IFX_FileRead
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700306{
307public:
Tom Sepezbfa9a822015-06-09 13:24:12 -0700308 CMemFile(uint8_t* pBuf, FX_FILESIZE size):m_pBuf(pBuf),m_size(size) {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700309
310 virtual void Release() {delete this;}
311 virtual FX_FILESIZE GetSize() {return m_size;}
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700312 virtual FX_BOOL ReadBlock(void* buffer, FX_FILESIZE offset, size_t size)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700313 {
Jun Fangdf449c02014-08-07 10:08:19 -0700314 if (offset < 0) {
315 return FALSE;
316 }
Tom Sepez35425892015-02-05 10:03:18 -0800317 FX_SAFE_FILESIZE newPos = pdfium::base::checked_cast<FX_FILESIZE, size_t>(size);
Jun Fangdf449c02014-08-07 10:08:19 -0700318 newPos += offset;
319 if (!newPos.IsValid() || newPos.ValueOrDie() > (FX_DWORD)m_size) {
320 return FALSE;
321 }
322 FXSYS_memcpy(buffer, m_pBuf+offset, size);
323 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700324 }
325private:
Tom Sepezbfa9a822015-06-09 13:24:12 -0700326 uint8_t* m_pBuf;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700327 FX_FILESIZE m_size;
328};
329DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadMemDocument(const void* data_buf, int size, FPDF_BYTESTRING password)
330{
331 CPDF_Parser* pParser = FX_NEW CPDF_Parser;
332 pParser->SetPassword(password);
Tom Sepezbfa9a822015-06-09 13:24:12 -0700333 CMemFile* pMemFile = new CMemFile((uint8_t*)data_buf, size);
Bo Xud4e406e2014-08-13 11:03:19 -0700334 FX_DWORD err_code = pParser->StartParse(pMemFile);
335 if (err_code) {
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700336 delete pParser;
Bo Xud4e406e2014-08-13 11:03:19 -0700337 ProcessParseError(err_code);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700338 return NULL;
339 }
Bo Xud4e406e2014-08-13 11:03:19 -0700340 CPDF_Document * pDoc = NULL;
341 pDoc = pParser?pParser->GetDocument():NULL;
342 CheckUnSupportError(pDoc, err_code);
Bo Xufdc00a72014-10-28 23:03:33 -0700343 CPDF_Document* pPDFDoc = pParser->GetDocument();
344 if (!pPDFDoc)
345 return NULL;
346
Tom Sepezbdeeb8a2015-05-27 12:25:00 -0700347 CPDFXFA_App* pProvider = CPDFXFA_App::GetInstance();
Bo Xufdc00a72014-10-28 23:03:33 -0700348 CPDFXFA_Document* pDocument = FX_NEW CPDFXFA_Document(pPDFDoc, pProvider);
Bo Xufdc00a72014-10-28 23:03:33 -0700349 return pDocument;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700350}
351
352DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadCustomDocument(FPDF_FILEACCESS* pFileAccess, FPDF_BYTESTRING password)
353{
354 CPDF_Parser* pParser = FX_NEW CPDF_Parser;
355 pParser->SetPassword(password);
356 CPDF_CustomAccess* pFile = FX_NEW CPDF_CustomAccess(pFileAccess);
Bo Xud4e406e2014-08-13 11:03:19 -0700357 FX_DWORD err_code = pParser->StartParse(pFile);
358 if (err_code) {
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700359 delete pParser;
Bo Xud4e406e2014-08-13 11:03:19 -0700360 ProcessParseError(err_code);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700361 return NULL;
362 }
Bo Xud4e406e2014-08-13 11:03:19 -0700363 CPDF_Document * pDoc = NULL;
364 pDoc = pParser?pParser->GetDocument():NULL;
365 CheckUnSupportError(pDoc, err_code);
Bo Xufdc00a72014-10-28 23:03:33 -0700366 CPDF_Document* pPDFDoc = pParser->GetDocument();
367 if (!pPDFDoc)
368 return NULL;
369
Tom Sepezbdeeb8a2015-05-27 12:25:00 -0700370 CPDFXFA_App* pProvider = CPDFXFA_App::GetInstance();
Bo Xufdc00a72014-10-28 23:03:33 -0700371 CPDFXFA_Document* pDocument = FX_NEW CPDFXFA_Document(pPDFDoc, pProvider);
Bo Xufdc00a72014-10-28 23:03:33 -0700372 return pDocument;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700373}
374
375DLLEXPORT FPDF_BOOL STDCALL FPDF_GetFileVersion(FPDF_DOCUMENT doc, int* fileVersion)
376{
377 if(!doc||!fileVersion) return FALSE;
378 *fileVersion = 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700379 CPDFXFA_Document* pDoc = (CPDFXFA_Document*)doc;
380 CPDF_Document* pPDFDoc = pDoc->GetPDFDoc();
381 if (!pPDFDoc) return (FX_DWORD)-1;
382 CPDF_Parser* pParser = (CPDF_Parser*)pPDFDoc->GetParser();
383
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700384 if(!pParser)
385 return FALSE;
386 *fileVersion = pParser->GetFileVersion();
387 return TRUE;
388}
389
390// jabdelmalek: changed return type from FX_DWORD to build on Linux (and match header).
391DLLEXPORT unsigned long STDCALL FPDF_GetDocPermissions(FPDF_DOCUMENT document)
392{
393 if (document == NULL) return 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700394 CPDFXFA_Document*pDoc = (CPDFXFA_Document*)document;
395 CPDF_Document* pPDFDoc = pDoc->GetPDFDoc();
396 if (!pPDFDoc) return (FX_DWORD)-1;
397 CPDF_Parser* pParser = (CPDF_Parser*)pPDFDoc->GetParser();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700398 CPDF_Dictionary* pDict = pParser->GetEncryptDict();
399 if (pDict == NULL) return (FX_DWORD)-1;
400
401 return pDict->GetInteger("P");
402}
403
Bo Xuc5cab022014-09-19 19:16:31 -0700404DLLEXPORT int STDCALL FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document)
405{
406 if (document == NULL) return -1;
Bo Xu4d62b6b2015-01-10 22:52:59 -0800407 CPDF_Document*pDoc = ((CPDFXFA_Document*)document)->GetPDFDoc();
Bo Xuc5cab022014-09-19 19:16:31 -0700408 CPDF_Parser* pParser = (CPDF_Parser*)pDoc->GetParser();
409 CPDF_Dictionary* pDict = pParser->GetEncryptDict();
410 if (pDict == NULL) return -1;
411
412 return pDict->GetInteger("R");
413}
414
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700415DLLEXPORT int STDCALL FPDF_GetPageCount(FPDF_DOCUMENT document)
416{
417 if (document == NULL) return 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700418 CPDFXFA_Document* pDoc = (CPDFXFA_Document*)document;
419 return pDoc->GetPageCount();
420// return ((CPDF_Document*)document)->GetPageCount();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700421}
422
423DLLEXPORT FPDF_PAGE STDCALL FPDF_LoadPage(FPDF_DOCUMENT document, int page_index)
424{
425 if (document == NULL) return NULL;
Bo Xufdc00a72014-10-28 23:03:33 -0700426 CPDFXFA_Document* pDoc = (CPDFXFA_Document*)document;
427 if (page_index < 0 || page_index >= pDoc->GetPageCount()) return NULL;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700428// CPDF_Parser* pParser = (CPDF_Parser*)document;
Bo Xufdc00a72014-10-28 23:03:33 -0700429 return pDoc->GetPage(page_index);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700430}
431
432DLLEXPORT double STDCALL FPDF_GetPageWidth(FPDF_PAGE page)
433{
434 if (!page)
435 return 0.0;
Bo Xufdc00a72014-10-28 23:03:33 -0700436 return ((CPDFXFA_Page*)page)->GetPageWidth();
437// return ((CPDF_Page*)page)->GetPageWidth();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700438}
439
440DLLEXPORT double STDCALL FPDF_GetPageHeight(FPDF_PAGE page)
441{
442 if (!page) return 0.0;
Bo Xufdc00a72014-10-28 23:03:33 -0700443// return ((CPDF_Page*)page)->GetPageHeight();
444 return ((CPDFXFA_Page*)page)->GetPageHeight();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700445}
446
447void DropContext(void* data)
448{
449 delete (CRenderContext*)data;
450}
451
452void FPDF_RenderPage_Retail(CRenderContext* pContext, FPDF_PAGE page, int start_x, int start_y, int size_x, int size_y,
453 int rotate, int flags,FX_BOOL bNeedToRestore, IFSDK_PAUSE_Adapter * pause );
454void (*Func_RenderPage)(CRenderContext*, FPDF_PAGE page, int start_x, int start_y, int size_x, int size_y,
455 int rotate, int flags,FX_BOOL bNeedToRestore, IFSDK_PAUSE_Adapter * pause ) = FPDF_RenderPage_Retail;
456
457#if defined(_DEBUG) || defined(DEBUG)
458#define DEBUG_TRACE
459#endif
460
461#if defined(_WIN32)
462DLLEXPORT void STDCALL FPDF_RenderPage(HDC dc, FPDF_PAGE page, int start_x, int start_y, int size_x, int size_y,
463 int rotate, int flags)
464{
465 if (page==NULL) return;
Bo Xufdc00a72014-10-28 23:03:33 -0700466 CPDF_Page* pPage = ((CPDFXFA_Page*)page)->GetPDFPage();
467 if (!pPage) return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700468
469 CRenderContext* pContext = FX_NEW CRenderContext;
470 pPage->SetPrivateData((void*)1, pContext, DropContext);
471
472#ifndef _WIN32_WCE
473 CFX_DIBitmap* pBitmap = NULL;
474 FX_BOOL bBackgroundAlphaNeeded=FALSE;
475 bBackgroundAlphaNeeded = pPage->BackgroundAlphaNeeded();
476 if (bBackgroundAlphaNeeded)
477 {
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700478
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700479 pBitmap = FX_NEW CFX_DIBitmap;
480 pBitmap->Create(size_x, size_y, FXDIB_Argb);
481 pBitmap->Clear(0x00ffffff);
482#ifdef _SKIA_SUPPORT_
483 pContext->m_pDevice = FX_NEW CFX_SkiaDevice;
484 ((CFX_SkiaDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)pBitmap);
485#else
486 pContext->m_pDevice = FX_NEW CFX_FxgeDevice;
487 ((CFX_FxgeDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)pBitmap);
488#endif
489 }
490 else
Bo Xu0f141852014-07-23 10:09:08 -0700491 pContext->m_pDevice = FX_NEW CFX_WindowsDevice(dc);
Bo Xud4e406e2014-08-13 11:03:19 -0700492
493 Func_RenderPage(pContext, page, start_x, start_y, size_x, size_y, rotate, flags,TRUE,NULL);
494
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700495 if (bBackgroundAlphaNeeded)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700496 {
497 if (pBitmap)
498 {
499 CFX_WindowsDevice WinDC(dc);
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700500
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700501 if (WinDC.GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER)
502 {
503 CFX_DIBitmap* pDst = FX_NEW CFX_DIBitmap;
Bo Xu7b6bcab2015-01-05 10:11:47 -0800504 int pitch = pBitmap->GetPitch();
505 pDst->Create(size_x, size_y, FXDIB_Rgb32);
506 FXSYS_memset(pDst->GetBuffer(), -1, pitch*size_y);
507 pDst->CompositeBitmap(0, 0, size_x, size_y, pBitmap, 0, 0, FXDIB_BLEND_NORMAL, NULL, FALSE, NULL);
Bo Xu0f141852014-07-23 10:09:08 -0700508 WinDC.StretchDIBits(pDst,0,0,size_x,size_y);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700509 delete pDst;
510 }
511 else
512 WinDC.SetDIBits(pBitmap,0,0);
513
514 }
515 }
516#else
517 // get clip region
518 RECT rect, cliprect;
519 rect.left = start_x;
520 rect.top = start_y;
521 rect.right = start_x + size_x;
522 rect.bottom = start_y + size_y;
523 GetClipBox(dc, &cliprect);
524 IntersectRect(&rect, &rect, &cliprect);
525 int width = rect.right - rect.left;
526 int height = rect.bottom - rect.top;
527
528#ifdef DEBUG_TRACE
529 {
530 char str[128];
Tom Sepez2080b3e2015-03-11 14:25:05 -0700531 memset(str, 0, sizeof(str));
532 FXSYS_snprintf(str, sizeof(str) - 1, "Rendering DIB %d x %d", width, height);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700533 CPDF_ModuleMgr::Get()->ReportError(999, str);
534 }
535#endif
536
537 // Create a DIB section
538 LPVOID pBuffer;
539 BITMAPINFOHEADER bmih;
540 FXSYS_memset(&bmih, 0, sizeof bmih);
541 bmih.biSize = sizeof bmih;
542 bmih.biBitCount = 24;
543 bmih.biHeight = -height;
544 bmih.biPlanes = 1;
545 bmih.biWidth = width;
546 pContext->m_hBitmap = CreateDIBSection(dc, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, &pBuffer, NULL, 0);
547 if (pContext->m_hBitmap == NULL) {
548#if defined(DEBUG) || defined(_DEBUG)
549 char str[128];
Tom Sepez2080b3e2015-03-11 14:25:05 -0700550 memset(str, 0, sizeof(str));
551 FXSYS_snprintf(str, sizeof(str) - 1, "Error CreateDIBSection: %d x %d, error code = %d", width, height, GetLastError());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700552 CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, str);
553#else
554 CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, NULL);
555#endif
556 }
557 FXSYS_memset(pBuffer, 0xff, height*((width*3+3)/4*4));
558
559#ifdef DEBUG_TRACE
560 {
561 CPDF_ModuleMgr::Get()->ReportError(999, "DIBSection created");
562 }
563#endif
564
565 // Create a device with this external buffer
Tom Sepezd7e5cc72015-06-10 14:33:37 -0700566 pContext->m_pBitmap = new CFX_DIBitmap;
567 pContext->m_pBitmap->Create(width, height, FXDIB_Rgb, (uint8_t*)pBuffer);
568 pContext->m_pDevice = new CPDF_FxgeDevice;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700569 ((CPDF_FxgeDevice*)pContext->m_pDevice)->Attach(pContext->m_pBitmap);
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700570
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700571#ifdef DEBUG_TRACE
572 CPDF_ModuleMgr::Get()->ReportError(999, "Ready for PDF rendering");
573#endif
574
575 // output to bitmap device
Bo Xud4e406e2014-08-13 11:03:19 -0700576 Func_RenderPage(pContext, page, start_x - rect.left, start_y - rect.top, size_x, size_y, rotate, flags);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700577
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];
Tom Sepez2080b3e2015-03-11 14:25:05 -0700587 memset(str, 0, sizeof(str));
588 FXSYS_snprintf(str, sizeof(str) - 1, "Error CreateCompatibleDC. Error code = %d", GetLastError());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700589 CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, str);
590#else
591 CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, NULL);
592#endif
593 }
594
595 HGDIOBJ hOldBitmap = SelectObject(hMemDC, pContext->m_hBitmap);
596
597#ifdef DEBUG_TRACE
598 CPDF_ModuleMgr::Get()->ReportError(999, "Ready for screen rendering");
599#endif
600
601 BitBlt(dc, rect.left, rect.top, width, height, hMemDC, 0, 0, SRCCOPY);
602 SelectObject(hMemDC, hOldBitmap);
603 DeleteDC(hMemDC);
604
605#ifdef DEBUG_TRACE
606 CPDF_ModuleMgr::Get()->ReportError(999, "Finished screen rendering");
607#endif
608
609#endif
Lei Zhang6d8b1c22015-06-19 17:26:17 -0700610 if (bBackgroundAlphaNeeded) {
611 delete pBitmap;
612 pBitmap = NULL;
613 }
614 delete pContext;
615 pPage->RemovePrivateData((void*)1);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700616}
617#endif
618
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700619DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap, FPDF_PAGE page, int start_x, int start_y,
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700620 int size_x, int size_y, int rotate, int flags)
621{
622 if (bitmap == NULL || page == NULL) return;
Bo Xufdc00a72014-10-28 23:03:33 -0700623 CPDF_Page* pPage = ((CPDFXFA_Page*)page)->GetPDFPage();
624 if (!pPage) return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700625
626 CRenderContext* pContext = FX_NEW CRenderContext;
627 pPage->SetPrivateData((void*)1, pContext, DropContext);
628#ifdef _SKIA_SUPPORT_
629 pContext->m_pDevice = FX_NEW CFX_SkiaDevice;
630
631 if (flags & FPDF_REVERSE_BYTE_ORDER)
632 ((CFX_SkiaDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)bitmap,0,TRUE);
633 else
634 ((CFX_SkiaDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)bitmap);
635#else
636 pContext->m_pDevice = FX_NEW CFX_FxgeDevice;
637
638 if (flags & FPDF_REVERSE_BYTE_ORDER)
639 ((CFX_FxgeDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)bitmap,0,TRUE);
640 else
641 ((CFX_FxgeDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)bitmap);
642#endif
Bo Xud4e406e2014-08-13 11:03:19 -0700643
644 Func_RenderPage(pContext, page, start_x, start_y, size_x, size_y, rotate, flags,TRUE,NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700645
646 delete pContext;
647 pPage->RemovePrivateData((void*)1);
648}
649
650DLLEXPORT void STDCALL FPDF_ClosePage(FPDF_PAGE page)
651{
652 if (!page) return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700653
Tom Sepezd7e5cc72015-06-10 14:33:37 -0700654 CPDFXFA_Page* pPage = (CPDFXFA_Page*)page;
655 pPage->Release();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700656}
657
658DLLEXPORT void STDCALL FPDF_CloseDocument(FPDF_DOCUMENT document)
659{
660 if (!document)
661 return;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700662 CPDFXFA_Document* pDoc = (CPDFXFA_Document*)document;
Bo Xufdc00a72014-10-28 23:03:33 -0700663 delete pDoc;
664
665// CPDF_Parser* pParser = (CPDF_Parser*)pDoc->GetParser();
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700666// if (pParser == NULL)
Bo Xufdc00a72014-10-28 23:03:33 -0700667// {
668// delete pDoc;
669// return;
670// }
671// delete pParser;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700672// delete pDoc;
673}
674
675DLLEXPORT unsigned long STDCALL FPDF_GetLastError()
676{
677 return GetLastError();
678}
679
680DLLEXPORT void STDCALL FPDF_DeviceToPage(FPDF_PAGE page, int start_x, int start_y, int size_x, int size_y,
681 int rotate, int device_x, int device_y, double* page_x, double* page_y)
682{
683 if (page == NULL || page_x == NULL || page_y == NULL) return;
Bo Xufdc00a72014-10-28 23:03:33 -0700684 CPDFXFA_Page* pPage = (CPDFXFA_Page*)page;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700685
Bo Xufdc00a72014-10-28 23:03:33 -0700686 pPage->DeviceToPage(start_x, start_y, size_x, size_y, rotate, device_x, device_y, page_x, page_y);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700687}
688
689DLLEXPORT void STDCALL FPDF_PageToDevice(FPDF_PAGE page, int start_x, int start_y, int size_x, int size_y,
690 int rotate, double page_x, double page_y, int* device_x, int* device_y)
691{
692 if (page == NULL || device_x == NULL || device_y == NULL) return;
Bo Xufdc00a72014-10-28 23:03:33 -0700693 CPDFXFA_Page* pPage = (CPDFXFA_Page*)page;
694 pPage->PageToDevice(start_x, start_y, size_x, size_y, rotate, page_x, page_y, device_x, device_y);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700695}
696
697DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_Create(int width, int height, int alpha)
698{
Tom Sepezbad79b32015-05-08 12:02:05 -0700699 nonstd::unique_ptr<CFX_DIBitmap> pBitmap(new CFX_DIBitmap);
700 if (!pBitmap->Create(width, height, alpha ? FXDIB_Argb : FXDIB_Rgb32)) {
701 return NULL;
702 }
703 return pBitmap.release();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700704}
705
706DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_CreateEx(int width, int height, int format, void* first_scan, int stride)
707{
708 FXDIB_Format fx_format;
709 switch (format) {
710 case FPDFBitmap_Gray:
711 fx_format = FXDIB_8bppRgb;
712 break;
713 case FPDFBitmap_BGR:
714 fx_format = FXDIB_Rgb;
715 break;
716 case FPDFBitmap_BGRx:
717 fx_format = FXDIB_Rgb32;
718 break;
719 case FPDFBitmap_BGRA:
720 fx_format = FXDIB_Argb;
721 break;
722 default:
723 return NULL;
724 }
Tom Sepezd7e5cc72015-06-10 14:33:37 -0700725 CFX_DIBitmap* pBitmap = new CFX_DIBitmap;
726 pBitmap->Create(width, height, fx_format, (uint8_t*)first_scan, stride);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700727 return pBitmap;
728}
729
Lei Zhang532a6a72014-07-09 11:47:15 -0700730DLLEXPORT void STDCALL FPDFBitmap_FillRect(FPDF_BITMAP bitmap, int left, int top, int width, int height, FPDF_DWORD color)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700731{
732 if (bitmap == NULL) return;
733#ifdef _SKIA_SUPPORT_
734 CFX_SkiaDevice device;
735#else
736 CFX_FxgeDevice device;
737#endif
738 device.Attach((CFX_DIBitmap*)bitmap);
Lei Zhang532a6a72014-07-09 11:47:15 -0700739 if (!((CFX_DIBitmap*)bitmap)->HasAlpha()) color |= 0xFF000000;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700740 FX_RECT rect(left, top, left+width, top+height);
Lei Zhang532a6a72014-07-09 11:47:15 -0700741 device.FillRect(&rect, color);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700742}
743
744DLLEXPORT void* STDCALL FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap)
745{
746 if (bitmap == NULL) return NULL;
747 return ((CFX_DIBitmap*)bitmap)->GetBuffer();
748}
749
750DLLEXPORT int STDCALL FPDFBitmap_GetWidth(FPDF_BITMAP bitmap)
751{
752 if (bitmap == NULL) return 0;
753 return ((CFX_DIBitmap*)bitmap)->GetWidth();
754}
755
756DLLEXPORT int STDCALL FPDFBitmap_GetHeight(FPDF_BITMAP bitmap)
757{
758 if (bitmap == NULL) return 0;
759 return ((CFX_DIBitmap*)bitmap)->GetHeight();
760}
761
762DLLEXPORT int STDCALL FPDFBitmap_GetStride(FPDF_BITMAP bitmap)
763{
764 if (bitmap == NULL) return 0;
765 return ((CFX_DIBitmap*)bitmap)->GetPitch();
766}
767
768DLLEXPORT void STDCALL FPDFBitmap_Destroy(FPDF_BITMAP bitmap)
769{
Lei Zhang6d8b1c22015-06-19 17:26:17 -0700770 delete (CFX_DIBitmap*)bitmap;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700771}
772
773void FPDF_RenderPage_Retail(CRenderContext* pContext, FPDF_PAGE page, int start_x, int start_y, int size_x, int size_y,
774 int rotate, int flags,FX_BOOL bNeedToRestore, IFSDK_PAUSE_Adapter * pause )
775{
Bo Xufdc00a72014-10-28 23:03:33 -0700776 CPDF_Page* pPage = ((CPDFXFA_Page*)page)->GetPDFPage();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700777 if (pPage == NULL) return;
778
779 if (!pContext->m_pOptions)
780 pContext->m_pOptions = new CPDF_RenderOptions;
781// CPDF_RenderOptions options;
782 if (flags & FPDF_LCD_TEXT)
783 pContext->m_pOptions->m_Flags |= RENDER_CLEARTYPE;
784 else
785 pContext->m_pOptions->m_Flags &= ~RENDER_CLEARTYPE;
786 if (flags & FPDF_NO_NATIVETEXT)
787 pContext->m_pOptions->m_Flags |= RENDER_NO_NATIVETEXT;
788 if (flags & FPDF_RENDER_LIMITEDIMAGECACHE)
789 pContext->m_pOptions->m_Flags |= RENDER_LIMITEDIMAGECACHE;
790 if (flags & FPDF_RENDER_FORCEHALFTONE)
791 pContext->m_pOptions->m_Flags |= RENDER_FORCE_HALFTONE;
792 //Grayscale output
793 if (flags & FPDF_GRAYSCALE)
794 {
795 pContext->m_pOptions->m_ColorMode = RENDER_COLOR_GRAY;
796 pContext->m_pOptions->m_ForeColor = 0;
797 pContext->m_pOptions->m_BackColor = 0xffffff;
798 }
799 const CPDF_OCContext::UsageType usage = (flags & FPDF_PRINTING) ? CPDF_OCContext::Print : CPDF_OCContext::View;
800
801 pContext->m_pOptions->m_AddFlags = flags >> 8;
802
803 pContext->m_pOptions->m_pOCContext = new CPDF_OCContext(pPage->m_pDocument, usage);
804
805
806 CFX_AffineMatrix matrix;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700807 pPage->GetDisplayMatrix(matrix, start_x, start_y, size_x, size_y, rotate);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700808
809 FX_RECT clip;
810 clip.left = start_x;
811 clip.right = start_x + size_x;
812 clip.top = start_y;
813 clip.bottom = start_y + size_y;
814 pContext->m_pDevice->SaveState();
815 pContext->m_pDevice->SetClip_Rect(&clip);
816
817 pContext->m_pContext = FX_NEW CPDF_RenderContext;
818 pContext->m_pContext->Create(pPage);
819 pContext->m_pContext->AppendObjectList(pPage, &matrix);
820
821 if (flags & FPDF_ANNOT) {
822 pContext->m_pAnnots = FX_NEW CPDF_AnnotList(pPage);
823 FX_BOOL bPrinting = pContext->m_pDevice->GetDeviceClass() != FXDC_DISPLAY;
824 pContext->m_pAnnots->DisplayAnnots(pPage, pContext->m_pContext, bPrinting, &matrix, TRUE, NULL);
825 }
826
827 pContext->m_pRenderer = FX_NEW CPDF_ProgressiveRenderer;
828 pContext->m_pRenderer->Start(pContext->m_pContext, pContext->m_pDevice, pContext->m_pOptions, pause);
829 if (bNeedToRestore)
830 {
831 pContext->m_pDevice->RestoreState();
832 }
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700833
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700834//#endif
835}
836
837DLLEXPORT int STDCALL FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document, int page_index, double* width, double* height)
838{
Bo Xufdc00a72014-10-28 23:03:33 -0700839// CPDF_Document* pDoc = (CPDF_Document*)document;
840// if(pDoc == NULL)
841// return FALSE;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700842//
Bo Xufdc00a72014-10-28 23:03:33 -0700843// CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
844// if (pDict == NULL) return FALSE;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700845//
Bo Xufdc00a72014-10-28 23:03:33 -0700846// CPDF_Page page;
847// page.Load(pDoc, pDict);
848// *width = page.GetPageWidth();
849// *height = page.GetPageHeight();
850
851 CPDFXFA_Document* pDoc = (CPDFXFA_Document*)document;
852 if (pDoc == NULL)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700853 return FALSE;
854
Bo Xufdc00a72014-10-28 23:03:33 -0700855 int count = pDoc->GetPageCount();
856 if (page_index < 0 || page_index >= count)
857 return FALSE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700858
Bo Xufdc00a72014-10-28 23:03:33 -0700859 CPDFXFA_Page* pPage = pDoc->GetPage(page_index);
860 if (!pPage)
861 return FALSE;
862
863 *width = pPage->GetPageWidth();
864 *height = pPage->GetPageHeight();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700865
866 return TRUE;
867}
868
869DLLEXPORT FPDF_BOOL STDCALL FPDF_VIEWERREF_GetPrintScaling(FPDF_DOCUMENT document)
870{
Bo Xufdc00a72014-10-28 23:03:33 -0700871 CPDFXFA_Document* pDoc = (CPDFXFA_Document*)document;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700872 if (!pDoc) return TRUE;
Bo Xufdc00a72014-10-28 23:03:33 -0700873 CPDF_Document* pPDFDoc = pDoc->GetPDFDoc();
874 if (!pPDFDoc) return TRUE;
875 CPDF_ViewerPreferences viewRef(pPDFDoc);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700876 return viewRef.PrintScaling();
877}
878
Bo Xu9114e832014-07-14 13:22:47 -0700879DLLEXPORT int STDCALL FPDF_VIEWERREF_GetNumCopies(FPDF_DOCUMENT document)
880{
Bo Xu4d62b6b2015-01-10 22:52:59 -0800881 CPDF_Document* pDoc = ((CPDFXFA_Document*)document)->GetPDFDoc();
Bo Xu9114e832014-07-14 13:22:47 -0700882 if (!pDoc) return 1;
883 CPDF_ViewerPreferences viewRef(pDoc);
884 return viewRef.NumCopies();
885}
886
887DLLEXPORT FPDF_PAGERANGE STDCALL FPDF_VIEWERREF_GetPrintPageRange(FPDF_DOCUMENT document)
888{
Bo Xu4d62b6b2015-01-10 22:52:59 -0800889 CPDF_Document* pDoc = ((CPDFXFA_Document*)document)->GetPDFDoc();
Bo Xu9114e832014-07-14 13:22:47 -0700890 if (!pDoc) return NULL;
891 CPDF_ViewerPreferences viewRef(pDoc);
892 return viewRef.PrintPageRange();
893}
894
895DLLEXPORT FPDF_DUPLEXTYPE STDCALL FPDF_VIEWERREF_GetDuplex(FPDF_DOCUMENT document)
896{
Bo Xu4d62b6b2015-01-10 22:52:59 -0800897 CPDF_Document* pDoc = ((CPDFXFA_Document*)document)->GetPDFDoc();
Bo Xu9114e832014-07-14 13:22:47 -0700898 if (!pDoc) return DuplexUndefined;
899 CPDF_ViewerPreferences viewRef(pDoc);
900 CFX_ByteString duplex = viewRef.Duplex();
901 if (FX_BSTRC("Simplex") == duplex)
902 return Simplex;
903 if (FX_BSTRC("DuplexFlipShortEdge") == duplex)
904 return DuplexFlipShortEdge;
905 if (FX_BSTRC("DuplexFlipLongEdge") == duplex)
906 return DuplexFlipLongEdge;
907 return DuplexUndefined;
908}
909
Bo Xu4d62b6b2015-01-10 22:52:59 -0800910DLLEXPORT FPDF_DWORD STDCALL FPDF_CountNamedDests(FPDF_DOCUMENT document)
911{
912 if (!document) return 0;
913 CPDF_Document* pDoc = ((CPDFXFA_Document*)document)->GetPDFDoc();
914
915 CPDF_Dictionary* pRoot = pDoc->GetRoot();
916 if (!pRoot) return 0;
917
918 CPDF_NameTree nameTree(pDoc, FX_BSTRC("Dests"));
919 int count = nameTree.GetCount();
920 CPDF_Dictionary* pDest = pRoot->GetDict(FX_BSTRC("Dests"));
921 if (pDest)
922 count += pDest->GetCount();
923 return count;
924}
925
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700926DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDestByName(FPDF_DOCUMENT document,FPDF_BYTESTRING name)
927{
Bo Xu4d62b6b2015-01-10 22:52:59 -0800928 if (!document)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700929 return NULL;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700930 if (!name || name[0] == 0)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700931 return NULL;
932
Bo Xufdc00a72014-10-28 23:03:33 -0700933 CPDFXFA_Document* pDoc = (CPDFXFA_Document*)document;
934 CPDF_Document* pPDFDoc = pDoc->GetPDFDoc();
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700935 if (!pPDFDoc)
Bo Xufdc00a72014-10-28 23:03:33 -0700936 return NULL;
937 CPDF_NameTree name_tree(pPDFDoc, FX_BSTRC("Dests"));
938 return name_tree.LookupNamedDest(pPDFDoc, name);
939}
940
941FPDF_RESULT FPDF_BStr_Init(FPDF_BSTR* str)
942{
943 if (!str)
944 return -1;
945
Tom Sepez65811752015-06-11 12:17:45 -0700946 FXSYS_memset(str, 0, sizeof(FPDF_BSTR));
Bo Xufdc00a72014-10-28 23:03:33 -0700947 return 0;
948}
949
950FPDF_RESULT FPDF_BStr_Set(FPDF_BSTR* str, FPDF_LPCSTR bstr, int length)
951{
952 if (!str) return -1;
953 if (!bstr || !length)
954 return -1;
955 if (length == -1)
956 length = FXSYS_strlen(bstr);
957
958 if (length == 0)
959 {
960 if (str->str)
961 {
962 FX_Free(str->str);
963 str->str = NULL;
964 }
965 str->len = 0;
966 return 0;
967 }
968
969 if (str->str && str->len < length)
970 str->str = FX_Realloc(char, str->str, length+1);
971 else if (!str->str)
972 str->str = FX_Alloc(char, length+1);
973
974 str->str[length] = 0;
975 if (str->str == NULL)
976 return -1;
977
978 FXSYS_memcpy(str->str, bstr, length);
979 str->len = length;
980
981 return 0;
982}
983
984FPDF_RESULT FPDF_BStr_Clear(FPDF_BSTR* str)
985{
986 if(!str)
987 return -1;
988
989 if (str->str)
990 {
991 FX_Free(str->str);
992 str->str = NULL;
993 }
994 str->len = 0;
995 return 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700996}
Bo Xu4d62b6b2015-01-10 22:52:59 -0800997
Tom Sepezcf22eb82015-05-12 17:28:08 -0700998DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDest(FPDF_DOCUMENT document, int index, void* buffer, long* buflen)
Bo Xu4d62b6b2015-01-10 22:52:59 -0800999{
1000 if (!buffer)
Tom Sepezcf22eb82015-05-12 17:28:08 -07001001 *buflen = 0;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001002 if (!document || index < 0) return NULL;
1003 CPDF_Document* pDoc = ((CPDFXFA_Document*)document)->GetPDFDoc();
1004
1005 CPDF_Dictionary* pRoot = pDoc->GetRoot();
1006 if (!pRoot) return NULL;
1007
1008 CPDF_Object* pDestObj = NULL;
1009 CFX_ByteString bsName;
1010 CPDF_NameTree nameTree(pDoc, FX_BSTRC("Dests"));
1011 int count = nameTree.GetCount();
1012 if (index >= count) {
1013 CPDF_Dictionary* pDest = pRoot->GetDict(FX_BSTRC("Dests"));
1014 if (!pDest) return NULL;
1015 if (index >= count + pDest->GetCount()) return NULL;
1016 index -= count;
1017 FX_POSITION pos = pDest->GetStartPos();
1018 int i = 0;
1019 while (pos) {
1020 pDestObj = pDest->GetNextElement(pos, bsName);
1021 if (!pDestObj) continue;
1022 if (i == index) break;
1023 i++;
1024 }
1025 } else {
1026 pDestObj = nameTree.LookupValue(index, bsName);
1027 }
1028 if (!pDestObj) return NULL;
Tom Sepezc8f6ab62015-01-22 11:20:06 -08001029 if (pDestObj->GetType() == PDFOBJ_DICTIONARY) {
Bo Xu4d62b6b2015-01-10 22:52:59 -08001030 pDestObj = ((CPDF_Dictionary*)pDestObj)->GetArray(FX_BSTRC("D"));
Tom Sepezc8f6ab62015-01-22 11:20:06 -08001031 if (!pDestObj) return NULL;
1032 }
Bo Xu4d62b6b2015-01-10 22:52:59 -08001033 if (pDestObj->GetType() != PDFOBJ_ARRAY) return NULL;
1034 CFX_WideString wsName = PDF_DecodeText(bsName);
1035 CFX_ByteString utf16Name = wsName.UTF16LE_Encode();
1036 unsigned int len = utf16Name.GetLength();
1037 if (!buffer) {
Tom Sepezcf22eb82015-05-12 17:28:08 -07001038 *buflen = len;
1039 } else if (*buflen >= len) {
Bo Xu4d62b6b2015-01-10 22:52:59 -08001040 memcpy(buffer, utf16Name.c_str(), len);
Tom Sepezcf22eb82015-05-12 17:28:08 -07001041 *buflen = len;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001042 } else {
Tom Sepezcf22eb82015-05-12 17:28:08 -07001043 *buflen = -1;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001044 }
1045 return (FPDF_DEST)pDestObj;
1046}