/src/skia/src/pdf/SkPDFDevice.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2011 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 | | |
8 | | #ifndef SkPDFDevice_DEFINED |
9 | | #define SkPDFDevice_DEFINED |
10 | | |
11 | | #include "include/core/SkBitmap.h" |
12 | | #include "include/core/SkCanvas.h" |
13 | | #include "include/core/SkData.h" |
14 | | #include "include/core/SkPaint.h" |
15 | | #include "include/core/SkRect.h" |
16 | | #include "include/core/SkRefCnt.h" |
17 | | #include "include/core/SkStream.h" |
18 | | #include "include/private/SkTHash.h" |
19 | | #include "src/core/SkClipStack.h" |
20 | | #include "src/core/SkClipStackDevice.h" |
21 | | #include "src/core/SkTextBlobPriv.h" |
22 | | #include "src/pdf/SkKeyedImage.h" |
23 | | #include "src/pdf/SkPDFGraphicStackState.h" |
24 | | #include "src/pdf/SkPDFTypes.h" |
25 | | |
26 | | #include <vector> |
27 | | |
28 | | class SkGlyphRunList; |
29 | | class SkKeyedImage; |
30 | | class SkPDFArray; |
31 | | class SkPDFDevice; |
32 | | class SkPDFDict; |
33 | | class SkPDFDocument; |
34 | | class SkPDFFont; |
35 | | class SkPDFObject; |
36 | | class SkPath; |
37 | | class SkRRect; |
38 | | struct SkPDFIndirectReference; |
39 | | |
40 | | /** |
41 | | * \class SkPDFDevice |
42 | | * |
43 | | * An SkPDFDevice is the drawing context for a page or layer of PDF |
44 | | * content. |
45 | | */ |
46 | | class SkPDFDevice final : public SkClipStackDevice { |
47 | | public: |
48 | | /** |
49 | | * @param pageSize Page size in point units. |
50 | | * 1 point == 127/360 mm == 1/72 inch |
51 | | * @param document A non-null pointer back to the |
52 | | * PDFDocument object. The document is responsible for |
53 | | * de-duplicating across pages (via the SkPDFDocument) and |
54 | | * for early serializing of large immutable objects, such |
55 | | * as images (via SkPDFDocument::serialize()). |
56 | | * @param initialTransform Transform to be applied to the entire page. |
57 | | */ |
58 | | SkPDFDevice(SkISize pageSize, SkPDFDocument* document, |
59 | | const SkMatrix& initialTransform = SkMatrix::I()); |
60 | | |
61 | 0 | sk_sp<SkPDFDevice> makeCongruentDevice() { |
62 | 0 | return sk_make_sp<SkPDFDevice>(this->size(), fDocument); |
63 | 0 | } |
64 | | |
65 | | ~SkPDFDevice() override; |
66 | | |
67 | | /** |
68 | | * These are called inside the per-device-layer loop for each draw call. |
69 | | * When these are called, we have already applied any saveLayer |
70 | | * operations, and are handling any looping from the paint. |
71 | | */ |
72 | | void drawPaint(const SkPaint& paint) override; |
73 | | void drawPoints(SkCanvas::PointMode mode, |
74 | | size_t count, const SkPoint[], |
75 | | const SkPaint& paint) override; |
76 | | void drawRect(const SkRect& r, const SkPaint& paint) override; |
77 | | void drawOval(const SkRect& oval, const SkPaint& paint) override; |
78 | | void drawRRect(const SkRRect& rr, const SkPaint& paint) override; |
79 | | void drawPath(const SkPath& origpath, const SkPaint& paint, bool pathIsMutable) override; |
80 | | |
81 | | void drawImageRect(const SkImage*, |
82 | | const SkRect* src, |
83 | | const SkRect& dst, |
84 | | const SkSamplingOptions&, |
85 | | const SkPaint&, |
86 | | SkCanvas::SrcRectConstraint) override; |
87 | | void onDrawGlyphRunList(const SkGlyphRunList& glyphRunList, const SkPaint& paint) override; |
88 | | void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) override; |
89 | | |
90 | | // PDF specific methods. |
91 | | void drawSprite(const SkBitmap& bitmap, int x, int y, |
92 | | const SkPaint& paint); |
93 | | |
94 | | /** Create the resource dictionary for this device. Destructive. */ |
95 | | std::unique_ptr<SkPDFDict> makeResourceDict(); |
96 | | |
97 | | /** Returns a SkStream with the page contents. |
98 | | */ |
99 | | std::unique_ptr<SkStreamAsset> content(); |
100 | | |
101 | 0 | SkISize size() const { return this->imageInfo().dimensions(); } |
102 | 0 | SkIRect bounds() const { return this->imageInfo().bounds(); } |
103 | | |
104 | | void DrawGlyphRunAsPath(SkPDFDevice* dev, const SkGlyphRun& glyphRun, SkPoint offset); |
105 | | |
106 | 0 | const SkMatrix& initialTransform() const { return fInitialTransform; } |
107 | | |
108 | | protected: |
109 | | sk_sp<SkSurface> makeSurface(const SkImageInfo&, const SkSurfaceProps&) override; |
110 | | |
111 | | void drawAnnotation(const SkRect&, const char key[], SkData* value) override; |
112 | | |
113 | | void drawDevice(SkBaseDevice*, const SkSamplingOptions&, const SkPaint&) override; |
114 | | void drawSpecial(SkSpecialImage*, const SkMatrix&, const SkSamplingOptions&, |
115 | | const SkPaint&) override; |
116 | | |
117 | | sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&) override; |
118 | | sk_sp<SkSpecialImage> makeSpecial(const SkImage*) override; |
119 | | SkImageFilterCache* getImageFilterCache() override; |
120 | | |
121 | | private: |
122 | | // TODO(vandebo): push most of SkPDFDevice's state into a core object in |
123 | | // order to get the right access levels without using friend. |
124 | | friend class ScopedContentEntry; |
125 | | |
126 | | SkMatrix fInitialTransform; |
127 | | |
128 | | SkTHashSet<SkPDFIndirectReference> fGraphicStateResources; |
129 | | SkTHashSet<SkPDFIndirectReference> fXObjectResources; |
130 | | SkTHashSet<SkPDFIndirectReference> fShaderResources; |
131 | | SkTHashSet<SkPDFIndirectReference> fFontResources; |
132 | | int fNodeId; |
133 | | |
134 | | SkDynamicMemoryWStream fContent; |
135 | | SkDynamicMemoryWStream fContentBuffer; |
136 | | bool fNeedsExtraSave = false; |
137 | | SkPDFGraphicStackState fActiveStackState; |
138 | | SkPDFDocument* fDocument; |
139 | | |
140 | | //////////////////////////////////////////////////////////////////////////// |
141 | | |
142 | | SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) override; |
143 | | |
144 | | // Set alpha to true if making a transparency group form x-objects. |
145 | | SkPDFIndirectReference makeFormXObjectFromDevice(bool alpha = false); |
146 | | SkPDFIndirectReference makeFormXObjectFromDevice(SkIRect bbox, bool alpha = false); |
147 | | |
148 | | void drawFormXObjectWithMask(SkPDFIndirectReference xObject, |
149 | | SkPDFIndirectReference sMask, |
150 | | SkBlendMode, |
151 | | bool invertClip); |
152 | | |
153 | | // If the paint or clip is such that we shouldn't draw anything, this |
154 | | // returns nullptr and does not create a content entry. |
155 | | // setUpContentEntry and finishContentEntry can be used directly, but |
156 | | // the preferred method is to use the ScopedContentEntry helper class. |
157 | | SkDynamicMemoryWStream* setUpContentEntry(const SkClipStack* clipStack, |
158 | | const SkMatrix& matrix, |
159 | | const SkPaint& paint, |
160 | | SkScalar, |
161 | | SkPDFIndirectReference* dst); |
162 | | void finishContentEntry(const SkClipStack*, SkBlendMode, SkPDFIndirectReference, SkPath*); |
163 | | bool isContentEmpty(); |
164 | | |
165 | | void internalDrawGlyphRun(const SkGlyphRun& glyphRun, SkPoint offset, const SkPaint& runPaint); |
166 | | void drawGlyphRunAsPath(const SkGlyphRun& glyphRun, SkPoint offset, const SkPaint& runPaint); |
167 | | |
168 | | void internalDrawImageRect(SkKeyedImage, |
169 | | const SkRect* src, |
170 | | const SkRect& dst, |
171 | | const SkSamplingOptions&, |
172 | | const SkPaint&, |
173 | | const SkMatrix& canvasTransformationMatrix); |
174 | | |
175 | | void internalDrawPath(const SkClipStack&, |
176 | | const SkMatrix&, |
177 | | const SkPath&, |
178 | | const SkPaint&, |
179 | | bool pathIsMutable); |
180 | | |
181 | | void internalDrawPathWithFilter(const SkClipStack& clipStack, |
182 | | const SkMatrix& ctm, |
183 | | const SkPath& origPath, |
184 | | const SkPaint& paint); |
185 | | |
186 | | bool handleInversePath(const SkPath& origPath, const SkPaint& paint, bool pathIsMutable); |
187 | | |
188 | | void clearMaskOnGraphicState(SkDynamicMemoryWStream*); |
189 | | void setGraphicState(SkPDFIndirectReference gs, SkDynamicMemoryWStream*); |
190 | | void drawFormXObject(SkPDFIndirectReference xObject, SkDynamicMemoryWStream*); |
191 | | |
192 | 0 | bool hasEmptyClip() const { return this->cs().isEmpty(this->bounds()); } |
193 | | |
194 | | void reset(); |
195 | | |
196 | | using INHERITED = SkClipStackDevice; |
197 | | }; |
198 | | |
199 | | #endif |