Coverage Report

Created: 2021-08-22 09:07

/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