| /* |
| * Copyright 2016 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| #ifndef SkPDFDocumentPriv_DEFINED |
| #define SkPDFDocumentPriv_DEFINED |
| |
| #include "include/core/SkCanvas.h" |
| #include "include/core/SkStream.h" |
| #include "include/docs/SkPDFDocument.h" |
| #include "include/private/base/SkMutex.h" |
| #include "src/core/SkTHash.h" |
| #include "src/pdf/SkPDFMetadata.h" |
| #include "src/pdf/SkPDFTag.h" |
| |
| #include <atomic> |
| #include <vector> |
| #include <memory> |
| |
| class SkExecutor; |
| class SkPDFDevice; |
| class SkPDFFont; |
| struct SkAdvancedTypefaceMetrics; |
| struct SkBitmapKey; |
| struct SkPDFFillGraphicState; |
| struct SkPDFImageShaderKey; |
| struct SkPDFStrokeGraphicState; |
| |
| namespace SkPDFGradientShader { |
| struct Key; |
| struct KeyHash; |
| } // namespace SkPDFGradientShader |
| |
| const char* SkPDFGetNodeIdKey(); |
| |
| // Logically part of SkPDFDocument, but separate to keep similar functionality together. |
| class SkPDFOffsetMap { |
| public: |
| void markStartOfDocument(const SkWStream*); |
| void markStartOfObject(int referenceNumber, const SkWStream*); |
| int objectCount() const; |
| int emitCrossReferenceTable(SkWStream* s) const; |
| private: |
| std::vector<int> fOffsets; |
| size_t fBaseOffset = SIZE_MAX; |
| }; |
| |
| |
| struct SkPDFNamedDestination { |
| sk_sp<SkData> fName; |
| SkPoint fPoint; |
| SkPDFIndirectReference fPage; |
| }; |
| |
| |
| struct SkPDFLink { |
| enum class Type { |
| kNone, |
| kUrl, |
| kNamedDestination, |
| }; |
| |
| SkPDFLink(Type type, SkData* data, const SkRect& rect, int nodeId) |
| : fType(type) |
| , fData(sk_ref_sp(data)) |
| , fRect(rect) |
| , fNodeId(nodeId) {} |
| const Type fType; |
| // The url or named destination, depending on |fType|. |
| const sk_sp<SkData> fData; |
| const SkRect fRect; |
| const int fNodeId; |
| }; |
| |
| |
| /** Concrete implementation of SkDocument that creates PDF files. This |
| class does not produced linearized or optimized PDFs; instead it |
| it attempts to use a minimum amount of RAM. */ |
| class SkPDFDocument : public SkDocument { |
| public: |
| SkPDFDocument(SkWStream*, SkPDF::Metadata); |
| ~SkPDFDocument() override; |
| SkCanvas* onBeginPage(SkScalar, SkScalar) override; |
| void onEndPage() override; |
| void onClose(SkWStream*) override; |
| void onAbort() override; |
| |
| /** |
| Serialize the object, as well as any other objects it |
| indirectly refers to. If any any other objects have been added |
| to the SkPDFObjNumMap without serializing them, they will be |
| serialized as well. |
| |
| It might go without saying that objects should not be changed |
| after calling serialize, since those changes will be too late. |
| */ |
| SkPDFIndirectReference emit(const SkPDFObject&, SkPDFIndirectReference); |
| SkPDFIndirectReference emit(const SkPDFObject& o) { return this->emit(o, this->reserveRef()); } |
| |
| template <typename T> |
| void emitStream(const SkPDFDict& dict, T writeStream, SkPDFIndirectReference ref) { |
| SkAutoMutexExclusive lock(fMutex); |
| SkWStream* stream = this->beginObject(ref); |
| dict.emitObject(stream); |
| stream->writeText(" stream\n"); |
| writeStream(stream); |
| stream->writeText("\nendstream"); |
| this->endObject(); |
| } |
| |
| const SkPDF::Metadata& metadata() const { return fMetadata; } |
| |
| SkPDFIndirectReference getPage(size_t pageIndex) const; |
| SkPDFIndirectReference currentPage() const { |
| return SkASSERT(!fPageRefs.empty()), fPageRefs.back(); |
| } |
| // Used to allow marked content to refer to its corresponding structure |
| // tree node, via a page entry in the parent tree. Returns -1 if no |
| // mark ID. |
| int createMarkIdForNodeId(int nodeId); |
| // Used to allow annotations to refer to their corresponding structure |
| // tree node, via the struct parent tree. Returns -1 if no struct parent |
| // key. |
| int createStructParentKeyForNodeId(int nodeId); |
| |
| std::unique_ptr<SkPDFArray> getAnnotations(); |
| |
| SkPDFIndirectReference reserveRef() { return SkPDFIndirectReference{fNextObjectNumber++}; } |
| |
| // Returns a tag to prepend to a PostScript name of a subset font. Includes the '+'. |
| SkString nextFontSubsetTag(); |
| |
| SkExecutor* executor() const { return fExecutor; } |
| void incrementJobCount(); |
| void signalJobComplete(); |
| size_t currentPageIndex() { return fPages.size(); } |
| size_t pageCount() { return fPageRefs.size(); } |
| |
| const SkMatrix& currentPageTransform() const; |
| |
| // Canonicalized objects |
| SkTHashMap<SkPDFImageShaderKey, SkPDFIndirectReference> fImageShaderMap; |
| SkTHashMap<SkPDFGradientShader::Key, SkPDFIndirectReference, SkPDFGradientShader::KeyHash> |
| fGradientPatternMap; |
| SkTHashMap<SkBitmapKey, SkPDFIndirectReference> fPDFBitmapMap; |
| SkTHashMap<uint32_t, std::unique_ptr<SkAdvancedTypefaceMetrics>> fTypefaceMetrics; |
| SkTHashMap<uint32_t, std::vector<SkString>> fType1GlyphNames; |
| SkTHashMap<uint32_t, std::vector<SkUnichar>> fToUnicodeMap; |
| SkTHashMap<uint32_t, SkPDFIndirectReference> fFontDescriptors; |
| SkTHashMap<uint32_t, SkPDFIndirectReference> fType3FontDescriptors; |
| SkTHashMap<uint64_t, SkPDFFont> fFontMap; |
| SkTHashMap<SkPDFStrokeGraphicState, SkPDFIndirectReference> fStrokeGSMap; |
| SkTHashMap<SkPDFFillGraphicState, SkPDFIndirectReference> fFillGSMap; |
| SkPDFIndirectReference fInvertFunction; |
| SkPDFIndirectReference fNoSmaskGraphicState; |
| std::vector<std::unique_ptr<SkPDFLink>> fCurrentPageLinks; |
| std::vector<SkPDFNamedDestination> fNamedDestinations; |
| |
| private: |
| SkPDFOffsetMap fOffsetMap; |
| SkCanvas fCanvas; |
| std::vector<std::unique_ptr<SkPDFDict>> fPages; |
| std::vector<SkPDFIndirectReference> fPageRefs; |
| |
| sk_sp<SkPDFDevice> fPageDevice; |
| std::atomic<int> fNextObjectNumber = {1}; |
| std::atomic<int> fJobCount = {0}; |
| uint32_t fNextFontSubsetTag = {0}; |
| SkUUID fUUID; |
| SkPDFIndirectReference fInfoDict; |
| SkPDFIndirectReference fXMP; |
| SkPDF::Metadata fMetadata; |
| SkScalar fRasterScale = 1; |
| SkScalar fInverseRasterScale = 1; |
| SkExecutor* fExecutor = nullptr; |
| |
| // For tagged PDFs. |
| SkPDFTagTree fTagTree; |
| |
| SkMutex fMutex; |
| SkSemaphore fSemaphore; |
| |
| void waitForJobs(); |
| SkWStream* beginObject(SkPDFIndirectReference); |
| void endObject(); |
| }; |
| |
| #endif // SkPDFDocumentPriv_DEFINED |