xref: /aosp_15_r20/external/skia/src/pdf/SkPDFDevice.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2011 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 
8*c8dee2aaSAndroid Build Coastguard Worker #ifndef SkPDFDevice_DEFINED
9*c8dee2aaSAndroid Build Coastguard Worker #define SkPDFDevice_DEFINED
10*c8dee2aaSAndroid Build Coastguard Worker 
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSamplingOptions.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkClipStack.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkClipStackDevice.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkTHash.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/pdf/SkKeyedImage.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/pdf/SkPDFGraphicStackState.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/pdf/SkPDFTag.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/pdf/SkPDFTypes.h"
24*c8dee2aaSAndroid Build Coastguard Worker 
25*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef>
26*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
27*c8dee2aaSAndroid Build Coastguard Worker 
28*c8dee2aaSAndroid Build Coastguard Worker class SkBitmap;
29*c8dee2aaSAndroid Build Coastguard Worker class SkBlender;
30*c8dee2aaSAndroid Build Coastguard Worker class SkData;
31*c8dee2aaSAndroid Build Coastguard Worker class SkDevice;
32*c8dee2aaSAndroid Build Coastguard Worker class SkImage;
33*c8dee2aaSAndroid Build Coastguard Worker class SkMesh;
34*c8dee2aaSAndroid Build Coastguard Worker class SkPDFDocument;
35*c8dee2aaSAndroid Build Coastguard Worker class SkPaint;
36*c8dee2aaSAndroid Build Coastguard Worker class SkPath;
37*c8dee2aaSAndroid Build Coastguard Worker class SkRRect;
38*c8dee2aaSAndroid Build Coastguard Worker class SkSpecialImage;
39*c8dee2aaSAndroid Build Coastguard Worker class SkSurface;
40*c8dee2aaSAndroid Build Coastguard Worker class SkSurfaceProps;
41*c8dee2aaSAndroid Build Coastguard Worker class SkVertices;
42*c8dee2aaSAndroid Build Coastguard Worker enum class SkBlendMode;
43*c8dee2aaSAndroid Build Coastguard Worker struct SkIRect;
44*c8dee2aaSAndroid Build Coastguard Worker struct SkISize;
45*c8dee2aaSAndroid Build Coastguard Worker struct SkImageInfo;
46*c8dee2aaSAndroid Build Coastguard Worker struct SkPoint;
47*c8dee2aaSAndroid Build Coastguard Worker struct SkRect;
48*c8dee2aaSAndroid Build Coastguard Worker 
49*c8dee2aaSAndroid Build Coastguard Worker namespace sktext {
50*c8dee2aaSAndroid Build Coastguard Worker class GlyphRun;
51*c8dee2aaSAndroid Build Coastguard Worker class GlyphRunList;
52*c8dee2aaSAndroid Build Coastguard Worker }
53*c8dee2aaSAndroid Build Coastguard Worker 
54*c8dee2aaSAndroid Build Coastguard Worker /**
55*c8dee2aaSAndroid Build Coastguard Worker  *  \class SkPDFDevice
56*c8dee2aaSAndroid Build Coastguard Worker  *
57*c8dee2aaSAndroid Build Coastguard Worker  *  An SkPDFDevice is the drawing context for a page or layer of PDF
58*c8dee2aaSAndroid Build Coastguard Worker  *  content.
59*c8dee2aaSAndroid Build Coastguard Worker  */
60*c8dee2aaSAndroid Build Coastguard Worker class SkPDFDevice final : public SkClipStackDevice {
61*c8dee2aaSAndroid Build Coastguard Worker public:
62*c8dee2aaSAndroid Build Coastguard Worker     /**
63*c8dee2aaSAndroid Build Coastguard Worker      *  @param pageSize Page size in point units.
64*c8dee2aaSAndroid Build Coastguard Worker      *         1 point == 127/360 mm == 1/72 inch
65*c8dee2aaSAndroid Build Coastguard Worker      *  @param document  A non-null pointer back to the
66*c8dee2aaSAndroid Build Coastguard Worker      *         PDFDocument object.  The document is responsible for
67*c8dee2aaSAndroid Build Coastguard Worker      *         de-duplicating across pages (via the SkPDFDocument) and
68*c8dee2aaSAndroid Build Coastguard Worker      *         for early serializing of large immutable objects, such
69*c8dee2aaSAndroid Build Coastguard Worker      *         as images (via SkPDFDocument::serialize()).
70*c8dee2aaSAndroid Build Coastguard Worker      *  @param initialTransform Transform to be applied to the entire page.
71*c8dee2aaSAndroid Build Coastguard Worker      */
72*c8dee2aaSAndroid Build Coastguard Worker     SkPDFDevice(SkISize pageSize, SkPDFDocument* document,
73*c8dee2aaSAndroid Build Coastguard Worker                 const SkMatrix& initialTransform = SkMatrix::I());
74*c8dee2aaSAndroid Build Coastguard Worker 
makeCongruentDevice()75*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkPDFDevice> makeCongruentDevice() {
76*c8dee2aaSAndroid Build Coastguard Worker         return sk_make_sp<SkPDFDevice>(this->size(), fDocument);
77*c8dee2aaSAndroid Build Coastguard Worker     }
78*c8dee2aaSAndroid Build Coastguard Worker 
79*c8dee2aaSAndroid Build Coastguard Worker     ~SkPDFDevice() override;
80*c8dee2aaSAndroid Build Coastguard Worker 
81*c8dee2aaSAndroid Build Coastguard Worker     /**
82*c8dee2aaSAndroid Build Coastguard Worker      *  These are called inside the per-device-layer loop for each draw call.
83*c8dee2aaSAndroid Build Coastguard Worker      *  When these are called, we have already applied any saveLayer
84*c8dee2aaSAndroid Build Coastguard Worker      *  operations, and are handling any looping from the paint.
85*c8dee2aaSAndroid Build Coastguard Worker      */
86*c8dee2aaSAndroid Build Coastguard Worker     void drawPaint(const SkPaint& paint) override;
87*c8dee2aaSAndroid Build Coastguard Worker     void drawPoints(SkCanvas::PointMode mode,
88*c8dee2aaSAndroid Build Coastguard Worker                     size_t count, const SkPoint[],
89*c8dee2aaSAndroid Build Coastguard Worker                     const SkPaint& paint) override;
90*c8dee2aaSAndroid Build Coastguard Worker     void drawRect(const SkRect& r, const SkPaint& paint) override;
91*c8dee2aaSAndroid Build Coastguard Worker     void drawOval(const SkRect& oval, const SkPaint& paint) override;
92*c8dee2aaSAndroid Build Coastguard Worker     void drawRRect(const SkRRect& rr, const SkPaint& paint) override;
93*c8dee2aaSAndroid Build Coastguard Worker     void drawPath(const SkPath& origpath, const SkPaint& paint, bool pathIsMutable) override;
94*c8dee2aaSAndroid Build Coastguard Worker 
95*c8dee2aaSAndroid Build Coastguard Worker     void drawImageRect(const SkImage*,
96*c8dee2aaSAndroid Build Coastguard Worker                        const SkRect* src,
97*c8dee2aaSAndroid Build Coastguard Worker                        const SkRect& dst,
98*c8dee2aaSAndroid Build Coastguard Worker                        const SkSamplingOptions&,
99*c8dee2aaSAndroid Build Coastguard Worker                        const SkPaint&,
100*c8dee2aaSAndroid Build Coastguard Worker                        SkCanvas::SrcRectConstraint) override;
101*c8dee2aaSAndroid Build Coastguard Worker 
102*c8dee2aaSAndroid Build Coastguard Worker     void drawVertices(const SkVertices*, sk_sp<SkBlender>, const SkPaint&, bool) override;
103*c8dee2aaSAndroid Build Coastguard Worker     void drawMesh(const SkMesh&, sk_sp<SkBlender>, const SkPaint&) override;
104*c8dee2aaSAndroid Build Coastguard Worker 
105*c8dee2aaSAndroid Build Coastguard Worker     void drawAnnotation(const SkRect&, const char key[], SkData* value) override;
106*c8dee2aaSAndroid Build Coastguard Worker 
107*c8dee2aaSAndroid Build Coastguard Worker     void drawDevice(SkDevice*, const SkSamplingOptions&, const SkPaint&) override;
108*c8dee2aaSAndroid Build Coastguard Worker     void drawSpecial(SkSpecialImage*, const SkMatrix&, const SkSamplingOptions&,
109*c8dee2aaSAndroid Build Coastguard Worker                      const SkPaint&, SkCanvas::SrcRectConstraint) override;
110*c8dee2aaSAndroid Build Coastguard Worker 
111*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkSurface> makeSurface(const SkImageInfo&, const SkSurfaceProps&) override;
112*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkDevice> createDevice(const CreateInfo&, const SkPaint*) override;
113*c8dee2aaSAndroid Build Coastguard Worker 
114*c8dee2aaSAndroid Build Coastguard Worker     // PDF specific methods.
115*c8dee2aaSAndroid Build Coastguard Worker     void drawSprite(const SkBitmap& bitmap, int x, int y,
116*c8dee2aaSAndroid Build Coastguard Worker                     const SkPaint& paint);
117*c8dee2aaSAndroid Build Coastguard Worker 
118*c8dee2aaSAndroid Build Coastguard Worker     /** Create the resource dictionary for this device. Destructive. */
119*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<SkPDFDict> makeResourceDict();
120*c8dee2aaSAndroid Build Coastguard Worker 
121*c8dee2aaSAndroid Build Coastguard Worker     /** Returns a SkStream with the page contents.
122*c8dee2aaSAndroid Build Coastguard Worker      */
123*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<SkStreamAsset> content();
124*c8dee2aaSAndroid Build Coastguard Worker 
initialTransform()125*c8dee2aaSAndroid Build Coastguard Worker     const SkMatrix& initialTransform() const { return fInitialTransform; }
126*c8dee2aaSAndroid Build Coastguard Worker 
127*c8dee2aaSAndroid Build Coastguard Worker protected:
128*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&) override;
129*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkSpecialImage> makeSpecial(const SkImage*) override;
130*c8dee2aaSAndroid Build Coastguard Worker 
131*c8dee2aaSAndroid Build Coastguard Worker private:
132*c8dee2aaSAndroid Build Coastguard Worker     // TODO(vandebo): push most of SkPDFDevice's state into a core object in
133*c8dee2aaSAndroid Build Coastguard Worker     // order to get the right access levels without using friend.
134*c8dee2aaSAndroid Build Coastguard Worker     friend class ScopedContentEntry;
135*c8dee2aaSAndroid Build Coastguard Worker 
136*c8dee2aaSAndroid Build Coastguard Worker     SkMatrix fInitialTransform;
137*c8dee2aaSAndroid Build Coastguard Worker 
138*c8dee2aaSAndroid Build Coastguard Worker     skia_private::THashSet<SkPDFIndirectReference> fGraphicStateResources;
139*c8dee2aaSAndroid Build Coastguard Worker     skia_private::THashSet<SkPDFIndirectReference> fXObjectResources;
140*c8dee2aaSAndroid Build Coastguard Worker     skia_private::THashSet<SkPDFIndirectReference> fShaderResources;
141*c8dee2aaSAndroid Build Coastguard Worker     skia_private::THashSet<SkPDFIndirectReference> fFontResources;
142*c8dee2aaSAndroid Build Coastguard Worker 
143*c8dee2aaSAndroid Build Coastguard Worker     class MarkedContentManager {
144*c8dee2aaSAndroid Build Coastguard Worker     public:
145*c8dee2aaSAndroid Build Coastguard Worker         MarkedContentManager(SkPDFDocument* document, SkDynamicMemoryWStream* out);
146*c8dee2aaSAndroid Build Coastguard Worker         ~MarkedContentManager();
147*c8dee2aaSAndroid Build Coastguard Worker 
148*c8dee2aaSAndroid Build Coastguard Worker         // Sets the current element identifier. Associate future draws with the structure element
149*c8dee2aaSAndroid Build Coastguard Worker         // with the given element identifier. Element identifier 0 is reserved to mean no structure
150*c8dee2aaSAndroid Build Coastguard Worker         // element.
151*c8dee2aaSAndroid Build Coastguard Worker         void setNextMarksElemId(int nextMarksElemId);
152*c8dee2aaSAndroid Build Coastguard Worker 
153*c8dee2aaSAndroid Build Coastguard Worker         // The current element identifier.
154*c8dee2aaSAndroid Build Coastguard Worker         int elemId() const;
155*c8dee2aaSAndroid Build Coastguard Worker 
156*c8dee2aaSAndroid Build Coastguard Worker         // Starts a marked-content sequence for a content item for the structure element with the
157*c8dee2aaSAndroid Build Coastguard Worker         // current element identifier. If there is an active marked-content sequence associated with
158*c8dee2aaSAndroid Build Coastguard Worker         // a different element identifier the active marked-content sequence will first be closed.
159*c8dee2aaSAndroid Build Coastguard Worker         // If there is no structure element with the current element identifier then the
160*c8dee2aaSAndroid Build Coastguard Worker         // marked-content sequence will not be started.
161*c8dee2aaSAndroid Build Coastguard Worker         void beginMark();
162*c8dee2aaSAndroid Build Coastguard Worker 
163*c8dee2aaSAndroid Build Coastguard Worker         // Tests if there is an active marked-content sequence.
164*c8dee2aaSAndroid Build Coastguard Worker         bool hasActiveMark() const;
165*c8dee2aaSAndroid Build Coastguard Worker 
166*c8dee2aaSAndroid Build Coastguard Worker         // Accumulates an upper left location for the active mark. The point is in PDF page space
167*c8dee2aaSAndroid Build Coastguard Worker         // and so is y-up. Only use if this.hasActiveMark()
168*c8dee2aaSAndroid Build Coastguard Worker         void accumulate(const SkPoint& p);
169*c8dee2aaSAndroid Build Coastguard Worker 
170*c8dee2aaSAndroid Build Coastguard Worker         // Tests if this marked content manager made any marks.
madeMarks()171*c8dee2aaSAndroid Build Coastguard Worker         bool madeMarks() const { return fMadeMarks; }
172*c8dee2aaSAndroid Build Coastguard Worker 
173*c8dee2aaSAndroid Build Coastguard Worker     private:
174*c8dee2aaSAndroid Build Coastguard Worker         SkPDFDocument* fDoc;
175*c8dee2aaSAndroid Build Coastguard Worker         SkDynamicMemoryWStream* fOut;
176*c8dee2aaSAndroid Build Coastguard Worker         SkPDFStructTree::Mark fCurrentlyActiveMark;
177*c8dee2aaSAndroid Build Coastguard Worker         int fNextMarksElemId;
178*c8dee2aaSAndroid Build Coastguard Worker         bool fMadeMarks;
179*c8dee2aaSAndroid Build Coastguard Worker     } fMarkManager;
180*c8dee2aaSAndroid Build Coastguard Worker 
181*c8dee2aaSAndroid Build Coastguard Worker     SkDynamicMemoryWStream fContent;
182*c8dee2aaSAndroid Build Coastguard Worker     SkDynamicMemoryWStream fContentBuffer;
183*c8dee2aaSAndroid Build Coastguard Worker     bool fNeedsExtraSave = false;
184*c8dee2aaSAndroid Build Coastguard Worker     SkPDFGraphicStackState fActiveStackState;
185*c8dee2aaSAndroid Build Coastguard Worker     SkPDFDocument* fDocument;
186*c8dee2aaSAndroid Build Coastguard Worker 
187*c8dee2aaSAndroid Build Coastguard Worker     ////////////////////////////////////////////////////////////////////////////
188*c8dee2aaSAndroid Build Coastguard Worker 
189*c8dee2aaSAndroid Build Coastguard Worker     void onDrawGlyphRunList(SkCanvas*, const sktext::GlyphRunList&, const SkPaint& paint) override;
190*c8dee2aaSAndroid Build Coastguard Worker 
191*c8dee2aaSAndroid Build Coastguard Worker     // Set alpha to true if making a transparency group form x-objects.
192*c8dee2aaSAndroid Build Coastguard Worker     SkPDFIndirectReference makeFormXObjectFromDevice(bool alpha = false);
193*c8dee2aaSAndroid Build Coastguard Worker     SkPDFIndirectReference makeFormXObjectFromDevice(SkIRect bbox, bool alpha = false);
194*c8dee2aaSAndroid Build Coastguard Worker 
195*c8dee2aaSAndroid Build Coastguard Worker     void drawFormXObjectWithMask(SkPDFIndirectReference xObject,
196*c8dee2aaSAndroid Build Coastguard Worker                                  SkPDFIndirectReference sMask,
197*c8dee2aaSAndroid Build Coastguard Worker                                  SkBlendMode,
198*c8dee2aaSAndroid Build Coastguard Worker                                  bool invertClip);
199*c8dee2aaSAndroid Build Coastguard Worker 
200*c8dee2aaSAndroid Build Coastguard Worker     // If the paint or clip is such that we shouldn't draw anything, this
201*c8dee2aaSAndroid Build Coastguard Worker     // returns nullptr and does not create a content entry.
202*c8dee2aaSAndroid Build Coastguard Worker     // setUpContentEntry and finishContentEntry can be used directly, but
203*c8dee2aaSAndroid Build Coastguard Worker     // the preferred method is to use the ScopedContentEntry helper class.
204*c8dee2aaSAndroid Build Coastguard Worker     SkDynamicMemoryWStream* setUpContentEntry(const SkClipStack* clipStack,
205*c8dee2aaSAndroid Build Coastguard Worker                                               const SkMatrix& matrix,
206*c8dee2aaSAndroid Build Coastguard Worker                                               const SkPaint& paint,
207*c8dee2aaSAndroid Build Coastguard Worker                                               SkScalar,
208*c8dee2aaSAndroid Build Coastguard Worker                                               SkPDFIndirectReference* dst);
209*c8dee2aaSAndroid Build Coastguard Worker     void finishContentEntry(const SkClipStack*, SkBlendMode, SkPDFIndirectReference, SkPath*);
210*c8dee2aaSAndroid Build Coastguard Worker     bool isContentEmpty();
211*c8dee2aaSAndroid Build Coastguard Worker 
212*c8dee2aaSAndroid Build Coastguard Worker     void internalDrawGlyphRun(
213*c8dee2aaSAndroid Build Coastguard Worker             const sktext::GlyphRun& glyphRun, SkPoint offset, const SkPaint& runPaint);
214*c8dee2aaSAndroid Build Coastguard Worker     void drawGlyphRunAsPath(
215*c8dee2aaSAndroid Build Coastguard Worker             const sktext::GlyphRun& glyphRun, SkPoint offset, const SkPaint& runPaint);
216*c8dee2aaSAndroid Build Coastguard Worker 
217*c8dee2aaSAndroid Build Coastguard Worker     void internalDrawImageRect(SkKeyedImage,
218*c8dee2aaSAndroid Build Coastguard Worker                                const SkRect* src,
219*c8dee2aaSAndroid Build Coastguard Worker                                const SkRect& dst,
220*c8dee2aaSAndroid Build Coastguard Worker                                const SkSamplingOptions&,
221*c8dee2aaSAndroid Build Coastguard Worker                                const SkPaint&,
222*c8dee2aaSAndroid Build Coastguard Worker                                const SkMatrix& canvasTransformationMatrix);
223*c8dee2aaSAndroid Build Coastguard Worker 
224*c8dee2aaSAndroid Build Coastguard Worker     void internalDrawPath(const SkClipStack&,
225*c8dee2aaSAndroid Build Coastguard Worker                           const SkMatrix&,
226*c8dee2aaSAndroid Build Coastguard Worker                           const SkPath&,
227*c8dee2aaSAndroid Build Coastguard Worker                           const SkPaint&,
228*c8dee2aaSAndroid Build Coastguard Worker                           bool pathIsMutable);
229*c8dee2aaSAndroid Build Coastguard Worker 
230*c8dee2aaSAndroid Build Coastguard Worker     void internalDrawPathWithFilter(const SkClipStack& clipStack,
231*c8dee2aaSAndroid Build Coastguard Worker                                     const SkMatrix& ctm,
232*c8dee2aaSAndroid Build Coastguard Worker                                     const SkPath& origPath,
233*c8dee2aaSAndroid Build Coastguard Worker                                     const SkPaint& paint);
234*c8dee2aaSAndroid Build Coastguard Worker 
235*c8dee2aaSAndroid Build Coastguard Worker     bool handleInversePath(const SkPath& origPath, const SkPaint& paint, bool pathIsMutable);
236*c8dee2aaSAndroid Build Coastguard Worker 
237*c8dee2aaSAndroid Build Coastguard Worker     void clearMaskOnGraphicState(SkDynamicMemoryWStream*);
238*c8dee2aaSAndroid Build Coastguard Worker     void setGraphicState(SkPDFIndirectReference gs, SkDynamicMemoryWStream*);
239*c8dee2aaSAndroid Build Coastguard Worker     void drawFormXObject(SkPDFIndirectReference xObject, SkDynamicMemoryWStream*, SkPath* shape);
240*c8dee2aaSAndroid Build Coastguard Worker 
hasEmptyClip()241*c8dee2aaSAndroid Build Coastguard Worker     bool hasEmptyClip() const { return this->cs().isEmpty(this->bounds()); }
242*c8dee2aaSAndroid Build Coastguard Worker 
243*c8dee2aaSAndroid Build Coastguard Worker     void reset();
244*c8dee2aaSAndroid Build Coastguard Worker };
245*c8dee2aaSAndroid Build Coastguard Worker 
246*c8dee2aaSAndroid Build Coastguard Worker #endif
247