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