blob: 47a92f1bca224f664bf26d37a3df1cdea9226296 [file] [log] [blame]
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001// Copyright 2014 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
Lei Zhangb4e7f302015-11-06 15:52:32 -08007#include "public/fpdfview.h"
8
Lei Zhangaa8bf7e2015-12-24 19:13:32 -08009#include <memory>
thestigd4c34f22016-09-28 17:04:51 -070010#include <utility>
rbpottercec01802017-04-17 09:10:21 -070011#include <vector>
Lei Zhangaa8bf7e2015-12-24 19:13:32 -080012
dsinclair39c62fd2016-09-29 12:49:17 -070013#include "core/fpdfapi/cpdf_modulemgr.h"
14#include "core/fpdfapi/cpdf_pagerendercontext.h"
rbpottercec01802017-04-17 09:10:21 -070015#include "core/fpdfapi/page/cpdf_image.h"
16#include "core/fpdfapi/page/cpdf_imageobject.h"
dsinclair41872fa2016-10-04 11:29:35 -070017#include "core/fpdfapi/page/cpdf_page.h"
rbpottercec01802017-04-17 09:10:21 -070018#include "core/fpdfapi/page/cpdf_pageobject.h"
Jane Liu3b057432017-06-19 10:44:01 -040019#include "core/fpdfapi/page/cpdf_pathobject.h"
dsinclair488b7ad2016-10-04 11:55:50 -070020#include "core/fpdfapi/parser/cpdf_array.h"
Jane Liu4fd9a472017-06-01 18:56:09 -040021#include "core/fpdfapi/parser/cpdf_dictionary.h"
dsinclair488b7ad2016-10-04 11:55:50 -070022#include "core/fpdfapi/parser/cpdf_document.h"
23#include "core/fpdfapi/parser/fpdf_parser_decode.h"
dsinclair69d9c682016-10-04 12:18:35 -070024#include "core/fpdfapi/render/cpdf_progressiverenderer.h"
25#include "core/fpdfapi/render/cpdf_renderoptions.h"
dsinclair1727aee2016-09-29 13:12:56 -070026#include "core/fpdfdoc/cpdf_annotlist.h"
27#include "core/fpdfdoc/cpdf_nametree.h"
28#include "core/fpdfdoc/cpdf_occontext.h"
29#include "core/fpdfdoc/cpdf_viewerpreferences.h"
dsinclaira52ab742016-09-29 13:59:29 -070030#include "core/fxcrt/fx_memory.h"
31#include "core/fxcrt/fx_safe_types.h"
Dan Sinclairbcd1e702017-08-31 13:19:18 -040032#include "core/fxcrt/fx_stream.h"
Dan Sinclaira5085d42017-05-11 16:26:50 -040033#include "core/fxge/cfx_defaultrenderdevice.h"
dsinclair74a34fc2016-09-29 16:41:42 -070034#include "core/fxge/cfx_gemodule.h"
dsinclairb402b172016-10-11 09:26:32 -070035#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
dsinclair114e46a2016-09-29 17:18:21 -070036#include "fpdfsdk/cpdfsdk_pageview.h"
37#include "fpdfsdk/fsdk_define.h"
38#include "fpdfsdk/fsdk_pauseadapter.h"
dsinclair64376be2016-03-31 20:03:24 -070039#include "fpdfsdk/javascript/ijs_runtime.h"
rbpottere8468c42017-07-11 10:04:29 -070040#include "public/fpdf_edit.h"
Lei Zhangb4e7f302015-11-06 15:52:32 -080041#include "public/fpdf_ext.h"
Ryan Harrisona74a6272017-10-16 10:57:48 -040042#include "public/fpdf_formfill.h"
Lei Zhangb4e7f302015-11-06 15:52:32 -080043#include "public/fpdf_progressive.h"
Chris Palmere4b035b2017-03-26 15:48:34 -070044#include "third_party/base/allocator/partition_allocator/partition_alloc.h"
Lei Zhang8241df72015-11-06 14:38:48 -080045#include "third_party/base/numerics/safe_conversions_impl.h"
tsepez36eb4bd2016-10-03 15:24:27 -070046#include "third_party/base/ptr_util.h"
Bo Xufdc00a72014-10-28 23:03:33 -070047
Tom Sepez40e9ff32015-11-30 12:39:54 -080048#ifdef PDF_ENABLE_XFA
dsinclair521b7502016-11-02 13:02:28 -070049#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
dsinclair4d29e782016-10-04 14:02:47 -070050#include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
51#include "fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h"
Dan Sinclaire7786682017-03-29 15:18:41 -040052#include "fxbarcode/BC_Library.h"
Tom Sepez40e9ff32015-11-30 12:39:54 -080053#endif // PDF_ENABLE_XFA
54
Dan Sinclair698aed72017-09-26 16:24:49 -040055#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
Dan Sinclaira5085d42017-05-11 16:26:50 -040056#include "core/fxge/cfx_windowsrenderdevice.h"
rbpottere8468c42017-07-11 10:04:29 -070057
58// These checks are here because core/ and public/ cannot depend on each other.
59static_assert(WindowsPrintMode::kModeEmf == FPDF_PRINTMODE_EMF,
60 "WindowsPrintMode::kModeEmf value mismatch");
61static_assert(WindowsPrintMode::kModeTextOnly == FPDF_PRINTMODE_TEXTONLY,
62 "WindowsPrintMode::kModeTextOnly value mismatch");
63static_assert(WindowsPrintMode::kModePostScript2 == FPDF_PRINTMODE_POSTSCRIPT2,
64 "WindowsPrintMode::kModePostScript2 value mismatch");
65static_assert(WindowsPrintMode::kModePostScript3 == FPDF_PRINTMODE_POSTSCRIPT3,
66 "WindowsPrintMode::kModePostScript3 value mismatch");
thestig25fa42f2016-05-25 21:39:46 -070067#endif
68
thestiga78ba602016-11-23 15:25:48 -080069namespace {
70
Dan Sinclair830897a2017-05-11 14:36:10 -040071bool g_bLibraryInitialized = false;
tsepez02759102016-12-01 08:29:25 -080072
thestiga78ba602016-11-23 15:25:48 -080073void RenderPageImpl(CPDF_PageRenderContext* pContext,
74 CPDF_Page* pPage,
75 const CFX_Matrix& matrix,
76 const FX_RECT& clipping_rect,
77 int flags,
78 bool bNeedToRestore,
79 IFSDK_PAUSE_Adapter* pause) {
80 if (!pContext->m_pOptions)
81 pContext->m_pOptions = pdfium::MakeUnique<CPDF_RenderOptions>();
82
Dan Sinclair921fe6b2017-10-05 11:14:12 -040083 uint32_t option_flags = pContext->m_pOptions->GetFlags();
thestiga78ba602016-11-23 15:25:48 -080084 if (flags & FPDF_LCD_TEXT)
Dan Sinclair921fe6b2017-10-05 11:14:12 -040085 option_flags |= RENDER_CLEARTYPE;
thestiga78ba602016-11-23 15:25:48 -080086 else
Dan Sinclair921fe6b2017-10-05 11:14:12 -040087 option_flags &= ~RENDER_CLEARTYPE;
thestiga78ba602016-11-23 15:25:48 -080088
89 if (flags & FPDF_NO_NATIVETEXT)
Dan Sinclair921fe6b2017-10-05 11:14:12 -040090 option_flags |= RENDER_NO_NATIVETEXT;
thestiga78ba602016-11-23 15:25:48 -080091 if (flags & FPDF_RENDER_LIMITEDIMAGECACHE)
Dan Sinclair921fe6b2017-10-05 11:14:12 -040092 option_flags |= RENDER_LIMITEDIMAGECACHE;
thestiga78ba602016-11-23 15:25:48 -080093 if (flags & FPDF_RENDER_FORCEHALFTONE)
Dan Sinclair921fe6b2017-10-05 11:14:12 -040094 option_flags |= RENDER_FORCE_HALFTONE;
thestiga78ba602016-11-23 15:25:48 -080095#ifndef PDF_ENABLE_XFA
96 if (flags & FPDF_RENDER_NO_SMOOTHTEXT)
Dan Sinclair921fe6b2017-10-05 11:14:12 -040097 option_flags |= RENDER_NOTEXTSMOOTH;
thestiga78ba602016-11-23 15:25:48 -080098 if (flags & FPDF_RENDER_NO_SMOOTHIMAGE)
Dan Sinclair921fe6b2017-10-05 11:14:12 -040099 option_flags |= RENDER_NOIMAGESMOOTH;
thestiga78ba602016-11-23 15:25:48 -0800100 if (flags & FPDF_RENDER_NO_SMOOTHPATH)
Dan Sinclair921fe6b2017-10-05 11:14:12 -0400101 option_flags |= RENDER_NOPATHSMOOTH;
thestiga78ba602016-11-23 15:25:48 -0800102#endif // PDF_ENABLE_XFA
Dan Sinclair921fe6b2017-10-05 11:14:12 -0400103 pContext->m_pOptions->SetFlags(option_flags);
thestiga78ba602016-11-23 15:25:48 -0800104
105 // Grayscale output
Dan Sinclairf55e72e2017-07-13 14:53:28 -0400106 if (flags & FPDF_GRAYSCALE)
Dan Sinclair921fe6b2017-10-05 11:14:12 -0400107 pContext->m_pOptions->SetColorMode(CPDF_RenderOptions::kGray);
thestiga78ba602016-11-23 15:25:48 -0800108
109 const CPDF_OCContext::UsageType usage =
110 (flags & FPDF_PRINTING) ? CPDF_OCContext::Print : CPDF_OCContext::View;
Dan Sinclair921fe6b2017-10-05 11:14:12 -0400111 pContext->m_pOptions->SetOCContext(
112 pdfium::MakeRetain<CPDF_OCContext>(pPage->m_pDocument.Get(), usage));
thestiga78ba602016-11-23 15:25:48 -0800113
114 pContext->m_pDevice->SaveState();
115 pContext->m_pDevice->SetClip_Rect(clipping_rect);
thestiga78ba602016-11-23 15:25:48 -0800116 pContext->m_pContext = pdfium::MakeUnique<CPDF_RenderContext>(pPage);
117 pContext->m_pContext->AppendLayer(pPage, &matrix);
118
119 if (flags & FPDF_ANNOT) {
120 pContext->m_pAnnots = pdfium::MakeUnique<CPDF_AnnotList>(pPage);
121 bool bPrinting = pContext->m_pDevice->GetDeviceClass() != FXDC_DISPLAY;
122 pContext->m_pAnnots->DisplayAnnots(pPage, pContext->m_pContext.get(),
123 bPrinting, &matrix, false, nullptr);
124 }
125
126 pContext->m_pRenderer = pdfium::MakeUnique<CPDF_ProgressiveRenderer>(
127 pContext->m_pContext.get(), pContext->m_pDevice.get(),
128 pContext->m_pOptions.get());
129 pContext->m_pRenderer->Start(pause);
130 if (bNeedToRestore)
131 pContext->m_pDevice->RestoreState(false);
132}
133
tsepezbea04972016-12-01 13:54:42 -0800134class CPDF_CustomAccess final : public IFX_SeekableReadStream {
135 public:
Tom Sepez40badde2017-05-01 13:21:39 -0700136 template <typename T, typename... Args>
Dan Sinclair0b950422017-09-21 15:49:49 -0400137 friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
tsepezbea04972016-12-01 13:54:42 -0800138
139 // IFX_SeekableReadStream
140 FX_FILESIZE GetSize() override;
tsepezbea04972016-12-01 13:54:42 -0800141 bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override;
142
143 private:
tsepez833619b2016-12-07 09:21:17 -0800144 explicit CPDF_CustomAccess(FPDF_FILEACCESS* pFileAccess);
145
tsepezbea04972016-12-01 13:54:42 -0800146 FPDF_FILEACCESS m_FileAccess;
147};
148
149CPDF_CustomAccess::CPDF_CustomAccess(FPDF_FILEACCESS* pFileAccess)
150 : m_FileAccess(*pFileAccess) {}
151
152FX_FILESIZE CPDF_CustomAccess::GetSize() {
153 return m_FileAccess.m_FileLen;
154}
155
tsepezbea04972016-12-01 13:54:42 -0800156bool CPDF_CustomAccess::ReadBlock(void* buffer,
157 FX_FILESIZE offset,
158 size_t size) {
159 if (offset < 0)
160 return false;
161
162 FX_SAFE_FILESIZE newPos = pdfium::base::checked_cast<FX_FILESIZE>(size);
163 newPos += offset;
164 if (!newPos.IsValid() ||
165 newPos.ValueOrDie() > static_cast<FX_FILESIZE>(m_FileAccess.m_FileLen)) {
166 return false;
167 }
168 return !!m_FileAccess.m_GetBlock(m_FileAccess.m_Param, offset,
Nicolas Pena46abb662017-05-17 17:23:22 -0400169 static_cast<uint8_t*>(buffer), size);
tsepezbea04972016-12-01 13:54:42 -0800170}
171
Tom Sepez40e9ff32015-11-30 12:39:54 -0800172#ifdef PDF_ENABLE_XFA
Dan Sinclaira7caeb52017-09-26 09:23:29 -0400173class FPDF_FileHandlerContext : public IFX_SeekableStream {
tsepezfa89a202016-12-02 09:48:30 -0800174 public:
Tom Sepez40badde2017-05-01 13:21:39 -0700175 template <typename T, typename... Args>
Dan Sinclair0b950422017-09-21 15:49:49 -0400176 friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
Tom Sepez40badde2017-05-01 13:21:39 -0700177
Dan Sinclaira7caeb52017-09-26 09:23:29 -0400178 ~FPDF_FileHandlerContext() override;
Tom Sepez471a1032015-10-15 16:17:18 -0700179
tsepezfa89a202016-12-02 09:48:30 -0800180 // IFX_SeekableStream:
tsepezfa89a202016-12-02 09:48:30 -0800181 FX_FILESIZE GetSize() override;
182 bool IsEOF() override;
183 FX_FILESIZE GetPosition() override;
184 bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override;
185 size_t ReadBlock(void* buffer, size_t size) override;
186 bool WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size) override;
187 bool Flush() override;
Tom Sepezbf59a072015-10-21 14:07:23 -0700188
tsepezfa89a202016-12-02 09:48:30 -0800189 void SetPosition(FX_FILESIZE pos) { m_nCurPos = pos; }
Tom Sepezdb0be962015-10-16 14:00:21 -0700190
tsepezfa89a202016-12-02 09:48:30 -0800191 protected:
Dan Sinclaira7caeb52017-09-26 09:23:29 -0400192 explicit FPDF_FileHandlerContext(FPDF_FILEHANDLER* pFS);
tsepez833619b2016-12-07 09:21:17 -0800193
tsepezfa89a202016-12-02 09:48:30 -0800194 FPDF_FILEHANDLER* m_pFS;
195 FX_FILESIZE m_nCurPos;
196};
thestigbefa4502016-05-26 20:15:19 -0700197
Dan Sinclaira7caeb52017-09-26 09:23:29 -0400198FPDF_FileHandlerContext::FPDF_FileHandlerContext(FPDF_FILEHANDLER* pFS) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700199 m_pFS = pFS;
200 m_nCurPos = 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700201}
202
Dan Sinclaira7caeb52017-09-26 09:23:29 -0400203FPDF_FileHandlerContext::~FPDF_FileHandlerContext() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700204 if (m_pFS && m_pFS->Release)
205 m_pFS->Release(m_pFS->clientData);
Bo Xufdc00a72014-10-28 23:03:33 -0700206}
207
Dan Sinclaira7caeb52017-09-26 09:23:29 -0400208FX_FILESIZE FPDF_FileHandlerContext::GetSize() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700209 if (m_pFS && m_pFS->GetSize)
210 return (FX_FILESIZE)m_pFS->GetSize(m_pFS->clientData);
211 return 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700212}
213
Dan Sinclaira7caeb52017-09-26 09:23:29 -0400214bool FPDF_FileHandlerContext::IsEOF() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700215 return m_nCurPos >= GetSize();
Bo Xufdc00a72014-10-28 23:03:33 -0700216}
217
Dan Sinclaira7caeb52017-09-26 09:23:29 -0400218FX_FILESIZE FPDF_FileHandlerContext::GetPosition() {
weili625ad662016-06-15 11:21:33 -0700219 return m_nCurPos;
220}
221
Dan Sinclaira7caeb52017-09-26 09:23:29 -0400222bool FPDF_FileHandlerContext::ReadBlock(void* buffer,
223 FX_FILESIZE offset,
224 size_t size) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700225 if (!buffer || !size || !m_pFS->ReadBlock)
tsepezf39074c2016-10-26 15:33:58 -0700226 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700227
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700228 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
229 (FPDF_DWORD)size) == 0) {
230 m_nCurPos = offset + size;
tsepezf39074c2016-10-26 15:33:58 -0700231 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700232 }
tsepezf39074c2016-10-26 15:33:58 -0700233 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700234}
235
Dan Sinclaira7caeb52017-09-26 09:23:29 -0400236size_t FPDF_FileHandlerContext::ReadBlock(void* buffer, size_t size) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700237 if (!buffer || !size || !m_pFS->ReadBlock)
238 return 0;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700239
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700240 FX_FILESIZE nSize = GetSize();
241 if (m_nCurPos >= nSize)
242 return 0;
243 FX_FILESIZE dwAvail = nSize - m_nCurPos;
244 if (dwAvail < (FX_FILESIZE)size)
Ryan Harrison875e98c2017-09-27 10:53:11 -0400245 size = static_cast<size_t>(dwAvail);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700246 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)m_nCurPos, buffer,
247 (FPDF_DWORD)size) == 0) {
248 m_nCurPos += size;
249 return size;
250 }
Bo Xufdc00a72014-10-28 23:03:33 -0700251
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700252 return 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700253}
254
Dan Sinclaira7caeb52017-09-26 09:23:29 -0400255bool FPDF_FileHandlerContext::WriteBlock(const void* buffer,
256 FX_FILESIZE offset,
257 size_t size) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700258 if (!m_pFS || !m_pFS->WriteBlock)
tsepezf39074c2016-10-26 15:33:58 -0700259 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700260
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700261 if (m_pFS->WriteBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
262 (FPDF_DWORD)size) == 0) {
263 m_nCurPos = offset + size;
tsepezf39074c2016-10-26 15:33:58 -0700264 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700265 }
tsepezf39074c2016-10-26 15:33:58 -0700266 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700267}
268
Dan Sinclaira7caeb52017-09-26 09:23:29 -0400269bool FPDF_FileHandlerContext::Flush() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700270 if (!m_pFS || !m_pFS->Flush)
tsepezf39074c2016-10-26 15:33:58 -0700271 return true;
Bo Xufdc00a72014-10-28 23:03:33 -0700272
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700273 return m_pFS->Flush(m_pFS->clientData) == 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700274}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800275#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700276
Artem Strygin3f7ff052017-07-27 22:16:13 +0300277FPDF_DOCUMENT LoadDocumentImpl(
Dan Sinclair0b950422017-09-21 15:49:49 -0400278 const RetainPtr<IFX_SeekableReadStream>& pFileAccess,
Artem Strygin3f7ff052017-07-27 22:16:13 +0300279 FPDF_BYTESTRING password) {
Jane Liu8a1081f2017-08-22 16:28:05 -0400280 if (!pFileAccess) {
281 ProcessParseError(CPDF_Parser::FILE_ERROR);
Artem Strygin3f7ff052017-07-27 22:16:13 +0300282 return nullptr;
Jane Liu8a1081f2017-08-22 16:28:05 -0400283 }
Artem Strygin3f7ff052017-07-27 22:16:13 +0300284
285 auto pParser = pdfium::MakeUnique<CPDF_Parser>();
286 pParser->SetPassword(password);
287
288 auto pDocument = pdfium::MakeUnique<CPDF_Document>(std::move(pParser));
289 CPDF_Parser::Error error =
290 pDocument->GetParser()->StartParse(pFileAccess, pDocument.get());
291 if (error != CPDF_Parser::SUCCESS) {
292 ProcessParseError(error);
293 return nullptr;
294 }
295 CheckUnSupportError(pDocument.get(), error);
296 return FPDFDocumentFromCPDFDocument(pDocument.release());
297}
298
tsepezfa89a202016-12-02 09:48:30 -0800299} // namespace
300
301UnderlyingDocumentType* UnderlyingFromFPDFDocument(FPDF_DOCUMENT doc) {
302 return static_cast<UnderlyingDocumentType*>(doc);
303}
304
305FPDF_DOCUMENT FPDFDocumentFromUnderlying(UnderlyingDocumentType* doc) {
306 return static_cast<FPDF_DOCUMENT>(doc);
307}
308
309UnderlyingPageType* UnderlyingFromFPDFPage(FPDF_PAGE page) {
310 return static_cast<UnderlyingPageType*>(page);
311}
312
313CPDF_Document* CPDFDocumentFromFPDFDocument(FPDF_DOCUMENT doc) {
314#ifdef PDF_ENABLE_XFA
315 return doc ? UnderlyingFromFPDFDocument(doc)->GetPDFDoc() : nullptr;
316#else // PDF_ENABLE_XFA
317 return UnderlyingFromFPDFDocument(doc);
318#endif // PDF_ENABLE_XFA
319}
320
321FPDF_DOCUMENT FPDFDocumentFromCPDFDocument(CPDF_Document* doc) {
322#ifdef PDF_ENABLE_XFA
323 return doc ? FPDFDocumentFromUnderlying(
324 new CPDFXFA_Context(pdfium::WrapUnique(doc)))
325 : nullptr;
326#else // PDF_ENABLE_XFA
327 return FPDFDocumentFromUnderlying(doc);
328#endif // PDF_ENABLE_XFA
329}
330
331CPDF_Page* CPDFPageFromFPDFPage(FPDF_PAGE page) {
332#ifdef PDF_ENABLE_XFA
333 return page ? UnderlyingFromFPDFPage(page)->GetPDFPage() : nullptr;
334#else // PDF_ENABLE_XFA
335 return UnderlyingFromFPDFPage(page);
336#endif // PDF_ENABLE_XFA
337}
338
Jane Liu3b057432017-06-19 10:44:01 -0400339CPDF_PathObject* CPDFPathObjectFromFPDFPageObject(FPDF_PAGEOBJECT page_object) {
Lei Zhang038740c2017-09-13 13:22:54 -0700340 auto* obj = CPDFPageObjectFromFPDFPageObject(page_object);
341 return obj ? obj->AsPath() : nullptr;
Jane Liu3b057432017-06-19 10:44:01 -0400342}
343
Jane Liubaa7ff42017-06-29 19:18:23 -0400344CPDF_PageObject* CPDFPageObjectFromFPDFPageObject(FPDF_PAGEOBJECT page_object) {
345 return static_cast<CPDF_PageObject*>(page_object);
346}
347
Jane Liu18ae06d2017-07-18 10:15:16 -0400348CPDF_Object* CPDFObjectFromFPDFAttachment(FPDF_ATTACHMENT attachment) {
349 return static_cast<CPDF_Object*>(attachment);
350}
351
Ryan Harrison275e2602017-09-18 14:23:18 -0400352ByteString CFXByteStringFromFPDFWideString(FPDF_WIDESTRING wide_string) {
353 return WideString::FromUTF16LE(wide_string,
354 WideString::WStringLength(wide_string))
Jane Liu18ae06d2017-07-18 10:15:16 -0400355 .UTF8Encode();
356}
357
tsepezfa89a202016-12-02 09:48:30 -0800358CFX_DIBitmap* CFXBitmapFromFPDFBitmap(FPDF_BITMAP bitmap) {
359 return static_cast<CFX_DIBitmap*>(bitmap);
360}
361
Miklos Vajna36eed872017-09-20 22:52:43 +0200362const FX_PATHPOINT* FXPathPointFromFPDFPathSegment(FPDF_PATHSEGMENT segment) {
363 return static_cast<const FX_PATHPOINT*>(segment);
364}
365
Ryan Harrison275e2602017-09-18 14:23:18 -0400366unsigned long Utf16EncodeMaybeCopyAndReturnLength(const WideString& text,
Jane Liu18ae06d2017-07-18 10:15:16 -0400367 void* buffer,
368 unsigned long buflen) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400369 ByteString encoded_text = text.UTF16LE_Encode();
Jane Liu548334e2017-08-03 16:33:40 -0400370 unsigned long len = encoded_text.GetLength();
Jane Liu18ae06d2017-07-18 10:15:16 -0400371 if (buffer && len <= buflen)
Jane Liu548334e2017-08-03 16:33:40 -0400372 memcpy(buffer, encoded_text.c_str(), len);
373 return len;
374}
375
376unsigned long DecodeStreamMaybeCopyAndReturnLength(const CPDF_Stream* stream,
377 void* buffer,
378 unsigned long buflen) {
379 ASSERT(stream);
380 uint8_t* data = stream->GetRawData();
381 uint32_t len = stream->GetRawSize();
382 CPDF_Dictionary* dict = stream->GetDict();
383 CPDF_Object* decoder = dict ? dict->GetDirectObjectFor("Filter") : nullptr;
384 if (decoder && (decoder->IsArray() || decoder->IsName())) {
385 // Decode the stream if one or more stream filters are specified.
386 uint8_t* decoded_data = nullptr;
387 uint32_t decoded_len = 0;
Ryan Harrison275e2602017-09-18 14:23:18 -0400388 ByteString dummy_last_decoder;
Jane Liu548334e2017-08-03 16:33:40 -0400389 CPDF_Dictionary* dummy_last_param;
390 if (PDF_DataDecode(data, len, dict, dict->GetIntegerFor("DL"), false,
391 &decoded_data, &decoded_len, &dummy_last_decoder,
392 &dummy_last_param)) {
393 if (buffer && buflen >= decoded_len)
394 memcpy(buffer, decoded_data, decoded_len);
395
396 // Free the buffer for the decoded data if it was allocated by
397 // PDF_DataDecode(). Note that for images with a single image-specific
398 // filter, |decoded_data| is directly assigned to be |data|, so
399 // |decoded_data| does not need to be freed.
400 if (decoded_data != data)
401 FX_Free(decoded_data);
402
403 return decoded_len;
404 }
405 }
406 // Copy the raw data and return its length if there is no valid filter
407 // specified or if decoding failed.
408 if (buffer && buflen >= len)
409 memcpy(buffer, data, len);
410
Jane Liu18ae06d2017-07-18 10:15:16 -0400411 return len;
412}
413
Dan Sinclair0b950422017-09-21 15:49:49 -0400414RetainPtr<IFX_SeekableReadStream> MakeSeekableReadStream(
tsepez833619b2016-12-07 09:21:17 -0800415 FPDF_FILEACCESS* pFileAccess) {
Tom Sepez40badde2017-05-01 13:21:39 -0700416 return pdfium::MakeRetain<CPDF_CustomAccess>(pFileAccess);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700417}
418
tsepezfa89a202016-12-02 09:48:30 -0800419#ifdef PDF_ENABLE_XFA
Dan Sinclair0b950422017-09-21 15:49:49 -0400420RetainPtr<IFX_SeekableStream> MakeSeekableStream(
tsepez833619b2016-12-07 09:21:17 -0800421 FPDF_FILEHANDLER* pFilehandler) {
Dan Sinclaira7caeb52017-09-26 09:23:29 -0400422 return pdfium::MakeRetain<FPDF_FileHandlerContext>(pFilehandler);
tsepezfa89a202016-12-02 09:48:30 -0800423}
424#endif // PDF_ENABLE_XFA
425
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700426// 0 bit: FPDF_POLICY_MACHINETIME_ACCESS
tsepezc3255f52016-03-25 14:52:27 -0700427static uint32_t foxit_sandbox_policy = 0xFFFFFFFF;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700428
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700429void FSDK_SetSandBoxPolicy(FPDF_DWORD policy, FPDF_BOOL enable) {
430 switch (policy) {
431 case FPDF_POLICY_MACHINETIME_ACCESS: {
432 if (enable)
433 foxit_sandbox_policy |= 0x01;
434 else
435 foxit_sandbox_policy &= 0xFFFFFFFE;
436 } break;
437 default:
438 break;
439 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700440}
441
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700442FPDF_BOOL FSDK_IsSandBoxPolicyEnabled(FPDF_DWORD policy) {
443 switch (policy) {
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700444 case FPDF_POLICY_MACHINETIME_ACCESS:
Lei Zhangb0748bb2015-10-19 12:11:49 -0700445 return !!(foxit_sandbox_policy & 0x01);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700446 default:
tsepez4cf55152016-11-02 14:37:54 -0700447 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700448 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700449}
450
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400451FPDF_EXPORT void FPDF_CALLCONV FPDF_InitLibrary() {
Lei Zhang6f62d532015-09-23 15:31:44 -0700452 FPDF_InitLibraryWithConfig(nullptr);
453}
454
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400455FPDF_EXPORT void FPDF_CALLCONV
Dan Sinclairf766ad22016-03-14 13:51:24 -0400456FPDF_InitLibraryWithConfig(const FPDF_LIBRARY_CONFIG* cfg) {
Dan Sinclair830897a2017-05-11 14:36:10 -0400457 if (g_bLibraryInitialized)
tsepez02759102016-12-01 08:29:25 -0800458 return;
459
Dan Sinclairdbc3d3e2017-05-11 13:41:38 -0400460 FXMEM_InitializePartitionAlloc();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700461
weili47228ac2016-07-20 10:35:31 -0700462 CFX_GEModule* pModule = CFX_GEModule::Get();
Dan Sinclair830897a2017-05-11 14:36:10 -0400463 pModule->Init(cfg ? cfg->m_pUserFontPaths : nullptr);
tsepez02759102016-12-01 08:29:25 -0800464
Tom Sepez1b246282015-11-25 15:15:31 -0800465 CPDF_ModuleMgr* pModuleMgr = CPDF_ModuleMgr::Get();
Lei Zhang76020fc2017-05-18 15:51:20 -0700466 pModuleMgr->Init();
Tom Sepezb4a26182017-03-01 12:15:00 -0800467
Tom Sepez40e9ff32015-11-30 12:39:54 -0800468#ifdef PDF_ENABLE_XFA
dsinclair8837c912016-11-01 11:22:37 -0700469 FXJSE_Initialize();
470 BC_Library_Init();
Tom Sepez40e9ff32015-11-30 12:39:54 -0800471#endif // PDF_ENABLE_XFA
Tom Sepez452b4f32015-10-13 09:27:27 -0700472 if (cfg && cfg->version >= 2)
473 IJS_Runtime::Initialize(cfg->m_v8EmbedderSlot, cfg->m_pIsolate);
Dan Sinclair830897a2017-05-11 14:36:10 -0400474
475 g_bLibraryInitialized = true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700476}
477
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400478FPDF_EXPORT void FPDF_CALLCONV FPDF_DestroyLibrary() {
Dan Sinclair830897a2017-05-11 14:36:10 -0400479 if (!g_bLibraryInitialized)
tsepez02759102016-12-01 08:29:25 -0800480 return;
481
Tom Sepez51da0932015-11-25 16:05:49 -0800482#ifdef PDF_ENABLE_XFA
Tom Sepez5628fd72017-04-27 14:58:53 -0700483 BC_Library_Destroy();
dsinclair8837c912016-11-01 11:22:37 -0700484 FXJSE_Finalize();
Tom Sepez40e9ff32015-11-30 12:39:54 -0800485#endif // PDF_ENABLE_XFA
dsinclair8837c912016-11-01 11:22:37 -0700486
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700487 CPDF_ModuleMgr::Destroy();
488 CFX_GEModule::Destroy();
Tom Sepez2c286192015-06-18 12:47:11 -0700489
thestig2d6dda12016-06-28 07:39:09 -0700490 IJS_Runtime::Destroy();
Dan Sinclair830897a2017-05-11 14:36:10 -0400491
492 g_bLibraryInitialized = false;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700493}
494
495#ifndef _WIN32
496int g_LastError;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700497void SetLastError(int err) {
498 g_LastError = err;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700499}
500
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700501int GetLastError() {
502 return g_LastError;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700503}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800504#endif // _WIN32
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700505
Tom Sepezf10ae632016-01-26 14:19:52 -0800506void ProcessParseError(CPDF_Parser::Error err) {
tsepezc3255f52016-03-25 14:52:27 -0700507 uint32_t err_code = FPDF_ERR_SUCCESS;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700508 // Translate FPDFAPI error code to FPDFVIEW error code
Tom Sepezf10ae632016-01-26 14:19:52 -0800509 switch (err) {
510 case CPDF_Parser::SUCCESS:
511 err_code = FPDF_ERR_SUCCESS;
512 break;
513 case CPDF_Parser::FILE_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700514 err_code = FPDF_ERR_FILE;
515 break;
Tom Sepezf10ae632016-01-26 14:19:52 -0800516 case CPDF_Parser::FORMAT_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700517 err_code = FPDF_ERR_FORMAT;
518 break;
Tom Sepezf10ae632016-01-26 14:19:52 -0800519 case CPDF_Parser::PASSWORD_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700520 err_code = FPDF_ERR_PASSWORD;
521 break;
Tom Sepezf10ae632016-01-26 14:19:52 -0800522 case CPDF_Parser::HANDLER_ERROR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700523 err_code = FPDF_ERR_SECURITY;
524 break;
525 }
526 SetLastError(err_code);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700527}
528
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400529FPDF_EXPORT void FPDF_CALLCONV FPDF_SetSandBoxPolicy(FPDF_DWORD policy,
530 FPDF_BOOL enable) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700531 return FSDK_SetSandBoxPolicy(policy, enable);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700532}
533
rbpotterdb764702017-01-12 10:31:43 -0800534#if defined(_WIN32)
535#if defined(PDFIUM_PRINT_TEXT_WITH_GDI)
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400536FPDF_EXPORT void FPDF_CALLCONV
thestigfdb35ff2016-07-18 13:45:44 -0700537FPDF_SetTypefaceAccessibleFunc(PDFiumEnsureTypefaceCharactersAccessible func) {
538 g_pdfium_typeface_accessible_func = func;
539}
540
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400541FPDF_EXPORT void FPDF_CALLCONV FPDF_SetPrintTextWithGDI(FPDF_BOOL use_gdi) {
thestigfdb35ff2016-07-18 13:45:44 -0700542 g_pdfium_print_text_with_gdi = !!use_gdi;
543}
rbpotterdb764702017-01-12 10:31:43 -0800544#endif // PDFIUM_PRINT_TEXT_WITH_GDI
545
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400546FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
547FPDF_SetPrintPostscriptLevel(int postscript_level) {
rbpotter38a01b92017-07-13 11:58:01 -0700548 return postscript_level != 1 && FPDF_SetPrintMode(postscript_level);
549}
550
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400551FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_SetPrintMode(int mode) {
rbpottere8468c42017-07-11 10:04:29 -0700552 if (mode < FPDF_PRINTMODE_EMF || mode > FPDF_PRINTMODE_POSTSCRIPT3)
rbpotterdb764702017-01-12 10:31:43 -0800553 return FALSE;
rbpottere8468c42017-07-11 10:04:29 -0700554 g_pdfium_print_mode = mode;
rbpotterdb764702017-01-12 10:31:43 -0800555 return TRUE;
556}
557#endif // defined(_WIN32)
thestigfdb35ff2016-07-18 13:45:44 -0700558
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400559FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV
560FPDF_LoadDocument(FPDF_STRING file_path, FPDF_BYTESTRING password) {
Tom Sepeze3166a82015-08-05 10:50:32 -0700561 // NOTE: the creation of the file needs to be by the embedder on the
562 // other side of this API.
Artem Strygin3f7ff052017-07-27 22:16:13 +0300563 return LoadDocumentImpl(
564 IFX_SeekableReadStream::CreateFromFilename((const char*)file_path),
565 password);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700566}
Jun Fange118ce92015-02-17 06:50:08 -0800567
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400568FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_HasXFAField(FPDF_DOCUMENT document,
569 int* docType) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700570 if (!document)
tsepez4cf55152016-11-02 14:37:54 -0700571 return false;
JUN FANG827a1722015-03-05 13:39:21 -0800572
Ryan Harrisona74a6272017-10-16 10:57:48 -0400573 const CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Lei Zhang01581062017-08-30 14:19:26 -0700574 if (!pDoc)
tsepez4cf55152016-11-02 14:37:54 -0700575 return false;
JUN FANG827a1722015-03-05 13:39:21 -0800576
Lei Zhang01581062017-08-30 14:19:26 -0700577 const CPDF_Dictionary* pRoot = pDoc->GetRoot();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700578 if (!pRoot)
tsepez4cf55152016-11-02 14:37:54 -0700579 return false;
JUN FANG827a1722015-03-05 13:39:21 -0800580
dsinclair38fd8442016-09-15 10:15:32 -0700581 CPDF_Dictionary* pAcroForm = pRoot->GetDictFor("AcroForm");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700582 if (!pAcroForm)
tsepez4cf55152016-11-02 14:37:54 -0700583 return false;
JUN FANG827a1722015-03-05 13:39:21 -0800584
dsinclair38fd8442016-09-15 10:15:32 -0700585 CPDF_Object* pXFA = pAcroForm->GetObjectFor("XFA");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700586 if (!pXFA)
tsepez4cf55152016-11-02 14:37:54 -0700587 return false;
JUN FANG827a1722015-03-05 13:39:21 -0800588
dsinclair38fd8442016-09-15 10:15:32 -0700589 bool bDynamicXFA = pRoot->GetBooleanFor("NeedsRendering", false);
thestigded36342016-05-23 17:54:02 -0700590 *docType = bDynamicXFA ? DOCTYPE_DYNAMIC_XFA : DOCTYPE_STATIC_XFA;
tsepez4cf55152016-11-02 14:37:54 -0700591 return true;
Jun Fange118ce92015-02-17 06:50:08 -0800592}
593
Ryan Harrisona74a6272017-10-16 10:57:48 -0400594#ifdef PDF_ENABLE_XFA
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400595FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_LoadXFA(FPDF_DOCUMENT document) {
Lei Zhang01581062017-08-30 14:19:26 -0700596 return document && static_cast<CPDFXFA_Context*>(document)->LoadXFADoc();
Bo Xufdc00a72014-10-28 23:03:33 -0700597}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800598#endif // PDF_ENABLE_XFA
Bo Xufdc00a72014-10-28 23:03:33 -0700599
tsepezad2441e2016-10-24 10:19:11 -0700600class CMemFile final : public IFX_SeekableReadStream {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700601 public:
Dan Sinclair0b950422017-09-21 15:49:49 -0400602 static RetainPtr<CMemFile> Create(uint8_t* pBuf, FX_FILESIZE size) {
603 return RetainPtr<CMemFile>(new CMemFile(pBuf, size));
tsepez833619b2016-12-07 09:21:17 -0800604 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700605
Lei Zhang3884dba2015-10-19 17:27:53 -0700606 FX_FILESIZE GetSize() override { return m_size; }
tsepezf39074c2016-10-26 15:33:58 -0700607 bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override {
tsepez833619b2016-12-07 09:21:17 -0800608 if (offset < 0)
tsepezf39074c2016-10-26 15:33:58 -0700609 return false;
tsepez833619b2016-12-07 09:21:17 -0800610
tsepez4e597c82016-11-07 15:16:01 -0800611 FX_SAFE_FILESIZE newPos = pdfium::base::checked_cast<FX_FILESIZE>(size);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700612 newPos += offset;
tsepez833619b2016-12-07 09:21:17 -0800613 if (!newPos.IsValid() || newPos.ValueOrDie() > m_size)
tsepezf39074c2016-10-26 15:33:58 -0700614 return false;
tsepez833619b2016-12-07 09:21:17 -0800615
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400616 memcpy(buffer, m_pBuf + offset, size);
tsepezf39074c2016-10-26 15:33:58 -0700617 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700618 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700619
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700620 private:
tsepez833619b2016-12-07 09:21:17 -0800621 CMemFile(uint8_t* pBuf, FX_FILESIZE size) : m_pBuf(pBuf), m_size(size) {}
Lei Zhang2b1a2d52015-08-14 22:16:22 -0700622
Lei Zhang3884dba2015-10-19 17:27:53 -0700623 uint8_t* const m_pBuf;
624 const FX_FILESIZE m_size;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700625};
Lei Zhang3884dba2015-10-19 17:27:53 -0700626
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400627FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV
628FPDF_LoadMemDocument(const void* data_buf, int size, FPDF_BYTESTRING password) {
Artem Strygin3f7ff052017-07-27 22:16:13 +0300629 return LoadDocumentImpl(CMemFile::Create((uint8_t*)data_buf, size), password);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700630}
631
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400632FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700633FPDF_LoadCustomDocument(FPDF_FILEACCESS* pFileAccess,
634 FPDF_BYTESTRING password) {
Artem Strygin3f7ff052017-07-27 22:16:13 +0300635 return LoadDocumentImpl(pdfium::MakeRetain<CPDF_CustomAccess>(pFileAccess),
636 password);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700637}
638
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400639FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_GetFileVersion(FPDF_DOCUMENT doc,
640 int* fileVersion) {
Tom Sepez471a1032015-10-15 16:17:18 -0700641 if (!fileVersion)
tsepez4cf55152016-11-02 14:37:54 -0700642 return false;
Bo Xufdc00a72014-10-28 23:03:33 -0700643
Tom Sepez471a1032015-10-15 16:17:18 -0700644 *fileVersion = 0;
645 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(doc);
646 if (!pDoc)
tsepez4cf55152016-11-02 14:37:54 -0700647 return false;
Tom Sepez471a1032015-10-15 16:17:18 -0700648
Lei Zhang01581062017-08-30 14:19:26 -0700649 const CPDF_Parser* pParser = pDoc->GetParser();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700650 if (!pParser)
tsepez4cf55152016-11-02 14:37:54 -0700651 return false;
Tom Sepez471a1032015-10-15 16:17:18 -0700652
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700653 *fileVersion = pParser->GetFileVersion();
tsepez4cf55152016-11-02 14:37:54 -0700654 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700655}
656
tsepezc3255f52016-03-25 14:52:27 -0700657// jabdelmalek: changed return type from uint32_t to build on Linux (and match
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700658// header).
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400659FPDF_EXPORT unsigned long FPDF_CALLCONV
660FPDF_GetDocPermissions(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700661 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
thestig27ddf162016-05-23 15:06:59 -0700662 // https://bugs.chromium.org/p/pdfium/issues/detail?id=499
663 if (!pDoc) {
Tom Sepez51da0932015-11-25 16:05:49 -0800664#ifndef PDF_ENABLE_XFA
665 return 0;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800666#else // PDF_ENABLE_XFA
thestig27ddf162016-05-23 15:06:59 -0700667 return 0xFFFFFFFF;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800668#endif // PDF_ENABLE_XFA
thestig27ddf162016-05-23 15:06:59 -0700669 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700670
thestig27ddf162016-05-23 15:06:59 -0700671 return pDoc->GetUserPermissions();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700672}
673
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400674FPDF_EXPORT int FPDF_CALLCONV
675FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -0700676 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
thestigb8db5112016-04-06 12:12:52 -0700677 if (!pDoc || !pDoc->GetParser())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700678 return -1;
Bo Xuc5cab022014-09-19 19:16:31 -0700679
Tom Sepez471a1032015-10-15 16:17:18 -0700680 CPDF_Dictionary* pDict = pDoc->GetParser()->GetEncryptDict();
dsinclair38fd8442016-09-15 10:15:32 -0700681 return pDict ? pDict->GetIntegerFor("R") : -1;
Bo Xuc5cab022014-09-19 19:16:31 -0700682}
683
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400684FPDF_EXPORT int FPDF_CALLCONV FPDF_GetPageCount(FPDF_DOCUMENT document) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800685 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
Tom Sepez471a1032015-10-15 16:17:18 -0700686 return pDoc ? pDoc->GetPageCount() : 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700687}
688
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400689FPDF_EXPORT FPDF_PAGE FPDF_CALLCONV FPDF_LoadPage(FPDF_DOCUMENT document,
690 int page_index) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800691 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
692 if (!pDoc)
Tom Sepez471a1032015-10-15 16:17:18 -0700693 return nullptr;
Tom Sepez1b246282015-11-25 15:15:31 -0800694
Tom Sepezbbe0e4d2015-10-20 15:41:40 -0700695 if (page_index < 0 || page_index >= pDoc->GetPageCount())
Tom Sepez471a1032015-10-15 16:17:18 -0700696 return nullptr;
697
Tom Sepez40e9ff32015-11-30 12:39:54 -0800698#ifdef PDF_ENABLE_XFA
Tom Sepez9792f162017-05-16 14:11:30 -0700699 return pDoc->GetXFAPage(page_index).Leak();
Tom Sepez40e9ff32015-11-30 12:39:54 -0800700#else // PDF_ENABLE_XFA
Tom Sepez51da0932015-11-25 16:05:49 -0800701 CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
Lei Zhang412e9082015-12-14 18:34:00 -0800702 if (!pDict)
thestig5cc24652016-04-26 11:46:02 -0700703 return nullptr;
704
705 CPDF_Page* pPage = new CPDF_Page(pDoc, pDict, true);
706 pPage->ParseContent();
Tom Sepez51da0932015-11-25 16:05:49 -0800707 return pPage;
Tom Sepez40e9ff32015-11-30 12:39:54 -0800708#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700709}
710
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400711FPDF_EXPORT double FPDF_CALLCONV FPDF_GetPageWidth(FPDF_PAGE page) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800712 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezbf59a072015-10-21 14:07:23 -0700713 return pPage ? pPage->GetPageWidth() : 0.0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700714}
715
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400716FPDF_EXPORT double FPDF_CALLCONV FPDF_GetPageHeight(FPDF_PAGE page) {
Tom Sepez50d12ad2015-11-24 09:50:51 -0800717 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezbf59a072015-10-21 14:07:23 -0700718 return pPage ? pPage->GetPageHeight() : 0.0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700719}
720
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700721#if defined(_WIN32)
rbpottercec01802017-04-17 09:10:21 -0700722namespace {
723
724const double kEpsilonSize = 0.01f;
725
726void GetScaling(CPDF_Page* pPage,
727 int size_x,
728 int size_y,
729 int rotate,
730 double* scale_x,
731 double* scale_y) {
732 ASSERT(pPage);
733 ASSERT(scale_x);
734 ASSERT(scale_y);
735 double page_width = pPage->GetPageWidth();
736 double page_height = pPage->GetPageHeight();
737 if (page_width < kEpsilonSize || page_height < kEpsilonSize)
738 return;
739
740 if (rotate % 2 == 0) {
741 *scale_x = size_x / page_width;
742 *scale_y = size_y / page_height;
743 } else {
744 *scale_x = size_y / page_width;
745 *scale_y = size_x / page_height;
746 }
747}
748
749FX_RECT GetMaskDimensionsAndOffsets(CPDF_Page* pPage,
750 int start_x,
751 int start_y,
752 int size_x,
753 int size_y,
754 int rotate,
755 const CFX_FloatRect& mask_box) {
756 double scale_x = 0.0f;
757 double scale_y = 0.0f;
758 GetScaling(pPage, size_x, size_y, rotate, &scale_x, &scale_y);
759 if (scale_x < kEpsilonSize || scale_y < kEpsilonSize)
760 return FX_RECT();
761
762 // Compute sizes in page points. Round down to catch the entire bitmap.
763 int start_x_bm = static_cast<int>(mask_box.left * scale_x);
764 int start_y_bm = static_cast<int>(mask_box.bottom * scale_y);
765 int size_x_bm = static_cast<int>(mask_box.right * scale_x + 1.0f) -
766 static_cast<int>(mask_box.left * scale_x);
767 int size_y_bm = static_cast<int>(mask_box.top * scale_y + 1.0f) -
768 static_cast<int>(mask_box.bottom * scale_y);
769
770 // Get page rotation
rbpotterce8e51e2017-04-28 12:42:47 -0700771 int page_rotation = pPage->GetPageRotation();
rbpottercec01802017-04-17 09:10:21 -0700772
773 // Compute offsets
774 int offset_x = 0;
775 int offset_y = 0;
rbpotter8d7672e2017-08-16 16:45:44 -0700776 if (size_x > size_y)
777 std::swap(size_x_bm, size_y_bm);
778
rbpottercec01802017-04-17 09:10:21 -0700779 switch ((rotate + page_rotation) % 4) {
780 case 0:
781 offset_x = start_x_bm + start_x;
782 offset_y = start_y + size_y - size_y_bm - start_y_bm;
783 break;
784 case 1:
785 offset_x = start_y_bm + start_x;
786 offset_y = start_x_bm + start_y;
787 break;
788 case 2:
789 offset_x = start_x + size_x - size_x_bm - start_x_bm;
790 offset_y = start_y_bm + start_y;
791 break;
792 case 3:
793 offset_x = start_x + size_x - size_x_bm - start_y_bm;
794 offset_y = start_y + size_y - size_y_bm - start_x_bm;
795 break;
796 }
797 return FX_RECT(offset_x, offset_y, offset_x + size_x_bm,
798 offset_y + size_y_bm);
799}
800
801// Get a bitmap of just the mask section defined by |mask_box| from a full page
802// bitmap |pBitmap|.
Dan Sinclair0b950422017-09-21 15:49:49 -0400803RetainPtr<CFX_DIBitmap> GetMaskBitmap(CPDF_Page* pPage,
804 int start_x,
805 int start_y,
806 int size_x,
807 int size_y,
808 int rotate,
809 RetainPtr<CFX_DIBitmap>& pSrc,
810 const CFX_FloatRect& mask_box,
811 FX_RECT* bitmap_area) {
rbpottercec01802017-04-17 09:10:21 -0700812 ASSERT(bitmap_area);
813 *bitmap_area = GetMaskDimensionsAndOffsets(pPage, start_x, start_y, size_x,
814 size_y, rotate, mask_box);
815 if (bitmap_area->IsEmpty())
816 return nullptr;
817
818 // Create a new bitmap to transfer part of the page bitmap to.
Dan Sinclair0b950422017-09-21 15:49:49 -0400819 RetainPtr<CFX_DIBitmap> pDst = pdfium::MakeRetain<CFX_DIBitmap>();
rbpottercec01802017-04-17 09:10:21 -0700820 pDst->Create(bitmap_area->Width(), bitmap_area->Height(), FXDIB_Argb);
821 pDst->Clear(0x00ffffff);
822 pDst->TransferBitmap(0, 0, bitmap_area->Width(), bitmap_area->Height(), pSrc,
823 bitmap_area->left, bitmap_area->top);
824 return pDst;
825}
826
827void RenderBitmap(CFX_RenderDevice* device,
Dan Sinclair0b950422017-09-21 15:49:49 -0400828 const RetainPtr<CFX_DIBitmap>& pSrc,
rbpottercec01802017-04-17 09:10:21 -0700829 const FX_RECT& mask_area) {
830 int size_x_bm = mask_area.Width();
831 int size_y_bm = mask_area.Height();
832 if (size_x_bm == 0 || size_y_bm == 0)
833 return;
834
835 // Create a new bitmap from the old one
Dan Sinclair0b950422017-09-21 15:49:49 -0400836 RetainPtr<CFX_DIBitmap> pDst = pdfium::MakeRetain<CFX_DIBitmap>();
rbpottercec01802017-04-17 09:10:21 -0700837 pDst->Create(size_x_bm, size_y_bm, FXDIB_Rgb32);
838 pDst->Clear(0xffffffff);
839 pDst->CompositeBitmap(0, 0, size_x_bm, size_y_bm, pSrc, 0, 0,
840 FXDIB_BLEND_NORMAL, nullptr, false);
841
842 if (device->GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
rbpotter8d7672e2017-08-16 16:45:44 -0700843 device->StretchDIBits(pDst, mask_area.left, mask_area.top, size_x_bm,
844 size_y_bm);
rbpottercec01802017-04-17 09:10:21 -0700845 } else {
846 device->SetDIBits(pDst, mask_area.left, mask_area.top);
847 }
848}
849
850} // namespace
851
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400852FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPage(HDC dc,
853 FPDF_PAGE page,
854 int start_x,
855 int start_y,
856 int size_x,
857 int size_y,
858 int rotate,
859 int flags) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700860 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700861 if (!pPage)
862 return;
rbpottercec01802017-04-17 09:10:21 -0700863 pPage->SetRenderContext(pdfium::MakeUnique<CPDF_PageRenderContext>());
864 CPDF_PageRenderContext* pContext = pPage->GetRenderContext();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700865
Dan Sinclair0b950422017-09-21 15:49:49 -0400866 RetainPtr<CFX_DIBitmap> pBitmap;
rbpottercec01802017-04-17 09:10:21 -0700867 // Don't render the full page to bitmap for a mask unless there are a lot
868 // of masks. Full page bitmaps result in large spool sizes, so they should
869 // only be used when necessary. For large numbers of masks, rendering each
870 // individually is inefficient and unlikely to significantly improve spool
rbpotter8d7672e2017-08-16 16:45:44 -0700871 // size.
thestig84144e82016-09-27 15:06:01 -0700872 const bool bNewBitmap =
rbpotter8d7672e2017-08-16 16:45:44 -0700873 pPage->BackgroundAlphaNeeded() ||
874 (pPage->HasImageMask() && pPage->GetMaskBoundingBoxes().size() > 100);
rbpottercec01802017-04-17 09:10:21 -0700875 const bool bHasMask = pPage->HasImageMask() && !bNewBitmap;
876 if (bNewBitmap || bHasMask) {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700877 pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700878 pBitmap->Create(size_x, size_y, FXDIB_Argb);
879 pBitmap->Clear(0x00ffffff);
Dan Sinclaira5085d42017-05-11 16:26:50 -0400880 CFX_DefaultRenderDevice* pDevice = new CFX_DefaultRenderDevice;
tsepez36eb4bd2016-10-03 15:24:27 -0700881 pContext->m_pDevice = pdfium::WrapUnique(pDevice);
Tom Sepezf0799fe2017-03-28 09:31:32 -0700882 pDevice->Attach(pBitmap, false, nullptr, false);
rbpottercec01802017-04-17 09:10:21 -0700883 if (bHasMask) {
884 pContext->m_pOptions = pdfium::MakeUnique<CPDF_RenderOptions>();
Dan Sinclair921fe6b2017-10-05 11:14:12 -0400885 uint32_t option_flags = pContext->m_pOptions->GetFlags();
886 option_flags |= RENDER_BREAKFORMASKS;
887 pContext->m_pOptions->SetFlags(option_flags);
rbpottercec01802017-04-17 09:10:21 -0700888 }
Jun Fang1aeeceb2015-12-29 10:27:44 +0800889 } else {
Dan Sinclaira5085d42017-05-11 16:26:50 -0400890 pContext->m_pDevice = pdfium::MakeUnique<CFX_WindowsRenderDevice>(dc);
Jun Fang1aeeceb2015-12-29 10:27:44 +0800891 }
rbpottercec01802017-04-17 09:10:21 -0700892
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700893 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
tsepez4cf55152016-11-02 14:37:54 -0700894 rotate, flags, true, nullptr);
Bo Xud4e406e2014-08-13 11:03:19 -0700895
rbpottercec01802017-04-17 09:10:21 -0700896 if (bHasMask) {
897 // Finish rendering the page to bitmap and copy the correct segments
898 // of the page to individual image mask bitmaps.
899 const std::vector<CFX_FloatRect>& mask_boxes =
900 pPage->GetMaskBoundingBoxes();
901 std::vector<FX_RECT> bitmap_areas(mask_boxes.size());
Dan Sinclair0b950422017-09-21 15:49:49 -0400902 std::vector<RetainPtr<CFX_DIBitmap>> bitmaps(mask_boxes.size());
rbpottercec01802017-04-17 09:10:21 -0700903 for (size_t i = 0; i < mask_boxes.size(); i++) {
904 bitmaps[i] =
905 GetMaskBitmap(pPage, start_x, start_y, size_x, size_y, rotate,
906 pBitmap, mask_boxes[i], &bitmap_areas[i]);
907 pContext->m_pRenderer->Continue(nullptr);
908 }
909
910 // Reset rendering context
911 pPage->SetRenderContext(nullptr);
912
913 // Begin rendering to the printer. Add flag to indicate the renderer should
914 // pause after each image mask.
915 pPage->SetRenderContext(pdfium::MakeUnique<CPDF_PageRenderContext>());
916 pContext = pPage->GetRenderContext();
Dan Sinclaira5085d42017-05-11 16:26:50 -0400917 pContext->m_pDevice = pdfium::MakeUnique<CFX_WindowsRenderDevice>(dc);
rbpottercec01802017-04-17 09:10:21 -0700918 pContext->m_pOptions = pdfium::MakeUnique<CPDF_RenderOptions>();
Dan Sinclair921fe6b2017-10-05 11:14:12 -0400919
920 uint32_t option_flags = pContext->m_pOptions->GetFlags();
921 option_flags |= RENDER_BREAKFORMASKS;
922 pContext->m_pOptions->SetFlags(option_flags);
923
rbpottercec01802017-04-17 09:10:21 -0700924 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
925 rotate, flags, true, nullptr);
926
927 // Render masks
928 for (size_t i = 0; i < mask_boxes.size(); i++) {
929 // Render the bitmap for the mask and free the bitmap.
930 if (bitmaps[i]) { // will be null if mask has zero area
931 RenderBitmap(pContext->m_pDevice.get(), bitmaps[i], bitmap_areas[i]);
932 }
933 // Render the next portion of page.
934 pContext->m_pRenderer->Continue(nullptr);
935 }
936 } else if (bNewBitmap) {
Dan Sinclaira5085d42017-05-11 16:26:50 -0400937 CFX_WindowsRenderDevice WinDC(dc);
thestig84144e82016-09-27 15:06:01 -0700938 if (WinDC.GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700939 auto pDst = pdfium::MakeRetain<CFX_DIBitmap>();
thestig84144e82016-09-27 15:06:01 -0700940 int pitch = pBitmap->GetPitch();
941 pDst->Create(size_x, size_y, FXDIB_Rgb32);
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400942 memset(pDst->GetBuffer(), -1, pitch * size_y);
Tom Sepezf0799fe2017-03-28 09:31:32 -0700943 pDst->CompositeBitmap(0, 0, size_x, size_y, pBitmap, 0, 0,
Nicolas Pena6a5c20c2017-04-07 14:12:31 -0400944 FXDIB_BLEND_NORMAL, nullptr, false);
Tom Sepezf0799fe2017-03-28 09:31:32 -0700945 WinDC.StretchDIBits(pDst, 0, 0, size_x, size_y);
thestig84144e82016-09-27 15:06:01 -0700946 } else {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700947 WinDC.SetDIBits(pBitmap, 0, 0);
Lei Zhang6d8b1c22015-06-19 17:26:17 -0700948 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700949 }
rbpottercec01802017-04-17 09:10:21 -0700950
tsepeze5cb0b12016-10-26 15:06:11 -0700951 pPage->SetRenderContext(nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700952}
Lei Zhangae85f872016-02-19 14:57:07 -0800953#endif // defined(_WIN32)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700954
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400955FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPageBitmap(FPDF_BITMAP bitmap,
956 FPDF_PAGE page,
957 int start_x,
958 int start_y,
959 int size_x,
960 int size_y,
961 int rotate,
962 int flags) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700963 if (!bitmap)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700964 return;
tsepez1e2c5572016-05-25 14:58:09 -0700965
Tom Sepezdb0be962015-10-16 14:00:21 -0700966 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700967 if (!pPage)
968 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700969
weili9f515bc2016-07-24 08:08:24 -0700970 CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
tsepez36eb4bd2016-10-03 15:24:27 -0700971 pPage->SetRenderContext(pdfium::WrapUnique(pContext));
Tom Sepezf0799fe2017-03-28 09:31:32 -0700972
Dan Sinclaira5085d42017-05-11 16:26:50 -0400973 CFX_DefaultRenderDevice* pDevice = new CFX_DefaultRenderDevice;
weili9f515bc2016-07-24 08:08:24 -0700974 pContext->m_pDevice.reset(pDevice);
dsinclair31b08d42017-03-28 15:47:47 +0000975
Dan Sinclair0b950422017-09-21 15:49:49 -0400976 RetainPtr<CFX_DIBitmap> pBitmap(CFXBitmapFromFPDFBitmap(bitmap));
Tom Sepezf0799fe2017-03-28 09:31:32 -0700977 pDevice->Attach(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER), nullptr, false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700978 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
tsepez4cf55152016-11-02 14:37:54 -0700979 rotate, flags, true, nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700980
caryclark687fbde2016-11-22 12:44:25 -0800981#ifdef _SKIA_SUPPORT_PATHS_
Cary Clark364d18b2017-07-25 10:39:10 -0400982 pDevice->Flush(true);
caryclark687fbde2016-11-22 12:44:25 -0800983 pBitmap->UnPreMultiply();
984#endif
tsepeze5cb0b12016-10-26 15:06:11 -0700985 pPage->SetRenderContext(nullptr);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700986}
987
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400988FPDF_EXPORT void FPDF_CALLCONV
989FPDF_RenderPageBitmapWithMatrix(FPDF_BITMAP bitmap,
990 FPDF_PAGE page,
991 const FS_MATRIX* matrix,
992 const FS_RECTF* clipping,
993 int flags) {
thestiga78ba602016-11-23 15:25:48 -0800994 if (!bitmap)
995 return;
996
997 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
998 if (!pPage)
999 return;
1000
1001 CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
1002 pPage->SetRenderContext(pdfium::WrapUnique(pContext));
Tom Sepezf0799fe2017-03-28 09:31:32 -07001003
Dan Sinclaira5085d42017-05-11 16:26:50 -04001004 CFX_DefaultRenderDevice* pDevice = new CFX_DefaultRenderDevice;
thestiga78ba602016-11-23 15:25:48 -08001005 pContext->m_pDevice.reset(pDevice);
Tom Sepezf0799fe2017-03-28 09:31:32 -07001006
Dan Sinclair0b950422017-09-21 15:49:49 -04001007 RetainPtr<CFX_DIBitmap> pBitmap(CFXBitmapFromFPDFBitmap(bitmap));
thestiga78ba602016-11-23 15:25:48 -08001008 pDevice->Attach(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER), nullptr, false);
1009
thestiga78ba602016-11-23 15:25:48 -08001010 CFX_FloatRect clipping_rect;
1011 if (clipping) {
1012 clipping_rect.left = clipping->left;
1013 clipping_rect.bottom = clipping->bottom;
1014 clipping_rect.right = clipping->right;
1015 clipping_rect.top = clipping->top;
1016 }
Nicolas Pena60bde102017-07-26 13:50:12 -04001017 FX_RECT clip_rect = clipping_rect.ToFxRect();
Nicolas Pena24b07332017-09-13 18:02:11 -04001018 RenderPageImpl(
1019 pContext, pPage,
1020 pPage->GetDisplayMatrixWithTransformation(
1021 clip_rect.left, clip_rect.top, clip_rect.Width(), clip_rect.Height(),
1022 CFX_Matrix(matrix->a, matrix->b, matrix->c, matrix->d, matrix->e,
1023 matrix->f)),
1024 clip_rect, flags, true, nullptr);
thestiga78ba602016-11-23 15:25:48 -08001025
1026 pPage->SetRenderContext(nullptr);
1027}
1028
Cary Clark399be5b2016-03-14 16:51:29 -04001029#ifdef _SKIA_SUPPORT_
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001030FPDF_EXPORT FPDF_RECORDER FPDF_CALLCONV FPDF_RenderPageSkp(FPDF_PAGE page,
1031 int size_x,
1032 int size_y) {
Cary Clark399be5b2016-03-14 16:51:29 -04001033 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
1034 if (!pPage)
1035 return nullptr;
tsepez1e2c5572016-05-25 14:58:09 -07001036
weili9f515bc2016-07-24 08:08:24 -07001037 CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
tsepez36eb4bd2016-10-03 15:24:27 -07001038 pPage->SetRenderContext(pdfium::WrapUnique(pContext));
Dan Sinclaira5085d42017-05-11 16:26:50 -04001039 CFX_DefaultRenderDevice* skDevice = new CFX_DefaultRenderDevice;
Cary Clark399be5b2016-03-14 16:51:29 -04001040 FPDF_RECORDER recorder = skDevice->CreateRecorder(size_x, size_y);
weili9f515bc2016-07-24 08:08:24 -07001041 pContext->m_pDevice.reset(skDevice);
tsepez4cf55152016-11-02 14:37:54 -07001042 FPDF_RenderPage_Retail(pContext, page, 0, 0, size_x, size_y, 0, 0, true,
tsepez1e2c5572016-05-25 14:58:09 -07001043 nullptr);
tsepeze5cb0b12016-10-26 15:06:11 -07001044 pPage->SetRenderContext(nullptr);
Cary Clark399be5b2016-03-14 16:51:29 -04001045 return recorder;
1046}
1047#endif
1048
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001049FPDF_EXPORT void FPDF_CALLCONV FPDF_ClosePage(FPDF_PAGE page) {
tsepez1e2c5572016-05-25 14:58:09 -07001050 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001051 if (!page)
1052 return;
Tom Sepez40e9ff32015-11-30 12:39:54 -08001053#ifdef PDF_ENABLE_XFA
Tom Sepez9792f162017-05-16 14:11:30 -07001054 // Take it back across the API and throw it away.
Dan Sinclair0b950422017-09-21 15:49:49 -04001055 RetainPtr<CPDFXFA_Page>().Unleak(pPage);
Tom Sepez40e9ff32015-11-30 12:39:54 -08001056#else // PDF_ENABLE_XFA
Tom Sepez51da0932015-11-25 16:05:49 -08001057 CPDFSDK_PageView* pPageView =
tsepez1e2c5572016-05-25 14:58:09 -07001058 static_cast<CPDFSDK_PageView*>(pPage->GetView());
dsinclair1df1efa2016-09-07 09:55:37 -07001059 if (pPageView) {
dsinclairbcf46232016-10-03 13:02:27 -07001060 // We're already destroying the pageview, so bail early.
1061 if (pPageView->IsBeingDestroyed())
1062 return;
1063
dsinclair1df1efa2016-09-07 09:55:37 -07001064 if (pPageView->IsLocked()) {
1065 pPageView->TakePageOwnership();
1066 return;
1067 }
1068
1069 bool owned = pPageView->OwnsPage();
1070 // This will delete the |pPageView| object. We must cleanup the PageView
1071 // first because it will attempt to reset the View on the |pPage| during
1072 // destruction.
dsinclair7cbe68e2016-10-12 11:56:23 -07001073 pPageView->GetFormFillEnv()->RemovePageView(pPage);
dsinclair1df1efa2016-09-07 09:55:37 -07001074 // If the page was owned then the pageview will have deleted the page.
1075 if (owned)
1076 return;
Tom Sepez51da0932015-11-25 16:05:49 -08001077 }
tsepez1e2c5572016-05-25 14:58:09 -07001078 delete pPage;
Tom Sepez40e9ff32015-11-30 12:39:54 -08001079#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001080}
1081
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001082FPDF_EXPORT void FPDF_CALLCONV FPDF_CloseDocument(FPDF_DOCUMENT document) {
Jun Fangfc751362015-12-16 21:23:39 -08001083 delete UnderlyingFromFPDFDocument(document);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001084}
1085
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001086FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_GetLastError() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001087 return GetLastError();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001088}
1089
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001090FPDF_EXPORT void FPDF_CALLCONV FPDF_DeviceToPage(FPDF_PAGE page,
1091 int start_x,
1092 int start_y,
1093 int size_x,
1094 int size_y,
1095 int rotate,
1096 int device_x,
1097 int device_y,
1098 double* page_x,
1099 double* page_y) {
Lei Zhang412e9082015-12-14 18:34:00 -08001100 if (!page || !page_x || !page_y)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001101 return;
Tom Sepez50d12ad2015-11-24 09:50:51 -08001102 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepez40e9ff32015-11-30 12:39:54 -08001103#ifdef PDF_ENABLE_XFA
1104 pPage->DeviceToPage(start_x, start_y, size_x, size_y, rotate, device_x,
1105 device_y, page_x, page_y);
1106#else // PDF_ENABLE_XFA
Dan Sinclair1b08df12017-02-09 09:17:20 -05001107 CFX_Matrix page2device =
1108 pPage->GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate);
Dan Sinclair1b08df12017-02-09 09:17:20 -05001109
Nicolas Penab21f1742017-06-29 12:02:06 -04001110 CFX_PointF pos = page2device.GetInverse().Transform(
Dan Sinclair05df0752017-03-14 14:43:42 -04001111 CFX_PointF(static_cast<float>(device_x), static_cast<float>(device_y)));
Dan Sinclairafb44562017-02-09 13:07:43 -05001112
Dan Sinclaira0061af2017-02-23 09:25:17 -05001113 *page_x = pos.x;
1114 *page_y = pos.y;
Tom Sepez40e9ff32015-11-30 12:39:54 -08001115#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001116}
1117
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001118FPDF_EXPORT void FPDF_CALLCONV FPDF_PageToDevice(FPDF_PAGE page,
1119 int start_x,
1120 int start_y,
1121 int size_x,
1122 int size_y,
1123 int rotate,
1124 double page_x,
1125 double page_y,
1126 int* device_x,
1127 int* device_y) {
Tom Sepezdb0be962015-10-16 14:00:21 -07001128 if (!device_x || !device_y)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001129 return;
Tom Sepez50d12ad2015-11-24 09:50:51 -08001130 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
Tom Sepezdb0be962015-10-16 14:00:21 -07001131 if (!pPage)
1132 return;
Tom Sepez40e9ff32015-11-30 12:39:54 -08001133#ifdef PDF_ENABLE_XFA
1134 pPage->PageToDevice(start_x, start_y, size_x, size_y, rotate, page_x, page_y,
1135 device_x, device_y);
1136#else // PDF_ENABLE_XFA
Dan Sinclair1b08df12017-02-09 09:17:20 -05001137 CFX_Matrix page2device =
1138 pPage->GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate);
Dan Sinclaira0061af2017-02-23 09:25:17 -05001139 CFX_PointF pos = page2device.Transform(
Dan Sinclair05df0752017-03-14 14:43:42 -04001140 CFX_PointF(static_cast<float>(page_x), static_cast<float>(page_y)));
Dan Sinclairafb44562017-02-09 13:07:43 -05001141
Dan Sinclaira0061af2017-02-23 09:25:17 -05001142 *device_x = FXSYS_round(pos.x);
1143 *device_y = FXSYS_round(pos.y);
Tom Sepez40e9ff32015-11-30 12:39:54 -08001144#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001145}
1146
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001147FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV FPDFBitmap_Create(int width,
1148 int height,
1149 int alpha) {
Tom Sepezf0799fe2017-03-28 09:31:32 -07001150 auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
tsepez37b12ad2016-12-14 19:50:23 -08001151 if (!pBitmap->Create(width, height, alpha ? FXDIB_Argb : FXDIB_Rgb32))
thestig1cd352e2016-06-07 17:53:06 -07001152 return nullptr;
tsepez37b12ad2016-12-14 19:50:23 -08001153
Tom Sepezf0799fe2017-03-28 09:31:32 -07001154 return pBitmap.Leak();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001155}
1156
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001157FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV FPDFBitmap_CreateEx(int width,
1158 int height,
1159 int format,
1160 void* first_scan,
1161 int stride) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001162 FXDIB_Format fx_format;
1163 switch (format) {
1164 case FPDFBitmap_Gray:
1165 fx_format = FXDIB_8bppRgb;
1166 break;
1167 case FPDFBitmap_BGR:
1168 fx_format = FXDIB_Rgb;
1169 break;
1170 case FPDFBitmap_BGRx:
1171 fx_format = FXDIB_Rgb32;
1172 break;
1173 case FPDFBitmap_BGRA:
1174 fx_format = FXDIB_Argb;
1175 break;
1176 default:
thestig1cd352e2016-06-07 17:53:06 -07001177 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001178 }
Tom Sepezf0799fe2017-03-28 09:31:32 -07001179 auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001180 pBitmap->Create(width, height, fx_format, (uint8_t*)first_scan, stride);
Tom Sepezf0799fe2017-03-28 09:31:32 -07001181 return pBitmap.Leak();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001182}
1183
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001184FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetFormat(FPDF_BITMAP bitmap) {
Jane Liu28fb7ba2017-08-02 21:45:57 -04001185 if (!bitmap)
1186 return FPDFBitmap_Unknown;
1187
1188 FXDIB_Format format = CFXBitmapFromFPDFBitmap(bitmap)->GetFormat();
1189 switch (format) {
1190 case FXDIB_8bppRgb:
1191 case FXDIB_8bppMask:
1192 return FPDFBitmap_Gray;
1193 case FXDIB_Rgb:
1194 return FPDFBitmap_BGR;
1195 case FXDIB_Rgb32:
1196 return FPDFBitmap_BGRx;
1197 case FXDIB_Argb:
1198 return FPDFBitmap_BGRA;
1199 default:
1200 return FPDFBitmap_Unknown;
1201 }
1202}
1203
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001204FPDF_EXPORT void FPDF_CALLCONV FPDFBitmap_FillRect(FPDF_BITMAP bitmap,
1205 int left,
1206 int top,
1207 int width,
1208 int height,
1209 FPDF_DWORD color) {
Lei Zhang412e9082015-12-14 18:34:00 -08001210 if (!bitmap)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001211 return;
thestigbefa4502016-05-26 20:15:19 -07001212
Dan Sinclaira5085d42017-05-11 16:26:50 -04001213 CFX_DefaultRenderDevice device;
Dan Sinclair0b950422017-09-21 15:49:49 -04001214 RetainPtr<CFX_DIBitmap> pBitmap(CFXBitmapFromFPDFBitmap(bitmap));
thestigbefa4502016-05-26 20:15:19 -07001215 device.Attach(pBitmap, false, nullptr, false);
1216 if (!pBitmap->HasAlpha())
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001217 color |= 0xFF000000;
1218 FX_RECT rect(left, top, left + width, top + height);
1219 device.FillRect(&rect, color);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001220}
1221
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001222FPDF_EXPORT void* FPDF_CALLCONV FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap) {
thestigbefa4502016-05-26 20:15:19 -07001223 return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetBuffer() : nullptr;
Bo Xu9114e832014-07-14 13:22:47 -07001224}
1225
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001226FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetWidth(FPDF_BITMAP bitmap) {
thestigbefa4502016-05-26 20:15:19 -07001227 return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetWidth() : 0;
Bo Xu9114e832014-07-14 13:22:47 -07001228}
1229
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001230FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetHeight(FPDF_BITMAP bitmap) {
thestigbefa4502016-05-26 20:15:19 -07001231 return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetHeight() : 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001232}
1233
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001234FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetStride(FPDF_BITMAP bitmap) {
thestigbefa4502016-05-26 20:15:19 -07001235 return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetPitch() : 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001236}
1237
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001238FPDF_EXPORT void FPDF_CALLCONV FPDFBitmap_Destroy(FPDF_BITMAP bitmap) {
Dan Sinclair0b950422017-09-21 15:49:49 -04001239 RetainPtr<CFX_DIBitmap> destroyer;
Tom Sepezf0799fe2017-03-28 09:31:32 -07001240 destroyer.Unleak(CFXBitmapFromFPDFBitmap(bitmap));
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001241}
1242
weili9f515bc2016-07-24 08:08:24 -07001243void FPDF_RenderPage_Retail(CPDF_PageRenderContext* pContext,
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001244 FPDF_PAGE page,
1245 int start_x,
1246 int start_y,
1247 int size_x,
1248 int size_y,
1249 int rotate,
1250 int flags,
tsepez4cf55152016-11-02 14:37:54 -07001251 bool bNeedToRestore,
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001252 IFSDK_PAUSE_Adapter* pause) {
Tom Sepezdb0be962015-10-16 14:00:21 -07001253 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
1254 if (!pPage)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001255 return;
1256
Dan Sinclair1b08df12017-02-09 09:17:20 -05001257 RenderPageImpl(pContext, pPage, pPage->GetDisplayMatrix(
1258 start_x, start_y, size_x, size_y, rotate),
1259 FX_RECT(start_x, start_y, start_x + size_x, start_y + size_y),
1260 flags, bNeedToRestore, pause);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001261}
1262
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001263FPDF_EXPORT int FPDF_CALLCONV FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document,
1264 int page_index,
1265 double* width,
1266 double* height) {
Tom Sepez540c4362015-11-24 13:33:57 -08001267 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
1268 if (!pDoc)
tsepez4cf55152016-11-02 14:37:54 -07001269 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001270
Tom Sepez40e9ff32015-11-30 12:39:54 -08001271#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001272 int count = pDoc->GetPageCount();
1273 if (page_index < 0 || page_index >= count)
tsepez4cf55152016-11-02 14:37:54 -07001274 return false;
Dan Sinclair0b950422017-09-21 15:49:49 -04001275 RetainPtr<CPDFXFA_Page> pPage = pDoc->GetXFAPage(page_index);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001276 if (!pPage)
tsepez4cf55152016-11-02 14:37:54 -07001277 return false;
Tom Sepez40e9ff32015-11-30 12:39:54 -08001278 *width = pPage->GetPageWidth();
1279 *height = pPage->GetPageHeight();
1280#else // PDF_ENABLE_XFA
1281 CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
1282 if (!pDict)
tsepez4cf55152016-11-02 14:37:54 -07001283 return false;
thestig5cc24652016-04-26 11:46:02 -07001284
1285 CPDF_Page page(pDoc, pDict, true);
Tom Sepez51da0932015-11-25 16:05:49 -08001286 *width = page.GetPageWidth();
1287 *height = page.GetPageHeight();
Tom Sepez40e9ff32015-11-30 12:39:54 -08001288#endif // PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001289
tsepez4cf55152016-11-02 14:37:54 -07001290 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001291}
1292
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001293FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001294FPDF_VIEWERREF_GetPrintScaling(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001295 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001296 if (!pDoc)
tsepez4cf55152016-11-02 14:37:54 -07001297 return true;
Tom Sepez471a1032015-10-15 16:17:18 -07001298 CPDF_ViewerPreferences viewRef(pDoc);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001299 return viewRef.PrintScaling();
1300}
1301
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001302FPDF_EXPORT int FPDF_CALLCONV
1303FPDF_VIEWERREF_GetNumCopies(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001304 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001305 if (!pDoc)
1306 return 1;
1307 CPDF_ViewerPreferences viewRef(pDoc);
1308 return viewRef.NumCopies();
1309}
1310
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001311FPDF_EXPORT FPDF_PAGERANGE FPDF_CALLCONV
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001312FPDF_VIEWERREF_GetPrintPageRange(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001313 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001314 if (!pDoc)
thestig1cd352e2016-06-07 17:53:06 -07001315 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001316 CPDF_ViewerPreferences viewRef(pDoc);
1317 return viewRef.PrintPageRange();
1318}
1319
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001320FPDF_EXPORT FPDF_DUPLEXTYPE FPDF_CALLCONV
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001321FPDF_VIEWERREF_GetDuplex(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001322 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001323 if (!pDoc)
Bo Xu9114e832014-07-14 13:22:47 -07001324 return DuplexUndefined;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001325 CPDF_ViewerPreferences viewRef(pDoc);
Ryan Harrison275e2602017-09-18 14:23:18 -04001326 ByteString duplex = viewRef.Duplex();
Lei Zhangd983b092015-12-14 16:58:33 -08001327 if ("Simplex" == duplex)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001328 return Simplex;
Lei Zhangd983b092015-12-14 16:58:33 -08001329 if ("DuplexFlipShortEdge" == duplex)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001330 return DuplexFlipShortEdge;
Lei Zhangd983b092015-12-14 16:58:33 -08001331 if ("DuplexFlipLongEdge" == duplex)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001332 return DuplexFlipLongEdge;
1333 return DuplexUndefined;
Bo Xu9114e832014-07-14 13:22:47 -07001334}
1335
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001336FPDF_EXPORT unsigned long FPDF_CALLCONV
1337FPDF_VIEWERREF_GetName(FPDF_DOCUMENT document,
1338 FPDF_BYTESTRING key,
1339 char* buffer,
1340 unsigned long length) {
thestig04bebfe2016-11-04 16:07:25 -07001341 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1342 if (!pDoc)
1343 return 0;
1344
1345 CPDF_ViewerPreferences viewRef(pDoc);
Ryan Harrison275e2602017-09-18 14:23:18 -04001346 ByteString bsVal;
thestig04bebfe2016-11-04 16:07:25 -07001347 if (!viewRef.GenericName(key, &bsVal))
1348 return 0;
1349
1350 unsigned long dwStringLen = bsVal.GetLength() + 1;
1351 if (buffer && length >= dwStringLen)
1352 memcpy(buffer, bsVal.c_str(), dwStringLen);
1353 return dwStringLen;
1354}
1355
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001356FPDF_EXPORT FPDF_DWORD FPDF_CALLCONV
1357FPDF_CountNamedDests(FPDF_DOCUMENT document) {
Tom Sepez471a1032015-10-15 16:17:18 -07001358 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1359 if (!pDoc)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001360 return 0;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001361
Lei Zhang01581062017-08-30 14:19:26 -07001362 const CPDF_Dictionary* pRoot = pDoc->GetRoot();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001363 if (!pRoot)
1364 return 0;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001365
Lei Zhangd983b092015-12-14 16:58:33 -08001366 CPDF_NameTree nameTree(pDoc, "Dests");
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001367 pdfium::base::CheckedNumeric<FPDF_DWORD> count = nameTree.GetCount();
dsinclair38fd8442016-09-15 10:15:32 -07001368 CPDF_Dictionary* pDest = pRoot->GetDictFor("Dests");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001369 if (pDest)
1370 count += pDest->GetCount();
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001371
1372 if (!count.IsValid())
1373 return 0;
1374
1375 return count.ValueOrDie();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001376}
1377
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001378FPDF_EXPORT FPDF_DEST FPDF_CALLCONV
1379FPDF_GetNamedDestByName(FPDF_DOCUMENT document, FPDF_BYTESTRING name) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001380 if (!name || name[0] == 0)
Tom Sepez471a1032015-10-15 16:17:18 -07001381 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001382
Tom Sepez471a1032015-10-15 16:17:18 -07001383 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1384 if (!pDoc)
1385 return nullptr;
1386
Lei Zhangd983b092015-12-14 16:58:33 -08001387 CPDF_NameTree name_tree(pDoc, "Dests");
Ryan Harrison275e2602017-09-18 14:23:18 -04001388 return name_tree.LookupNamedDest(pDoc, PDF_DecodeText(ByteString(name)));
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001389}
1390
Tom Sepez51da0932015-11-25 16:05:49 -08001391#ifdef PDF_ENABLE_XFA
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001392FPDF_EXPORT FPDF_RESULT FPDF_CALLCONV FPDF_BStr_Init(FPDF_BSTR* str) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001393 if (!str)
1394 return -1;
1395
Dan Sinclair1c5d0b42017-04-03 15:05:11 -04001396 memset(str, 0, sizeof(FPDF_BSTR));
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001397 return 0;
1398}
1399
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001400FPDF_EXPORT FPDF_RESULT FPDF_CALLCONV FPDF_BStr_Set(FPDF_BSTR* str,
1401 FPDF_LPCSTR bstr,
1402 int length) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001403 if (!str)
1404 return -1;
1405 if (!bstr || !length)
1406 return -1;
1407 if (length == -1)
Ryan Harrison8b1408e2017-09-27 11:07:51 -04001408 length = strlen(bstr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001409
1410 if (length == 0) {
1411 if (str->str) {
1412 FX_Free(str->str);
thestig1cd352e2016-06-07 17:53:06 -07001413 str->str = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001414 }
1415 str->len = 0;
1416 return 0;
1417 }
1418
1419 if (str->str && str->len < length)
1420 str->str = FX_Realloc(char, str->str, length + 1);
1421 else if (!str->str)
1422 str->str = FX_Alloc(char, length + 1);
1423
1424 str->str[length] = 0;
Dan Sinclair1c5d0b42017-04-03 15:05:11 -04001425 memcpy(str->str, bstr, length);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001426 str->len = length;
1427
1428 return 0;
1429}
1430
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001431FPDF_EXPORT FPDF_RESULT FPDF_CALLCONV FPDF_BStr_Clear(FPDF_BSTR* str) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001432 if (!str)
1433 return -1;
1434
1435 if (str->str) {
1436 FX_Free(str->str);
thestig1cd352e2016-06-07 17:53:06 -07001437 str->str = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001438 }
1439 str->len = 0;
1440 return 0;
1441}
Tom Sepez40e9ff32015-11-30 12:39:54 -08001442#endif // PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001443
Dan Sinclair00d2ad12017-08-10 14:13:02 -04001444FPDF_EXPORT FPDF_DEST FPDF_CALLCONV FPDF_GetNamedDest(FPDF_DOCUMENT document,
1445 int index,
1446 void* buffer,
1447 long* buflen) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001448 if (!buffer)
1449 *buflen = 0;
Tom Sepez540c4362015-11-24 13:33:57 -08001450
1451 if (index < 0)
1452 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001453
Tom Sepezbf59a072015-10-21 14:07:23 -07001454 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Tom Sepez540c4362015-11-24 13:33:57 -08001455 if (!pDoc)
1456 return nullptr;
1457
Lei Zhang01581062017-08-30 14:19:26 -07001458 const CPDF_Dictionary* pRoot = pDoc->GetRoot();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001459 if (!pRoot)
Tom Sepez540c4362015-11-24 13:33:57 -08001460 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001461
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001462 CPDF_Object* pDestObj = nullptr;
Ryan Harrison275e2602017-09-18 14:23:18 -04001463 WideString wsName;
Lei Zhangd983b092015-12-14 16:58:33 -08001464 CPDF_NameTree nameTree(pDoc, "Dests");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001465 int count = nameTree.GetCount();
1466 if (index >= count) {
dsinclair38fd8442016-09-15 10:15:32 -07001467 CPDF_Dictionary* pDest = pRoot->GetDictFor("Dests");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001468 if (!pDest)
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001469 return nullptr;
1470
1471 pdfium::base::CheckedNumeric<int> checked_count = count;
1472 checked_count += pDest->GetCount();
1473 if (!checked_count.IsValid() || index >= checked_count.ValueOrDie())
1474 return nullptr;
1475
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001476 index -= count;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001477 int i = 0;
Ryan Harrison275e2602017-09-18 14:23:18 -04001478 ByteString bsName;
Oliver Chang3f1c71f2016-01-11 08:45:31 -08001479 for (const auto& it : *pDest) {
1480 bsName = it.first;
tsepez0e606b52016-11-18 16:22:41 -08001481 pDestObj = it.second.get();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001482 if (!pDestObj)
1483 continue;
1484 if (i == index)
1485 break;
1486 i++;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001487 }
Jane Liu67ccef72017-07-19 13:10:50 -04001488 wsName = PDF_DecodeText(bsName);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001489 } else {
Jane Liu67ccef72017-07-19 13:10:50 -04001490 pDestObj = nameTree.LookupValueAndName(index, &wsName);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001491 }
1492 if (!pDestObj)
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001493 return nullptr;
Dan Sinclairf1251c12015-10-20 16:24:45 -04001494 if (CPDF_Dictionary* pDict = pDestObj->AsDictionary()) {
dsinclair38fd8442016-09-15 10:15:32 -07001495 pDestObj = pDict->GetArrayFor("D");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001496 if (!pDestObj)
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001497 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001498 }
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001499 if (!pDestObj->IsArray())
1500 return nullptr;
1501
Ryan Harrison275e2602017-09-18 14:23:18 -04001502 ByteString utf16Name = wsName.UTF16LE_Encode();
weili47ca6922016-03-31 15:08:27 -07001503 int len = utf16Name.GetLength();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001504 if (!buffer) {
1505 *buflen = len;
thestig9067fd62016-11-23 14:10:06 -08001506 } else if (len <= *buflen) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001507 memcpy(buffer, utf16Name.c_str(), len);
1508 *buflen = len;
1509 } else {
1510 *buflen = -1;
1511 }
1512 return (FPDF_DEST)pDestObj;
Bo Xu4d62b6b2015-01-10 22:52:59 -08001513}