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
19class SkBaseDevice;
20class SkImageFilter;
21class SkMatrix;
22class SkReadBuffer;
23struct SkRect;
24class SkWriteBuffer;
25
26#if GRAPHITE_TEST_UTILS
27namespace skgpu::graphite {
28 class TextureProxy;
29}
30#endif
31
32class SkAutoCanvasMatrixPaint : SkNoncopyable {
33public:
34 SkAutoCanvasMatrixPaint(SkCanvas*, const SkMatrix*, const SkPaint*, const SkRect& bounds);
35 ~SkAutoCanvasMatrixPaint();
36
37private:
38 SkCanvas* fCanvas;
39 int fSaveCount;
40};
41
42class SkCanvasPriv {
43public:
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 */
110constexpr 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 */
127class AutoLayerForImageFilter {
128public:
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
147private:
148 SkPaint fPaint;
149 SkCanvas* fCanvas;
150 bool fTempLayerForImageFilter;
151
152 SkDEBUGCODE(int fSaveCount;)
153};
154
155#endif
156

source code of flutter_engine/third_party/skia/src/core/SkCanvasPriv.h