Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
fpdf_view.cpp
Go to the documentation of this file.
1// Copyright 2014 The PDFium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7#include "public/fpdfview.h"
8
9#include <memory>
10#include <utility>
11#include <vector>
12
13#include "build/build_config.h"
14#include "core/fpdfapi/page/cpdf_docpagedata.h"
15#include "core/fpdfapi/page/cpdf_occontext.h"
16#include "core/fpdfapi/page/cpdf_page.h"
17#include "core/fpdfapi/page/cpdf_pageimagecache.h"
18#include "core/fpdfapi/page/cpdf_pagemodule.h"
19#include "core/fpdfapi/parser/cpdf_array.h"
20#include "core/fpdfapi/parser/cpdf_dictionary.h"
21#include "core/fpdfapi/parser/cpdf_document.h"
22#include "core/fpdfapi/parser/cpdf_name.h"
23#include "core/fpdfapi/parser/cpdf_parser.h"
24#include "core/fpdfapi/parser/cpdf_stream.h"
25#include "core/fpdfapi/parser/cpdf_string.h"
26#include "core/fpdfapi/parser/fpdf_parser_decode.h"
27#include "core/fpdfapi/render/cpdf_docrenderdata.h"
28#include "core/fpdfapi/render/cpdf_pagerendercontext.h"
29#include "core/fpdfapi/render/cpdf_rendercontext.h"
30#include "core/fpdfapi/render/cpdf_renderoptions.h"
31#include "core/fpdfdoc/cpdf_nametree.h"
32#include "core/fpdfdoc/cpdf_viewerpreferences.h"
33#include "core/fxcrt/cfx_read_only_span_stream.h"
34#include "core/fxcrt/cfx_timer.h"
35#include "core/fxcrt/fx_safe_types.h"
36#include "core/fxcrt/fx_stream.h"
37#include "core/fxcrt/fx_system.h"
38#include "core/fxcrt/span_util.h"
39#include "core/fxcrt/stl_util.h"
40#include "core/fxcrt/unowned_ptr.h"
41#include "core/fxge/cfx_defaultrenderdevice.h"
42#include "core/fxge/cfx_gemodule.h"
43#include "core/fxge/cfx_glyphcache.h"
44#include "core/fxge/cfx_renderdevice.h"
45#include "core/fxge/dib/cfx_dibitmap.h"
46#include "fpdfsdk/cpdfsdk_customaccess.h"
47#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
48#include "fpdfsdk/cpdfsdk_helpers.h"
49#include "fpdfsdk/cpdfsdk_pageview.h"
50#include "fpdfsdk/cpdfsdk_renderpage.h"
51#include "fxjs/ijs_runtime.h"
52#include "public/fpdf_formfill.h"
53#include "third_party/base/check_op.h"
54#include "third_party/base/containers/span.h"
55#include "third_party/base/memory/ptr_util.h"
56#include "third_party/base/numerics/safe_conversions.h"
57
58#ifdef PDF_ENABLE_V8
59#include "fxjs/cfx_v8_array_buffer_allocator.h"
60#include "third_party/base/no_destructor.h"
61#endif
62
63#ifdef PDF_ENABLE_XFA
64#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
65#include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
66#endif // PDF_ENABLE_XFA
67
68#if BUILDFLAG(IS_WIN)
69#include "core/fpdfapi/render/cpdf_progressiverenderer.h"
70#include "core/fpdfapi/render/cpdf_windowsrenderdevice.h"
71#include "public/fpdf_edit.h"
72
73#if defined(PDF_USE_SKIA)
74class SkCanvas;
75#endif // defined(PDF_USE_SKIA)
76
77// These checks are here because core/ and public/ cannot depend on each other.
78static_assert(static_cast<int>(WindowsPrintMode::kEmf) == FPDF_PRINTMODE_EMF,
79 "WindowsPrintMode::kEmf value mismatch");
80static_assert(static_cast<int>(WindowsPrintMode::kTextOnly) ==
81 FPDF_PRINTMODE_TEXTONLY,
82 "WindowsPrintMode::kTextOnly value mismatch");
83static_assert(static_cast<int>(WindowsPrintMode::kPostScript2) ==
84 FPDF_PRINTMODE_POSTSCRIPT2,
85 "WindowsPrintMode::kPostScript2 value mismatch");
86static_assert(static_cast<int>(WindowsPrintMode::kPostScript3) ==
87 FPDF_PRINTMODE_POSTSCRIPT3,
88 "WindowsPrintMode::kPostScript3 value mismatch");
89static_assert(static_cast<int>(WindowsPrintMode::kPostScript2PassThrough) ==
90 FPDF_PRINTMODE_POSTSCRIPT2_PASSTHROUGH,
91 "WindowsPrintMode::kPostScript2PassThrough value mismatch");
92static_assert(static_cast<int>(WindowsPrintMode::kPostScript3PassThrough) ==
93 FPDF_PRINTMODE_POSTSCRIPT3_PASSTHROUGH,
94 "WindowsPrintMode::kPostScript3PassThrough value mismatch");
95static_assert(static_cast<int>(WindowsPrintMode::kEmfImageMasks) ==
96 FPDF_PRINTMODE_EMF_IMAGE_MASKS,
97 "WindowsPrintMode::kEmfImageMasks value mismatch");
98static_assert(static_cast<int>(WindowsPrintMode::kPostScript3Type42) ==
99 FPDF_PRINTMODE_POSTSCRIPT3_TYPE42,
100 "WindowsPrintMode::kPostScript3Type42 value mismatch");
101static_assert(
102 static_cast<int>(WindowsPrintMode::kPostScript3Type42PassThrough) ==
103 FPDF_PRINTMODE_POSTSCRIPT3_TYPE42_PASSTHROUGH,
104 "WindowsPrintMode::kPostScript3Type42PassThrough value mismatch");
105#endif // BUILDFLAG(IS_WIN)
106
107#if defined(PDF_USE_SKIA)
108// These checks are here because core/ and public/ cannot depend on each other.
109static_assert(static_cast<int>(CFX_DefaultRenderDevice::RendererType::kAgg) ==
110 FPDF_RENDERERTYPE_AGG,
111 "CFX_DefaultRenderDevice::RendererType::kAGG value mismatch");
112static_assert(static_cast<int>(CFX_DefaultRenderDevice::RendererType::kSkia) ==
113 FPDF_RENDERERTYPE_SKIA,
114 "CFX_DefaultRenderDevice::RendererType::kSkia value mismatch");
115#endif // defined(PDF_USE_SKIA)
116
117namespace {
118
119bool g_bLibraryInitialized = false;
120
121void SetRendererType(FPDF_RENDERER_TYPE public_type) {
122 // Internal definition of renderer types must stay updated with respect to
123 // the public definition, such that all public definitions can be mapped to
124 // an internal definition in `CFX_DefaultRenderDevice`. A public definition
125 // value might not be meaningful for a particular build configuration, which
126 // would mean use of that value is an error for that build.
127
128 // AGG is always present in a build. |FPDF_RENDERERTYPE_SKIA| is valid to use
129 // only if it is included in the build.
130#if defined(PDF_USE_SKIA)
131 // This build configuration has the option for runtime renderer selection.
132 if (public_type == FPDF_RENDERERTYPE_AGG ||
133 public_type == FPDF_RENDERERTYPE_SKIA) {
134 CFX_DefaultRenderDevice::SetRendererType(
135 static_cast<CFX_DefaultRenderDevice::RendererType>(public_type));
136 return;
137 }
138 CHECK(false);
139#else
140 // `FPDF_RENDERERTYPE_AGG` is used for fully AGG builds.
141 CHECK_EQ(public_type, FPDF_RENDERERTYPE_AGG);
142#endif
143}
144
145void ResetRendererType() {
146#if defined(PDF_USE_SKIA)
147 CFX_DefaultRenderDevice::SetRendererType(
148 CFX_DefaultRenderDevice::kDefaultRenderer);
149#endif
150}
151
152RetainPtr<const CPDF_Object> GetXFAEntryFromDocument(const CPDF_Document* doc) {
153 const CPDF_Dictionary* root = doc->GetRoot();
154 if (!root)
155 return nullptr;
156
157 RetainPtr<const CPDF_Dictionary> acro_form = root->GetDictFor("AcroForm");
158 return acro_form ? acro_form->GetObjectFor("XFA") : nullptr;
159}
160
161struct XFAPacket {
162 ByteString name;
163 RetainPtr<const CPDF_Stream> data;
164};
165
166std::vector<XFAPacket> GetXFAPackets(RetainPtr<const CPDF_Object> xfa_object) {
167 std::vector<XFAPacket> packets;
168
169 if (!xfa_object)
170 return packets;
171
172 RetainPtr<const CPDF_Stream> xfa_stream = ToStream(xfa_object->GetDirect());
173 if (xfa_stream) {
174 packets.push_back({"", std::move(xfa_stream)});
175 return packets;
176 }
177
178 RetainPtr<const CPDF_Array> xfa_array = ToArray(xfa_object->GetDirect());
179 if (!xfa_array)
180 return packets;
181
182 packets.reserve(1 + (xfa_array->size() / 2));
183 for (size_t i = 0; i < xfa_array->size(); i += 2) {
184 if (i + 1 == xfa_array->size())
185 break;
186
187 RetainPtr<const CPDF_String> name = xfa_array->GetStringAt(i);
188 if (!name)
189 continue;
190
191 RetainPtr<const CPDF_Stream> data = xfa_array->GetStreamAt(i + 1);
192 if (!data)
193 continue;
194
195 packets.push_back({name->GetString(), std::move(data)});
196 }
197 return packets;
198}
199
200FPDF_DOCUMENT LoadDocumentImpl(RetainPtr<IFX_SeekableReadStream> pFileAccess,
201 FPDF_BYTESTRING password) {
202 if (!pFileAccess) {
204 return nullptr;
205 }
206
207 auto pDocument =
208 std::make_unique<CPDF_Document>(std::make_unique<CPDF_DocRenderData>(),
209 std::make_unique<CPDF_DocPageData>());
210
211 CPDF_Parser::Error error =
212 pDocument->LoadDoc(std::move(pFileAccess), password);
213 if (error != CPDF_Parser::SUCCESS) {
215 return nullptr;
216 }
217
218 ReportUnsupportedFeatures(pDocument.get());
219 return FPDFDocumentFromCPDFDocument(pDocument.release());
220}
221
222} // namespace
223
227
229FPDF_InitLibraryWithConfig(const FPDF_LIBRARY_CONFIG* config) {
230 if (g_bLibraryInitialized)
231 return;
232
235 CFX_GEModule::Create(config ? config->m_pUserFontPaths : nullptr);
237
238#if defined(PDF_USE_SKIA)
239 CFX_GlyphCache::InitializeGlobals();
240#endif
241
242#ifdef PDF_ENABLE_XFA
243 CPDFXFA_ModuleInit();
244#endif // PDF_ENABLE_XFA
245
246 if (config && config->version >= 2) {
247 void* platform = config->version >= 3 ? config->m_pPlatform : nullptr;
248 IJS_Runtime::Initialize(config->m_v8EmbedderSlot, config->m_pIsolate,
249 platform);
250
251 if (config->version >= 4)
252 SetRendererType(config->m_RendererType);
253 }
254 g_bLibraryInitialized = true;
255}
256
258 if (!g_bLibraryInitialized)
259 return;
260
261 // Note: we teardown/destroy things in reverse order.
262 ResetRendererType();
263
265
266#ifdef PDF_ENABLE_XFA
267 CPDFXFA_ModuleDestroy();
268#endif // PDF_ENABLE_XFA
269
270#if defined(PDF_USE_SKIA)
271 CFX_GlyphCache::DestroyGlobals();
272#endif
273
277
278 g_bLibraryInitialized = false;
279}
280
282 FPDF_BOOL enable) {
283 return SetPDFSandboxPolicy(policy, enable);
284}
285
286#if BUILDFLAG(IS_WIN)
287FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_SetPrintMode(int mode) {
288 if (mode < FPDF_PRINTMODE_EMF ||
289 mode > FPDF_PRINTMODE_POSTSCRIPT3_TYPE42_PASSTHROUGH) {
290 return FALSE;
291 }
292
293 g_pdfium_print_mode = static_cast<WindowsPrintMode>(mode);
294 return TRUE;
295}
296#endif // BUILDFLAG(IS_WIN)
297
298FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV
299FPDF_LoadDocument(FPDF_STRING file_path, FPDF_BYTESTRING password) {
300 // NOTE: the creation of the file needs to be by the embedder on the
301 // other side of this API.
302 return LoadDocumentImpl(IFX_SeekableReadStream::CreateFromFilename(file_path),
303 password);
304}
305
306FPDF_EXPORT int FPDF_CALLCONV FPDF_GetFormType(FPDF_DOCUMENT document) {
307 const CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
308 if (!pDoc)
309 return FORMTYPE_NONE;
310
311 const CPDF_Dictionary* pRoot = pDoc->GetRoot();
312 if (!pRoot)
313 return FORMTYPE_NONE;
314
315 RetainPtr<const CPDF_Dictionary> pAcroForm = pRoot->GetDictFor("AcroForm");
316 if (!pAcroForm)
317 return FORMTYPE_NONE;
318
319 RetainPtr<const CPDF_Object> pXFA = pAcroForm->GetObjectFor("XFA");
320 if (!pXFA)
321 return FORMTYPE_ACRO_FORM;
322
323 bool bNeedsRendering = pRoot->GetBooleanFor("NeedsRendering", false);
324 return bNeedsRendering ? FORMTYPE_XFA_FULL : FORMTYPE_XFA_FOREGROUND;
325}
326
327FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_LoadXFA(FPDF_DOCUMENT document) {
328#ifdef PDF_ENABLE_XFA
329 auto* pDoc = CPDFDocumentFromFPDFDocument(document);
330 if (!pDoc)
331 return false;
332
333 auto* pContext = static_cast<CPDFXFA_Context*>(pDoc->GetExtension());
334 if (pContext)
335 return pContext->LoadXFADoc();
336#endif // PDF_ENABLE_XFA
337 return false;
338}
339
340FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV
341FPDF_LoadMemDocument(const void* data_buf, int size, FPDF_BYTESTRING password) {
342 if (size < 0) {
343 return nullptr;
344 }
345
346 return LoadDocumentImpl(
347 pdfium::MakeRetain<CFX_ReadOnlySpanStream>(pdfium::make_span(
348 static_cast<const uint8_t*>(data_buf), static_cast<size_t>(size))),
349 password);
350}
351
352FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV
353FPDF_LoadMemDocument64(const void* data_buf,
354 size_t size,
355 FPDF_BYTESTRING password) {
356 return LoadDocumentImpl(
357 pdfium::MakeRetain<CFX_ReadOnlySpanStream>(
358 pdfium::make_span(static_cast<const uint8_t*>(data_buf), size)),
359 password);
360}
361
362FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV
363FPDF_LoadCustomDocument(FPDF_FILEACCESS* pFileAccess,
364 FPDF_BYTESTRING password) {
365 if (!pFileAccess)
366 return nullptr;
367 return LoadDocumentImpl(pdfium::MakeRetain<CPDFSDK_CustomAccess>(pFileAccess),
368 password);
369}
370
372 int* fileVersion) {
373 if (!fileVersion)
374 return false;
375
376 *fileVersion = 0;
378 if (!pDoc)
379 return false;
380
381 const CPDF_Parser* pParser = pDoc->GetParser();
382 if (!pParser)
383 return false;
384
385 *fileVersion = pParser->GetFileVersion();
386 return true;
387}
388
394
395FPDF_EXPORT unsigned long FPDF_CALLCONV
396FPDF_GetDocPermissions(FPDF_DOCUMENT document) {
398 return pDoc ? pDoc->GetUserPermissions(/*get_owner_perms=*/true) : 0;
399}
400
401FPDF_EXPORT unsigned long FPDF_CALLCONV
402FPDF_GetDocUserPermissions(FPDF_DOCUMENT document) {
404 return pDoc ? pDoc->GetUserPermissions(/*get_owner_perms=*/false) : 0;
405}
406
408FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document) {
410 if (!pDoc || !pDoc->GetParser())
411 return -1;
412
413 RetainPtr<const CPDF_Dictionary> pDict = pDoc->GetParser()->GetEncryptDict();
414 return pDict ? pDict->GetIntegerFor("R") : -1;
415}
416
417FPDF_EXPORT int FPDF_CALLCONV FPDF_GetPageCount(FPDF_DOCUMENT document) {
418 auto* pDoc = CPDFDocumentFromFPDFDocument(document);
419 if (!pDoc)
420 return 0;
421
422 auto* pExtension = pDoc->GetExtension();
423 return pExtension ? pExtension->GetPageCount() : pDoc->GetPageCount();
424}
425
426FPDF_EXPORT FPDF_PAGE FPDF_CALLCONV FPDF_LoadPage(FPDF_DOCUMENT document,
427 int page_index) {
428 auto* pDoc = CPDFDocumentFromFPDFDocument(document);
429 if (!pDoc)
430 return nullptr;
431
432 if (page_index < 0 || page_index >= FPDF_GetPageCount(document))
433 return nullptr;
434
435#ifdef PDF_ENABLE_XFA
436 auto* pContext = static_cast<CPDFXFA_Context*>(pDoc->GetExtension());
437 if (pContext) {
438 return FPDFPageFromIPDFPage(
439 pContext->GetOrCreateXFAPage(page_index).Leak());
440 }
441#endif // PDF_ENABLE_XFA
442
443 RetainPtr<CPDF_Dictionary> pDict = pDoc->GetMutablePageDictionary(page_index);
444 if (!pDict)
445 return nullptr;
446
447 auto pPage = pdfium::MakeRetain<CPDF_Page>(pDoc, std::move(pDict));
448 pPage->AddPageImageCache();
449 pPage->ParseContent();
450
451 return FPDFPageFromIPDFPage(pPage.Leak());
452}
453
456 return pPage ? pPage->GetPageWidth() : 0.0f;
457}
458
460 return FPDF_GetPageWidthF(page);
461}
462
465 return pPage ? pPage->GetPageHeight() : 0.0f;
466}
467
469 return FPDF_GetPageHeightF(page);
470}
471
473 FS_RECTF* rect) {
474 if (!rect)
475 return false;
476
477 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
478 if (!pPage)
479 return false;
480
481 *rect = FSRectFFromCFXFloatRect(pPage->GetBBox());
482 return true;
483}
484
485#if BUILDFLAG(IS_WIN)
486namespace {
487
488constexpr float kEpsilonSize = 0.01f;
489
490bool IsPageTooSmall(const CPDF_Page* page) {
491 const CFX_SizeF& page_size = page->GetPageSize();
492 return page_size.width < kEpsilonSize || page_size.height < kEpsilonSize;
493}
494
495bool IsScalingTooSmall(const CFX_Matrix& matrix) {
496 float horizontal;
497 float vertical;
498 if (matrix.a == 0.0f && matrix.d == 0.0f) {
499 horizontal = matrix.b;
500 vertical = matrix.c;
501 } else {
502 horizontal = matrix.a;
503 vertical = matrix.d;
504 }
505 return fabsf(horizontal) < kEpsilonSize || fabsf(vertical) < kEpsilonSize;
506}
507
508// Get a bitmap of just the mask section defined by |mask_box| from a full page
509// bitmap |pBitmap|.
510RetainPtr<CFX_DIBitmap> GetMaskBitmap(CPDF_Page* pPage,
511 int start_x,
512 int start_y,
513 int size_x,
514 int size_y,
515 int rotate,
516 RetainPtr<const CFX_DIBitmap> source,
517 const CFX_FloatRect& mask_box,
518 FX_RECT* bitmap_area) {
519 if (IsPageTooSmall(pPage))
520 return nullptr;
521
522 FX_RECT page_rect(start_x, start_y, start_x + size_x, start_y + size_y);
523 CFX_Matrix matrix = pPage->GetDisplayMatrix(page_rect, rotate);
524 if (IsScalingTooSmall(matrix))
525 return nullptr;
526
527 *bitmap_area = matrix.TransformRect(mask_box).GetOuterRect();
528 if (bitmap_area->IsEmpty())
529 return nullptr;
530
531 // Create a new bitmap to transfer part of the page bitmap to.
532 RetainPtr<CFX_DIBitmap> pDst = pdfium::MakeRetain<CFX_DIBitmap>();
533 if (!pDst->Create(bitmap_area->Width(), bitmap_area->Height(),
534 FXDIB_Format::kArgb)) {
535 return nullptr;
536 }
537 pDst->Clear(0x00ffffff);
538 pDst->TransferBitmap(0, 0, bitmap_area->Width(), bitmap_area->Height(),
539 std::move(source), bitmap_area->left, bitmap_area->top);
540 return pDst;
541}
542
543void RenderBitmap(CFX_RenderDevice* device,
544 RetainPtr<const CFX_DIBitmap> source,
545 const FX_RECT& mask_area) {
546 int size_x_bm = mask_area.Width();
547 int size_y_bm = mask_area.Height();
548 if (size_x_bm == 0 || size_y_bm == 0)
549 return;
550
551 // Create a new bitmap from the old one
552 RetainPtr<CFX_DIBitmap> dest = pdfium::MakeRetain<CFX_DIBitmap>();
553 if (!dest->Create(size_x_bm, size_y_bm, FXDIB_Format::kRgb32)) {
554 return;
555 }
556
557 dest->Clear(0xffffffff);
558 dest->CompositeBitmap(0, 0, size_x_bm, size_y_bm, std::move(source), 0, 0,
559 BlendMode::kNormal, nullptr, false);
560
561 if (device->GetDeviceType() == DeviceType::kPrinter) {
562 device->StretchDIBits(std::move(dest), mask_area.left, mask_area.top,
563 size_x_bm, size_y_bm);
564 } else {
565 device->SetDIBits(std::move(dest), mask_area.left, mask_area.top);
566 }
567}
568
569} // namespace
570
571FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPage(HDC dc,
572 FPDF_PAGE page,
573 int start_x,
574 int start_y,
575 int size_x,
576 int size_y,
577 int rotate,
578 int flags) {
579 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
580 if (!pPage)
581 return;
582
583 auto owned_context = std::make_unique<CPDF_PageRenderContext>();
584 CPDF_PageRenderContext* context = owned_context.get();
585 CPDF_Page::RenderContextClearer clearer(pPage);
586 pPage->SetRenderContext(std::move(owned_context));
587
588 // Don't render the full page to bitmap for a mask unless there are a lot
589 // of masks. Full page bitmaps result in large spool sizes, so they should
590 // only be used when necessary. For large numbers of masks, rendering each
591 // individually is inefficient and unlikely to significantly improve spool
592 // size.
593 const bool bEnableImageMasks =
594 g_pdfium_print_mode == WindowsPrintMode::kEmfImageMasks;
595 const bool bNewBitmap = pPage->BackgroundAlphaNeeded() ||
596 (pPage->HasImageMask() && !bEnableImageMasks) ||
597 pPage->GetMaskBoundingBoxes().size() > 100;
598 const bool bHasMask = pPage->HasImageMask() && !bNewBitmap;
599 auto* render_data = CPDF_DocRenderData::FromDocument(pPage->GetDocument());
600 if (!bNewBitmap && !bHasMask) {
601 context->m_pDevice = std::make_unique<CPDF_WindowsRenderDevice>(
602 dc, render_data->GetPSFontTracker());
603 CPDFSDK_RenderPageWithContext(context, pPage, start_x, start_y, size_x,
604 size_y, rotate, flags,
605 /*color_scheme=*/nullptr,
606 /*need_to_restore=*/true, /*pause=*/nullptr);
607 return;
608 }
609
610 RetainPtr<CFX_DIBitmap> pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
611 // Create will probably work fine even if it fails here: we will just attach
612 // a zero-sized bitmap to `device`.
613 pBitmap->Create(size_x, size_y, FXDIB_Format::kArgb);
614 if (!CFX_DefaultRenderDevice::UseSkiaRenderer()) {
615 // Not needed by Skia. Call it for AGG to preserve pre-existing behavior.
616 pBitmap->Clear(0x00ffffff);
617 }
618
619 auto device = std::make_unique<CFX_DefaultRenderDevice>();
620 device->Attach(pBitmap);
621 context->m_pDevice = std::move(device);
622 if (bHasMask) {
623 context->m_pOptions = std::make_unique<CPDF_RenderOptions>();
624 context->m_pOptions->GetOptions().bBreakForMasks = true;
625 }
626
627 CPDFSDK_RenderPageWithContext(context, pPage, start_x, start_y, size_x,
628 size_y, rotate, flags, /*color_scheme=*/nullptr,
629 /*need_to_restore=*/true,
630 /*pause=*/nullptr);
631
632#if defined(PDF_USE_SKIA)
633 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
634 pBitmap->UnPreMultiply();
635 }
636#endif
637
638 if (!bHasMask) {
639 CPDF_WindowsRenderDevice win_dc(dc, render_data->GetPSFontTracker());
640 bool bitsStretched = false;
641 if (win_dc.GetDeviceType() == DeviceType::kPrinter) {
642 auto dest_bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
643 if (dest_bitmap->Create(size_x, size_y, FXDIB_Format::kRgb32)) {
644 fxcrt::spanset(dest_bitmap->GetWritableBuffer().first(
645 pBitmap->GetPitch() * size_y),
646 -1);
647 dest_bitmap->CompositeBitmap(0, 0, size_x, size_y, pBitmap, 0, 0,
648 BlendMode::kNormal, nullptr, false);
649 win_dc.StretchDIBits(std::move(dest_bitmap), 0, 0, size_x, size_y);
650 bitsStretched = true;
651 }
652 }
653 if (!bitsStretched)
654 win_dc.SetDIBits(std::move(pBitmap), 0, 0);
655 return;
656 }
657
658 // Finish rendering the page to bitmap and copy the correct segments
659 // of the page to individual image mask bitmaps.
660 const std::vector<CFX_FloatRect>& mask_boxes = pPage->GetMaskBoundingBoxes();
661 std::vector<FX_RECT> bitmap_areas(mask_boxes.size());
662 std::vector<RetainPtr<CFX_DIBitmap>> bitmaps(mask_boxes.size());
663 for (size_t i = 0; i < mask_boxes.size(); i++) {
664 bitmaps[i] = GetMaskBitmap(pPage, start_x, start_y, size_x, size_y, rotate,
665 pBitmap, mask_boxes[i], &bitmap_areas[i]);
666 context->m_pRenderer->Continue(nullptr);
667 }
668
669 // Begin rendering to the printer. Add flag to indicate the renderer should
670 // pause after each image mask.
671 pPage->ClearRenderContext();
672 owned_context = std::make_unique<CPDF_PageRenderContext>();
673 context = owned_context.get();
674 pPage->SetRenderContext(std::move(owned_context));
675 context->m_pDevice = std::make_unique<CPDF_WindowsRenderDevice>(
676 dc, render_data->GetPSFontTracker());
677 context->m_pOptions = std::make_unique<CPDF_RenderOptions>();
678 context->m_pOptions->GetOptions().bBreakForMasks = true;
679
680 CPDFSDK_RenderPageWithContext(context, pPage, start_x, start_y, size_x,
681 size_y, rotate, flags, /*color_scheme=*/nullptr,
682 /*need_to_restore=*/true,
683 /*pause=*/nullptr);
684
685 // Render masks
686 for (size_t i = 0; i < mask_boxes.size(); i++) {
687 // Render the bitmap for the mask and free the bitmap.
688 if (bitmaps[i]) { // will be null if mask has zero area
689 RenderBitmap(context->m_pDevice.get(), std::move(bitmaps[i]),
690 bitmap_areas[i]);
691 }
692 // Render the next portion of page.
693 context->m_pRenderer->Continue(nullptr);
694 }
695}
696#endif // BUILDFLAG(IS_WIN)
697
699 FPDF_PAGE page,
700 int start_x,
701 int start_y,
702 int size_x,
703 int size_y,
704 int rotate,
705 int flags) {
706 if (!bitmap)
707 return;
708
709 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
710 if (!pPage)
711 return;
712
713 auto owned_context = std::make_unique<CPDF_PageRenderContext>();
714 CPDF_PageRenderContext* context = owned_context.get();
715 CPDF_Page::RenderContextClearer clearer(pPage);
716 pPage->SetRenderContext(std::move(owned_context));
717
718 RetainPtr<CFX_DIBitmap> pBitmap(CFXDIBitmapFromFPDFBitmap(bitmap));
719 auto device = std::make_unique<CFX_DefaultRenderDevice>();
720 device->AttachWithRgbByteOrder(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER));
721 context->m_pDevice = std::move(device);
722
723 CPDFSDK_RenderPageWithContext(context, pPage, start_x, start_y, size_x,
724 size_y, rotate, flags, /*color_scheme=*/nullptr,
725 /*need_to_restore=*/true,
726 /*pause=*/nullptr);
727
728#if defined(PDF_USE_SKIA)
729 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
730 pBitmap->UnPreMultiply();
731 }
732#endif
733}
734
737 FPDF_PAGE page,
738 const FS_MATRIX* matrix,
739 const FS_RECTF* clipping,
740 int flags) {
741 if (!bitmap)
742 return;
743
744 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
745 if (!pPage)
746 return;
747
748 auto owned_context = std::make_unique<CPDF_PageRenderContext>();
749 CPDF_PageRenderContext* context = owned_context.get();
750 CPDF_Page::RenderContextClearer clearer(pPage);
751 pPage->SetRenderContext(std::move(owned_context));
752
753 RetainPtr<CFX_DIBitmap> pBitmap(CFXDIBitmapFromFPDFBitmap(bitmap));
754 auto device = std::make_unique<CFX_DefaultRenderDevice>();
755 device->AttachWithRgbByteOrder(std::move(pBitmap),
756 !!(flags & FPDF_REVERSE_BYTE_ORDER));
757 context->m_pDevice = std::move(device);
758
759 CFX_FloatRect clipping_rect;
760 if (clipping)
761 clipping_rect = CFXFloatRectFromFSRectF(*clipping);
762 FX_RECT clip_rect = clipping_rect.ToFxRect();
763
764 const FX_RECT rect(0, 0, pPage->GetPageWidth(), pPage->GetPageHeight());
765 CFX_Matrix transform_matrix = pPage->GetDisplayMatrix(rect, 0);
766 if (matrix)
767 transform_matrix *= CFXMatrixFromFSMatrix(*matrix);
768 CPDFSDK_RenderPage(context, pPage, transform_matrix, clip_rect, flags,
769 /*color_scheme=*/nullptr);
770}
771
772#if defined(PDF_USE_SKIA)
773FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPageSkia(FPDF_SKIA_CANVAS canvas,
774 FPDF_PAGE page,
775 int size_x,
776 int size_y) {
777 if (!canvas) {
778 return;
779 }
780
781 CPDF_Page* cpdf_page = CPDFPageFromFPDFPage(page);
782 if (!cpdf_page) {
783 return;
784 }
785
786 auto owned_context = std::make_unique<CPDF_PageRenderContext>();
787 CPDF_PageRenderContext* context = owned_context.get();
788 CPDF_Page::RenderContextClearer clearer(cpdf_page);
789 cpdf_page->SetRenderContext(std::move(owned_context));
790
791 auto device = std::make_unique<CFX_DefaultRenderDevice>();
792 device->AttachCanvas(reinterpret_cast<SkCanvas*>(canvas));
793 context->m_pDevice = std::move(device);
794
795 CPDFSDK_RenderPageWithContext(context, cpdf_page, 0, 0, size_x, size_y, 0, 0,
796 /*color_scheme=*/nullptr,
797 /*need_to_restore=*/true, /*pause=*/nullptr);
798}
799#endif // defined(PDF_USE_SKIA)
800
802 if (!page)
803 return;
804
805 // Take it back across the API and hold for duration of this function.
806 RetainPtr<IPDF_Page> pPage;
807 pPage.Unleak(IPDFPageFromFPDFPage(page));
808
809 if (pPage->AsXFAPage())
810 return;
811
812 // This will delete the PageView object corresponding to |pPage|. We must
813 // cleanup the PageView before releasing the reference on |pPage| as it will
814 // attempt to reset the PageView during destruction.
815 pPage->AsPDFPage()->ClearView();
816}
817
818FPDF_EXPORT void FPDF_CALLCONV FPDF_CloseDocument(FPDF_DOCUMENT document) {
819 // Take it back across the API and throw it away,
820 std::unique_ptr<CPDF_Document>(CPDFDocumentFromFPDFDocument(document));
821}
822
826
828 int start_x,
829 int start_y,
830 int size_x,
831 int size_y,
832 int rotate,
833 int device_x,
834 int device_y,
835 double* page_x,
836 double* page_y) {
837 if (!page || !page_x || !page_y)
838 return false;
839
841 const FX_RECT rect(start_x, start_y, start_x + size_x, start_y + size_y);
842 absl::optional<CFX_PointF> pos =
843 pPage->DeviceToPage(rect, rotate, CFX_PointF(device_x, device_y));
844 if (!pos.has_value())
845 return false;
846
847 *page_x = pos->x;
848 *page_y = pos->y;
849 return true;
850}
851
853 int start_x,
854 int start_y,
855 int size_x,
856 int size_y,
857 int rotate,
858 double page_x,
859 double page_y,
860 int* device_x,
861 int* device_y) {
862 if (!page || !device_x || !device_y)
863 return false;
864
866 const FX_RECT rect(start_x, start_y, start_x + size_x, start_y + size_y);
867 CFX_PointF page_point(static_cast<float>(page_x), static_cast<float>(page_y));
868 absl::optional<CFX_PointF> pos =
869 pPage->PageToDevice(rect, rotate, page_point);
870 if (!pos.has_value())
871 return false;
872
873 *device_x = FXSYS_roundf(pos->x);
874 *device_y = FXSYS_roundf(pos->y);
875 return true;
876}
877
879 int height,
880 int alpha) {
881 auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
882 if (!pBitmap->Create(width, height,
884 return nullptr;
885 }
886 return FPDFBitmapFromCFXDIBitmap(pBitmap.Leak());
887}
888
890 int height,
891 int format,
892 void* first_scan,
893 int stride) {
894 FXDIB_Format fx_format;
895 switch (format) {
896 case FPDFBitmap_Gray:
897 fx_format = FXDIB_Format::k8bppRgb;
898 break;
899 case FPDFBitmap_BGR:
900 fx_format = FXDIB_Format::kRgb;
901 break;
902 case FPDFBitmap_BGRx:
903 fx_format = FXDIB_Format::kRgb32;
904 break;
905 case FPDFBitmap_BGRA:
906 fx_format = FXDIB_Format::kArgb;
907 break;
908 default:
909 return nullptr;
910 }
911
912 // Ensure external memory is good at least for the duration of this call.
913 UnownedPtr<uint8_t> pChecker(static_cast<uint8_t*>(first_scan));
914 auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
915 if (!pBitmap->Create(width, height, fx_format, pChecker, stride))
916 return nullptr;
917
918 return FPDFBitmapFromCFXDIBitmap(pBitmap.Leak());
919}
920
922 if (!bitmap)
923 return FPDFBitmap_Unknown;
924
926 switch (format) {
929 return FPDFBitmap_Gray;
931 return FPDFBitmap_BGR;
933 return FPDFBitmap_BGRx;
935 return FPDFBitmap_BGRA;
936 default:
937 return FPDFBitmap_Unknown;
938 }
939}
940
942 int left,
943 int top,
944 int width,
945 int height,
946 FPDF_DWORD color) {
947 if (!bitmap)
948 return;
949
950 CFX_DefaultRenderDevice device;
951 RetainPtr<CFX_DIBitmap> pBitmap(CFXDIBitmapFromFPDFBitmap(bitmap));
952 device.Attach(pBitmap);
953 if (!pBitmap->IsAlphaFormat())
954 color |= 0xFF000000;
955 device.FillRect(FX_RECT(left, top, left + width, top + height),
956 static_cast<uint32_t>(color));
957}
958
960 return bitmap ? CFXDIBitmapFromFPDFBitmap(bitmap)->GetWritableBuffer().data()
961 : nullptr;
962}
963
965 return bitmap ? CFXDIBitmapFromFPDFBitmap(bitmap)->GetWidth() : 0;
966}
967
969 return bitmap ? CFXDIBitmapFromFPDFBitmap(bitmap)->GetHeight() : 0;
970}
971
973 return bitmap ? CFXDIBitmapFromFPDFBitmap(bitmap)->GetPitch() : 0;
974}
975
977 RetainPtr<CFX_DIBitmap> destroyer;
978 destroyer.Unleak(CFXDIBitmapFromFPDFBitmap(bitmap));
979}
980
982FPDF_GetPageSizeByIndexF(FPDF_DOCUMENT document,
983 int page_index,
984 FS_SIZEF* size) {
985 if (!size)
986 return false;
987
988 auto* pDoc = CPDFDocumentFromFPDFDocument(document);
989 if (!pDoc)
990 return false;
991
992#ifdef PDF_ENABLE_XFA
993 if (page_index < 0 || page_index >= FPDF_GetPageCount(document))
994 return false;
995
996 auto* pContext = static_cast<CPDFXFA_Context*>(pDoc->GetExtension());
997 if (pContext) {
998 RetainPtr<CPDFXFA_Page> pPage = pContext->GetOrCreateXFAPage(page_index);
999 if (!pPage)
1000 return false;
1001
1002 size->width = pPage->GetPageWidth();
1003 size->height = pPage->GetPageHeight();
1004 return true;
1005 }
1006#endif // PDF_ENABLE_XFA
1007
1008 RetainPtr<CPDF_Dictionary> pDict = pDoc->GetMutablePageDictionary(page_index);
1009 if (!pDict)
1010 return false;
1011
1012 auto page = pdfium::MakeRetain<CPDF_Page>(pDoc, std::move(pDict));
1013 page->AddPageImageCache();
1014 size->width = page->GetPageWidth();
1015 size->height = page->GetPageHeight();
1016 return true;
1017}
1018
1020 int page_index,
1021 double* width,
1022 double* height) {
1023 if (!width || !height)
1024 return false;
1025
1026 FS_SIZEF size;
1027 if (!FPDF_GetPageSizeByIndexF(document, page_index, &size))
1028 return false;
1029
1030 *width = size.width;
1031 *height = size.height;
1032 return true;
1033}
1034
1035FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
1036FPDF_VIEWERREF_GetPrintScaling(FPDF_DOCUMENT document) {
1037 const CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1038 if (!pDoc)
1039 return true;
1040 CPDF_ViewerPreferences viewRef(pDoc);
1041 return viewRef.PrintScaling();
1042}
1043
1045FPDF_VIEWERREF_GetNumCopies(FPDF_DOCUMENT document) {
1046 const CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1047 if (!pDoc)
1048 return 1;
1049 CPDF_ViewerPreferences viewRef(pDoc);
1050 return viewRef.NumCopies();
1051}
1052
1053FPDF_EXPORT FPDF_PAGERANGE FPDF_CALLCONV
1054FPDF_VIEWERREF_GetPrintPageRange(FPDF_DOCUMENT document) {
1055 const CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1056 if (!pDoc)
1057 return nullptr;
1058 CPDF_ViewerPreferences viewRef(pDoc);
1059
1060 // Unretained reference in public API. NOLINTNEXTLINE
1061 return FPDFPageRangeFromCPDFArray(viewRef.PrintPageRange());
1062}
1063
1065FPDF_VIEWERREF_GetPrintPageRangeCount(FPDF_PAGERANGE pagerange) {
1066 const CPDF_Array* pArray = CPDFArrayFromFPDFPageRange(pagerange);
1067 return pArray ? pArray->size() : 0;
1068}
1069
1072 size_t index) {
1073 const CPDF_Array* pArray = CPDFArrayFromFPDFPageRange(pagerange);
1074 if (!pArray || index >= pArray->size())
1075 return -1;
1076 return pArray->GetIntegerAt(index);
1077}
1078
1079FPDF_EXPORT FPDF_DUPLEXTYPE FPDF_CALLCONV
1080FPDF_VIEWERREF_GetDuplex(FPDF_DOCUMENT document) {
1081 const CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1082 if (!pDoc)
1083 return DuplexUndefined;
1084 CPDF_ViewerPreferences viewRef(pDoc);
1085 ByteString duplex = viewRef.Duplex();
1086 if ("Simplex" == duplex)
1087 return Simplex;
1088 if ("DuplexFlipShortEdge" == duplex)
1089 return DuplexFlipShortEdge;
1090 if ("DuplexFlipLongEdge" == duplex)
1091 return DuplexFlipLongEdge;
1092 return DuplexUndefined;
1093}
1094
1095FPDF_EXPORT unsigned long FPDF_CALLCONV
1096FPDF_VIEWERREF_GetName(FPDF_DOCUMENT document,
1097 FPDF_BYTESTRING key,
1098 char* buffer,
1099 unsigned long length) {
1100 const CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
1101 if (!pDoc)
1102 return 0;
1103
1104 CPDF_ViewerPreferences viewRef(pDoc);
1105 absl::optional<ByteString> bsVal = viewRef.GenericName(key);
1106 if (!bsVal.has_value())
1107 return 0;
1108
1109 return NulTerminateMaybeCopyAndReturnLength(bsVal.value(), buffer, length);
1110}
1111
1112FPDF_EXPORT FPDF_DWORD FPDF_CALLCONV
1113FPDF_CountNamedDests(FPDF_DOCUMENT document) {
1115 if (!pDoc)
1116 return 0;
1117
1118 const CPDF_Dictionary* pRoot = pDoc->GetRoot();
1119 if (!pRoot)
1120 return 0;
1121
1122 auto name_tree = CPDF_NameTree::Create(pDoc, "Dests");
1123 FX_SAFE_UINT32 count = name_tree ? name_tree->GetCount() : 0;
1124 RetainPtr<const CPDF_Dictionary> pOldStyleDests = pRoot->GetDictFor("Dests");
1125 if (pOldStyleDests)
1126 count += pOldStyleDests->size();
1127 return count.ValueOrDefault(0);
1128}
1129
1130FPDF_EXPORT FPDF_DEST FPDF_CALLCONV
1131FPDF_GetNamedDestByName(FPDF_DOCUMENT document, FPDF_BYTESTRING name) {
1132 if (!name || name[0] == 0)
1133 return nullptr;
1134
1136 if (!pDoc)
1137 return nullptr;
1138
1139 ByteString dest_name(name);
1140
1141 // TODO(tsepez): murky ownership, should caller get a reference?
1142 // Unretained reference in public API. NOLINTNEXTLINE
1143 return FPDFDestFromCPDFArray(CPDF_NameTree::LookupNamedDest(pDoc, dest_name));
1144}
1145
1146#ifdef PDF_ENABLE_V8
1147FPDF_EXPORT const char* FPDF_CALLCONV FPDF_GetRecommendedV8Flags() {
1148 // Use interpreted JS only to avoid RWX pages in our address space. Also,
1149 // --jitless implies --no-expose-wasm, which reduce exposure since no PDF
1150 // should contain web assembly.
1151 return "--jitless";
1152}
1153
1154FPDF_EXPORT void* FPDF_CALLCONV FPDF_GetArrayBufferAllocatorSharedInstance() {
1155 static pdfium::base::NoDestructor<CFX_V8ArrayBufferAllocator> allocator;
1156 return allocator.get();
1157}
1158#endif // PDF_ENABLE_V8
1159
1160#ifdef PDF_ENABLE_XFA
1161FPDF_EXPORT FPDF_RESULT FPDF_CALLCONV FPDF_BStr_Init(FPDF_BSTR* bstr) {
1162 if (!bstr)
1163 return -1;
1164
1165 bstr->str = nullptr;
1166 bstr->len = 0;
1167 return 0;
1168}
1169
1170FPDF_EXPORT FPDF_RESULT FPDF_CALLCONV FPDF_BStr_Set(FPDF_BSTR* bstr,
1171 const char* cstr,
1172 int length) {
1173 if (!bstr || !cstr)
1174 return -1;
1175
1176 if (length == -1)
1177 length = pdfium::base::checked_cast<int>(strlen(cstr));
1178
1179 if (length == 0) {
1180 FPDF_BStr_Clear(bstr);
1181 return 0;
1182 }
1183
1184 if (bstr->str && bstr->len < length)
1185 bstr->str = FX_Realloc(char, bstr->str, length + 1);
1186 else if (!bstr->str)
1187 bstr->str = FX_Alloc(char, length + 1);
1188
1189 bstr->str[length] = 0;
1190 memcpy(bstr->str, cstr, length);
1191 bstr->len = length;
1192 return 0;
1193}
1194
1195FPDF_EXPORT FPDF_RESULT FPDF_CALLCONV FPDF_BStr_Clear(FPDF_BSTR* bstr) {
1196 if (!bstr)
1197 return -1;
1198
1199 if (bstr->str) {
1200 FX_Free(bstr->str);
1201 bstr->str = nullptr;
1202 }
1203 bstr->len = 0;
1204 return 0;
1205}
1206#endif // PDF_ENABLE_XFA
1207
1208FPDF_EXPORT FPDF_DEST FPDF_CALLCONV FPDF_GetNamedDest(FPDF_DOCUMENT document,
1209 int index,
1210 void* buffer,
1211 long* buflen) {
1212 if (!buffer)
1213 *buflen = 0;
1214
1215 if (index < 0)
1216 return nullptr;
1217
1219 if (!pDoc)
1220 return nullptr;
1221
1222 const CPDF_Dictionary* pRoot = pDoc->GetRoot();
1223 if (!pRoot)
1224 return nullptr;
1225
1226 auto name_tree = CPDF_NameTree::Create(pDoc, "Dests");
1227 size_t name_tree_count = name_tree ? name_tree->GetCount() : 0;
1228 RetainPtr<const CPDF_Object> pDestObj;
1229 WideString wsName;
1230 if (static_cast<size_t>(index) >= name_tree_count) {
1231 // If |index| is out of bounds, then try to retrieve the Nth old style named
1232 // destination. Where N is 0-indexed, with N = index - name_tree_count.
1233 RetainPtr<const CPDF_Dictionary> pDest = pRoot->GetDictFor("Dests");
1234 if (!pDest)
1235 return nullptr;
1236
1237 FX_SAFE_INT32 checked_count = name_tree_count;
1238 checked_count += pDest->size();
1239 if (!checked_count.IsValid() || index >= checked_count.ValueOrDie())
1240 return nullptr;
1241
1242 index -= name_tree_count;
1243 int i = 0;
1244 ByteStringView bsName;
1245 CPDF_DictionaryLocker locker(pDest);
1246 for (const auto& it : locker) {
1247 bsName = it.first.AsStringView();
1248 pDestObj = it.second;
1249 if (i == index)
1250 break;
1251 i++;
1252 }
1253 wsName = PDF_DecodeText(bsName.raw_span());
1254 } else {
1255 pDestObj = name_tree->LookupValueAndName(index, &wsName);
1256 }
1257 if (!pDestObj)
1258 return nullptr;
1259 if (const CPDF_Dictionary* pDict = pDestObj->AsDictionary()) {
1260 pDestObj = pDict->GetArrayFor("D");
1261 if (!pDestObj)
1262 return nullptr;
1263 }
1264 if (!pDestObj->IsArray())
1265 return nullptr;
1266
1267 ByteString utf16Name = wsName.ToUTF16LE();
1268 int len = pdfium::base::checked_cast<int>(utf16Name.GetLength());
1269 if (!buffer) {
1270 *buflen = len;
1271 } else if (len <= *buflen) {
1272 memcpy(buffer, utf16Name.c_str(), len);
1273 *buflen = len;
1274 } else {
1275 *buflen = -1;
1276 }
1277 return FPDFDestFromCPDFArray(pDestObj->AsArray());
1278}
1279
1282 if (!doc)
1283 return -1;
1284
1285 return fxcrt::CollectionSize<int>(
1286 GetXFAPackets(GetXFAEntryFromDocument(doc)));
1287}
1288
1289FPDF_EXPORT unsigned long FPDF_CALLCONV
1290FPDF_GetXFAPacketName(FPDF_DOCUMENT document,
1291 int index,
1292 void* buffer,
1293 unsigned long buflen) {
1295 if (!doc || index < 0)
1296 return 0;
1297
1298 std::vector<XFAPacket> xfa_packets =
1299 GetXFAPackets(GetXFAEntryFromDocument(doc));
1300 if (static_cast<size_t>(index) >= xfa_packets.size())
1301 return 0;
1302
1303 return NulTerminateMaybeCopyAndReturnLength(xfa_packets[index].name, buffer,
1304 buflen);
1305}
1306
1307FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
1308FPDF_GetXFAPacketContent(FPDF_DOCUMENT document,
1309 int index,
1310 void* buffer,
1311 unsigned long buflen,
1312 unsigned long* out_buflen) {
1314 if (!doc || index < 0 || !out_buflen)
1315 return false;
1316
1317 std::vector<XFAPacket> xfa_packets =
1318 GetXFAPackets(GetXFAEntryFromDocument(doc));
1319 if (static_cast<size_t>(index) >= xfa_packets.size())
1320 return false;
1321
1322 *out_buflen = DecodeStreamMaybeCopyAndReturnLength(
1323 xfa_packets[index].data,
1324 {static_cast<uint8_t*>(buffer), static_cast<size_t>(buflen)});
1325 return true;
1326}
1327
1328FPDF_EXPORT unsigned long FPDF_CALLCONV
1329FPDF_GetTrailerEnds(FPDF_DOCUMENT document,
1330 unsigned int* buffer,
1331 unsigned long length) {
1332 auto* doc = CPDFDocumentFromFPDFDocument(document);
1333 if (!doc)
1334 return 0;
1335
1336 // Start recording trailer ends.
1337 auto* parser = doc->GetParser();
1338 std::vector<unsigned int> trailer_ends = parser->GetTrailerEnds();
1339 const unsigned long trailer_ends_len =
1340 fxcrt::CollectionSize<unsigned long>(trailer_ends);
1341 if (buffer && length >= trailer_ends_len) {
1342 for (size_t i = 0; i < trailer_ends_len; ++i)
1343 buffer[i] = trailer_ends[i];
1344 }
1345
1346 return trailer_ends_len;
1347}
FXDIB_Format GetFormat() const
Definition cfx_dibbase.h:56
uint32_t GetPitch() const
Definition cfx_dibbase.h:54
int GetHeight() const
Definition cfx_dibbase.h:53
int GetWidth() const
Definition cfx_dibbase.h:52
bool Attach(RetainPtr< CFX_DIBitmap > pBitmap)
CFX_FloatRect & operator=(const CFX_FloatRect &that)=default
FX_RECT ToFxRect() const
static void Create(const char **pUserFontPaths)
static void Destroy()
CFX_Matrix & operator*=(const CFX_Matrix &other)
bool FillRect(const FX_RECT &rect, uint32_t color)
static void DestroyGlobals()
Definition cfx_timer.cpp:27
static void InitializeGlobals()
Definition cfx_timer.cpp:21
bool GetBooleanFor(const ByteString &key, bool bDefault) const
RetainPtr< const CPDF_Array > GetArrayFor(const ByteString &key) const
virtual int GetPageCount() const =0
bool has_valid_cross_reference_table() const
int GetPageCount() const
CPDF_Parser * GetParser() const
Extension * GetExtension() const
uint32_t GetUserPermissions(bool get_owner_perms) const
const CPDF_Dictionary * GetRoot() const
static RetainPtr< const CPDF_Array > LookupNamedDest(CPDF_Document *doc, const ByteString &name)
static void Destroy()
static void Create()
const CFX_FloatRect & GetBBox() const
RenderContextClearer(CPDF_Page *pPage)
float GetPageHeight() const override
Definition cpdf_page.cpp:59
float GetPageWidth() const override
Definition cpdf_page.cpp:55
CFX_Matrix GetDisplayMatrix(const FX_RECT &rect, int iRotate) const override
int GetFileVersion() const
RetainPtr< const CPDF_Array > PrintPageRange() const
CPDF_ViewerPreferences(const CPDF_Document *pDoc)
static RetainPtr< IFX_SeekableReadStream > CreateFromFilename(const char *filename)
Definition fx_stream.cpp:68
static void Initialize(unsigned int slot, void *isolate, void *platform)
static void Destroy()
virtual float GetPageWidth() const =0
virtual float GetPageHeight() const =0
ByteString(const char *ptr)
const char * c_str() const
Definition bytestring.h:76
ByteString ToUTF16LE() const
const CPDF_Array * CPDFArrayFromFPDFPageRange(FPDF_PAGERANGE range)
IPDF_Page * IPDFPageFromFPDFPage(FPDF_PAGE page)
void ProcessParseError(CPDF_Parser::Error err)
CFX_DIBitmap * CFXDIBitmapFromFPDFBitmap(FPDF_BITMAP bitmap)
void SetPDFSandboxPolicy(FPDF_DWORD policy, FPDF_BOOL enable)
CFX_FloatRect CFXFloatRectFromFSRectF(const FS_RECTF &rect)
CPDF_Page * CPDFPageFromFPDFPage(FPDF_PAGE page)
CPDF_Document * CPDFDocumentFromFPDFDocument(FPDF_DOCUMENT doc)
CFX_Matrix CFXMatrixFromFSMatrix(const FS_MATRIX &matrix)
void CPDFSDK_RenderPageWithContext(CPDF_PageRenderContext *pContext, CPDF_Page *pPage, int start_x, int start_y, int size_x, int size_y, int rotate, int flags, const FPDF_COLORSCHEME *color_scheme, bool need_to_restore, CPDFSDK_PauseAdapter *pause)
void CPDFSDK_RenderPage(CPDF_PageRenderContext *pContext, CPDF_Page *pPage, const CFX_Matrix &matrix, const FX_RECT &clipping_rect, int flags, const FPDF_COLORSCHEME *color_scheme)
#define FORMTYPE_NONE
#define FORMTYPE_XFA_FOREGROUND
#define FORMTYPE_XFA_FULL
FPDF_EXPORT int FPDF_CALLCONV FPDF_GetFormType(FPDF_DOCUMENT document)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_LoadXFA(FPDF_DOCUMENT document)
#define FORMTYPE_ACRO_FORM
FPDF_EXPORT FPDF_PAGE FPDF_CALLCONV FPDF_LoadPage(FPDF_DOCUMENT document, int page_index)
FPDF_EXPORT int FPDF_CALLCONV FPDF_GetPageCount(FPDF_DOCUMENT document)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_GetLastError()
FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV FPDFBitmap_CreateEx(int width, int height, int format, void *first_scan, int stride)
FPDF_EXPORT void FPDF_CALLCONV FPDF_SetSandBoxPolicy(FPDF_DWORD policy, FPDF_BOOL enable)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_VIEWERREF_GetPrintScaling(FPDF_DOCUMENT document)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_DeviceToPage(FPDF_PAGE page, int start_x, int start_y, int size_x, int size_y, int rotate, int device_x, int device_y, double *page_x, double *page_y)
FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV FPDF_LoadCustomDocument(FPDF_FILEACCESS *pFileAccess, FPDF_BYTESTRING password)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_PageToDevice(FPDF_PAGE page, int start_x, int start_y, int size_x, int size_y, int rotate, double page_x, double page_y, int *device_x, int *device_y)
FPDF_EXPORT size_t FPDF_CALLCONV FPDF_VIEWERREF_GetPrintPageRangeCount(FPDF_PAGERANGE pagerange)
FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV FPDF_LoadDocument(FPDF_STRING file_path, FPDF_BYTESTRING password)
FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetHeight(FPDF_BITMAP bitmap)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_DocumentHasValidCrossReferenceTable(FPDF_DOCUMENT document)
FPDF_EXPORT void FPDF_CALLCONV FPDFBitmap_Destroy(FPDF_BITMAP bitmap)
FPDF_EXPORT FPDF_DUPLEXTYPE FPDF_CALLCONV FPDF_VIEWERREF_GetDuplex(FPDF_DOCUMENT document)
FPDF_EXPORT float FPDF_CALLCONV FPDF_GetPageHeightF(FPDF_PAGE page)
FPDF_EXPORT void FPDF_CALLCONV FPDF_DestroyLibrary()
FPDF_EXPORT int FPDF_CALLCONV FPDF_GetXFAPacketCount(FPDF_DOCUMENT document)
FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV FPDFBitmap_Create(int width, int height, int alpha)
FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetStride(FPDF_BITMAP bitmap)
FPDF_EXPORT FPDF_PAGERANGE FPDF_CALLCONV FPDF_VIEWERREF_GetPrintPageRange(FPDF_DOCUMENT document)
FPDF_EXPORT int FPDF_CALLCONV FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document, int page_index, double *width, double *height)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_GetDocUserPermissions(FPDF_DOCUMENT document)
FPDF_EXPORT double FPDF_CALLCONV FPDF_GetPageWidth(FPDF_PAGE page)
FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV FPDF_LoadMemDocument64(const void *data_buf, size_t size, FPDF_BYTESTRING password)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_GetDocPermissions(FPDF_DOCUMENT document)
FPDF_EXPORT void FPDF_CALLCONV FPDF_InitLibrary()
FPDF_EXPORT FPDF_DEST FPDF_CALLCONV FPDF_GetNamedDest(FPDF_DOCUMENT document, int index, void *buffer, long *buflen)
FPDF_EXPORT FPDF_DEST FPDF_CALLCONV FPDF_GetNamedDestByName(FPDF_DOCUMENT document, FPDF_BYTESTRING name)
FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPageBitmap(FPDF_BITMAP bitmap, FPDF_PAGE page, int start_x, int start_y, int size_x, int size_y, int rotate, int flags)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_GetFileVersion(FPDF_DOCUMENT doc, int *fileVersion)
FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPageBitmapWithMatrix(FPDF_BITMAP bitmap, FPDF_PAGE page, const FS_MATRIX *matrix, const FS_RECTF *clipping, int flags)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_GetPageBoundingBox(FPDF_PAGE page, FS_RECTF *rect)
FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetFormat(FPDF_BITMAP bitmap)
FPDF_EXPORT void FPDF_CALLCONV FPDFBitmap_FillRect(FPDF_BITMAP bitmap, int left, int top, int width, int height, FPDF_DWORD color)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_VIEWERREF_GetName(FPDF_DOCUMENT document, FPDF_BYTESTRING key, char *buffer, unsigned long length)
FPDF_EXPORT void FPDF_CALLCONV FPDF_InitLibraryWithConfig(const FPDF_LIBRARY_CONFIG *config)
FPDF_EXPORT void *FPDF_CALLCONV FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap)
FPDF_EXPORT FPDF_DWORD FPDF_CALLCONV FPDF_CountNamedDests(FPDF_DOCUMENT document)
FPDF_EXPORT void FPDF_CALLCONV FPDF_CloseDocument(FPDF_DOCUMENT document)
FPDF_EXPORT int FPDF_CALLCONV FPDF_VIEWERREF_GetPrintPageRangeElement(FPDF_PAGERANGE pagerange, size_t index)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_GetPageSizeByIndexF(FPDF_DOCUMENT document, int page_index, FS_SIZEF *size)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_GetXFAPacketContent(FPDF_DOCUMENT document, int index, void *buffer, unsigned long buflen, unsigned long *out_buflen)
FPDF_EXPORT int FPDF_CALLCONV FPDF_VIEWERREF_GetNumCopies(FPDF_DOCUMENT document)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_GetXFAPacketName(FPDF_DOCUMENT document, int index, void *buffer, unsigned long buflen)
FPDF_EXPORT double FPDF_CALLCONV FPDF_GetPageHeight(FPDF_PAGE page)
FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetWidth(FPDF_BITMAP bitmap)
FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV FPDF_LoadMemDocument(const void *data_buf, int size, FPDF_BYTESTRING password)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_GetTrailerEnds(FPDF_DOCUMENT document, unsigned int *buffer, unsigned long length)
FPDF_EXPORT float FPDF_CALLCONV FPDF_GetPageWidthF(FPDF_PAGE page)
FPDF_EXPORT void FPDF_CALLCONV FPDF_ClosePage(FPDF_PAGE page)
FPDF_EXPORT int FPDF_CALLCONV FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document)
#define FPDFBitmap_BGR
Definition fpdfview.h:1100
#define FPDFBitmap_BGRx
Definition fpdfview.h:1102
#define FPDF_REVERSE_BYTE_ORDER
Definition fpdfview.h:831
#define FPDFBitmap_BGRA
Definition fpdfview.h:1104
#define FPDF_CALLCONV
Definition fpdfview.h:227
#define FPDFBitmap_Unknown
Definition fpdfview.h:1096
#define FPDF_EXPORT
Definition fpdfview.h:221
#define FPDFBitmap_Gray
Definition fpdfview.h:1098
FXDIB_Format
Definition fx_dib.h:19
void FX_InitializeMemoryAllocators()
uint32_t FXSYS_GetLastError()
bool operator==(const char *lhs, const ByteString &rhs)
Definition bytestring.h:233
constexpr FX_RECT(int l, int t, int r, int b)