7#include "public/fpdf_ppo.h"
17#include "constants/page_object.h"
18#include "core/fpdfapi/page/cpdf_form.h"
19#include "core/fpdfapi/page/cpdf_formobject.h"
20#include "core/fpdfapi/page/cpdf_page.h"
21#include "core/fpdfapi/page/cpdf_pageimagecache.h"
22#include "core/fpdfapi/page/cpdf_pageobject.h"
23#include "core/fpdfapi/parser/cpdf_array.h"
24#include "core/fpdfapi/parser/cpdf_dictionary.h"
25#include "core/fpdfapi/parser/cpdf_document.h"
26#include "core/fpdfapi/parser/cpdf_name.h"
27#include "core/fpdfapi/parser/cpdf_number.h"
28#include "core/fpdfapi/parser/cpdf_object.h"
29#include "core/fpdfapi/parser/cpdf_reference.h"
30#include "core/fpdfapi/parser/cpdf_stream.h"
31#include "core/fpdfapi/parser/cpdf_stream_acc.h"
32#include "core/fpdfapi/parser/cpdf_string.h"
33#include "core/fpdfapi/parser/fpdf_parser_utility.h"
34#include "core/fxcrt/fx_safe_types.h"
35#include "core/fxcrt/fx_string_wrappers.h"
36#include "core/fxcrt/retain_ptr.h"
37#include "core/fxcrt/unowned_ptr.h"
38#include "fpdfsdk/cpdfsdk_helpers.h"
39#include "public/cpp/fpdf_scopers.h"
40#include "third_party/base/check.h"
41#include "third_party/base/containers/span.h"
53struct NupPageSettings {
54 CFX_PointF subPageStartPoint;
63 NupState(
const CFX_SizeF& pagesize,
65 size_t nPagesOnYAxis);
69 NupPageSettings CalculateNewPagePosition(
const CFX_SizeF& pagesize);
76 std::pair<size_t, size_t> ConvertPageOrder()
const;
81 NupPageSettings CalculatePageEdit(size_t iSubX,
83 const CFX_SizeF& pagesize)
const;
85 const CFX_SizeF m_destPageSize;
86 const size_t m_nPagesOnXAxis;
87 const size_t m_nPagesOnYAxis;
88 const size_t m_nPagesPerSheet;
89 CFX_SizeF m_subPageSize;
92 size_t m_subPageIndex = 0;
95NupState::NupState(
const CFX_SizeF& pagesize,
98 : m_destPageSize(pagesize),
99 m_nPagesOnXAxis(nPagesOnXAxis),
100 m_nPagesOnYAxis(nPagesOnYAxis),
101 m_nPagesPerSheet(nPagesOnXAxis * nPagesOnYAxis) {
102 DCHECK(m_nPagesOnXAxis > 0);
103 DCHECK(m_nPagesOnYAxis > 0);
104 DCHECK(m_destPageSize.width > 0);
105 DCHECK(m_destPageSize.height > 0);
107 m_subPageSize.width = m_destPageSize.width / m_nPagesOnXAxis;
108 m_subPageSize.height = m_destPageSize.height / m_nPagesOnYAxis;
111std::pair<size_t, size_t> NupState::ConvertPageOrder()
const {
112 size_t iSubX = m_subPageIndex % m_nPagesOnXAxis;
113 size_t iSubY = m_subPageIndex / m_nPagesOnXAxis;
116 iSubY = m_nPagesOnYAxis - iSubY - 1;
118 return {iSubX, iSubY};
121NupPageSettings NupState::CalculatePageEdit(size_t iSubX,
123 const CFX_SizeF& pagesize)
const {
124 NupPageSettings settings;
125 settings.subPageStartPoint.x = iSubX * m_subPageSize.width;
126 settings.subPageStartPoint.y = iSubY * m_subPageSize.height;
128 const float xScale = m_subPageSize.width / pagesize.width;
129 const float yScale = m_subPageSize.height / pagesize.height;
130 settings.scale =
std::min(xScale, yScale);
132 float subWidth = pagesize.width * settings.scale;
133 float subHeight = pagesize.height * settings.scale;
135 settings.subPageStartPoint.x += (m_subPageSize.width - subWidth) / 2;
137 settings.subPageStartPoint.y += (m_subPageSize.height - subHeight) / 2;
141NupPageSettings NupState::CalculateNewPagePosition(
const CFX_SizeF& pagesize) {
142 if (m_subPageIndex >= m_nPagesPerSheet)
147 std::tie(iSubX, iSubY) = ConvertPageOrder();
149 return CalculatePageEdit(iSubX, iSubY, pagesize);
154 const ByteString& bsSrcTag) {
163 ToName(pDict->GetObjectFor(pdfium::page_object::kType)->GetDirect());
164 if (!pName || pName->GetString() !=
"Page")
167 RetainPtr<
const CPDF_Dictionary> pp = ToDictionary(
168 pDict->GetObjectFor(pdfium::page_object::kParent)->GetDirect());
172 if (pDict->KeyExist(bsSrcTag))
173 return pDict->GetObjectFor(bsSrcTag);
176 if (pp->KeyExist(bsSrcTag))
177 return pp->GetObjectFor(bsSrcTag);
186bool CopyInheritable(
RetainPtr<CPDF_Dictionary> pDestPageDict,
187 RetainPtr<
const CPDF_Dictionary> pSrcPageDict,
188 const ByteString& key) {
189 if (pDestPageDict->KeyExist(key))
193 PageDictGetInheritableTag(std::move(pSrcPageDict), key);
197 pDestPageDict->SetFor(key, pInheritable->Clone());
201std::vector<uint32_t> GetPageIndices(
const CPDF_Document& doc,
202 const ByteString& bsPageRange) {
204 if (!bsPageRange.IsEmpty())
205 return ParsePageRangeString(bsPageRange, nCount);
207 std::vector<uint32_t> page_indices(nCount);
208 std::iota(page_indices.begin(), page_indices.end(), 0);
212class CPDF_PageOrganizer {
215 ~CPDF_PageOrganizer();
228 void AddObjectMapping(uint32_t dwOldPageObj, uint32_t dwNewPageObj) {
229 m_ObjectNumberMap[dwOldPageObj] = dwNewPageObj;
232 void ClearObjectNumberMap() { m_ObjectNumberMap.clear(); }
237 uint32_t GetNewObjId(CPDF_Reference* pRef);
243 std::map<uint32_t, uint32_t> m_ObjectNumberMap;
246CPDF_PageOrganizer::CPDF_PageOrganizer(
CPDF_Document* pDestDoc,
248 : m_pDestDoc(pDestDoc), m_pSrcDoc(pSrcDoc) {}
250CPDF_PageOrganizer::~CPDF_PageOrganizer() =
default;
252bool CPDF_PageOrganizer::Init() {
256 return InitDestDoc();
259bool CPDF_PageOrganizer::InitDestDoc() {
260 RetainPtr<CPDF_Dictionary> root = dest()->GetMutableRoot();
265 RetainPtr<CPDF_Dictionary> info = dest()->GetInfo();
267 info->SetNewFor<CPDF_String>(
"Producer",
"PDFium",
false);
270 if (root->GetByteStringFor(
"Type", ByteString
()).IsEmpty()) {
271 root->SetNewFor<CPDF_Name>(
"Type",
"Catalog");
277 pages = ToDictionary(current_pages->GetMutableDirect());
280 pages = dest()->NewIndirect<CPDF_Dictionary>();
281 root->SetNewFor<CPDF_Reference>(
"Pages", dest(), pages->GetObjNum());
283 if (pages->GetByteStringFor(
"Type", ByteString
()).IsEmpty()) {
284 pages->SetNewFor<CPDF_Name>(
"Type",
"Pages");
287 if (!pages->GetArrayFor(
"Kids")) {
288 auto kids_array = dest()->NewIndirect<CPDF_Array>();
289 pages->SetNewFor<CPDF_Number>(
"Count", 0);
290 pages->SetNewFor<CPDF_Reference>(
"Kids", dest(), kids_array->GetObjNum());
296 switch (pObj->GetType()) {
298 CPDF_Reference* pReference = pObj->AsMutableReference();
299 uint32_t newobjnum = GetNewObjId(pReference);
302 pReference
->SetRef(dest(), newobjnum);
306 CPDF_Dictionary* pDict = pObj->AsMutableDictionary();
307 std::vector<ByteString> bad_keys;
310 for (
const auto& it : locker) {
311 const ByteString& key = it.first;
312 if (key ==
"Parent" || key ==
"Prev" || key ==
"First")
314 RetainPtr<CPDF_Object> pNextObj = it.second;
315 if (!UpdateReference(pNextObj))
316 bad_keys.push_back(key);
319 for (
const auto& key : bad_keys)
320 pDict->RemoveFor(key.AsStringView());
324 CPDF_Array* pArray = pObj->AsMutableArray();
325 for (size_t i = 0; i < pArray->size(); ++i) {
326 if (!UpdateReference(pArray->GetMutableObjectAt(i)))
332 CPDF_Stream* pStream = pObj->AsMutableStream();
333 RetainPtr<CPDF_Dictionary> pDict = pStream->GetMutableDict();
334 return pDict && UpdateReference(
std::move(pDict));
341uint32_t CPDF_PageOrganizer::GetNewObjId(CPDF_Reference* pRef) {
346 uint32_t dwNewObjNum = 0;
347 const auto it = m_ObjectNumberMap.find(dwObjnum);
348 if (it != m_ObjectNumberMap.end())
349 dwNewObjNum = it->second;
358 const CPDF_Dictionary* pDictClone = pClone->AsDictionary();
368 AddObjectMapping(dwObjnum, dwNewObjNum);
369 if (!UpdateReference(
std::move(pClone)))
377class CPDF_PageExporter
final :
public CPDF_PageOrganizer {
380 ~CPDF_PageExporter();
385 bool ExportPage(pdfium::span<
const uint32_t> pageIndices,
int nIndex);
390 : CPDF_PageOrganizer(pDestDoc, pSrcDoc) {}
392CPDF_PageExporter::~CPDF_PageExporter() =
default;
394bool CPDF_PageExporter::ExportPage(pdfium::span<
const uint32_t> pageIndices,
399 int curpage = nIndex;
400 for (uint32_t pageIndex : pageIndices) {
401 RetainPtr<CPDF_Dictionary> pDestPageDict = dest()->CreateNewPage(curpage);
402 RetainPtr<
const CPDF_Dictionary> pSrcPageDict =
403 src()->GetPageDictionary(pageIndex);
404 if (!pSrcPageDict || !pDestPageDict)
408 CPDF_DictionaryLocker locker(pSrcPageDict);
409 for (
const auto& it : locker) {
410 const ByteString& cbSrcKeyStr = it.first;
411 const RetainPtr<CPDF_Object>& pObj = it.second;
412 if (cbSrcKeyStr == pdfium::page_object::kType ||
413 cbSrcKeyStr == pdfium::page_object::kParent) {
416 pDestPageDict->SetFor(cbSrcKeyStr, pObj->Clone());
423 if (!CopyInheritable(pDestPageDict, pSrcPageDict,
424 pdfium::page_object::kMediaBox)) {
427 RetainPtr<
const CPDF_Object> pInheritable = PageDictGetInheritableTag(
428 pSrcPageDict, pdfium::page_object::kCropBox);
430 pDestPageDict->SetFor(pdfium::page_object::kMediaBox,
431 pInheritable->Clone());
434 static const CFX_FloatRect kDefaultLetterRect(0, 0, 612, 792);
435 pDestPageDict->SetRectFor(pdfium::page_object::kMediaBox,
441 if (!CopyInheritable(pDestPageDict, pSrcPageDict,
442 pdfium::page_object::kResources)) {
444 pDestPageDict->SetNewFor<CPDF_Dictionary>(
445 pdfium::page_object::kResources);
449 CopyInheritable(pDestPageDict, pSrcPageDict, pdfium::page_object::kCropBox);
451 CopyInheritable(pDestPageDict, pSrcPageDict, pdfium::page_object::kRotate);
454 uint32_t dwOldPageObj = pSrcPageDict->GetObjNum();
455 uint32_t dwNewPageObj = pDestPageDict->GetObjNum();
456 AddObjectMapping(dwOldPageObj, dwNewPageObj);
457 UpdateReference(pDestPageDict);
467class CPDF_NPageToOneExporter
final :
public CPDF_PageOrganizer {
470 ~CPDF_NPageToOneExporter();
480 bool ExportNPagesToOne(pdfium::span<
const uint32_t> pageIndices,
481 const CFX_SizeF& destPageSize,
482 size_t nPagesOnXAxis,
483 size_t nPagesOnYAxis);
485 std::unique_ptr<XObjectContext> CreateXObjectContextFromPage(
490 using PageXObjectMap = std::map<uint32_t, ByteString>;
496 ByteString AddSubPage(
const RetainPtr<CPDF_Page>& pSrcPage,
497 const NupPageSettings& settings);
501 ByteString MakeXObjectFromPage(
RetainPtr<CPDF_Page> pSrcPage);
507 void FinishPage(
RetainPtr<CPDF_Dictionary> pDestPageDict,
508 const ByteString& bsContent);
511 uint32_t m_nObjectNumber = 0;
515 std::map<ByteString, uint32_t> m_XObjectNameToNumberMap;
520 PageXObjectMap m_SrcPageXObjectMap;
523CPDF_NPageToOneExporter::CPDF_NPageToOneExporter(
CPDF_Document* pDestDoc,
525 : CPDF_PageOrganizer(pDestDoc, pSrcDoc) {}
527CPDF_NPageToOneExporter::~CPDF_NPageToOneExporter() =
default;
529bool CPDF_NPageToOneExporter::ExportNPagesToOne(
530 pdfium::span<
const uint32_t> pageIndices,
531 const CFX_SizeF& destPageSize,
532 size_t nPagesOnXAxis,
533 size_t nPagesOnYAxis) {
537 FX_SAFE_SIZE_T nSafePagesPerSheet = nPagesOnXAxis;
538 nSafePagesPerSheet *= nPagesOnYAxis;
539 if (!nSafePagesPerSheet.IsValid())
542 ClearObjectNumberMap();
543 m_SrcPageXObjectMap.clear();
544 size_t nPagesPerSheet = nSafePagesPerSheet.ValueOrDie();
545 NupState nupState(destPageSize, nPagesOnXAxis, nPagesOnYAxis);
547 FX_SAFE_INT32 curpage = 0;
549 destPageSize.height);
550 for (size_t iOuterPage = 0; iOuterPage < pageIndices.size();
551 iOuterPage += nPagesPerSheet) {
552 m_XObjectNameToNumberMap.clear();
554 RetainPtr<CPDF_Dictionary> pDestPageDict =
555 dest()->CreateNewPage(curpage.ValueOrDie());
560 ByteString bsContent;
561 size_t iInnerPageMax =
562 std::min(iOuterPage + nPagesPerSheet, pageIndices.size());
563 for (size_t i = iOuterPage; i < iInnerPageMax; ++i) {
564 RetainPtr<CPDF_Dictionary> pSrcPageDict =
565 src()->GetMutablePageDictionary(pageIndices[i]);
569 auto pSrcPage = pdfium::MakeRetain<CPDF_Page>(src(), pSrcPageDict);
570 pSrcPage->AddPageImageCache();
571 NupPageSettings settings =
572 nupState.CalculateNewPagePosition(pSrcPage->GetPageSize());
573 bsContent += AddSubPage(pSrcPage, settings);
576 FinishPage(pDestPageDict, bsContent);
583ByteString CPDF_NPageToOneExporter::AddSubPage(
585 const NupPageSettings& settings) {
586 uint32_t dwSrcPageObjnum = pSrcPage->GetDict()->GetObjNum();
587 const auto it = m_SrcPageXObjectMap.find(dwSrcPageObjnum);
588 ByteString bsXObjectName = it != m_SrcPageXObjectMap.end()
590 : MakeXObjectFromPage(pSrcPage);
593 matrix
.Scale(settings.scale
, settings.scale
);
594 matrix.Translate(settings.subPageStartPoint.x, settings.subPageStartPoint.y);
596 fxcrt::ostringstream contentStream;
597 contentStream <<
"q\n"
598 << matrix
.a <<
" " << matrix
.b <<
" " << matrix
.c <<
" "
599 << matrix
.d <<
" " << matrix
.e <<
" " << matrix
.f <<
" cm\n"
600 <<
"/" << bsXObjectName <<
" Do Q\n";
601 return ByteString(contentStream);
604RetainPtr<CPDF_Stream> CPDF_NPageToOneExporter::MakeXObjectFromPageRaw(
606 RetainPtr<
const CPDF_Dictionary> pSrcPageDict = pSrcPage->GetDict();
608 pSrcPageDict->GetDirectObjectFor(pdfium::page_object::kContents);
611 dest()->NewIndirect<CPDF_Stream>(dest()->New<CPDF_Dictionary>());
612 RetainPtr<CPDF_Dictionary> pNewXObjectDict = pNewXObject->GetMutableDict();
613 static const char kResourceString[] =
"Resources";
614 if (!CopyInheritable(pNewXObjectDict, pSrcPageDict, kResourceString)) {
616 pNewXObjectDict->SetNewFor<CPDF_Dictionary>(kResourceString);
618 uint32_t dwSrcPageObj = pSrcPageDict->GetObjNum();
619 uint32_t dwNewXobjectObj = pNewXObjectDict->GetObjNum();
620 AddObjectMapping(dwSrcPageObj, dwNewXobjectObj);
621 UpdateReference(pNewXObjectDict);
622 pNewXObjectDict->SetNewFor<CPDF_Name>(
"Type",
"XObject");
623 pNewXObjectDict->SetNewFor<CPDF_Name>(
"Subtype",
"Form");
624 pNewXObjectDict->SetNewFor<CPDF_Number>(
"FormType", 1);
625 pNewXObjectDict->SetRectFor(
"BBox", pSrcPage->GetBBox());
626 pNewXObjectDict->SetMatrixFor(
"Matrix", pSrcPage->GetPageMatrix());
628 if (pSrcContentObj) {
629 ByteString bsSrcContentStream;
630 const CPDF_Array* pSrcContentArray = pSrcContentObj->AsArray();
631 if (pSrcContentArray) {
632 for (size_t i = 0; i < pSrcContentArray->size(); ++i) {
633 RetainPtr<
const CPDF_Stream> pStream = pSrcContentArray->GetStreamAt(i);
634 auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(
std::move(pStream));
635 pAcc->LoadAllDataFiltered();
636 bsSrcContentStream
+= ByteString(pAcc->GetSpan());
637 bsSrcContentStream
+= "\n";
640 RetainPtr<
const CPDF_Stream> pStream(pSrcContentObj->AsStream());
641 auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(
std::move(pStream));
642 pAcc->LoadAllDataFiltered();
643 bsSrcContentStream
= ByteString(pAcc->GetSpan());
645 pNewXObject->SetDataAndRemoveFilter(bsSrcContentStream.raw_span());
650ByteString CPDF_NPageToOneExporter::MakeXObjectFromPage(
652 RetainPtr<CPDF_Stream> pNewXObject = MakeXObjectFromPageRaw(pSrcPage);
655 ByteString bsXObjectName = ByteString
::Format("X%d", ++m_nObjectNumber
);
656 m_XObjectNameToNumberMap[bsXObjectName] = pNewXObject->GetObjNum();
657 m_SrcPageXObjectMap[pSrcPage->GetDict()->GetObjNum()] = bsXObjectName;
658 return bsXObjectName;
661std::unique_ptr<XObjectContext>
662CPDF_NPageToOneExporter::CreateXObjectContextFromPage(
int src_page_index) {
663 RetainPtr<CPDF_Dictionary> src_page_dict =
664 src()->GetMutablePageDictionary(src_page_index);
668 auto src_page = pdfium::MakeRetain<CPDF_Page>(src(), src_page_dict);
670 xobject->dest_doc = dest();
671 xobject->xobject.Reset(MakeXObjectFromPageRaw(src_page));
675void CPDF_NPageToOneExporter::FinishPage(
676 RetainPtr<CPDF_Dictionary> pDestPageDict,
677 const ByteString& bsContent) {
679 pDestPageDict->GetOrCreateDictFor(pdfium::page_object::kResources);
680 RetainPtr<CPDF_Dictionary> pPageXObject = pRes->GetOrCreateDictFor(
"XObject");
681 for (
auto& it : m_XObjectNameToNumberMap)
682 pPageXObject->SetNewFor<CPDF_Reference>(it.first, dest(), it.second);
685 dest()->NewIndirect<CPDF_Stream>(dest()->New<CPDF_Dictionary>());
686 pStream->SetData(bsContent.raw_span());
688 dest(), pStream->GetObjNum());
692bool IsValidViewerPreferencesArray(
const CPDF_Array* array) {
694 for (
const auto& obj : locker) {
695 if (obj->IsArray() || obj->IsDictionary() || obj->IsReference() ||
703bool IsValidViewerPreferencesObject(
const CPDF_Object* obj) {
715 return IsValidViewerPreferencesArray(array);
722 FPDF_DOCUMENT src_doc,
723 const int* page_indices,
724 unsigned long length,
734 CPDF_PageExporter exporter(pDestDoc, pSrcDoc);
738 std::iota(page_indices_vec.begin(), page_indices_vec.end(), 0);
739 return exporter.ExportPage(page_indices_vec, index);
745 return exporter.ExportPage(
746 pdfium::make_span(
reinterpret_cast<
const uint32_t*>(page_indices),
752 FPDF_DOCUMENT src_doc,
753 FPDF_BYTESTRING pagerange,
763 std::vector<uint32_t> page_indices = GetPageIndices(*pSrcDoc, pagerange);
764 if (page_indices.empty())
767 CPDF_PageExporter exporter(pDestDoc, pSrcDoc);
768 return exporter.ExportPage(page_indices, index);
775 size_t num_pages_on_x_axis,
776 size_t num_pages_on_y_axis) {
781 if (output_width <= 0 || output_height <= 0 || num_pages_on_x_axis <= 0 ||
782 num_pages_on_y_axis <= 0) {
790 CPDF_Document* pDestDoc = CPDFDocumentFromFPDFDocument(output_doc.get());
793 std::vector<uint32_t> page_indices = GetPageIndices(*pSrcDoc, ByteString());
794 if (page_indices.empty())
797 if (num_pages_on_x_axis == 1 && num_pages_on_y_axis == 1) {
798 CPDF_PageExporter exporter(pDestDoc, pSrcDoc);
799 if (!exporter.ExportPage(page_indices, 0))
801 return output_doc.release();
804 CPDF_NPageToOneExporter exporter(pDestDoc, pSrcDoc);
805 if (!exporter.ExportNPagesToOne(page_indices,
806 CFX_SizeF(output_width, output_height),
807 num_pages_on_x_axis, num_pages_on_y_axis)) {
810 return output_doc.release();
815 FPDF_DOCUMENT src_doc,
816 int src_page_index) {
825 CPDF_NPageToOneExporter exporter(dest, src);
826 std::unique_ptr<XObjectContext> xobject =
827 exporter.CreateXObjectContextFromPage(src_page_index);
828 return FPDFXObjectFromXObjectContext(xobject.release());
832 std::unique_ptr<XObjectContext> xobject_deleter(
842 auto form =
std::make_unique<CPDF_Form>(xobj->dest_doc,
nullptr,
843 xobj->xobject,
nullptr);
844 form->ParseContent(
nullptr,
nullptr,
nullptr);
845 auto form_object =
std::make_unique<CPDF_FormObject>(
847 return FPDFPageObjectFromCPDFPageObject(form_object.release());
860 RetainPtr<
const CPDF_Dictionary> pPrefDict =
861 pSrcDoc->GetRoot()->GetDictFor(
"ViewerPreferences");
865 RetainPtr<CPDF_Dictionary> pDstDict = pDstDoc->GetMutableRoot();
869 auto cloned_dict = pdfium::MakeRetain<CPDF_Dictionary>();
871 for (
const auto& it : locker) {
872 if (IsValidViewerPreferencesObject(it.second)) {
873 cloned_dict->SetFor(it.first, it.second->Clone());
877 pDstDict->SetFor(
"ViewerPreferences",
std::move(cloned_dict));
void Scale(float sx, float sy)
CPDF_ArrayLocker(const CPDF_Array *pArray)
CPDF_DictionaryLocker(const CPDF_Dictionary *pDictionary)
bool KeyExist(const ByteString &key) const
ByteString GetByteStringFor(const ByteString &key) const
uint32_t AddIndirectObject(RetainPtr< CPDF_Object > pObj)
bool IsDictionary() const
const CPDF_Array * AsArray() const
static constexpr int32_t kNoContentStream
void SetRef(CPDF_IndirectObjectHolder *pDoc, uint32_t objnum)
uint32_t GetRefObjNum() const
bool EqualNoCase(ByteStringView str) const
static ByteString Format(const char *pFormat,...)
ByteString & operator+=(const ByteString &str)
ByteString & operator+=(const char *str)
ByteString & operator=(ByteString &&that) noexcept
XObjectContext * XObjectContextFromFPDFXObject(FPDF_XOBJECT xobject)
CPDF_Document * CPDFDocumentFromFPDFDocument(FPDF_DOCUMENT doc)
FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV FPDF_CreateNewDocument()
FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV FPDF_ImportNPagesToOne(FPDF_DOCUMENT src_doc, float output_width, float output_height, size_t num_pages_on_x_axis, size_t num_pages_on_y_axis)
FPDF_EXPORT void FPDF_CALLCONV FPDF_CloseXObject(FPDF_XOBJECT xobject)
FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV FPDF_NewFormObjectFromXObject(FPDF_XOBJECT xobject)
FPDF_EXPORT FPDF_XOBJECT FPDF_CALLCONV FPDF_NewXObjectFromPage(FPDF_DOCUMENT dest_doc, FPDF_DOCUMENT src_doc, int src_page_index)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_CopyViewerPreferences(FPDF_DOCUMENT dest_doc, FPDF_DOCUMENT src_doc)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_ImportPages(FPDF_DOCUMENT dest_doc, FPDF_DOCUMENT src_doc, FPDF_BYTESTRING pagerange, int index)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_ImportPagesByIndex(FPDF_DOCUMENT dest_doc, FPDF_DOCUMENT src_doc, const int *page_indices, unsigned long length, int index)
UnownedPtr< CPDF_Document > dest_doc
RetainPtr< CPDF_Stream > xobject