halcanary | 23f4d4d | 2016-03-12 05:59:39 -0800 | [diff] [blame] | 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 | */ |
Hal Canary | 23564b9 | 2018-09-07 14:33:14 -0400 | [diff] [blame] | 7 | #ifndef SkPDFDocumentPriv_DEFINED |
| 8 | #define SkPDFDocumentPriv_DEFINED |
halcanary | 23f4d4d | 2016-03-12 05:59:39 -0800 | [diff] [blame] | 9 | |
Hal Canary | 2473d94 | 2018-09-10 13:06:42 -0400 | [diff] [blame] | 10 | #include "SkCanvas.h" |
halcanary | d11c726 | 2016-03-25 05:52:57 -0700 | [diff] [blame] | 11 | #include "SkPDFCanon.h" |
Hal Canary | 9a3f554 | 2018-12-10 19:59:07 -0500 | [diff] [blame^] | 12 | #include "SkPDFDocument.h" |
halcanary | cc77c12 | 2016-03-23 06:26:31 -0700 | [diff] [blame] | 13 | #include "SkPDFFont.h" |
Hal Canary | 2473d94 | 2018-09-10 13:06:42 -0400 | [diff] [blame] | 14 | #include "SkPDFMetadata.h" |
Hal Canary | 9a3f554 | 2018-12-10 19:59:07 -0500 | [diff] [blame^] | 15 | #include "SkUUID.h" |
| 16 | |
| 17 | #include <atomic> |
halcanary | 23f4d4d | 2016-03-12 05:59:39 -0800 | [diff] [blame] | 18 | |
halcanary | 989da4a | 2016-03-21 14:33:17 -0700 | [diff] [blame] | 19 | class SkPDFDevice; |
Dominic Mazzoni | 656cefe | 2018-09-25 20:29:15 -0700 | [diff] [blame] | 20 | class SkPDFTag; |
Hal Canary | 9a3f554 | 2018-12-10 19:59:07 -0500 | [diff] [blame^] | 21 | class SkExecutor; |
Dominic Mazzoni | 656cefe | 2018-09-25 20:29:15 -0700 | [diff] [blame] | 22 | |
| 23 | const char* SkPDFGetNodeIdKey(); |
halcanary | 989da4a | 2016-03-21 14:33:17 -0700 | [diff] [blame] | 24 | |
Hal Canary | f6462c4 | 2018-11-13 16:19:59 -0500 | [diff] [blame] | 25 | struct SkPDFFileOffset { |
| 26 | int fValue; |
| 27 | }; |
| 28 | |
| 29 | struct SkPDFOffsetMap { |
| 30 | void set(SkPDFIndirectReference, SkPDFFileOffset); |
| 31 | SkPDFFileOffset get(SkPDFIndirectReference r); |
| 32 | std::vector<SkPDFFileOffset> fOffsets; |
| 33 | }; |
| 34 | |
halcanary | 50e82e6 | 2016-03-21 13:45:05 -0700 | [diff] [blame] | 35 | // Logically part of SkPDFDocument (like SkPDFCanon), but separate to |
| 36 | // keep similar functionality together. |
Hal Canary | 9e41c21 | 2018-09-03 12:00:23 -0400 | [diff] [blame] | 37 | struct SkPDFObjectSerializer { |
Hal Canary | 9a3f554 | 2018-12-10 19:59:07 -0500 | [diff] [blame^] | 38 | std::atomic<int> fNextObjectNumber = {1}; |
| 39 | SkPDFIndirectReference reserve() { return SkPDFIndirectReference{fNextObjectNumber++}; } |
Hal Canary | f6462c4 | 2018-11-13 16:19:59 -0500 | [diff] [blame] | 40 | SkPDFOffsetMap fOffsets; |
Hal Canary | f6462c4 | 2018-11-13 16:19:59 -0500 | [diff] [blame] | 41 | size_t fBaseOffset = SIZE_MAX; |
halcanary | 50e82e6 | 2016-03-21 13:45:05 -0700 | [diff] [blame] | 42 | |
| 43 | SkPDFObjectSerializer(); |
halcanary | a50151d | 2016-03-25 11:57:49 -0700 | [diff] [blame] | 44 | ~SkPDFObjectSerializer(); |
Hal Canary | 9a3f554 | 2018-12-10 19:59:07 -0500 | [diff] [blame^] | 45 | SkPDFObjectSerializer(SkPDFObjectSerializer&&) = delete; |
| 46 | SkPDFObjectSerializer& operator=(SkPDFObjectSerializer&&) = delete; |
Hal Canary | 9e41c21 | 2018-09-03 12:00:23 -0400 | [diff] [blame] | 47 | SkPDFObjectSerializer(const SkPDFObjectSerializer&) = delete; |
| 48 | SkPDFObjectSerializer& operator=(const SkPDFObjectSerializer&) = delete; |
Hal Canary | 6736236 | 2018-04-24 13:58:37 -0400 | [diff] [blame] | 49 | |
Hal Canary | a121183 | 2018-11-13 16:45:14 -0500 | [diff] [blame] | 50 | SkWStream* beginObject(SkPDFIndirectReference, SkWStream*); |
| 51 | void endObject(SkWStream*); |
Hal Canary | 9a3f554 | 2018-12-10 19:59:07 -0500 | [diff] [blame^] | 52 | void serializeHeader(SkWStream*); |
Hal Canary | f6462c4 | 2018-11-13 16:19:59 -0500 | [diff] [blame] | 53 | void serializeObject(const sk_sp<SkPDFObject>&, SkWStream*); |
Hal Canary | 9a3f554 | 2018-12-10 19:59:07 -0500 | [diff] [blame^] | 54 | void serializeFooter(SkWStream*, |
| 55 | SkPDFIndirectReference infoDict, |
| 56 | SkPDFIndirectReference docCatalog, |
| 57 | SkUUID uuid); |
Hal Canary | f6462c4 | 2018-11-13 16:19:59 -0500 | [diff] [blame] | 58 | SkPDFFileOffset offset(SkWStream*); |
halcanary | 50e82e6 | 2016-03-21 13:45:05 -0700 | [diff] [blame] | 59 | }; |
| 60 | |
| 61 | /** Concrete implementation of SkDocument that creates PDF files. This |
| 62 | class does not produced linearized or optimized PDFs; instead it |
| 63 | it attempts to use a minimum amount of RAM. */ |
| 64 | class SkPDFDocument : public SkDocument { |
| 65 | public: |
Hal Canary | 23564b9 | 2018-09-07 14:33:14 -0400 | [diff] [blame] | 66 | SkPDFDocument(SkWStream*, SkPDF::Metadata); |
Brian Salomon | d3b6597 | 2017-03-22 12:05:03 -0400 | [diff] [blame] | 67 | ~SkPDFDocument() override; |
Hal Canary | b1de5f9 | 2017-07-01 22:17:15 -0400 | [diff] [blame] | 68 | SkCanvas* onBeginPage(SkScalar, SkScalar) override; |
halcanary | 50e82e6 | 2016-03-21 13:45:05 -0700 | [diff] [blame] | 69 | void onEndPage() override; |
reed | d14df7c | 2016-09-22 14:12:46 -0700 | [diff] [blame] | 70 | void onClose(SkWStream*) override; |
halcanary | 50e82e6 | 2016-03-21 13:45:05 -0700 | [diff] [blame] | 71 | void onAbort() override; |
halcanary | e86134f | 2016-09-06 09:32:13 -0700 | [diff] [blame] | 72 | |
halcanary | 50e82e6 | 2016-03-21 13:45:05 -0700 | [diff] [blame] | 73 | /** |
| 74 | Serialize the object, as well as any other objects it |
| 75 | indirectly refers to. If any any other objects have been added |
| 76 | to the SkPDFObjNumMap without serializing them, they will be |
| 77 | serialized as well. |
| 78 | |
| 79 | It might go without saying that objects should not be changed |
| 80 | after calling serialize, since those changes will be too late. |
halcanary | 50e82e6 | 2016-03-21 13:45:05 -0700 | [diff] [blame] | 81 | */ |
Hal Canary | b10f92e | 2018-11-16 17:01:50 -0500 | [diff] [blame] | 82 | SkPDFIndirectReference serialize(const sk_sp<SkPDFObject>&); |
Hal Canary | 9a3f554 | 2018-12-10 19:59:07 -0500 | [diff] [blame^] | 83 | SkPDFIndirectReference emit(const SkPDFObject&, SkPDFIndirectReference); |
| 84 | SkPDFIndirectReference emit(const SkPDFObject& o) { return this->emit(o, this->reserveRef()); } |
halcanary | 50e82e6 | 2016-03-21 13:45:05 -0700 | [diff] [blame] | 85 | SkPDFCanon* canon() { return &fCanon; } |
Hal Canary | 23564b9 | 2018-09-07 14:33:14 -0400 | [diff] [blame] | 86 | const SkPDF::Metadata& metadata() const { return fMetadata; } |
halcanary | 50e82e6 | 2016-03-21 13:45:05 -0700 | [diff] [blame] | 87 | |
Dominic Mazzoni | 656cefe | 2018-09-25 20:29:15 -0700 | [diff] [blame] | 88 | sk_sp<SkPDFDict> getPage(int pageIndex) const; |
| 89 | // Returns -1 if no mark ID. |
| 90 | int getMarkIdForNodeId(int nodeId); |
| 91 | |
Hal Canary | 9a3f554 | 2018-12-10 19:59:07 -0500 | [diff] [blame^] | 92 | SkPDFIndirectReference reserveRef(); |
Hal Canary | a121183 | 2018-11-13 16:45:14 -0500 | [diff] [blame] | 93 | SkWStream* beginObject(SkPDFIndirectReference); |
| 94 | void endObject(); |
| 95 | |
Hal Canary | 9a3f554 | 2018-12-10 19:59:07 -0500 | [diff] [blame^] | 96 | SkExecutor* executor() const { return fExecutor; } |
| 97 | |
halcanary | 50e82e6 | 2016-03-21 13:45:05 -0700 | [diff] [blame] | 98 | private: |
Dominic Mazzoni | 656cefe | 2018-09-25 20:29:15 -0700 | [diff] [blame] | 99 | sk_sp<SkPDFTag> recursiveBuildTagTree(const SkPDF::StructureElementNode& node, |
| 100 | sk_sp<SkPDFTag> parent); |
| 101 | |
halcanary | 50e82e6 | 2016-03-21 13:45:05 -0700 | [diff] [blame] | 102 | SkPDFObjectSerializer fObjectSerializer; |
| 103 | SkPDFCanon fCanon; |
Hal Canary | 2473d94 | 2018-09-10 13:06:42 -0400 | [diff] [blame] | 104 | SkCanvas fCanvas; |
Hal Canary | 9e41c21 | 2018-09-03 12:00:23 -0400 | [diff] [blame] | 105 | std::vector<sk_sp<SkPDFDict>> fPages; |
halcanary | cc77c12 | 2016-03-23 06:26:31 -0700 | [diff] [blame] | 106 | sk_sp<SkPDFDict> fDests; |
| 107 | sk_sp<SkPDFDevice> fPageDevice; |
Hal Canary | 9a3f554 | 2018-12-10 19:59:07 -0500 | [diff] [blame^] | 108 | SkUUID fUUID; |
| 109 | SkPDFIndirectReference fInfoDict; |
| 110 | SkPDFIndirectReference fXMP; |
Hal Canary | 23564b9 | 2018-09-07 14:33:14 -0400 | [diff] [blame] | 111 | SkPDF::Metadata fMetadata; |
Hal Canary | 7d06ab2 | 2018-09-10 14:39:13 -0400 | [diff] [blame] | 112 | SkScalar fRasterScale = 1; |
| 113 | SkScalar fInverseRasterScale = 1; |
Hal Canary | 9a3f554 | 2018-12-10 19:59:07 -0500 | [diff] [blame^] | 114 | SkExecutor* fExecutor = nullptr; |
halcanary | 530032a | 2016-08-18 14:22:52 -0700 | [diff] [blame] | 115 | |
Dominic Mazzoni | 656cefe | 2018-09-25 20:29:15 -0700 | [diff] [blame] | 116 | // For tagged PDFs. |
| 117 | |
| 118 | // The tag root, which owns its child tags and so on. |
| 119 | sk_sp<SkPDFTag> fTagRoot; |
| 120 | // Array of page -> array of marks mapping to tags. |
| 121 | SkTArray<SkTArray<sk_sp<SkPDFTag>>> fMarksPerPage; |
| 122 | // A mapping from node ID to tag for fast lookup. |
| 123 | SkTHashMap<int, sk_sp<SkPDFTag>> fNodeIdToTag; |
| 124 | |
Hal Canary | 9a3f554 | 2018-12-10 19:59:07 -0500 | [diff] [blame^] | 125 | std::atomic<int> fOutstandingRefs = {0}; |
| 126 | SkMutex fMutex; |
| 127 | SkSemaphore fSemaphore; |
Hal Canary | a121183 | 2018-11-13 16:45:14 -0500 | [diff] [blame] | 128 | |
halcanary | 530032a | 2016-08-18 14:22:52 -0700 | [diff] [blame] | 129 | void reset(); |
halcanary | 50e82e6 | 2016-03-21 13:45:05 -0700 | [diff] [blame] | 130 | }; |
| 131 | |
Hal Canary | 23564b9 | 2018-09-07 14:33:14 -0400 | [diff] [blame] | 132 | #endif // SkPDFDocumentPriv_DEFINED |