1 | // Copyright 2013 The Flutter Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | #ifndef FLUTTER_DISPLAY_LIST_TESTING_DL_TEST_SNIPPETS_H_ |
6 | #define FLUTTER_DISPLAY_LIST_TESTING_DL_TEST_SNIPPETS_H_ |
7 | |
8 | #include "flutter/display_list/display_list.h" |
9 | #include "flutter/display_list/dl_builder.h" |
10 | |
11 | #include "third_party/skia/include/core/SkCanvas.h" |
12 | #include "third_party/skia/include/core/SkSurface.h" |
13 | #include "third_party/skia/include/effects/SkDashPathEffect.h" |
14 | #include "third_party/skia/include/effects/SkGradientShader.h" |
15 | #include "third_party/skia/include/effects/SkImageFilters.h" |
16 | |
17 | namespace flutter { |
18 | namespace testing { |
19 | |
20 | sk_sp<DisplayList> GetSampleDisplayList(); |
21 | sk_sp<DisplayList> GetSampleDisplayList(int ops); |
22 | sk_sp<DisplayList> GetSampleNestedDisplayList(); |
23 | |
24 | typedef const std::function<void(DlOpReceiver&)> DlInvoker; |
25 | |
26 | constexpr SkPoint kEndPoints[] = { |
27 | {.fX: 0, .fY: 0}, |
28 | {.fX: 100, .fY: 100}, |
29 | }; |
30 | const DlColor kColors[] = { |
31 | DlColor::kGreen(), |
32 | DlColor::kYellow(), |
33 | DlColor::kBlue(), |
34 | }; |
35 | constexpr float kStops[] = { |
36 | 0.0, |
37 | 0.5, |
38 | 1.0, |
39 | }; |
40 | static std::vector<uint32_t> color_vector(kColors, kColors + 3); |
41 | static std::vector<float> stops_vector(kStops, kStops + 3); |
42 | |
43 | // clang-format off |
44 | constexpr float kRotateColorMatrix[20] = { |
45 | 0, 1, 0, 0, 0, |
46 | 0, 0, 1, 0, 0, |
47 | 1, 0, 0, 0, 0, |
48 | 0, 0, 0, 1, 0, |
49 | }; |
50 | constexpr float kInvertColorMatrix[20] = { |
51 | -1.0, 0, 0, 1.0, 0, |
52 | 0, -1.0, 0, 1.0, 0, |
53 | 0, 0, -1.0, 1.0, 0, |
54 | 1.0, 1.0, 1.0, 1.0, 0, |
55 | }; |
56 | // clang-format on |
57 | |
58 | const SkScalar kTestDashes1[] = {4.0, 2.0}; |
59 | const SkScalar kTestDashes2[] = {1.0, 1.5}; |
60 | |
61 | constexpr SkPoint TestPoints[] = { |
62 | {.fX: 10, .fY: 10}, |
63 | {.fX: 20, .fY: 20}, |
64 | {.fX: 10, .fY: 20}, |
65 | {.fX: 20, .fY: 10}, |
66 | }; |
67 | #define TestPointCount sizeof(TestPoints) / (sizeof(TestPoints[0])) |
68 | |
69 | static DlImageSampling kNearestSampling = DlImageSampling::kNearestNeighbor; |
70 | static DlImageSampling kLinearSampling = DlImageSampling::kLinear; |
71 | |
72 | static sk_sp<DlImage> MakeTestImage(int w, int h, int checker_size) { |
73 | sk_sp<SkSurface> surface = |
74 | SkSurfaces::Raster(imageInfo: SkImageInfo::MakeN32Premul(width: w, height: h)); |
75 | SkCanvas* canvas = surface->getCanvas(); |
76 | SkPaint p0, p1; |
77 | p0.setStyle(SkPaint::kFill_Style); |
78 | p0.setColor(SK_ColorGREEN); |
79 | p1.setStyle(SkPaint::kFill_Style); |
80 | p1.setColor(SK_ColorBLUE); |
81 | p1.setAlpha(128); |
82 | for (int y = 0; y < w; y += checker_size) { |
83 | for (int x = 0; x < h; x += checker_size) { |
84 | SkPaint& cellp = ((x + y) & 1) == 0 ? p0 : p1; |
85 | canvas->drawRect(rect: SkRect::MakeXYWH(x, y, w: checker_size, h: checker_size), |
86 | paint: cellp); |
87 | } |
88 | } |
89 | return DlImage::Make(image: surface->makeImageSnapshot()); |
90 | } |
91 | |
92 | static auto TestImage1 = MakeTestImage(w: 40, h: 40, checker_size: 5); |
93 | static auto TestImage2 = MakeTestImage(w: 50, h: 50, checker_size: 5); |
94 | static auto TestSkImage = MakeTestImage(w: 30, h: 30, checker_size: 5)->skia_image(); |
95 | |
96 | static const DlImageColorSource kTestSource1(TestImage1, |
97 | DlTileMode::kClamp, |
98 | DlTileMode::kMirror, |
99 | kLinearSampling); |
100 | static const std::shared_ptr<DlColorSource> kTestSource2 = |
101 | DlColorSource::MakeLinear(start_point: kEndPoints[0], |
102 | end_point: kEndPoints[1], |
103 | stop_count: 3, |
104 | colors: kColors, |
105 | stops: kStops, |
106 | tile_mode: DlTileMode::kMirror); |
107 | static const std::shared_ptr<DlColorSource> kTestSource3 = |
108 | DlColorSource::MakeRadial(center: kEndPoints[0], |
109 | radius: 10.0, |
110 | stop_count: 3, |
111 | colors: kColors, |
112 | stops: kStops, |
113 | tile_mode: DlTileMode::kMirror); |
114 | static const std::shared_ptr<DlColorSource> kTestSource4 = |
115 | DlColorSource::MakeConical(start_center: kEndPoints[0], |
116 | start_radius: 10.0, |
117 | end_center: kEndPoints[1], |
118 | end_radius: 200.0, |
119 | stop_count: 3, |
120 | colors: kColors, |
121 | stops: kStops, |
122 | tile_mode: DlTileMode::kDecal); |
123 | static const std::shared_ptr<DlColorSource> kTestSource5 = |
124 | DlColorSource::MakeSweep(center: kEndPoints[0], |
125 | start: 0.0, |
126 | end: 360.0, |
127 | stop_count: 3, |
128 | colors: kColors, |
129 | stops: kStops, |
130 | tile_mode: DlTileMode::kDecal); |
131 | static const DlBlendColorFilter kTestBlendColorFilter1(DlColor::kRed(), |
132 | DlBlendMode::kDstATop); |
133 | static const DlBlendColorFilter kTestBlendColorFilter2(DlColor::kBlue(), |
134 | DlBlendMode::kDstATop); |
135 | static const DlBlendColorFilter kTestBlendColorFilter3(DlColor::kRed(), |
136 | DlBlendMode::kDstIn); |
137 | static const DlMatrixColorFilter kTestMatrixColorFilter1(kRotateColorMatrix); |
138 | static const DlMatrixColorFilter kTestMatrixColorFilter2(kInvertColorMatrix); |
139 | static const DlBlurImageFilter kTestBlurImageFilter1(5.0, |
140 | 5.0, |
141 | DlTileMode::kClamp); |
142 | static const DlBlurImageFilter kTestBlurImageFilter2(6.0, |
143 | 5.0, |
144 | DlTileMode::kClamp); |
145 | static const DlBlurImageFilter kTestBlurImageFilter3(5.0, |
146 | 6.0, |
147 | DlTileMode::kClamp); |
148 | static const DlBlurImageFilter kTestBlurImageFilter4(5.0, |
149 | 5.0, |
150 | DlTileMode::kDecal); |
151 | static const DlDilateImageFilter kTestDilateImageFilter1(5.0, 5.0); |
152 | static const DlDilateImageFilter kTestDilateImageFilter2(6.0, 5.0); |
153 | static const DlDilateImageFilter kTestDilateImageFilter3(5.0, 6.0); |
154 | static const DlErodeImageFilter kTestErodeImageFilter1(4.0, 4.0); |
155 | static const DlErodeImageFilter kTestErodeImageFilter2(4.0, 3.0); |
156 | static const DlErodeImageFilter kTestErodeImageFilter3(3.0, 4.0); |
157 | static const DlMatrixImageFilter kTestMatrixImageFilter1( |
158 | SkMatrix::RotateDeg(deg: 45), |
159 | kNearestSampling); |
160 | static const DlMatrixImageFilter kTestMatrixImageFilter2( |
161 | SkMatrix::RotateDeg(deg: 85), |
162 | kNearestSampling); |
163 | static const DlMatrixImageFilter kTestMatrixImageFilter3( |
164 | SkMatrix::RotateDeg(deg: 45), |
165 | kLinearSampling); |
166 | static const DlComposeImageFilter kTestComposeImageFilter1( |
167 | kTestBlurImageFilter1, |
168 | kTestMatrixImageFilter1); |
169 | static const DlComposeImageFilter kTestComposeImageFilter2( |
170 | kTestBlurImageFilter2, |
171 | kTestMatrixImageFilter1); |
172 | static const DlComposeImageFilter kTestComposeImageFilter3( |
173 | kTestBlurImageFilter1, |
174 | kTestMatrixImageFilter2); |
175 | static const DlColorFilterImageFilter kTestCFImageFilter1( |
176 | kTestBlendColorFilter1); |
177 | static const DlColorFilterImageFilter kTestCFImageFilter2( |
178 | kTestBlendColorFilter2); |
179 | static const std::shared_ptr<DlPathEffect> kTestPathEffect1 = |
180 | DlDashPathEffect::Make(intervals: kTestDashes1, count: 2, phase: 0.0f); |
181 | static const std::shared_ptr<DlPathEffect> kTestPathEffect2 = |
182 | DlDashPathEffect::Make(intervals: kTestDashes2, count: 2, phase: 0.0f); |
183 | static const DlBlurMaskFilter kTestMaskFilter1(DlBlurStyle::kNormal, 3.0); |
184 | static const DlBlurMaskFilter kTestMaskFilter2(DlBlurStyle::kNormal, 5.0); |
185 | static const DlBlurMaskFilter kTestMaskFilter3(DlBlurStyle::kSolid, 3.0); |
186 | static const DlBlurMaskFilter kTestMaskFilter4(DlBlurStyle::kInner, 3.0); |
187 | static const DlBlurMaskFilter kTestMaskFilter5(DlBlurStyle::kOuter, 3.0); |
188 | constexpr SkRect kTestBounds = SkRect::MakeLTRB(l: 10, t: 10, r: 50, b: 60); |
189 | static const SkRRect kTestRRect = SkRRect::MakeRectXY(rect: kTestBounds, xRad: 5, yRad: 5); |
190 | static const SkRRect kTestRRectRect = SkRRect::MakeRect(r: kTestBounds); |
191 | static const SkRRect kTestInnerRRect = |
192 | SkRRect::MakeRectXY(rect: kTestBounds.makeInset(dx: 5, dy: 5), xRad: 2, yRad: 2); |
193 | static const SkPath kTestPathRect = SkPath::Rect(kTestBounds); |
194 | static const SkPath kTestPathOval = SkPath::Oval(kTestBounds); |
195 | static const SkPath kTestPath1 = |
196 | SkPath::Polygon(list: {{.fX: 0, .fY: 0}, {.fX: 10, .fY: 10}, {.fX: 10, .fY: 0}, {.fX: 0, .fY: 10}}, isClosed: true); |
197 | static const SkPath kTestPath2 = |
198 | SkPath::Polygon(list: {{.fX: 0, .fY: 0}, {.fX: 10, .fY: 10}, {.fX: 0, .fY: 10}, {.fX: 10, .fY: 0}}, isClosed: true); |
199 | static const SkPath kTestPath3 = |
200 | SkPath::Polygon(list: {{.fX: 0, .fY: 0}, {.fX: 10, .fY: 10}, {.fX: 10, .fY: 0}, {.fX: 0, .fY: 10}}, isClosed: false); |
201 | static const SkMatrix kTestMatrix1 = SkMatrix::Scale(sx: 2, sy: 2); |
202 | static const SkMatrix kTestMatrix2 = SkMatrix::RotateDeg(deg: 45); |
203 | |
204 | static std::shared_ptr<const DlVertices> TestVertices1 = |
205 | DlVertices::Make(mode: DlVertexMode::kTriangles, // |
206 | vertex_count: 3, |
207 | vertices: TestPoints, |
208 | texture_coordinates: nullptr, |
209 | colors: kColors); |
210 | static std::shared_ptr<const DlVertices> TestVertices2 = |
211 | DlVertices::Make(mode: DlVertexMode::kTriangleFan, // |
212 | vertex_count: 3, |
213 | vertices: TestPoints, |
214 | texture_coordinates: nullptr, |
215 | colors: kColors); |
216 | |
217 | static sk_sp<DisplayList> MakeTestDisplayList(int w, int h, SkColor color) { |
218 | DisplayListBuilder builder; |
219 | builder.DrawRect(rect: SkRect::MakeWH(w, h), paint: DlPaint(color)); |
220 | return builder.Build(); |
221 | } |
222 | static sk_sp<DisplayList> TestDisplayList1 = |
223 | MakeTestDisplayList(w: 20, h: 20, color: SK_ColorGREEN); |
224 | static sk_sp<DisplayList> TestDisplayList2 = |
225 | MakeTestDisplayList(w: 25, h: 25, color: SK_ColorBLUE); |
226 | |
227 | static sk_sp<SkTextBlob> MakeTextBlob(std::string string) { |
228 | return SkTextBlob::MakeFromText(string.c_str(), string.size(), SkFont(), |
229 | SkTextEncoding::kUTF8); |
230 | } |
231 | static sk_sp<SkTextBlob> TestBlob1 = MakeTextBlob(string: "TestBlob1" ); |
232 | static sk_sp<SkTextBlob> TestBlob2 = MakeTextBlob(string: "TestBlob2" ); |
233 | |
234 | struct DisplayListInvocation { |
235 | unsigned int op_count_; |
236 | size_t byte_count_; |
237 | |
238 | // in some cases, running the sequence through an SkCanvas will result |
239 | // in fewer ops/bytes. Attribute invocations are recorded in an SkPaint |
240 | // and not forwarded on, and SkCanvas culls unused save/restore/transforms. |
241 | int sk_op_count_; |
242 | size_t sk_byte_count_; |
243 | |
244 | DlInvoker invoker; |
245 | bool supports_group_opacity_ = false; |
246 | |
247 | bool is_empty() { return byte_count_ == 0; } |
248 | |
249 | bool supports_group_opacity() { return supports_group_opacity_; } |
250 | |
251 | unsigned int op_count() { return op_count_; } |
252 | // byte count for the individual ops, no DisplayList overhead |
253 | size_t raw_byte_count() { return byte_count_; } |
254 | // byte count for the ops with DisplayList overhead, comparable |
255 | // to |DisplayList.byte_count(). |
256 | size_t byte_count() { return sizeof(DisplayList) + byte_count_; } |
257 | |
258 | void Invoke(DlOpReceiver& builder) { invoker(builder); } |
259 | |
260 | // sk_sp<DisplayList> Build() { |
261 | // DisplayListBuilder builder; |
262 | // invoker(builder.asReceiver()); |
263 | // return builder.Build(); |
264 | // } |
265 | }; |
266 | |
267 | struct DisplayListInvocationGroup { |
268 | std::string op_name; |
269 | std::vector<DisplayListInvocation> variants; |
270 | }; |
271 | |
272 | std::vector<DisplayListInvocationGroup> CreateAllRenderingOps(); |
273 | std::vector<DisplayListInvocationGroup> CreateAllGroups(); |
274 | |
275 | } // namespace testing |
276 | } // namespace flutter |
277 | |
278 | #endif // FLUTTER_DISPLAY_LIST_TESTING_DL_TEST_SNIPPETS_H_ |
279 | |