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 SkBaseDevice; |
20 | class SkImageFilter; |
21 | class SkMatrix; |
22 | class SkReadBuffer; |
23 | struct SkRect; |
24 | class SkWriteBuffer; |
25 | |
26 | #if 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 | |
53 | static int SaveBehind(SkCanvas* canvas, const SkRect* subset) { |
54 | return canvas->only_axis_aligned_saveBehind(subset); |
55 | } |
56 | static void DrawBehind(SkCanvas* canvas, const SkPaint& paint) { |
57 | canvas->drawClippedToSaveBehind(paint); |
58 | } |
59 | |
60 | // Exposed for testing on non-Android framework builds |
61 | static void ResetClip(SkCanvas* canvas) { |
62 | canvas->internal_private_resetClip(); |
63 | } |
64 | |
65 | static SkBaseDevice* TopDevice(const SkCanvas* canvas) { |
66 | return canvas->topDevice(); |
67 | } |
68 | |
69 | #if GRAPHITE_TEST_UTILS |
70 | static skgpu::graphite::TextureProxy* TopDeviceGraphiteTargetProxy(SkCanvas*); |
71 | #endif |
72 | |
73 | // The experimental_DrawEdgeAAImageSet API accepts separate dstClips and preViewMatrices arrays, |
74 | // where entries refer into them, but no explicit size is provided. Given a set of entries, |
75 | // computes the minimum length for these arrays that would provide index access errors. |
76 | static void GetDstClipAndMatrixCounts(const SkCanvas::ImageSetEntry set[], int count, |
77 | int* totalDstClipCount, int* totalMatrixCount); |
78 | |
79 | static SkCanvas::SaveLayerRec ScaledBackdropLayer(const SkRect* bounds, |
80 | const SkPaint* paint, |
81 | const SkImageFilter* backdrop, |
82 | SkScalar backdropScale, |
83 | SkCanvas::SaveLayerFlags saveLayerFlags) { |
84 | return SkCanvas::SaveLayerRec(bounds, paint, backdrop, backdropScale, saveLayerFlags); |
85 | } |
86 | |
87 | static SkScalar GetBackdropScaleFactor(const SkCanvas::SaveLayerRec& rec) { |
88 | return rec.fExperimentalBackdropScale; |
89 | } |
90 | |
91 | static void SetBackdropScaleFactor(SkCanvas::SaveLayerRec* rec, SkScalar scale) { |
92 | rec->fExperimentalBackdropScale = scale; |
93 | } |
94 | |
95 | // Attempts to convert an image filter to its equivalent color filter, which if possible, |
96 | // modifies the paint to compose the image filter's color filter into the paint's color filter |
97 | // slot. |
98 | // Returns true if the paint has been modified. |
99 | // Requires the paint to have an image filter and the copy-on-write be initialized. |
100 | static bool ImageToColorFilter(SkPaint*); |
101 | }; |
102 | |
103 | /** |
104 | * This constant is trying to balance the speed of ref'ing a subpicture into a parent picture, |
105 | * against the playback cost of recursing into the subpicture to get at its actual ops. |
106 | * |
107 | * For now we pick a conservatively small value, though measurement (and other heuristics like |
108 | * the type of ops contained) may justify changing this value. |
109 | */ |
110 | constexpr int kMaxPictureOpsToUnrollInsteadOfRef = 1; |
111 | |
112 | /** |
113 | * We implement ImageFilters for a given draw by creating a layer, then applying the |
114 | * imagefilter to the pixels of that layer (its backing surface/image), and then |
115 | * we call restore() to xfer that layer to the main canvas. |
116 | * |
117 | * 1. SaveLayer (with a paint containing the current imagefilter and xfermode) |
118 | * 2. Generate the src pixels: |
119 | * Remove the imagefilter and the xfermode from the paint that we (AutoDrawLooper) |
120 | * return (fPaint). We then draw the primitive (using srcover) into a cleared |
121 | * buffer/surface. |
122 | * 3. Restore the layer created in #1 |
123 | * The imagefilter is passed the buffer/surface from the layer (now filled with the |
124 | * src pixels of the primitive). It returns a new "filtered" buffer, which we |
125 | * draw onto the previous layer using the xfermode from the original paint. |
126 | */ |
127 | class AutoLayerForImageFilter { |
128 | public: |
129 | // "rawBounds" is the original bounds of the primitive about to be drawn, unmodified by the |
130 | // paint. It's used to determine the size of the offscreen layer for filters. |
131 | // If null, the clip will be used instead. |
132 | // |
133 | // Draw functions should use layer->paint() instead of the passed-in paint. |
134 | AutoLayerForImageFilter(SkCanvas* canvas, |
135 | const SkPaint& paint, |
136 | const SkRect* rawBounds = nullptr); |
137 | |
138 | AutoLayerForImageFilter(const AutoLayerForImageFilter&) = delete; |
139 | AutoLayerForImageFilter& operator=(const AutoLayerForImageFilter&) = delete; |
140 | AutoLayerForImageFilter(AutoLayerForImageFilter&&) = default; |
141 | AutoLayerForImageFilter& operator=(AutoLayerForImageFilter&&) = default; |
142 | |
143 | ~AutoLayerForImageFilter(); |
144 | |
145 | const SkPaint& paint() const { return fPaint; } |
146 | |
147 | private: |
148 | SkPaint fPaint; |
149 | SkCanvas* fCanvas; |
150 | bool fTempLayerForImageFilter; |
151 | |
152 | SkDEBUGCODE(int fSaveCount;) |
153 | }; |
154 | |
155 | #endif |
156 | |