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 executor()132 SkExecutor* executor() const { return fExecutor; } 133 void incrementJobCount(); 134 void signalJobComplete(); currentPageIndex()135 size_t currentPageIndex() { return fPages.size(); } pageCount()136 size_t pageCount() { return fPageRefs.size(); } 137 138 const SkMatrix& currentPageTransform() const; 139 140 // Canonicalized objects 141 SkTHashMap<SkPDFImageShaderKey, SkPDFIndirectReference> fImageShaderMap; 142 SkTHashMap<SkPDFGradientShader::Key, SkPDFIndirectReference, SkPDFGradientShader::KeyHash> 143 fGradientPatternMap; 144 SkTHashMap<SkBitmapKey, SkPDFIndirectReference> fPDFBitmapMap; 145 SkTHashMap<uint32_t, std::unique_ptr<SkAdvancedTypefaceMetrics>> fTypefaceMetrics; 146 SkTHashMap<uint32_t, std::vector<SkString>> fType1GlyphNames; 147 SkTHashMap<uint32_t, std::vector<SkUnichar>> fToUnicodeMap; 148 SkTHashMap<uint32_t, SkPDFIndirectReference> fFontDescriptors; 149 SkTHashMap<uint32_t, SkPDFIndirectReference> fType3FontDescriptors; 150 SkTHashMap<uint64_t, SkPDFFont> fFontMap; 151 SkTHashMap<SkPDFStrokeGraphicState, SkPDFIndirectReference> fStrokeGSMap; 152 SkTHashMap<SkPDFFillGraphicState, SkPDFIndirectReference> fFillGSMap; 153 SkPDFIndirectReference fInvertFunction; 154 SkPDFIndirectReference fNoSmaskGraphicState; 155 std::vector<std::unique_ptr<SkPDFLink>> fCurrentPageLinks; 156 std::vector<SkPDFNamedDestination> fNamedDestinations; 157 158 private: 159 SkPDFOffsetMap fOffsetMap; 160 SkCanvas fCanvas; 161 std::vector<std::unique_ptr<SkPDFDict>> fPages; 162 std::vector<SkPDFIndirectReference> fPageRefs; 163 164 sk_sp<SkPDFDevice> fPageDevice; 165 std::atomic<int> fNextObjectNumber = {1}; 166 std::atomic<int> fJobCount = {0}; 167 SkUUID fUUID; 168 SkPDFIndirectReference fInfoDict; 169 SkPDFIndirectReference fXMP; 170 SkPDF::Metadata fMetadata; 171 SkScalar fRasterScale = 1; 172 SkScalar fInverseRasterScale = 1; 173 SkExecutor* fExecutor = nullptr; 174 175 // For tagged PDFs. 176 SkPDFTagTree fTagTree; 177 178 SkMutex fMutex; 179 SkSemaphore fSemaphore; 180 181 void waitForJobs(); 182 SkWStream* beginObject(SkPDFIndirectReference); 183 void endObject(); 184 }; 185 186 #endif // SkPDFDocumentPriv_DEFINED 187