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