• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 #ifndef SkPDFDocumentPriv_DEFINED
8 #define SkPDFDocumentPriv_DEFINED
9 
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkStream.h"
12 #include "include/docs/SkPDFDocument.h"
13 #include "include/private/SkMutex.h"
14 #include "include/private/SkTHash.h"
15 #include "src/pdf/SkPDFMetadata.h"
16 #include "src/pdf/SkPDFTag.h"
17 
18 #include <atomic>
19 #include <vector>
20 #include <memory>
21 
22 class SkExecutor;
23 class SkPDFDevice;
24 class SkPDFFont;
25 struct SkAdvancedTypefaceMetrics;
26 struct SkBitmapKey;
27 struct SkPDFFillGraphicState;
28 struct SkPDFImageShaderKey;
29 struct SkPDFStrokeGraphicState;
30 
31 namespace SkPDFGradientShader {
32 struct Key;
33 struct KeyHash;
34 }  // namespace SkPDFGradientShader
35 
36 const char* SkPDFGetNodeIdKey();
37 
38 // Logically part of SkPDFDocument, but separate to keep similar functionality together.
39 class SkPDFOffsetMap {
40 public:
41     void markStartOfDocument(const SkWStream*);
42     void markStartOfObject(int referenceNumber, const SkWStream*);
43     int objectCount() const;
44     int emitCrossReferenceTable(SkWStream* s) const;
45 private:
46     std::vector<int> fOffsets;
47     size_t fBaseOffset = SIZE_MAX;
48 };
49 
50 
51 struct SkPDFNamedDestination {
52     sk_sp<SkData> fName;
53     SkPoint fPoint;
54     SkPDFIndirectReference fPage;
55 };
56 
57 
58 struct SkPDFLink {
59     enum class Type {
60         kNone,
61         kUrl,
62         kNamedDestination,
63     };
64 
SkPDFLinkSkPDFLink65     SkPDFLink(Type type, SkData* data, const SkRect& rect, int nodeId)
66         : fType(type)
67         , fData(sk_ref_sp(data))
68         , fRect(rect)
69         , fNodeId(nodeId) {}
70     const Type fType;
71     // The url or named destination, depending on |fType|.
72     const sk_sp<SkData> fData;
73     const SkRect fRect;
74     const int fNodeId;
75 };
76 
77 
78 /** Concrete implementation of SkDocument that creates PDF files. This
79     class does not produced linearized or optimized PDFs; instead it
80     it attempts to use a minimum amount of RAM. */
81 class SkPDFDocument : public SkDocument {
82 public:
83     SkPDFDocument(SkWStream*, SkPDF::Metadata);
84     ~SkPDFDocument() override;
85     SkCanvas* onBeginPage(SkScalar, SkScalar) override;
86     void onEndPage() override;
87     void onClose(SkWStream*) override;
88     void onAbort() override;
89 
90     /**
91        Serialize the object, as well as any other objects it
92        indirectly refers to.  If any any other objects have been added
93        to the SkPDFObjNumMap without serializing them, they will be
94        serialized as well.
95 
96        It might go without saying that objects should not be changed
97        after calling serialize, since those changes will be too late.
98      */
99     SkPDFIndirectReference emit(const SkPDFObject&, SkPDFIndirectReference);
emit(const SkPDFObject & o)100     SkPDFIndirectReference emit(const SkPDFObject& o) { return this->emit(o, this->reserveRef()); }
101 
102     template <typename T>
emitStream(const SkPDFDict & dict,T writeStream,SkPDFIndirectReference ref)103     void emitStream(const SkPDFDict& dict, T writeStream, SkPDFIndirectReference ref) {
104         SkAutoMutexExclusive lock(fMutex);
105         SkWStream* stream = this->beginObject(ref);
106         dict.emitObject(stream);
107         stream->writeText(" stream\n");
108         writeStream(stream);
109         stream->writeText("\nendstream");
110         this->endObject();
111     }
112 
metadata()113     const SkPDF::Metadata& metadata() const { return fMetadata; }
114 
115     SkPDFIndirectReference getPage(size_t pageIndex) const;
currentPage()116     SkPDFIndirectReference currentPage() const {
117         return SkASSERT(!fPageRefs.empty()), fPageRefs.back();
118     }
119     // Used to allow marked content to refer to its corresponding structure
120     // tree node, via a page entry in the parent tree. Returns -1 if no
121     // mark ID.
122     int createMarkIdForNodeId(int nodeId);
123     // Used to allow annotations to refer to their corresponding structure
124     // tree node, via the struct parent tree. Returns -1 if no struct parent
125     // key.
126     int createStructParentKeyForNodeId(int nodeId);
127 
128     std::unique_ptr<SkPDFArray> getAnnotations();
129 
reserveRef()130     SkPDFIndirectReference reserveRef() { return SkPDFIndirectReference{fNextObjectNumber++}; }
131 
132     // Returns a tag to prepend to a PostScript name of a subset font. Includes the '+'.
133     SkString nextFontSubsetTag();
134 
executor()135     SkExecutor* executor() const { return fExecutor; }
136     void incrementJobCount();
137     void signalJobComplete();
currentPageIndex()138     size_t currentPageIndex() { return fPages.size(); }
pageCount()139     size_t pageCount() { return fPageRefs.size(); }
140 
141     const SkMatrix& currentPageTransform() const;
142 
143     // Canonicalized objects
144     SkTHashMap<SkPDFImageShaderKey, SkPDFIndirectReference> fImageShaderMap;
145     SkTHashMap<SkPDFGradientShader::Key, SkPDFIndirectReference, SkPDFGradientShader::KeyHash>
146         fGradientPatternMap;
147     SkTHashMap<SkBitmapKey, SkPDFIndirectReference> fPDFBitmapMap;
148     SkTHashMap<uint32_t, std::unique_ptr<SkAdvancedTypefaceMetrics>> fTypefaceMetrics;
149     SkTHashMap<uint32_t, std::vector<SkString>> fType1GlyphNames;
150     SkTHashMap<uint32_t, std::vector<SkUnichar>> fToUnicodeMap;
151     SkTHashMap<uint32_t, SkPDFIndirectReference> fFontDescriptors;
152     SkTHashMap<uint32_t, SkPDFIndirectReference> fType3FontDescriptors;
153     SkTHashMap<uint64_t, SkPDFFont> fFontMap;
154     SkTHashMap<SkPDFStrokeGraphicState, SkPDFIndirectReference> fStrokeGSMap;
155     SkTHashMap<SkPDFFillGraphicState, SkPDFIndirectReference> fFillGSMap;
156     SkPDFIndirectReference fInvertFunction;
157     SkPDFIndirectReference fNoSmaskGraphicState;
158     std::vector<std::unique_ptr<SkPDFLink>> fCurrentPageLinks;
159     std::vector<SkPDFNamedDestination> fNamedDestinations;
160 
161 private:
162     SkPDFOffsetMap fOffsetMap;
163     SkCanvas fCanvas;
164     std::vector<std::unique_ptr<SkPDFDict>> fPages;
165     std::vector<SkPDFIndirectReference> fPageRefs;
166 
167     sk_sp<SkPDFDevice> fPageDevice;
168     std::atomic<int> fNextObjectNumber = {1};
169     std::atomic<int> fJobCount = {0};
170     uint32_t fNextFontSubsetTag = {0};
171     SkUUID fUUID;
172     SkPDFIndirectReference fInfoDict;
173     SkPDFIndirectReference fXMP;
174     SkPDF::Metadata fMetadata;
175     SkScalar fRasterScale = 1;
176     SkScalar fInverseRasterScale = 1;
177     SkExecutor* fExecutor = nullptr;
178 
179     // For tagged PDFs.
180     SkPDFTagTree fTagTree;
181 
182     SkMutex fMutex;
183     SkSemaphore fSemaphore;
184 
185     void waitForJobs();
186     SkWStream* beginObject(SkPDFIndirectReference);
187     void endObject();
188 };
189 
190 #endif  // SkPDFDocumentPriv_DEFINED
191