blob: 27810dd4be0c13f683627d8cd1887238c0d0aa69 [file] [log] [blame]
halcanary23f4d4d2016-03-12 05:59:39 -08001/*
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 Canary23564b92018-09-07 14:33:14 -04007#ifndef SkPDFDocumentPriv_DEFINED
8#define SkPDFDocumentPriv_DEFINED
halcanary23f4d4d2016-03-12 05:59:39 -08009
Hal Canary2473d942018-09-10 13:06:42 -040010#include "SkCanvas.h"
halcanaryd11c7262016-03-25 05:52:57 -070011#include "SkPDFCanon.h"
Hal Canary9a3f5542018-12-10 19:59:07 -050012#include "SkPDFDocument.h"
halcanarycc77c122016-03-23 06:26:31 -070013#include "SkPDFFont.h"
Hal Canary2473d942018-09-10 13:06:42 -040014#include "SkPDFMetadata.h"
Hal Canary9a3f5542018-12-10 19:59:07 -050015#include "SkUUID.h"
16
17#include <atomic>
halcanary23f4d4d2016-03-12 05:59:39 -080018
halcanary989da4a2016-03-21 14:33:17 -070019class SkPDFDevice;
Dominic Mazzoni656cefe2018-09-25 20:29:15 -070020class SkPDFTag;
Hal Canary9a3f5542018-12-10 19:59:07 -050021class SkExecutor;
Dominic Mazzoni656cefe2018-09-25 20:29:15 -070022
23const char* SkPDFGetNodeIdKey();
halcanary989da4a2016-03-21 14:33:17 -070024
Hal Canaryf6462c42018-11-13 16:19:59 -050025struct SkPDFFileOffset {
26 int fValue;
27};
28
29struct SkPDFOffsetMap {
30 void set(SkPDFIndirectReference, SkPDFFileOffset);
31 SkPDFFileOffset get(SkPDFIndirectReference r);
32 std::vector<SkPDFFileOffset> fOffsets;
33};
34
halcanary50e82e62016-03-21 13:45:05 -070035// Logically part of SkPDFDocument (like SkPDFCanon), but separate to
36// keep similar functionality together.
Hal Canary9e41c212018-09-03 12:00:23 -040037struct SkPDFObjectSerializer {
Hal Canary9a3f5542018-12-10 19:59:07 -050038 std::atomic<int> fNextObjectNumber = {1};
39 SkPDFIndirectReference reserve() { return SkPDFIndirectReference{fNextObjectNumber++}; }
Hal Canaryf6462c42018-11-13 16:19:59 -050040 SkPDFOffsetMap fOffsets;
Hal Canaryf6462c42018-11-13 16:19:59 -050041 size_t fBaseOffset = SIZE_MAX;
halcanary50e82e62016-03-21 13:45:05 -070042
43 SkPDFObjectSerializer();
halcanarya50151d2016-03-25 11:57:49 -070044 ~SkPDFObjectSerializer();
Hal Canary9a3f5542018-12-10 19:59:07 -050045 SkPDFObjectSerializer(SkPDFObjectSerializer&&) = delete;
46 SkPDFObjectSerializer& operator=(SkPDFObjectSerializer&&) = delete;
Hal Canary9e41c212018-09-03 12:00:23 -040047 SkPDFObjectSerializer(const SkPDFObjectSerializer&) = delete;
48 SkPDFObjectSerializer& operator=(const SkPDFObjectSerializer&) = delete;
Hal Canary67362362018-04-24 13:58:37 -040049
Hal Canarya1211832018-11-13 16:45:14 -050050 SkWStream* beginObject(SkPDFIndirectReference, SkWStream*);
51 void endObject(SkWStream*);
Hal Canary9a3f5542018-12-10 19:59:07 -050052 void serializeHeader(SkWStream*);
Hal Canaryf6462c42018-11-13 16:19:59 -050053 void serializeObject(const sk_sp<SkPDFObject>&, SkWStream*);
Hal Canary9a3f5542018-12-10 19:59:07 -050054 void serializeFooter(SkWStream*,
55 SkPDFIndirectReference infoDict,
56 SkPDFIndirectReference docCatalog,
57 SkUUID uuid);
Hal Canaryf6462c42018-11-13 16:19:59 -050058 SkPDFFileOffset offset(SkWStream*);
halcanary50e82e62016-03-21 13:45:05 -070059};
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. */
64class SkPDFDocument : public SkDocument {
65public:
Hal Canary23564b92018-09-07 14:33:14 -040066 SkPDFDocument(SkWStream*, SkPDF::Metadata);
Brian Salomond3b65972017-03-22 12:05:03 -040067 ~SkPDFDocument() override;
Hal Canaryb1de5f92017-07-01 22:17:15 -040068 SkCanvas* onBeginPage(SkScalar, SkScalar) override;
halcanary50e82e62016-03-21 13:45:05 -070069 void onEndPage() override;
reedd14df7c2016-09-22 14:12:46 -070070 void onClose(SkWStream*) override;
halcanary50e82e62016-03-21 13:45:05 -070071 void onAbort() override;
halcanarye86134f2016-09-06 09:32:13 -070072
halcanary50e82e62016-03-21 13:45:05 -070073 /**
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.
halcanary50e82e62016-03-21 13:45:05 -070081 */
Hal Canaryb10f92e2018-11-16 17:01:50 -050082 SkPDFIndirectReference serialize(const sk_sp<SkPDFObject>&);
Hal Canary9a3f5542018-12-10 19:59:07 -050083 SkPDFIndirectReference emit(const SkPDFObject&, SkPDFIndirectReference);
84 SkPDFIndirectReference emit(const SkPDFObject& o) { return this->emit(o, this->reserveRef()); }
halcanary50e82e62016-03-21 13:45:05 -070085 SkPDFCanon* canon() { return &fCanon; }
Hal Canary23564b92018-09-07 14:33:14 -040086 const SkPDF::Metadata& metadata() const { return fMetadata; }
halcanary50e82e62016-03-21 13:45:05 -070087
Dominic Mazzoni656cefe2018-09-25 20:29:15 -070088 sk_sp<SkPDFDict> getPage(int pageIndex) const;
89 // Returns -1 if no mark ID.
90 int getMarkIdForNodeId(int nodeId);
91
Hal Canary9a3f5542018-12-10 19:59:07 -050092 SkPDFIndirectReference reserveRef();
Hal Canarya1211832018-11-13 16:45:14 -050093 SkWStream* beginObject(SkPDFIndirectReference);
94 void endObject();
95
Hal Canary9a3f5542018-12-10 19:59:07 -050096 SkExecutor* executor() const { return fExecutor; }
97
halcanary50e82e62016-03-21 13:45:05 -070098private:
Dominic Mazzoni656cefe2018-09-25 20:29:15 -070099 sk_sp<SkPDFTag> recursiveBuildTagTree(const SkPDF::StructureElementNode& node,
100 sk_sp<SkPDFTag> parent);
101
halcanary50e82e62016-03-21 13:45:05 -0700102 SkPDFObjectSerializer fObjectSerializer;
103 SkPDFCanon fCanon;
Hal Canary2473d942018-09-10 13:06:42 -0400104 SkCanvas fCanvas;
Hal Canary9e41c212018-09-03 12:00:23 -0400105 std::vector<sk_sp<SkPDFDict>> fPages;
halcanarycc77c122016-03-23 06:26:31 -0700106 sk_sp<SkPDFDict> fDests;
107 sk_sp<SkPDFDevice> fPageDevice;
Hal Canary9a3f5542018-12-10 19:59:07 -0500108 SkUUID fUUID;
109 SkPDFIndirectReference fInfoDict;
110 SkPDFIndirectReference fXMP;
Hal Canary23564b92018-09-07 14:33:14 -0400111 SkPDF::Metadata fMetadata;
Hal Canary7d06ab22018-09-10 14:39:13 -0400112 SkScalar fRasterScale = 1;
113 SkScalar fInverseRasterScale = 1;
Hal Canary9a3f5542018-12-10 19:59:07 -0500114 SkExecutor* fExecutor = nullptr;
halcanary530032a2016-08-18 14:22:52 -0700115
Dominic Mazzoni656cefe2018-09-25 20:29:15 -0700116 // 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 Canary9a3f5542018-12-10 19:59:07 -0500125 std::atomic<int> fOutstandingRefs = {0};
126 SkMutex fMutex;
127 SkSemaphore fSemaphore;
Hal Canarya1211832018-11-13 16:45:14 -0500128
halcanary530032a2016-08-18 14:22:52 -0700129 void reset();
halcanary50e82e62016-03-21 13:45:05 -0700130};
131
Hal Canary23564b92018-09-07 14:33:14 -0400132#endif // SkPDFDocumentPriv_DEFINED