xref: /aosp_15_r20/external/skia/src/pdf/SkPDFDocumentPriv.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2016 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker #ifndef SkPDFDocumentPriv_DEFINED
8*c8dee2aaSAndroid Build Coastguard Worker #define SkPDFDocumentPriv_DEFINED
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkData.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkDocument.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSpan.h"  // IWYU pragma: keep
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/docs/SkPDFDocument.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkMutex.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkSemaphore.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkUTF.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkTHash.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/pdf/SkPDFBitmap.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/pdf/SkPDFFont.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "src/pdf/SkPDFGraphicState.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "src/pdf/SkPDFShader.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "src/pdf/SkPDFTag.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "src/pdf/SkPDFTypes.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "src/pdf/SkUUID.h"
33*c8dee2aaSAndroid Build Coastguard Worker 
34*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef>
35*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
36*c8dee2aaSAndroid Build Coastguard Worker #include <atomic>
37*c8dee2aaSAndroid Build Coastguard Worker #include <vector>
38*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
39*c8dee2aaSAndroid Build Coastguard Worker 
40*c8dee2aaSAndroid Build Coastguard Worker class SkDescriptor;
41*c8dee2aaSAndroid Build Coastguard Worker class SkExecutor;
42*c8dee2aaSAndroid Build Coastguard Worker class SkPDFDevice;
43*c8dee2aaSAndroid Build Coastguard Worker struct SkAdvancedTypefaceMetrics;
44*c8dee2aaSAndroid Build Coastguard Worker struct SkBitmapKey;
45*c8dee2aaSAndroid Build Coastguard Worker class SkMatrix;
46*c8dee2aaSAndroid Build Coastguard Worker 
47*c8dee2aaSAndroid Build Coastguard Worker namespace SkPDFGradientShader {
48*c8dee2aaSAndroid Build Coastguard Worker struct Key;
49*c8dee2aaSAndroid Build Coastguard Worker struct KeyHash;
50*c8dee2aaSAndroid Build Coastguard Worker }  // namespace SkPDFGradientShader
51*c8dee2aaSAndroid Build Coastguard Worker 
52*c8dee2aaSAndroid Build Coastguard Worker const char* SkPDFGetElemIdKey();
53*c8dee2aaSAndroid Build Coastguard Worker 
54*c8dee2aaSAndroid Build Coastguard Worker // Logically part of SkPDFDocument, but separate to keep similar functionality together.
55*c8dee2aaSAndroid Build Coastguard Worker class SkPDFOffsetMap {
56*c8dee2aaSAndroid Build Coastguard Worker public:
57*c8dee2aaSAndroid Build Coastguard Worker     void markStartOfDocument(const SkWStream*);
58*c8dee2aaSAndroid Build Coastguard Worker     void markStartOfObject(int referenceNumber, const SkWStream*);
59*c8dee2aaSAndroid Build Coastguard Worker     int objectCount() const;
60*c8dee2aaSAndroid Build Coastguard Worker     int emitCrossReferenceTable(SkWStream* s) const;
61*c8dee2aaSAndroid Build Coastguard Worker private:
62*c8dee2aaSAndroid Build Coastguard Worker     std::vector<int> fOffsets;
63*c8dee2aaSAndroid Build Coastguard Worker     size_t fBaseOffset = SIZE_MAX;
64*c8dee2aaSAndroid Build Coastguard Worker };
65*c8dee2aaSAndroid Build Coastguard Worker 
66*c8dee2aaSAndroid Build Coastguard Worker 
67*c8dee2aaSAndroid Build Coastguard Worker struct SkPDFNamedDestination {
68*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkData> fName;
69*c8dee2aaSAndroid Build Coastguard Worker     SkPoint fPoint;
70*c8dee2aaSAndroid Build Coastguard Worker     SkPDFIndirectReference fPage;
71*c8dee2aaSAndroid Build Coastguard Worker };
72*c8dee2aaSAndroid Build Coastguard Worker 
73*c8dee2aaSAndroid Build Coastguard Worker 
74*c8dee2aaSAndroid Build Coastguard Worker struct SkPDFLink {
75*c8dee2aaSAndroid Build Coastguard Worker     enum class Type {
76*c8dee2aaSAndroid Build Coastguard Worker         kNone,
77*c8dee2aaSAndroid Build Coastguard Worker         kUrl,
78*c8dee2aaSAndroid Build Coastguard Worker         kNamedDestination,
79*c8dee2aaSAndroid Build Coastguard Worker     };
80*c8dee2aaSAndroid Build Coastguard Worker 
SkPDFLinkSkPDFLink81*c8dee2aaSAndroid Build Coastguard Worker     SkPDFLink(Type type, SkData* data, const SkRect& rect, int elemId)
82*c8dee2aaSAndroid Build Coastguard Worker         : fType(type)
83*c8dee2aaSAndroid Build Coastguard Worker         , fData(sk_ref_sp(data))
84*c8dee2aaSAndroid Build Coastguard Worker         , fRect(rect)
85*c8dee2aaSAndroid Build Coastguard Worker         , fElemId(elemId) {}
86*c8dee2aaSAndroid Build Coastguard Worker     const Type fType;
87*c8dee2aaSAndroid Build Coastguard Worker     // The url or named destination, depending on |fType|.
88*c8dee2aaSAndroid Build Coastguard Worker     const sk_sp<SkData> fData;
89*c8dee2aaSAndroid Build Coastguard Worker     const SkRect fRect;
90*c8dee2aaSAndroid Build Coastguard Worker     const int fElemId;
91*c8dee2aaSAndroid Build Coastguard Worker };
92*c8dee2aaSAndroid Build Coastguard Worker 
93*c8dee2aaSAndroid Build Coastguard Worker 
94*c8dee2aaSAndroid Build Coastguard Worker /** Concrete implementation of SkDocument that creates PDF files. This
95*c8dee2aaSAndroid Build Coastguard Worker     class does not produced linearized or optimized PDFs; instead it
96*c8dee2aaSAndroid Build Coastguard Worker     it attempts to use a minimum amount of RAM. */
97*c8dee2aaSAndroid Build Coastguard Worker class SkPDFDocument : public SkDocument {
98*c8dee2aaSAndroid Build Coastguard Worker public:
99*c8dee2aaSAndroid Build Coastguard Worker     SkPDFDocument(SkWStream*, SkPDF::Metadata);
100*c8dee2aaSAndroid Build Coastguard Worker     ~SkPDFDocument() override;
101*c8dee2aaSAndroid Build Coastguard Worker     SkCanvas* onBeginPage(SkScalar, SkScalar) override;
102*c8dee2aaSAndroid Build Coastguard Worker     void onEndPage() override;
103*c8dee2aaSAndroid Build Coastguard Worker     void onClose(SkWStream*) override;
104*c8dee2aaSAndroid Build Coastguard Worker     void onAbort() override;
105*c8dee2aaSAndroid Build Coastguard Worker 
106*c8dee2aaSAndroid Build Coastguard Worker     /**
107*c8dee2aaSAndroid Build Coastguard Worker        Serialize the object, as well as any other objects it
108*c8dee2aaSAndroid Build Coastguard Worker        indirectly refers to.  If any any other objects have been added
109*c8dee2aaSAndroid Build Coastguard Worker        to the SkPDFObjNumMap without serializing them, they will be
110*c8dee2aaSAndroid Build Coastguard Worker        serialized as well.
111*c8dee2aaSAndroid Build Coastguard Worker 
112*c8dee2aaSAndroid Build Coastguard Worker        It might go without saying that objects should not be changed
113*c8dee2aaSAndroid Build Coastguard Worker        after calling serialize, since those changes will be too late.
114*c8dee2aaSAndroid Build Coastguard Worker      */
115*c8dee2aaSAndroid Build Coastguard Worker     SkPDFIndirectReference emit(const SkPDFObject&, SkPDFIndirectReference);
emit(const SkPDFObject & o)116*c8dee2aaSAndroid Build Coastguard Worker     SkPDFIndirectReference emit(const SkPDFObject& o) { return this->emit(o, this->reserveRef()); }
117*c8dee2aaSAndroid Build Coastguard Worker 
118*c8dee2aaSAndroid Build Coastguard Worker     template <typename T>
emitStream(const SkPDFDict & dict,T writeStream,SkPDFIndirectReference ref)119*c8dee2aaSAndroid Build Coastguard Worker     void emitStream(const SkPDFDict& dict, T writeStream, SkPDFIndirectReference ref) {
120*c8dee2aaSAndroid Build Coastguard Worker         SkAutoMutexExclusive lock(fMutex);
121*c8dee2aaSAndroid Build Coastguard Worker         SkWStream* stream = this->beginObject(ref);
122*c8dee2aaSAndroid Build Coastguard Worker         dict.emitObject(stream);
123*c8dee2aaSAndroid Build Coastguard Worker         stream->writeText(" stream\n");
124*c8dee2aaSAndroid Build Coastguard Worker         writeStream(stream);
125*c8dee2aaSAndroid Build Coastguard Worker         stream->writeText("\nendstream");
126*c8dee2aaSAndroid Build Coastguard Worker         this->endObject();
127*c8dee2aaSAndroid Build Coastguard Worker     }
128*c8dee2aaSAndroid Build Coastguard Worker 
metadata()129*c8dee2aaSAndroid Build Coastguard Worker     const SkPDF::Metadata& metadata() const { return fMetadata; }
130*c8dee2aaSAndroid Build Coastguard Worker 
131*c8dee2aaSAndroid Build Coastguard Worker     SkPDFIndirectReference getPage(size_t pageIndex) const;
hasCurrentPage()132*c8dee2aaSAndroid Build Coastguard Worker     bool hasCurrentPage() const { return bool(fPageDevice); }
currentPage()133*c8dee2aaSAndroid Build Coastguard Worker     SkPDFIndirectReference currentPage() const {
134*c8dee2aaSAndroid Build Coastguard Worker         return SkASSERT(this->hasCurrentPage() && !fPageRefs.empty()), fPageRefs.back();
135*c8dee2aaSAndroid Build Coastguard Worker     }
136*c8dee2aaSAndroid Build Coastguard Worker 
137*c8dee2aaSAndroid Build Coastguard Worker     // Create a new marked-content identifier (MCID) to be used with a marked-content sequence
138*c8dee2aaSAndroid Build Coastguard Worker     // parented by the structure element (StructElem) with the given element identifier (elemId).
139*c8dee2aaSAndroid Build Coastguard Worker     // Returns a false Mark if if elemId does not refer to a StructElem.
140*c8dee2aaSAndroid Build Coastguard Worker     SkPDFStructTree::Mark createMarkForElemId(int elemId);
141*c8dee2aaSAndroid Build Coastguard Worker 
142*c8dee2aaSAndroid Build Coastguard Worker     // Create a key to use with /StructParent in a content item (usually an annotation) which refers
143*c8dee2aaSAndroid Build Coastguard Worker     // to the structure element (StructElem) with the given element identifier (elemId).
144*c8dee2aaSAndroid Build Coastguard Worker     // Returns -1 if elemId does not refer to a StructElem.
145*c8dee2aaSAndroid Build Coastguard Worker     int createStructParentKeyForElemId(int elemId, SkPDFIndirectReference contentItemRef);
146*c8dee2aaSAndroid Build Coastguard Worker 
147*c8dee2aaSAndroid Build Coastguard Worker     void addStructElemTitle(int elemId, SkSpan<const char>);
148*c8dee2aaSAndroid Build Coastguard Worker 
149*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<SkPDFArray> getAnnotations();
150*c8dee2aaSAndroid Build Coastguard Worker 
reserveRef()151*c8dee2aaSAndroid Build Coastguard Worker     SkPDFIndirectReference reserveRef() { return SkPDFIndirectReference{fNextObjectNumber++}; }
152*c8dee2aaSAndroid Build Coastguard Worker 
153*c8dee2aaSAndroid Build Coastguard Worker     // Returns a tag to prepend to a PostScript name of a subset font. Includes the '+'.
154*c8dee2aaSAndroid Build Coastguard Worker     SkString nextFontSubsetTag();
155*c8dee2aaSAndroid Build Coastguard Worker 
executor()156*c8dee2aaSAndroid Build Coastguard Worker     SkExecutor* executor() const { return fExecutor; }
157*c8dee2aaSAndroid Build Coastguard Worker     void incrementJobCount();
158*c8dee2aaSAndroid Build Coastguard Worker     void signalJobComplete();
currentPageIndex()159*c8dee2aaSAndroid Build Coastguard Worker     size_t currentPageIndex() { return fPages.size(); }
pageCount()160*c8dee2aaSAndroid Build Coastguard Worker     size_t pageCount() { return fPageRefs.size(); }
161*c8dee2aaSAndroid Build Coastguard Worker 
162*c8dee2aaSAndroid Build Coastguard Worker     const SkMatrix& currentPageTransform() const;
163*c8dee2aaSAndroid Build Coastguard Worker 
164*c8dee2aaSAndroid Build Coastguard Worker     // Canonicalized objects
165*c8dee2aaSAndroid Build Coastguard Worker     skia_private::THashMap<SkPDFImageShaderKey,
166*c8dee2aaSAndroid Build Coastguard Worker                            SkPDFIndirectReference,
167*c8dee2aaSAndroid Build Coastguard Worker                            SkPDFImageShaderKey::Hash> fImageShaderMap;
168*c8dee2aaSAndroid Build Coastguard Worker     skia_private::THashMap<SkPDFGradientShader::Key,
169*c8dee2aaSAndroid Build Coastguard Worker                            SkPDFIndirectReference,
170*c8dee2aaSAndroid Build Coastguard Worker                            SkPDFGradientShader::KeyHash> fGradientPatternMap;
171*c8dee2aaSAndroid Build Coastguard Worker     skia_private::THashMap<SkBitmapKey, SkPDFIndirectReference> fPDFBitmapMap;
172*c8dee2aaSAndroid Build Coastguard Worker     skia_private::THashMap<SkPDFIccProfileKey,
173*c8dee2aaSAndroid Build Coastguard Worker                            SkPDFIndirectReference,
174*c8dee2aaSAndroid Build Coastguard Worker                            SkPDFIccProfileKey::Hash> fICCProfileMap;
175*c8dee2aaSAndroid Build Coastguard Worker     skia_private::THashMap<uint32_t, std::unique_ptr<SkAdvancedTypefaceMetrics>> fTypefaceMetrics;
176*c8dee2aaSAndroid Build Coastguard Worker     skia_private::THashMap<uint32_t, std::vector<SkString>> fType1GlyphNames;
177*c8dee2aaSAndroid Build Coastguard Worker     skia_private::THashMap<uint32_t, std::vector<SkUnichar>> fToUnicodeMap;
178*c8dee2aaSAndroid Build Coastguard Worker     skia_private::THashMap<uint32_t, skia_private::THashMap<SkGlyphID, SkString>> fToUnicodeMapEx;
179*c8dee2aaSAndroid Build Coastguard Worker     skia_private::THashMap<uint32_t, SkPDFIndirectReference> fFontDescriptors;
180*c8dee2aaSAndroid Build Coastguard Worker     skia_private::THashMap<uint32_t, SkPDFIndirectReference> fType3FontDescriptors;
181*c8dee2aaSAndroid Build Coastguard Worker     skia_private::THashTable<sk_sp<SkPDFStrike>, const SkDescriptor&, SkPDFStrike::Traits> fStrikes;
182*c8dee2aaSAndroid Build Coastguard Worker     skia_private::THashMap<SkPDFStrokeGraphicState,
183*c8dee2aaSAndroid Build Coastguard Worker                            SkPDFIndirectReference,
184*c8dee2aaSAndroid Build Coastguard Worker                            SkPDFStrokeGraphicState::Hash> fStrokeGSMap;
185*c8dee2aaSAndroid Build Coastguard Worker     skia_private::THashMap<SkPDFFillGraphicState,
186*c8dee2aaSAndroid Build Coastguard Worker                            SkPDFIndirectReference,
187*c8dee2aaSAndroid Build Coastguard Worker                            SkPDFFillGraphicState::Hash> fFillGSMap;
188*c8dee2aaSAndroid Build Coastguard Worker     SkPDFIndirectReference fInvertFunction;
189*c8dee2aaSAndroid Build Coastguard Worker     SkPDFIndirectReference fNoSmaskGraphicState;
190*c8dee2aaSAndroid Build Coastguard Worker     std::vector<std::unique_ptr<SkPDFLink>> fCurrentPageLinks;
191*c8dee2aaSAndroid Build Coastguard Worker     std::vector<SkPDFNamedDestination> fNamedDestinations;
192*c8dee2aaSAndroid Build Coastguard Worker 
193*c8dee2aaSAndroid Build Coastguard Worker private:
194*c8dee2aaSAndroid Build Coastguard Worker     SkPDFOffsetMap fOffsetMap;
195*c8dee2aaSAndroid Build Coastguard Worker     SkCanvas fCanvas;
196*c8dee2aaSAndroid Build Coastguard Worker     std::vector<std::unique_ptr<SkPDFDict>> fPages;
197*c8dee2aaSAndroid Build Coastguard Worker     std::vector<SkPDFIndirectReference> fPageRefs;
198*c8dee2aaSAndroid Build Coastguard Worker 
199*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkPDFDevice> fPageDevice;
200*c8dee2aaSAndroid Build Coastguard Worker     std::atomic<int> fNextObjectNumber = {1};
201*c8dee2aaSAndroid Build Coastguard Worker     std::atomic<int> fJobCount = {0};
202*c8dee2aaSAndroid Build Coastguard Worker     uint32_t fNextFontSubsetTag = {0};
203*c8dee2aaSAndroid Build Coastguard Worker     SkUUID fUUID;
204*c8dee2aaSAndroid Build Coastguard Worker     SkPDFIndirectReference fInfoDict;
205*c8dee2aaSAndroid Build Coastguard Worker     SkPDFIndirectReference fXMP;
206*c8dee2aaSAndroid Build Coastguard Worker     const SkPDF::Metadata fMetadata;
207*c8dee2aaSAndroid Build Coastguard Worker     const SkScalar fRasterScale;
208*c8dee2aaSAndroid Build Coastguard Worker     const SkScalar fInverseRasterScale;
209*c8dee2aaSAndroid Build Coastguard Worker     SkExecutor *const fExecutor;
210*c8dee2aaSAndroid Build Coastguard Worker 
211*c8dee2aaSAndroid Build Coastguard Worker     // For tagged PDFs.
212*c8dee2aaSAndroid Build Coastguard Worker     SkPDFStructTree fStructTree;
213*c8dee2aaSAndroid Build Coastguard Worker 
214*c8dee2aaSAndroid Build Coastguard Worker     SkMutex fMutex;
215*c8dee2aaSAndroid Build Coastguard Worker     SkSemaphore fSemaphore;
216*c8dee2aaSAndroid Build Coastguard Worker 
217*c8dee2aaSAndroid Build Coastguard Worker     void waitForJobs();
218*c8dee2aaSAndroid Build Coastguard Worker     SkWStream* beginObject(SkPDFIndirectReference);
219*c8dee2aaSAndroid Build Coastguard Worker     void endObject();
220*c8dee2aaSAndroid Build Coastguard Worker };
221*c8dee2aaSAndroid Build Coastguard Worker 
222*c8dee2aaSAndroid Build Coastguard Worker #endif  // SkPDFDocumentPriv_DEFINED
223