• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 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 SkCanvasPriv_DEFINED
9 #define SkCanvasPriv_DEFINED
10 
11 #include "include/core/SkCanvas.h"
12 #include "include/core/SkPaint.h"
13 #include "include/core/SkScalar.h"
14 #include "include/private/base/SkDebug.h"
15 #include "include/private/base/SkNoncopyable.h"
16 
17 #include <cstddef>
18 
19 class SkDevice;
20 class SkImageFilter;
21 class SkMatrix;
22 class SkReadBuffer;
23 struct SkRect;
24 class SkWriteBuffer;
25 
26 #if defined(GRAPHITE_TEST_UTILS)
27 namespace skgpu::graphite {
28     class TextureProxy;
29 }
30 #endif
31 
32 class SkAutoCanvasMatrixPaint : SkNoncopyable {
33 public:
34     SkAutoCanvasMatrixPaint(SkCanvas*, const SkMatrix*, const SkPaint*, const SkRect& bounds);
35     ~SkAutoCanvasMatrixPaint();
36 
37 private:
38     SkCanvas*   fCanvas;
39     int         fSaveCount;
40 };
41 
42 class SkCanvasPriv {
43 public:
44     // The lattice has pointers directly into the readbuffer
45     static bool ReadLattice(SkReadBuffer&, SkCanvas::Lattice*);
46 
47     static void WriteLattice(SkWriteBuffer&, const SkCanvas::Lattice&);
48 
49     // return the byte-size of the lattice, even if the buffer is null
50     // storage must be 4-byte aligned
51     static size_t WriteLattice(void* storage, const SkCanvas::Lattice&);
52 
SaveBehind(SkCanvas * canvas,const SkRect * subset)53     static int SaveBehind(SkCanvas* canvas, const SkRect* subset) {
54         return canvas->only_axis_aligned_saveBehind(subset);
55     }
DrawBehind(SkCanvas * canvas,const SkPaint & paint)56     static void DrawBehind(SkCanvas* canvas, const SkPaint& paint) {
57         canvas->drawClippedToSaveBehind(paint);
58     }
59 
60     // Exposed for testing on non-Android framework builds
ResetClip(SkCanvas * canvas)61     static void ResetClip(SkCanvas* canvas) {
62         canvas->internal_private_resetClip();
63     }
64 
TopDevice(const SkCanvas * canvas)65     static SkDevice* TopDevice(const SkCanvas* canvas) {
66         return canvas->topDevice();
67     }
68 
69     // The experimental_DrawEdgeAAImageSet API accepts separate dstClips and preViewMatrices arrays,
70     // where entries refer into them, but no explicit size is provided. Given a set of entries,
71     // computes the minimum length for these arrays that would provide index access errors.
72     static void GetDstClipAndMatrixCounts(const SkCanvas::ImageSetEntry set[], int count,
73                                           int* totalDstClipCount, int* totalMatrixCount);
74 
75     static SkCanvas::SaveLayerRec ScaledBackdropLayer(const SkRect* bounds,
76                                                       const SkPaint* paint,
77                                                       const SkImageFilter* backdrop,
78                                                       SkScalar backdropScale,
79                                                       SkCanvas::SaveLayerFlags saveLayerFlags,
80                                                       SkCanvas::FilterSpan filters = {}) {
81         return SkCanvas::SaveLayerRec(
82                 bounds, paint, backdrop, nullptr, backdropScale, saveLayerFlags, filters);
83     }
84 
GetBackdropScaleFactor(const SkCanvas::SaveLayerRec & rec)85     static SkScalar GetBackdropScaleFactor(const SkCanvas::SaveLayerRec& rec) {
86         return rec.fExperimentalBackdropScale;
87     }
88 
SetBackdropScaleFactor(SkCanvas::SaveLayerRec * rec,SkScalar scale)89     static void SetBackdropScaleFactor(SkCanvas::SaveLayerRec* rec, SkScalar scale) {
90         rec->fExperimentalBackdropScale = scale;
91     }
92 
93     // Attempts to convert an image filter to its equivalent color filter, which if possible,
94     // modifies the paint to compose the image filter's color filter into the paint's color filter
95     // slot.
96     // Returns true if the paint has been modified.
97     // Requires the paint to have an image filter and the copy-on-write be initialized.
98     static bool ImageToColorFilter(SkPaint*);
99 };
100 
101 /**
102  *  This constant is trying to balance the speed of ref'ing a subpicture into a parent picture,
103  *  against the playback cost of recursing into the subpicture to get at its actual ops.
104  *
105  *  For now we pick a conservatively small value, though measurement (and other heuristics like
106  *  the type of ops contained) may justify changing this value.
107  */
108 constexpr int kMaxPictureOpsToUnrollInsteadOfRef = 1;
109 
110 /**
111  *  We implement ImageFilters and MaskFilters for a given draw by creating a layer, then applying
112  *  the filter to the pixels of that layer (its backing surface/image), and then we call restore()
113  *  to blend that layer to the main canvas.
114  *
115  *  If the paint has neither an image filter nor a mask filter, there will be no layer and paint()
116  *  returns the original without modification.
117  *
118  * NOTE: This works by assuming all sources of color and shading are represented by the SkPaint.
119  * Operations like drawImageRect must convert to an equivalent drawRect call if there's a mask
120  * filter, or otherwise ensure there are no mask filters (e.g. drawAtlas).
121  */
122 class AutoLayerForImageFilter {
123 public:
124     // `rawBounds` is the original bounds of the primitive about to be drawn, unmodified by the
125     // paint. It's used to determine the size of the offscreen layer for filters.
126     // If null, the clip will be used instead.
127     //
128     // If `skipMaskFilterLayer` is true, any SkMaskFilter on `paint` will be left as-is and is
129     // assumed to be handled by the SkDevice that handles the draw.
130     //
131     // Draw functions should use layer->paint() instead of the passed-in paint.
132     AutoLayerForImageFilter(SkCanvas* canvas,
133                             const SkPaint& paint,
134                             const SkRect* rawBounds,
135                             bool skipMaskFilterLayer);
136 
137     AutoLayerForImageFilter(const AutoLayerForImageFilter&) = delete;
138     AutoLayerForImageFilter& operator=(const AutoLayerForImageFilter&) = delete;
139     AutoLayerForImageFilter(AutoLayerForImageFilter&&);
140     AutoLayerForImageFilter& operator=(AutoLayerForImageFilter&&);
141 
142     ~AutoLayerForImageFilter();
143 
paint()144     const SkPaint& paint() const { return fPaint; }
145 
146     // This is public so that a canvas can attempt to specially handle mask filters, specifically
147     // for blurs, and then if the attempt fails fall back on a regular draw with the same autolayer.
148     void addMaskFilterLayer(const SkRect* drawBounds);
149 
150 private:
151     void addImageFilterLayer(const SkRect* drawBounds);
152 
153     void addLayer(const SkPaint& restorePaint, const SkRect* drawBounds, bool coverageOnly);
154 
155     SkPaint         fPaint;
156     SkCanvas*       fCanvas;
157     int             fTempLayersForFilters;
158 
159     SkDEBUGCODE(int fSaveCount;)
160 };
161 
162 #endif
163