• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 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 #ifndef CORE_FPDFAPI_EDIT_CPDF_NPAGETOONEEXPORTER_H_
8 #define CORE_FPDFAPI_EDIT_CPDF_NPAGETOONEEXPORTER_H_
9 
10 #include <stddef.h>
11 #include <stdint.h>
12 
13 #include <map>
14 #include <memory>
15 
16 #include "core/fpdfapi/edit/cpdf_pageorganizer.h"
17 #include "core/fpdfapi/parser/cpdf_stream.h"
18 #include "core/fxcrt/bytestring.h"
19 #include "core/fxcrt/fx_coordinates.h"
20 #include "core/fxcrt/retain_ptr.h"
21 #include "core/fxcrt/span.h"
22 #include "core/fxcrt/unowned_ptr.h"
23 
24 class CPDF_Document;
25 class CPDF_Page;
26 
27 struct XObjectContext {
28   XObjectContext();
29   ~XObjectContext();
30 
31   UnownedPtr<CPDF_Document> dest_doc;
32   RetainPtr<CPDF_Stream> xobject;
33 };
34 
35 // Copies pages from a source document into a destination document. Creates 1
36 // page in the destination document for every N source pages. This class is
37 // intended to be used once via ExportNPagesToOne() and then destroyed.
38 class CPDF_NPageToOneExporter final : public CPDF_PageOrganizer {
39  public:
40   // Struct that stores sub page origin and scale information.  When importing
41   // more than one pages onto the same page, most likely the pages will need to
42   // be scaled down, and scale is in range of (0, 1) exclusive.
43   struct NupPageSettings {
44     CFX_PointF sub_page_start_point;
45     float scale = 0.0f;
46   };
47 
48   CPDF_NPageToOneExporter(CPDF_Document* dest_doc, CPDF_Document* src_doc);
49   ~CPDF_NPageToOneExporter();
50 
51   // For the pages from the source document with `page_indices` as their page
52   // indices, insert them into the destination document, starting at page index
53   // 0.
54   // `page_indices` is 0-based.
55   // `dest_page_size` is the destination document page dimensions, measured in
56   // PDF "user space" units.
57   // `pages_on_x_axis` and `nPagesOnXAxis` together defines how many source
58   // pages fit on one destination page.
59   bool ExportNPagesToOne(pdfium::span<const uint32_t> page_indices,
60                          const CFX_SizeF& dest_page_size,
61                          size_t pages_on_x_axis,
62                          size_t pages_on_y_axis);
63 
64   std::unique_ptr<XObjectContext> CreateXObjectContextFromPage(
65       int src_page_index);
66 
67   // Helper that generates the content stream for a sub-page. Exposed for
68   // testing.
69   static ByteString GenerateSubPageContentStreamForTesting(
70       const ByteString& xobject_name,
71       const NupPageSettings& settings);
72 
73  private:
74   // Map page object number to XObject object name.
75   using PageXObjectMap = std::map<uint32_t, ByteString>;
76 
77   // Creates an XObject from `src_page`, or find an existing XObject that
78   // represents `src_page`. The transformation matrix is specified in
79   // `settings`.
80   // Returns the XObject reference surrounded by the transformation matrix.
81   ByteString AddSubPage(const RetainPtr<CPDF_Page>& src_page,
82                         const NupPageSettings& settings);
83 
84   // Creates an XObject from `src_page`. Updates mapping as needed.
85   // Returns the name of the newly created XObject.
86   ByteString MakeXObjectFromPage(RetainPtr<CPDF_Page> src_page);
87   RetainPtr<CPDF_Stream> MakeXObjectFromPageRaw(RetainPtr<CPDF_Page> src_page);
88 
89   // Adds `content` as the Contents key in `dest_page_dict`.
90   // Adds the objects in `xobject_name_to_number_map_` to the XObject
91   // dictionary in `dest_page_dict`'s Resources dictionary.
92   void FinishPage(RetainPtr<CPDF_Dictionary> dest_page_dict,
93                   const ByteString& content);
94 
95   // Counter for giving new XObjects unique names.
96   uint32_t object_number_ = 0;
97 
98   // Keeps track of created XObjects in the current page.
99   // Map XObject's object name to it's object number.
100   std::map<ByteString, uint32_t> xobject_name_to_number_map_;
101 
102   // Mapping of source page object number and XObject name of the entire doc.
103   // If there are multiple source pages that reference the same object number,
104   // they can also share the same created XObject.
105   PageXObjectMap src_page_xobject_map_;
106 };
107 
108 #endif  // CORE_FPDFAPI_EDIT_CPDF_NPAGETOONEEXPORTER_H_
109