• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
makeCongruentDevice()61     sk_sp<SkPDFDevice> makeCongruentDevice() {
62         return sk_make_sp<SkPDFDevice>(this->size(), fDocument);
63     }
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     void drawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
81                         const SkRect& dst, const SkPaint&, SkCanvas::SrcRectConstraint) override;
82     void drawSprite(const SkBitmap& bitmap, int x, int y,
83                     const SkPaint& paint) override;
84 
85     void drawImageRect(const SkImage*,
86                        const SkRect* src,
87                        const SkRect& dst,
88                        const SkPaint&,
89                        SkCanvas::SrcRectConstraint) override;
90     void drawGlyphRunList(const SkGlyphRunList& glyphRunList) override;
91     void drawVertices(const SkVertices*, const SkVertices::Bone bones[], int boneCount, SkBlendMode,
92                       const SkPaint&) override;
93     void drawDevice(SkBaseDevice*, int x, int y,
94                     const SkPaint&) override;
95 
96     // PDF specific methods.
97 
98     /** Create the resource dictionary for this device. Destructive. */
99     std::unique_ptr<SkPDFDict> makeResourceDict();
100 
101     /** Returns a SkStream with the page contents.
102      */
103     std::unique_ptr<SkStreamAsset> content();
104 
size()105     SkISize size() const { return this->imageInfo().dimensions(); }
bounds()106     SkIRect bounds() const { return this->imageInfo().bounds(); }
107 
108     void DrawGlyphRunAsPath(SkPDFDevice* dev, const SkGlyphRun& glyphRun, SkPoint offset);
109 
initialTransform()110     const SkMatrix& initialTransform() const { return fInitialTransform; }
111 
112 protected:
113     sk_sp<SkSurface> makeSurface(const SkImageInfo&, const SkSurfaceProps&) override;
114 
115     void drawAnnotation(const SkRect&, const char key[], SkData* value) override;
116 
117     void drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&,
118                      SkImage*, const SkMatrix&) override;
119     sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&) override;
120     sk_sp<SkSpecialImage> makeSpecial(const SkImage*) override;
121     sk_sp<SkSpecialImage> snapSpecial() override;
122     SkImageFilterCache* getImageFilterCache() override;
123 
124 private:
125     // TODO(vandebo): push most of SkPDFDevice's state into a core object in
126     // order to get the right access levels without using friend.
127     friend class ScopedContentEntry;
128 
129     SkMatrix fInitialTransform;
130 
131     SkTHashSet<SkPDFIndirectReference> fGraphicStateResources;
132     SkTHashSet<SkPDFIndirectReference> fXObjectResources;
133     SkTHashSet<SkPDFIndirectReference> fShaderResources;
134     SkTHashSet<SkPDFIndirectReference> fFontResources;
135     int fNodeId;
136 
137     SkDynamicMemoryWStream fContent;
138     SkDynamicMemoryWStream fContentBuffer;
139     bool fNeedsExtraSave = false;
140     SkPDFGraphicStackState fActiveStackState;
141     SkPDFDocument* fDocument;
142 
143     ////////////////////////////////////////////////////////////////////////////
144 
145     SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) override;
146 
147     // Set alpha to true if making a transparency group form x-objects.
148     SkPDFIndirectReference makeFormXObjectFromDevice(bool alpha = false);
149     SkPDFIndirectReference makeFormXObjectFromDevice(SkIRect bbox, bool alpha = false);
150 
151     void drawFormXObjectWithMask(SkPDFIndirectReference xObject,
152                                  SkPDFIndirectReference sMask,
153                                  SkBlendMode,
154                                  bool invertClip);
155 
156     // If the paint or clip is such that we shouldn't draw anything, this
157     // returns nullptr and does not create a content entry.
158     // setUpContentEntry and finishContentEntry can be used directly, but
159     // the preferred method is to use the ScopedContentEntry helper class.
160     SkDynamicMemoryWStream* setUpContentEntry(const SkClipStack* clipStack,
161                                               const SkMatrix& matrix,
162                                               const SkPaint& paint,
163                                               SkScalar,
164                                               SkPDFIndirectReference* dst);
165     void finishContentEntry(const SkClipStack*, SkBlendMode, SkPDFIndirectReference, SkPath*);
166     bool isContentEmpty();
167 
168     void internalDrawGlyphRun(const SkGlyphRun& glyphRun, SkPoint offset, const SkPaint& runPaint);
169     void drawGlyphRunAsPath(const SkGlyphRun& glyphRun, SkPoint offset, const SkPaint& runPaint);
170 
171     void internalDrawImageRect(SkKeyedImage,
172                                const SkRect* src,
173                                const SkRect& dst,
174                                const SkPaint&,
175                                const SkMatrix& canvasTransformationMatrix);
176 
177     void internalDrawPath(const SkClipStack&,
178                           const SkMatrix&,
179                           const SkPath&,
180                           const SkPaint&,
181                           bool pathIsMutable);
182 
183     void internalDrawPathWithFilter(const SkClipStack& clipStack,
184                                     const SkMatrix& ctm,
185                                     const SkPath& origPath,
186                                     const SkPaint& paint);
187 
188     bool handleInversePath(const SkPath& origPath, const SkPaint& paint, bool pathIsMutable);
189 
190     void clearMaskOnGraphicState(SkDynamicMemoryWStream*);
191     void setGraphicState(SkPDFIndirectReference gs, SkDynamicMemoryWStream*);
192     void drawFormXObject(SkPDFIndirectReference xObject, SkDynamicMemoryWStream*);
193 
hasEmptyClip()194     bool hasEmptyClip() const { return this->cs().isEmpty(this->bounds()); }
195 
196     void reset();
197 
198     typedef SkClipStackDevice INHERITED;
199 };
200 
201 #endif
202