Flutter Engine
 
Loading...
Searching...
No Matches
aiks_dl_basic_unittests.cc
Go to the documentation of this file.
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
13
24
25namespace impeller {
26namespace testing {
27
28using namespace flutter;
29
30TEST_P(AiksTest, CanRenderColoredRect) {
31 DisplayListBuilder builder;
32 DlPaint paint;
33 paint.setColor(DlColor::kBlue());
34 builder.DrawPath(DlPath::MakeRectXYWH(100.0f, 100.0f, 100.0f, 100.0f), paint);
35 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
36}
37
38namespace {
39using DrawRectProc =
40 std::function<void(DisplayListBuilder&, const DlRect&, const DlPaint&)>;
41
42sk_sp<DisplayList> MakeWideStrokedRects(Point scale,
43 const DrawRectProc& draw_rect) {
44 DisplayListBuilder builder;
45 builder.Scale(scale.x, scale.y);
46 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
47
48 DlPaint paint;
49 paint.setColor(DlColor::kBlue().withAlphaF(0.5));
50 paint.setDrawStyle(DlDrawStyle::kStroke);
51 paint.setStrokeWidth(30.0f);
52
53 // Each of these 3 sets of rects includes (with different join types):
54 // - One rectangle with a gap in the middle
55 // - One rectangle with no gap because it is too narrow
56 // - One rectangle with no gap because it is too short
57 paint.setStrokeJoin(DlStrokeJoin::kBevel);
58 draw_rect(builder, DlRect::MakeXYWH(100.0f, 100.0f, 100.0f, 100.0f), paint);
59 draw_rect(builder, DlRect::MakeXYWH(250.0f, 100.0f, 10.0f, 100.0f), paint);
60 draw_rect(builder, DlRect::MakeXYWH(100.0f, 250.0f, 100.0f, 10.0f), paint);
61
62 paint.setStrokeJoin(DlStrokeJoin::kRound);
63 draw_rect(builder, DlRect::MakeXYWH(350.0f, 100.0f, 100.0f, 100.0f), paint);
64 draw_rect(builder, DlRect::MakeXYWH(500.0f, 100.0f, 10.0f, 100.0f), paint);
65 draw_rect(builder, DlRect::MakeXYWH(350.0f, 250.0f, 100.0f, 10.0f), paint);
66
67 paint.setStrokeJoin(DlStrokeJoin::kMiter);
68 draw_rect(builder, DlRect::MakeXYWH(600.0f, 100.0f, 100.0f, 100.0f), paint);
69 draw_rect(builder, DlRect::MakeXYWH(750.0f, 100.0f, 10.0f, 100.0f), paint);
70 draw_rect(builder, DlRect::MakeXYWH(600.0f, 250.0f, 100.0f, 10.0f), paint);
71
72 // And now draw 3 rectangles with a stroke width so large that that it
73 // overlaps in the middle in both directions (horizontal/vertical).
74 paint.setStrokeWidth(110.0f);
75
76 paint.setStrokeJoin(DlStrokeJoin::kBevel);
77 draw_rect(builder, DlRect::MakeXYWH(100.0f, 400.0f, 100.0f, 100.0f), paint);
78
79 paint.setStrokeJoin(DlStrokeJoin::kRound);
80 draw_rect(builder, DlRect::MakeXYWH(350.0f, 400.0f, 100.0f, 100.0f), paint);
81
82 paint.setStrokeJoin(DlStrokeJoin::kMiter);
83 draw_rect(builder, DlRect::MakeXYWH(600.0f, 400.0f, 100.0f, 100.0f), paint);
84
85 return builder.Build();
86}
87} // namespace
88
89TEST_P(AiksTest, CanRenderWideStrokedRectWithoutOverlap) {
90 ASSERT_TRUE(OpenPlaygroundHere(MakeWideStrokedRects(
91 GetContentScale(), [](DisplayListBuilder& builder, const DlRect& rect,
92 const DlPaint& paint) {
93 // Draw the rect directly
94 builder.DrawRect(rect, paint);
95 })));
96}
97
98TEST_P(AiksTest, CanRenderWideStrokedRectPathWithoutOverlap) {
99 ASSERT_TRUE(OpenPlaygroundHere(MakeWideStrokedRects(
100 GetContentScale(), [](DisplayListBuilder& builder, const DlRect& rect,
101 const DlPaint& paint) {
102 // Draw the rect as a Path
103 builder.DrawPath(DlPath::MakeRect(rect), paint);
104 })));
105}
106
107TEST_P(AiksTest, CanRenderImage) {
108 DisplayListBuilder builder;
109 DlPaint paint;
110 paint.setColor(DlColor::kRed());
111 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
112 builder.DrawImage(image, DlPoint(100.0, 100.0),
113 DlImageSampling::kNearestNeighbor, &paint);
114 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
115}
116
117TEST_P(AiksTest, CanRenderInvertedImageWithColorFilter) {
118 DisplayListBuilder builder;
119 DlPaint paint;
120 paint.setColor(DlColor::kRed());
121 paint.setColorFilter(
122 DlColorFilter::MakeBlend(DlColor::kYellow(), DlBlendMode::kSrcOver));
123 paint.setInvertColors(true);
124 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
125
126 builder.DrawImage(image, DlPoint(100.0, 100.0),
127 DlImageSampling::kNearestNeighbor, &paint);
128 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
129}
130
131TEST_P(AiksTest, CanRenderColorFilterWithInvertColors) {
132 DisplayListBuilder builder;
133 DlPaint paint;
134 paint.setColor(DlColor::kRed());
135 paint.setColorFilter(
136 DlColorFilter::MakeBlend(DlColor::kYellow(), DlBlendMode::kSrcOver));
137 paint.setInvertColors(true);
138
139 builder.DrawRect(DlRect::MakeLTRB(0, 0, 100, 100), paint);
140 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
141}
142
143TEST_P(AiksTest, CanRenderColorFilterWithInvertColorsDrawPaint) {
144 DisplayListBuilder builder;
145 DlPaint paint;
146 paint.setColor(DlColor::kRed());
147 paint.setColorFilter(
148 DlColorFilter::MakeBlend(DlColor::kYellow(), DlBlendMode::kSrcOver));
149 paint.setInvertColors(true);
150
151 builder.DrawPaint(paint);
152 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
153}
154
155namespace {
156bool GenerateMipmap(const std::shared_ptr<Context>& context,
157 std::shared_ptr<Texture> texture,
158 std::string_view label) {
159 auto buffer = context->CreateCommandBuffer();
160 if (!buffer) {
161 return false;
162 }
163 auto pass = buffer->CreateBlitPass();
164 if (!pass) {
165 return false;
166 }
167 pass->GenerateMipmap(std::move(texture), label);
168
169 pass->EncodeCommands();
170 return context->GetCommandQueue()->Submit({buffer}).ok();
171}
172
173void CanRenderTiledTexture(AiksTest* aiks_test,
174 DlTileMode tile_mode,
175 Matrix local_matrix = {}) {
176 auto context = aiks_test->GetContext();
177 ASSERT_TRUE(context);
178 auto texture = aiks_test->CreateTextureForFixture("table_mountain_nx.png",
179 /*enable_mipmapping=*/true);
180 GenerateMipmap(context, texture, "table_mountain_nx");
182 auto color_source = DlColorSource::MakeImage(
183 image, tile_mode, tile_mode, DlImageSampling::kNearestNeighbor,
184 &local_matrix);
185
186 DisplayListBuilder builder;
187 DlPaint paint;
188 paint.setColor(DlColor::kWhite());
189 paint.setColorSource(color_source);
190
191 builder.Scale(aiks_test->GetContentScale().x, aiks_test->GetContentScale().y);
192 builder.Translate(100.0f, 100.0f);
193 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
194
195 // Should not change the image.
196 constexpr auto stroke_width = 64;
197 paint.setDrawStyle(DlDrawStyle::kStroke);
198 paint.setStrokeWidth(stroke_width);
199 if (tile_mode == DlTileMode::kDecal) {
200 builder.DrawRect(DlRect::MakeXYWH(stroke_width, stroke_width, 600, 600),
201 paint);
202 } else {
203 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
204 }
205
206 {
207 // Should not change the image.
208 DlPathBuilder path_builder;
209 path_builder.AddCircle(DlPoint(150, 150), 150);
210 path_builder.AddRoundRect(
211 RoundRect::MakeRectXY(DlRect::MakeLTRB(300, 300, 600, 600), 10, 10));
212 DlPath path = path_builder.TakePath();
213
214 // Make sure path cannot be simplified...
215 EXPECT_FALSE(path.IsRect(nullptr));
216 EXPECT_FALSE(path.IsOval(nullptr));
217 EXPECT_FALSE(path.IsRoundRect(nullptr));
218
219 // Make sure path will not trigger the optimal convex code
220 EXPECT_FALSE(path.IsConvex());
221
222 paint.setDrawStyle(DlDrawStyle::kFill);
223 builder.DrawPath(path, paint);
224 }
225
226 {
227 // Should not change the image. Tests the Convex short-cut code.
228
229 // To avoid simplification, construct an explicit circle using conics.
230 constexpr float kConicWeight = 0.707106781f; // sqrt(2)/2
231 const DlPath path = DlPathBuilder()
232 .MoveTo({150, 300})
233 .ConicCurveTo({300, 300}, {300, 450}, kConicWeight)
234 .ConicCurveTo({300, 600}, {150, 600}, kConicWeight)
235 .ConicCurveTo({0, 600}, {0, 450}, kConicWeight)
236 .ConicCurveTo({0, 300}, {150, 300}, kConicWeight)
237 .Close()
238 .TakePath();
239
240 // Make sure path cannot be simplified...
241 EXPECT_FALSE(path.IsRect(nullptr));
242 EXPECT_FALSE(path.IsOval(nullptr));
243 EXPECT_FALSE(path.IsRoundRect(nullptr));
244
245 // But check that we will trigger the optimal convex code
246 EXPECT_TRUE(path.IsConvex());
247
248 paint.setDrawStyle(DlDrawStyle::kFill);
249 builder.DrawPath(path, paint);
250 }
251
252 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
253}
254} // namespace
255
256TEST_P(AiksTest, CanRenderTiledTextureClamp) {
257 CanRenderTiledTexture(this, DlTileMode::kClamp);
258}
259
260TEST_P(AiksTest, CanRenderTiledTextureRepeat) {
261 CanRenderTiledTexture(this, DlTileMode::kRepeat);
262}
263
264TEST_P(AiksTest, CanRenderTiledTextureMirror) {
265 CanRenderTiledTexture(this, DlTileMode::kMirror);
266}
267
268TEST_P(AiksTest, CanRenderTiledTextureDecal) {
269 CanRenderTiledTexture(this, DlTileMode::kDecal);
270}
271
272TEST_P(AiksTest, CanRenderTiledTextureClampWithTranslate) {
273 CanRenderTiledTexture(this, DlTileMode::kClamp,
274 Matrix::MakeTranslation({172.f, 172.f, 0.f}));
275}
276
277TEST_P(AiksTest, CanRenderImageRect) {
278 DisplayListBuilder builder;
279 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
280
281 DlISize image_half_size =
282 DlISize(image->GetSize().width * 0.5f, image->GetSize().height * 0.5f);
283
284 // Render the bottom right quarter of the source image in a stretched rect.
285 auto source_rect = DlRect::MakeSize(image_half_size);
286 source_rect =
287 source_rect.Shift(image_half_size.width, image_half_size.height);
288
289 builder.DrawImageRect(image, source_rect,
290 DlRect::MakeXYWH(100, 100, 600, 600),
291 DlImageSampling::kNearestNeighbor);
292 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
293}
294
295TEST_P(AiksTest, DrawImageRectSrcOutsideBounds) {
296 DisplayListBuilder builder;
297 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
298
299 // Use a source rect that is partially outside the bounds of the image.
300 auto source_rect = DlRect::MakeXYWH(
301 image->GetSize().width * 0.25f, image->GetSize().height * 0.4f,
302 image->GetSize().width, image->GetSize().height);
303
304 auto dest_rect = DlRect::MakeXYWH(100, 100, 600, 600);
305
306 DlPaint paint;
308 builder.DrawRect(dest_rect, paint);
309
310 builder.DrawImageRect(image, source_rect, dest_rect,
311 DlImageSampling::kNearestNeighbor);
312 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
313}
314
315TEST_P(AiksTest, CanRenderSimpleClips) {
316 DisplayListBuilder builder;
317 builder.Scale(GetContentScale().x, GetContentScale().y);
318 DlPaint paint;
319
320 paint.setColor(DlColor::kWhite());
321 builder.DrawPaint(paint);
322
323 auto draw = [&builder](const DlPaint& paint, Scalar x, Scalar y) {
324 builder.Save();
325 builder.Translate(x, y);
326 {
327 builder.Save();
328 builder.ClipRect(DlRect::MakeLTRB(50, 50, 150, 150));
329 builder.DrawPaint(paint);
330 builder.Restore();
331 }
332 {
333 builder.Save();
334 builder.ClipOval(DlRect::MakeLTRB(200, 50, 300, 150));
335 builder.DrawPaint(paint);
336 builder.Restore();
337 }
338 {
339 builder.Save();
340 builder.ClipRoundRect(
341 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(50, 200, 150, 300), 20, 20));
342 builder.DrawPaint(paint);
343 builder.Restore();
344 }
345 {
346 builder.Save();
348 DlRect::MakeLTRB(200, 230, 300, 270), 20, 20));
349 builder.DrawPaint(paint);
350 builder.Restore();
351 }
352 {
353 builder.Save();
355 DlRect::MakeLTRB(230, 200, 270, 300), 20, 20));
356 builder.DrawPaint(paint);
357 builder.Restore();
358 }
359 builder.Restore();
360 };
361
362 paint.setColor(DlColor::kBlue());
363 draw(paint, 0, 0);
364
365 DlColor gradient_colors[7] = {
366 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
367 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
368 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
369 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
370 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
371 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
372 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
373 };
374 Scalar stops[7] = {
375 0.0,
376 (1.0 / 6.0) * 1,
377 (1.0 / 6.0) * 2,
378 (1.0 / 6.0) * 3,
379 (1.0 / 6.0) * 4,
380 (1.0 / 6.0) * 5,
381 1.0,
382 };
383 auto texture = CreateTextureForFixture("airplane.jpg",
384 /*enable_mipmapping=*/true);
386
388 DlPoint(500, 600), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
389 draw(paint, 0, 300);
390
391 paint.setColorSource(
392 DlColorSource::MakeImage(image, DlTileMode::kRepeat, DlTileMode::kRepeat,
393 DlImageSampling::kNearestNeighbor));
394 draw(paint, 300, 0);
395
396 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
397}
398
399TEST_P(AiksTest, CanSaveLayerStandalone) {
400 DisplayListBuilder builder;
401
402 DlPaint red;
403 red.setColor(DlColor::kRed());
404
405 DlPaint alpha;
406 alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
407
408 builder.SaveLayer(std::nullopt, &alpha);
409
410 builder.DrawCircle(DlPoint(125, 125), 125, red);
411
412 builder.Restore();
413
414 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
415}
416
417TEST_P(AiksTest, CanRenderDifferentShapesWithSameColorSource) {
418 DisplayListBuilder builder;
419 DlPaint paint;
420
421 DlColor colors[2] = {
422 DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
423 DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0),
424 };
425 DlScalar stops[2] = {
426 0.0,
427 1.0,
428 };
429
431 /*start_point=*/DlPoint(0, 0), //
432 /*end_point=*/DlPoint(100, 100), //
433 /*stop_count=*/2, //
434 /*colors=*/colors, //
435 /*stops=*/stops, //
436 /*tile_mode=*/DlTileMode::kRepeat //
437 ));
438
439 builder.Save();
440 builder.Translate(100, 100);
441 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), paint);
442 builder.Restore();
443
444 builder.Save();
445 builder.Translate(100, 400);
446 builder.DrawCircle(DlPoint(100, 100), 100, paint);
447 builder.Restore();
448 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
449}
450
451TEST_P(AiksTest, CanRenderRoundedRectWithNonUniformRadii) {
452 DisplayListBuilder builder;
453 DlPaint paint;
454 paint.setColor(DlColor::kRed());
455
456 RoundingRadii radii = {
457 .top_left = DlSize(50, 25),
458 .top_right = DlSize(25, 50),
459 .bottom_left = DlSize(25, 50),
460 .bottom_right = DlSize(50, 25),
461 };
462 DlRoundRect rrect =
463 DlRoundRect::MakeRectRadii(DlRect::MakeXYWH(100, 100, 500, 500), radii);
464
465 builder.DrawRoundRect(rrect, paint);
466
467 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
468}
469
470TEST_P(AiksTest, CanDrawPaint) {
471 auto medium_turquoise =
472 DlColor::RGBA(72.0f / 255.0f, 209.0f / 255.0f, 204.0f / 255.0f, 1.0f);
473
474 DisplayListBuilder builder;
475 builder.Scale(0.2, 0.2);
476 builder.DrawPaint(DlPaint().setColor(medium_turquoise));
477 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
478}
479
480TEST_P(AiksTest, CanDrawPaintMultipleTimes) {
481 auto medium_turquoise =
482 DlColor::RGBA(72.0f / 255.0f, 209.0f / 255.0f, 204.0f / 255.0f, 1.0f);
483 auto orange_red =
484 DlColor::RGBA(255.0f / 255.0f, 69.0f / 255.0f, 0.0f / 255.0f, 1.0f);
485
486 DisplayListBuilder builder;
487 builder.Scale(0.2, 0.2);
488 builder.DrawPaint(DlPaint().setColor(medium_turquoise));
489 builder.DrawPaint(DlPaint().setColor(orange_red.modulateOpacity(0.5f)));
490 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
491}
492
493TEST_P(AiksTest, StrokedRectsRenderCorrectly) {
494 DisplayListBuilder builder;
495 builder.Scale(GetContentScale().x, GetContentScale().y);
496
497 DlPaint paint;
498 paint.setColor(DlColor::kPurple());
499 paint.setDrawStyle(DlDrawStyle::kStroke);
500 paint.setStrokeWidth(20.0f);
501
502 DlPaint thin_paint = paint;
503 thin_paint.setColor(DlColor::kYellow());
504 thin_paint.setStrokeWidth(0.0f);
505
506 DlRect rect = DlRect::MakeLTRB(10, 10, 90, 90);
507 DlRect thin_tall_rect = DlRect::MakeLTRB(120, 10, 120, 90);
508 DlRect thin_wide_rect = DlRect::MakeLTRB(10, 120, 90, 120);
509 DlRect empty_rect = DlRect::MakeLTRB(120, 120, 120, 120);
510
511 // We draw the following sets of rectangles:
512 //
513 // A E X
514 // X
515 // B F X
516 // X
517 // C D G H X
518 //
519 // Purple A,B,C,D are all drawn with stroke width 20 (non-overflowing).
520 // Each of those sets has 4 rectangles of dimension 80x80, 80x0, 0x80,
521 // and 0,0 to demonstrate the basic behavior and also the behavior of
522 // empty dimensions.
523 //
524 // Blue E,F,G,H are the same 80x80 rectangles, but with an overflowing
525 // stroke width of 120 to show the behavior with degenerately large
526 // stroke widths.
527 //
528 // A,E are drawn with Bevel joins.
529 // B,F are drawn with Round joins.
530 // C,G are drawn with Miter joins and a large enough miter limit.
531 // D,H are drawn with Miter joins and a too small miter limit (== Bevel).
532 //
533 // All orange X rectangles are drawn with round joins and increasing stroke
534 // widths to demonstrate fidelity of the rounding code at various arc sizes.
535 // These X rectangles also help test that the variable sizing estimates in
536 // the round join code are accurate.
537
538 // rects (A)
539 paint.setStrokeJoin(DlStrokeJoin::kBevel);
540 builder.DrawRect(rect.Shift({100, 100}), paint);
541 builder.DrawRect(rect.Shift({100, 100}), thin_paint);
542 builder.DrawRect(thin_tall_rect.Shift({100, 100}), paint);
543 builder.DrawRect(thin_tall_rect.Shift({100, 100}), thin_paint);
544 builder.DrawRect(thin_wide_rect.Shift({100, 100}), paint);
545 builder.DrawRect(thin_wide_rect.Shift({100, 100}), thin_paint);
546 builder.DrawRect(empty_rect.Shift({100, 100}), paint);
547 builder.DrawRect(empty_rect.Shift({100, 100}), thin_paint);
548
549 // rects (B)
550 paint.setStrokeJoin(DlStrokeJoin::kRound);
551 builder.DrawRect(rect.Shift({100, 300}), paint);
552 builder.DrawRect(rect.Shift({100, 300}), thin_paint);
553 builder.DrawRect(thin_tall_rect.Shift({100, 300}), paint);
554 builder.DrawRect(thin_tall_rect.Shift({100, 300}), thin_paint);
555 builder.DrawRect(thin_wide_rect.Shift({100, 300}), paint);
556 builder.DrawRect(thin_wide_rect.Shift({100, 300}), thin_paint);
557 builder.DrawRect(empty_rect.Shift({100, 300}), paint);
558 builder.DrawRect(empty_rect.Shift({100, 300}), thin_paint);
559
560 // rects (C)
561 paint.setStrokeJoin(DlStrokeJoin::kMiter);
563 builder.DrawRect(rect.Shift({100, 500}), paint);
564 builder.DrawRect(rect.Shift({100, 500}), thin_paint);
565 builder.DrawRect(thin_tall_rect.Shift({100, 500}), paint);
566 builder.DrawRect(thin_tall_rect.Shift({100, 500}), thin_paint);
567 builder.DrawRect(thin_wide_rect.Shift({100, 500}), paint);
568 builder.DrawRect(thin_wide_rect.Shift({100, 500}), thin_paint);
569 builder.DrawRect(empty_rect.Shift({100, 500}), paint);
570 builder.DrawRect(empty_rect.Shift({100, 500}), thin_paint);
571
572 // rects (D)
573 paint.setStrokeJoin(DlStrokeJoin::kMiter);
575 builder.DrawRect(rect.Shift({300, 500}), paint);
576 builder.DrawRect(rect.Shift({300, 500}), thin_paint);
577 builder.DrawRect(thin_tall_rect.Shift({300, 500}), paint);
578 builder.DrawRect(thin_tall_rect.Shift({300, 500}), thin_paint);
579 builder.DrawRect(thin_wide_rect.Shift({300, 500}), paint);
580 builder.DrawRect(thin_wide_rect.Shift({300, 500}), thin_paint);
581 builder.DrawRect(empty_rect.Shift({300, 500}), paint);
582 builder.DrawRect(empty_rect.Shift({300, 500}), thin_paint);
583
584 paint.setStrokeWidth(120.0f);
585 paint.setColor(DlColor::kBlue());
586 rect = rect.Expand(-20);
587
588 // rect (E)
589 paint.setStrokeJoin(DlStrokeJoin::kBevel);
590 builder.DrawRect(rect.Shift({500, 100}), paint);
591 builder.DrawRect(rect.Shift({500, 100}), thin_paint);
592
593 // rect (F)
594 paint.setStrokeJoin(DlStrokeJoin::kRound);
595 builder.DrawRect(rect.Shift({500, 300}), paint);
596 builder.DrawRect(rect.Shift({500, 300}), thin_paint);
597
598 // rect (G)
599 paint.setStrokeJoin(DlStrokeJoin::kMiter);
601 builder.DrawRect(rect.Shift({500, 500}), paint);
602 builder.DrawRect(rect.Shift({500, 500}), thin_paint);
603
604 // rect (H)
605 paint.setStrokeJoin(DlStrokeJoin::kMiter);
607 builder.DrawRect(rect.Shift({700, 500}), paint);
608 builder.DrawRect(rect.Shift({700, 500}), thin_paint);
609
610 DlPaint round_mock_paint;
611 round_mock_paint.setColor(DlColor::kGreen());
612 round_mock_paint.setDrawStyle(DlDrawStyle::kFill);
613
614 // array of rects (X)
615 Scalar x = 900;
616 Scalar y = 50;
617 for (int i = 0; i < 15; i++) {
618 paint.setStrokeWidth(i);
619 paint.setColor(DlColor::kOrange());
620 paint.setStrokeJoin(DlStrokeJoin::kRound);
621 builder.DrawRect(DlRect::MakeXYWH(x, y, 30, 30), paint);
622 y += 32 + i;
623 }
624
625 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
626}
627
628TEST_P(AiksTest, FilledCirclesRenderCorrectly) {
629 DisplayListBuilder builder;
630 builder.Scale(GetContentScale().x, GetContentScale().y);
631 DlPaint paint;
632 const int color_count = 3;
633 DlColor colors[color_count] = {
636 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
637 };
638
639 paint.setColor(DlColor::kWhite());
640 builder.DrawPaint(paint);
641
642 int c_index = 0;
643 int radius = 600;
644 while (radius > 0) {
645 paint.setColor(colors[(c_index++) % color_count]);
646 builder.DrawCircle(DlPoint(10, 10), radius, paint);
647 if (radius > 30) {
648 radius -= 10;
649 } else {
650 radius -= 2;
651 }
652 }
653
654 DlColor gradient_colors[7] = {
655 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
656 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
657 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
658 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
659 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
660 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
661 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
662 };
663 DlScalar stops[7] = {
664 0.0,
665 (1.0 / 6.0) * 1,
666 (1.0 / 6.0) * 2,
667 (1.0 / 6.0) * 3,
668 (1.0 / 6.0) * 4,
669 (1.0 / 6.0) * 5,
670 1.0,
671 };
672 auto texture = CreateTextureForFixture("airplane.jpg",
673 /*enable_mipmapping=*/true);
675
677 DlPoint(500, 600), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
678 builder.DrawCircle(DlPoint(500, 600), 100, paint);
679
680 DlMatrix local_matrix = DlMatrix::MakeTranslation({700, 200});
682 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
683 DlImageSampling::kNearestNeighbor, &local_matrix));
684 builder.DrawCircle(DlPoint(800, 300), 100, paint);
685
686 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
687}
688
689TEST_P(AiksTest, StrokedCirclesRenderCorrectly) {
690 DisplayListBuilder builder;
691 builder.Scale(GetContentScale().x, GetContentScale().y);
692 DlPaint paint;
693 const int color_count = 3;
694 DlColor colors[color_count] = {
697 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
698 };
699
700 paint.setColor(DlColor::kWhite());
701 builder.DrawPaint(paint);
702
703 int c_index = 0;
704
705 auto draw = [&paint, &colors, &c_index](DlCanvas& canvas, DlPoint center,
706 Scalar r, Scalar dr, int n) {
707 for (int i = 0; i < n; i++) {
708 paint.setColor(colors[(c_index++) % color_count]);
709 canvas.DrawCircle(center, r, paint);
710 r += dr;
711 }
712 };
713
714 paint.setDrawStyle(DlDrawStyle::kStroke);
715 paint.setStrokeWidth(1);
716 draw(builder, DlPoint(10, 10), 2, 2, 14); // r = [2, 28], covers [1,29]
717 paint.setStrokeWidth(5);
718 draw(builder, DlPoint(10, 10), 35, 10, 56); // r = [35, 585], covers [30,590]
719
720 DlColor gradient_colors[7] = {
721 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
722 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
723 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
724 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
725 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
726 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
727 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
728 };
729 DlScalar stops[7] = {
730 0.0,
731 (1.0 / 6.0) * 1,
732 (1.0 / 6.0) * 2,
733 (1.0 / 6.0) * 3,
734 (1.0 / 6.0) * 4,
735 (1.0 / 6.0) * 5,
736 1.0,
737 };
738 auto texture = CreateTextureForFixture("airplane.jpg",
739 /*enable_mipmapping=*/true);
741
743 DlPoint(500, 600), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
744 draw(builder, DlPoint(500, 600), 5, 10, 10);
745
746 DlMatrix local_matrix = DlMatrix::MakeTranslation({700, 200});
748 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
749 DlImageSampling::kNearestNeighbor, &local_matrix));
750 draw(builder, DlPoint(800, 300), 5, 10, 10);
751
752 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
753}
754
755TEST_P(AiksTest, FilledEllipsesRenderCorrectly) {
756 DisplayListBuilder builder;
757 builder.Scale(GetContentScale().x, GetContentScale().y);
758 DlPaint paint;
759 const int color_count = 3;
760 DlColor colors[color_count] = {
763 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
764 };
765
766 paint.setColor(DlColor::kWhite());
767 builder.DrawPaint(paint);
768
769 int c_index = 0;
770 int long_radius = 600;
771 int short_radius = 600;
772 while (long_radius > 0 && short_radius > 0) {
773 paint.setColor(colors[(c_index++) % color_count]);
774 builder.DrawOval(DlRect::MakeXYWH(10 - long_radius, 10 - short_radius,
775 long_radius * 2, short_radius * 2),
776 paint);
777 builder.DrawOval(DlRect::MakeXYWH(1000 - short_radius, 750 - long_radius,
778 short_radius * 2, long_radius * 2),
779 paint);
780 if (short_radius > 30) {
781 short_radius -= 10;
782 long_radius -= 5;
783 } else {
784 short_radius -= 2;
785 long_radius -= 1;
786 }
787 }
788
789 DlColor gradient_colors[7] = {
790 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
791 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
792 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
793 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
794 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
795 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
796 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
797 };
798 DlScalar stops[7] = {
799 0.0,
800 (1.0 / 6.0) * 1,
801 (1.0 / 6.0) * 2,
802 (1.0 / 6.0) * 3,
803 (1.0 / 6.0) * 4,
804 (1.0 / 6.0) * 5,
805 1.0,
806 };
807 auto texture = CreateTextureForFixture("airplane.jpg",
808 /*enable_mipmapping=*/true);
810
811 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
812
814 DlPoint(300, 650), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
815 builder.DrawOval(DlRect::MakeXYWH(200, 625, 200, 50), paint);
816 builder.DrawOval(DlRect::MakeXYWH(275, 550, 50, 200), paint);
817
818 DlMatrix local_matrix = DlMatrix::MakeTranslation({610, 15});
820 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
821 DlImageSampling::kNearestNeighbor, &local_matrix));
822 builder.DrawOval(DlRect::MakeXYWH(610, 90, 200, 50), paint);
823 builder.DrawOval(DlRect::MakeXYWH(685, 15, 50, 200), paint);
824
825 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
826}
827
828namespace {
829struct ArcFarmOptions {
830 bool use_center = false;
831 bool full_circles = false;
832 bool sweeps_over_360 = false;
834};
835
836void RenderArcFarm(DisplayListBuilder& builder,
837 const DlPaint& paint,
838 const ArcFarmOptions& opts) {
839 builder.Save();
840 builder.Translate(50, 50);
841 const Rect arc_bounds = Rect::MakeLTRB(0, 0, 42, 42 * opts.vertical_scale);
842 const int sweep_limit = opts.sweeps_over_360 ? 420 : 360;
843 for (int start = 0; start <= 360; start += 30) {
844 builder.Save();
845 for (int sweep = 30; sweep <= sweep_limit; sweep += 30) {
846 builder.DrawArc(arc_bounds, start, opts.full_circles ? 360 : sweep,
847 opts.use_center, paint);
848 builder.Translate(50, 0);
849 }
850 builder.Restore();
851 builder.Translate(0, 50);
852 }
853 builder.Restore();
854}
855} // namespace
856
857TEST_P(AiksTest, FilledArcsRenderCorrectly) {
858 DisplayListBuilder builder;
859 builder.Scale(GetContentScale().x, GetContentScale().y);
860 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
861
862 DlPaint paint;
863 paint.setColor(DlColor::kBlue());
864
865 RenderArcFarm(builder, paint,
866 {
867 .use_center = false,
868 .full_circles = false,
869 });
870
871 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
872}
873
874TEST_P(AiksTest, FilledArcsRenderCorrectlyWithCenter) {
875 DisplayListBuilder builder;
876 builder.Scale(GetContentScale().x, GetContentScale().y);
877 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
878
879 DlPaint paint;
880 paint.setColor(DlColor::kBlue());
881
882 RenderArcFarm(builder, paint,
883 {
884 .use_center = true,
885 .full_circles = false,
886 });
887
888 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
889}
890
891TEST_P(AiksTest, NonSquareFilledArcsRenderCorrectly) {
892 DisplayListBuilder builder;
893 builder.Scale(GetContentScale().x, GetContentScale().y);
894 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
895
896 DlPaint paint;
897 paint.setColor(DlColor::kBlue());
898
899 RenderArcFarm(builder, paint,
900 {
901 .use_center = false,
902 .full_circles = false,
903 .vertical_scale = 0.8f,
904 });
905
906 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
907}
908
909TEST_P(AiksTest, NonSquareFilledArcsRenderCorrectlyWithCenter) {
910 DisplayListBuilder builder;
911 builder.Scale(GetContentScale().x, GetContentScale().y);
912 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
913
914 DlPaint paint;
915 paint.setColor(DlColor::kBlue());
916
917 RenderArcFarm(builder, paint,
918 {
919 .use_center = true,
920 .full_circles = false,
921 .vertical_scale = 0.8f,
922 });
923
924 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
925}
926
927TEST_P(AiksTest, StrokedArcsRenderCorrectlyWithButtEnds) {
928 DisplayListBuilder builder;
929 builder.Scale(GetContentScale().x, GetContentScale().y);
930 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
931
932 DlPaint paint;
933 paint.setDrawStyle(DlDrawStyle::kStroke);
934 paint.setStrokeWidth(6.0f);
935 paint.setStrokeCap(DlStrokeCap::kButt);
936 paint.setColor(DlColor::kBlue());
937
938 RenderArcFarm(builder, paint,
939 {
940 .use_center = false,
941 .full_circles = false,
942 });
943
944 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
945}
946
947TEST_P(AiksTest, StrokedArcsRenderCorrectlyWithSquareEnds) {
948 DisplayListBuilder builder;
949 builder.Scale(GetContentScale().x, GetContentScale().y);
950 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
951
952 DlPaint paint;
953 paint.setDrawStyle(DlDrawStyle::kStroke);
954 paint.setStrokeWidth(6.0f);
955 paint.setStrokeCap(DlStrokeCap::kSquare);
956 paint.setColor(DlColor::kBlue());
957
958 RenderArcFarm(builder, paint,
959 {
960 .use_center = false,
961 .full_circles = false,
962 });
963
964 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
965}
966
967TEST_P(AiksTest, StrokedArcsRenderCorrectlyWithRoundEnds) {
968 DisplayListBuilder builder;
969 builder.Scale(GetContentScale().x, GetContentScale().y);
970 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
971
972 DlPaint paint;
973 paint.setDrawStyle(DlDrawStyle::kStroke);
974 paint.setStrokeWidth(6.0f);
975 paint.setStrokeCap(DlStrokeCap::kRound);
976 paint.setColor(DlColor::kBlue());
977
978 RenderArcFarm(builder, paint,
979 {
980 .use_center = false,
981 .full_circles = false,
982 });
983
984 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
985}
986
987TEST_P(AiksTest, StrokedArcsRenderCorrectlyWithBevelJoinsAndCenter) {
988 DisplayListBuilder builder;
989 builder.Scale(GetContentScale().x, GetContentScale().y);
990 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
991
992 DlPaint paint;
993 paint.setDrawStyle(DlDrawStyle::kStroke);
994 paint.setStrokeWidth(6.0f);
995 paint.setStrokeJoin(DlStrokeJoin::kBevel);
996 paint.setColor(DlColor::kBlue());
997
998 RenderArcFarm(builder, paint,
999 {
1000 .use_center = true,
1001 .full_circles = false,
1002 .sweeps_over_360 = true,
1003 });
1004
1005 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1006}
1007
1008TEST_P(AiksTest, StrokedArcsRenderCorrectlyWithMiterJoinsAndCenter) {
1009 DisplayListBuilder builder;
1010 builder.Scale(GetContentScale().x, GetContentScale().y);
1011 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1012
1013 DlPaint paint;
1014 paint.setDrawStyle(DlDrawStyle::kStroke);
1015 paint.setStrokeWidth(6.0f);
1016 paint.setStrokeJoin(DlStrokeJoin::kMiter);
1017 // Default miter of 4.0 does a miter on all of the centers, but
1018 // using 3.0 will show some bevels on the widest interior angles...
1019 paint.setStrokeMiter(3.0f);
1020 paint.setColor(DlColor::kBlue());
1021
1022 RenderArcFarm(builder, paint,
1023 {
1024 .use_center = true,
1025 .full_circles = false,
1026 .sweeps_over_360 = true,
1027 });
1028
1029 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1030}
1031
1032TEST_P(AiksTest, StrokedArcsRenderCorrectlyWithRoundJoinsAndCenter) {
1033 DisplayListBuilder builder;
1034 builder.Scale(GetContentScale().x, GetContentScale().y);
1035 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1036
1037 DlPaint paint;
1038 paint.setDrawStyle(DlDrawStyle::kStroke);
1039 paint.setStrokeWidth(6.0f);
1040 paint.setStrokeJoin(DlStrokeJoin::kRound);
1041 paint.setColor(DlColor::kBlue());
1042
1043 RenderArcFarm(builder, paint,
1044 {
1045 .use_center = true,
1046 .full_circles = false,
1047 .sweeps_over_360 = true,
1048 });
1049
1050 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1051}
1052
1053TEST_P(AiksTest, StrokedArcsRenderCorrectlyWithSquareAndButtEnds) {
1054 DisplayListBuilder builder;
1055 builder.Scale(GetContentScale().x, GetContentScale().y);
1056 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1057
1058 DlPaint paint;
1059 paint.setDrawStyle(DlDrawStyle::kStroke);
1060 paint.setStrokeWidth(8.0f);
1061 paint.setStrokeCap(DlStrokeCap::kSquare);
1062 paint.setColor(DlColor::kRed());
1063
1064 RenderArcFarm(builder, paint,
1065 {
1066 .use_center = false,
1067 .full_circles = false,
1068 });
1069
1070 paint.setStrokeCap(DlStrokeCap::kButt);
1071 paint.setColor(DlColor::kBlue());
1072
1073 RenderArcFarm(builder, paint,
1074 {
1075 .use_center = false,
1076 .full_circles = false,
1077 });
1078
1079 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1080}
1081
1082TEST_P(AiksTest, StrokedArcsRenderCorrectlyWithSquareAndButtAndRoundEnds) {
1083 DisplayListBuilder builder;
1084 builder.Scale(GetContentScale().x, GetContentScale().y);
1085 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1086
1087 DlPaint paint;
1088 paint.setDrawStyle(DlDrawStyle::kStroke);
1089 paint.setStrokeWidth(8.0f);
1090 paint.setStrokeCap(DlStrokeCap::kSquare);
1091 paint.setColor(DlColor::kRed());
1092
1093 RenderArcFarm(builder, paint,
1094 {
1095 .use_center = false,
1096 .full_circles = false,
1097 });
1098
1099 paint.setStrokeCap(DlStrokeCap::kRound);
1100 paint.setColor(DlColor::kGreen());
1101
1102 RenderArcFarm(builder, paint,
1103 {
1104 .use_center = false,
1105 .full_circles = false,
1106 });
1107
1108 paint.setStrokeCap(DlStrokeCap::kButt);
1109 paint.setColor(DlColor::kBlue());
1110
1111 RenderArcFarm(builder, paint,
1112 {
1113 .use_center = false,
1114 .full_circles = false,
1115 });
1116
1117 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1118}
1119
1120TEST_P(AiksTest, StrokedArcsCoverFullArcWithButtEnds) {
1121 // This test compares the rendering of a full circle arc against a partial
1122 // arc by drawing a one over the other in high contrast. If the partial
1123 // arc misses any pixels that were drawn by the full arc, there will be
1124 // some "pixel dirt" around the missing "erased" parts of the arcs. This
1125 // case arises while rendering a CircularProgressIndicator with a background
1126 // color where we want the rendering of the background full arc to hit the
1127 // same pixels around the edges as the partial arc that covers it.
1128 //
1129 // In this case we draw a full blue circle and then draw a partial arc
1130 // over it in the background color (white).
1131
1132 DisplayListBuilder builder;
1133 builder.Scale(GetContentScale().x, GetContentScale().y);
1134 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1135
1136 DlPaint paint;
1137 paint.setDrawStyle(DlDrawStyle::kStroke);
1138 paint.setStrokeWidth(6.0f);
1139 paint.setStrokeCap(DlStrokeCap::kButt);
1140 paint.setColor(DlColor::kBlue());
1141
1142 // First draw full circles in blue to establish the pixels to be erased
1143 RenderArcFarm(builder, paint,
1144 {
1145 .use_center = false,
1146 .full_circles = true,
1147 });
1148
1149 paint.setColor(DlColor::kWhite());
1150
1151 // Then draw partial arcs in white over the circles to "erase" them
1152 RenderArcFarm(builder, paint,
1153 {
1154 .use_center = false,
1155 .full_circles = false,
1156 });
1157
1158 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1159}
1160
1161TEST_P(AiksTest, FilledRoundRectsRenderCorrectly) {
1162 DisplayListBuilder builder;
1163 builder.Scale(GetContentScale().x, GetContentScale().y);
1164 DlPaint paint;
1165 const int color_count = 3;
1166 DlColor colors[color_count] = {
1169 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
1170 };
1171
1172 paint.setColor(DlColor::kWhite());
1173 builder.DrawPaint(paint);
1174
1175 int c_index = 0;
1176 for (int i = 0; i < 4; i++) {
1177 for (int j = 0; j < 4; j++) {
1178 paint.setColor(colors[(c_index++) % color_count]);
1179 builder.DrawRoundRect(
1181 DlRect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80), //
1182 i * 5 + 10, j * 5 + 10),
1183 paint);
1184 }
1185 }
1186 paint.setColor(colors[(c_index++) % color_count]);
1187 builder.DrawRoundRect(
1188 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(10, 420, 380, 80), 40, 40),
1189 paint);
1190 paint.setColor(colors[(c_index++) % color_count]);
1191 builder.DrawRoundRect(
1192 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(410, 20, 80, 380), 40, 40),
1193 paint);
1194
1195 DlColor gradient_colors[7] = {
1196 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
1197 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
1198 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
1199 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
1200 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
1201 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
1202 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
1203 };
1204 DlScalar stops[7] = {
1205 0.0,
1206 (1.0 / 6.0) * 1,
1207 (1.0 / 6.0) * 2,
1208 (1.0 / 6.0) * 3,
1209 (1.0 / 6.0) * 4,
1210 (1.0 / 6.0) * 5,
1211 1.0,
1212 };
1213 auto texture = CreateTextureForFixture("airplane.jpg",
1214 /*enable_mipmapping=*/true);
1216
1217 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1219 DlPoint(550, 550), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
1220 for (int i = 1; i <= 10; i++) {
1221 int j = 11 - i;
1222 builder.DrawRoundRect(
1223 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(550 - i * 20, 550 - j * 20, //
1224 550 + i * 20, 550 + j * 20),
1225 i * 10, j * 10),
1226 paint);
1227 }
1228
1229 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1231 DlPoint(200, 650), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
1232 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1233 builder.DrawRoundRect(
1234 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(100, 610, 300, 690), 40, 40),
1235 paint);
1236 builder.DrawRoundRect(
1237 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(160, 550, 240, 750), 40, 40),
1238 paint);
1239
1240 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1241 DlMatrix local_matrix = DlMatrix::MakeTranslation({520, 20});
1243 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
1244 DlImageSampling::kNearestNeighbor, &local_matrix));
1245 for (int i = 1; i <= 10; i++) {
1246 int j = 11 - i;
1247 builder.DrawRoundRect(
1248 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(720 - i * 20, 220 - j * 20, //
1249 720 + i * 20, 220 + j * 20),
1250 i * 10, j * 10),
1251 paint);
1252 }
1253
1254 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1255 local_matrix = DlMatrix::MakeTranslation({800, 300});
1257 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
1258 DlImageSampling::kNearestNeighbor, &local_matrix));
1259 builder.DrawRoundRect(
1260 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(800, 410, 1000, 490), 40, 40),
1261 paint);
1262 builder.DrawRoundRect(
1263 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(860, 350, 940, 550), 40, 40),
1264 paint);
1265
1266 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1267}
1268
1269TEST_P(AiksTest, SolidColorCirclesOvalsRRectsMaskBlurCorrectly) {
1270 DisplayListBuilder builder;
1271 builder.Scale(GetContentScale().x, GetContentScale().y);
1272 DlPaint paint;
1273 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 1.0f));
1274
1275 builder.DrawPaint(DlPaint().setColor(DlColor::kWhite()));
1276
1277 paint.setColor(
1278 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f));
1279 Scalar y = 100.0f;
1280 for (int i = 0; i < 5; i++) {
1281 Scalar x = (i + 1) * 100;
1282 Scalar radius = x / 10.0f;
1283 builder.DrawRect(DlRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
1284 radius, 60.0f - radius),
1285 paint);
1286 }
1287
1288 paint.setColor(DlColor::kBlue());
1289 y += 100.0f;
1290 for (int i = 0; i < 5; i++) {
1291 Scalar x = (i + 1) * 100;
1292 Scalar radius = x / 10.0f;
1293 builder.DrawCircle(DlPoint(x + 25, y + 25), radius, paint);
1294 }
1295
1296 paint.setColor(DlColor::kGreen());
1297 y += 100.0f;
1298 for (int i = 0; i < 5; i++) {
1299 Scalar x = (i + 1) * 100;
1300 Scalar radius = x / 10.0f;
1301 builder.DrawOval(DlRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
1302 radius, 60.0f - radius),
1303 paint);
1304 }
1305
1306 paint.setColor(
1307 DlColor::RGBA(128.0f / 255.0f, 0.0f / 255.0f, 128.0f / 255.0f, 1.0f));
1308 y += 100.0f;
1309 for (int i = 0; i < 5; i++) {
1310 Scalar x = (i + 1) * 100;
1311 Scalar radius = x / 20.0f;
1312 builder.DrawRoundRect(
1313 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(x, y, 60.0f, 60.0f), //
1314 radius, radius),
1315 paint);
1316 }
1317
1318 paint.setColor(
1319 DlColor::RGBA(255.0f / 255.0f, 165.0f / 255.0f, 0.0f / 255.0f, 1.0f));
1320 y += 100.0f;
1321 for (int i = 0; i < 5; i++) {
1322 Scalar x = (i + 1) * 100;
1323 Scalar radius = x / 20.0f;
1324 builder.DrawRoundRect(
1325 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(x, y, 60.0f, 60.0f), //
1326 radius, 5.0f),
1327 paint);
1328 }
1329
1330 auto dl = builder.Build();
1331 ASSERT_TRUE(OpenPlaygroundHere(dl));
1332}
1333
1334TEST_P(AiksTest, CanRenderClippedBackdropFilter) {
1335 DisplayListBuilder builder;
1336
1337 builder.Scale(GetContentScale().x, GetContentScale().y);
1338
1339 // Draw something interesting in the background.
1340 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
1341 DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0)};
1342 std::vector<Scalar> stops = {
1343 0.0,
1344 1.0,
1345 };
1346 DlPaint paint;
1348 /*start_point=*/DlPoint(0, 0), //
1349 /*end_point=*/DlPoint(100, 100), //
1350 /*stop_count=*/2, //
1351 /*colors=*/colors.data(), //
1352 /*stops=*/stops.data(), //
1353 /*tile_mode=*/DlTileMode::kRepeat //
1354 ));
1355
1356 builder.DrawPaint(paint);
1357
1358 DlRect clip_rect = DlRect::MakeLTRB(50, 50, 400, 300);
1359 DlRoundRect clip_rrect = DlRoundRect::MakeRectXY(clip_rect, 100, 100);
1360
1361 // Draw a clipped SaveLayer, where the clip coverage and SaveLayer size are
1362 // the same.
1363 builder.ClipRoundRect(clip_rrect, DlClipOp::kIntersect);
1364
1365 DlPaint save_paint;
1366 auto backdrop_filter = DlImageFilter::MakeColorFilter(
1367 DlColorFilter::MakeBlend(DlColor::kRed(), DlBlendMode::kExclusion));
1368 builder.SaveLayer(clip_rect, &save_paint, backdrop_filter.get());
1369
1370 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1371}
1372
1373TEST_P(AiksTest, CanDrawPerspectiveTransformWithClips) {
1374 // Avoiding `GetSecondsElapsed()` to reduce risk of golden flakiness.
1375 int time = 0;
1376 auto callback = [&]() -> sk_sp<DisplayList> {
1377 DisplayListBuilder builder;
1378
1379 builder.Save();
1380 {
1381 builder.Translate(300, 300);
1382
1383 // 1. Draw/restore a clip before drawing the image, which will get drawn
1384 // to the depth buffer behind the image.
1385 builder.Save();
1386 {
1387 DlPaint paint;
1388 paint.setColor(DlColor::kGreen());
1389 builder.DrawPaint(paint);
1390 builder.ClipRect(DlRect::MakeLTRB(-180, -180, 180, 180),
1391 DlClipOp::kDifference);
1392
1393 paint.setColor(DlColor::kBlack());
1394 builder.DrawPaint(paint);
1395 }
1396 builder.Restore(); // Restore rectangle difference clip.
1397
1398 builder.Save();
1399 {
1400 // 2. Draw an oval clip that applies to the image, which will get drawn
1401 // in front of the image on the depth buffer.
1402 builder.ClipOval(DlRect::MakeLTRB(-200, -200, 200, 200));
1403
1404 Matrix result =
1405 Matrix(1.0, 0.0, 0.0, 0.0, //
1406 0.0, 1.0, 0.0, 0.0, //
1407 0.0, 0.0, 1.0, 0.003, //
1408 0.0, 0.0, 0.0, 1.0) *
1409 Matrix::MakeRotationY({Radians{-1.0f + (time++ / 60.0f)}});
1410
1411 // 3. Draw the rotating image with a perspective transform.
1412 builder.Transform(result);
1413
1414 auto image =
1415 DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
1416 auto position =
1417 -DlPoint(image->GetSize().width, image->GetSize().height) * 0.5;
1418 builder.DrawImage(image, position, {});
1419 }
1420 builder.Restore(); // Restore oval intersect clip.
1421
1422 // 4. Draw a semi-translucent blue circle atop all previous draws.
1423 DlPaint paint;
1424 paint.setColor(DlColor::kBlue().modulateOpacity(0.4));
1425 builder.DrawCircle(DlPoint(), 230, paint);
1426 }
1427 builder.Restore(); // Restore translation.
1428
1429 return builder.Build();
1430 };
1431 ASSERT_TRUE(OpenPlaygroundHere(callback));
1432}
1433
1434TEST_P(AiksTest, ImageColorSourceEffectTransform) {
1435 // Compare with https://fiddle.skia.org/c/6cdc5aefb291fda3833b806ca347a885
1436
1437 DisplayListBuilder builder;
1438 auto texture = DlImageImpeller::Make(CreateTextureForFixture("monkey.png"));
1439
1440 DlPaint paint;
1441 paint.setColor(DlColor::kWhite());
1442 builder.DrawPaint(paint);
1443
1444 // Translation
1445 {
1446 DlMatrix matrix = DlMatrix::MakeTranslation({50, 50});
1447 DlPaint paint;
1449 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1450 DlImageSampling::kNearestNeighbor, &matrix));
1451
1452 builder.DrawRect(DlRect::MakeLTRB(0, 0, 100, 100), paint);
1453 }
1454
1455 // Rotation/skew
1456 {
1457 builder.Save();
1458 builder.Rotate(45);
1459 DlPaint paint;
1460
1461 Matrix matrix(1, -1, 0, 0, //
1462 1, 1, 0, 0, //
1463 0, 0, 1, 0, //
1464 0, 0, 0, 1);
1466 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1467 DlImageSampling::kNearestNeighbor, &matrix));
1468 builder.DrawRect(DlRect::MakeLTRB(100, 0, 200, 100), paint);
1469 builder.Restore();
1470 }
1471
1472 // Scale
1473 {
1474 builder.Save();
1475 builder.Translate(100, 0);
1476 builder.Scale(100, 100);
1477 DlPaint paint;
1478
1479 DlMatrix matrix = DlMatrix::MakeScale({0.005, 0.005, 1});
1481 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1482 DlImageSampling::kNearestNeighbor, &matrix));
1483
1484 builder.DrawRect(DlRect::MakeLTRB(0, 0, 1, 1), paint);
1485 builder.Restore();
1486 }
1487
1488 // Perspective
1489 {
1490 builder.Save();
1491 builder.Translate(150, 150);
1492 DlPaint paint;
1493
1494 DlMatrix matrix =
1495 DlMatrix::MakePerspective(Radians{0.5}, ISize{200, 200}, 0.05, 1);
1497 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1498 DlImageSampling::kNearestNeighbor, &matrix));
1499
1500 builder.DrawRect(DlRect::MakeLTRB(0, 0, 200, 200), paint);
1501 builder.Restore();
1502 }
1503
1504 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1505}
1506
1507TEST_P(AiksTest, SubpassWithClearColorOptimization) {
1508 DisplayListBuilder builder;
1509
1510 // Use a non-srcOver blend mode to ensure that we don't detect this as an
1511 // opacity peephole optimization.
1512 DlPaint paint;
1513 paint.setColor(DlColor::kBlue().modulateOpacity(0.5));
1514 paint.setBlendMode(DlBlendMode::kSrc);
1515
1516 DlRect bounds = DlRect::MakeLTRB(0, 0, 200, 200);
1517 builder.SaveLayer(bounds, &paint);
1518
1520 paint.setBlendMode(DlBlendMode::kSrc);
1521 builder.DrawPaint(paint);
1522 builder.Restore();
1523
1524 paint.setColor(DlColor::kBlue());
1525 paint.setBlendMode(DlBlendMode::kDstOver);
1526 builder.SaveLayer(std::nullopt, &paint);
1527 builder.Restore();
1528
1529 // This playground should appear blank on CI since we are only drawing
1530 // transparent black. If the clear color optimization is broken, the texture
1531 // will be filled with NaNs and may produce a magenta texture on macOS or iOS.
1532 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1533}
1534
1535// Render a white circle at the top left corner of the screen.
1536TEST_P(AiksTest, MatrixImageFilterDoesntCullWhenTranslatedFromOffscreen) {
1537 DisplayListBuilder builder;
1538 builder.Scale(GetContentScale().x, GetContentScale().y);
1539 builder.Translate(100, 100);
1540 // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
1541 // +300 translation applied by a SaveLayer image filter.
1542 DlPaint paint;
1543 DlMatrix translate = DlMatrix::MakeTranslation({300, 0});
1544 paint.setImageFilter(
1545 DlImageFilter::MakeMatrix(translate, DlImageSampling::kLinear));
1546 builder.SaveLayer(std::nullopt, &paint);
1547
1548 DlPaint circle_paint;
1549 circle_paint.setColor(DlColor::kGreen());
1550 builder.DrawCircle(DlPoint(-300, 0), 100, circle_paint);
1551 builder.Restore();
1552
1553 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1554}
1555
1556// Render a white circle at the top left corner of the screen.
1558 MatrixImageFilterDoesntCullWhenScaledAndTranslatedFromOffscreen) {
1559 DisplayListBuilder builder;
1560 builder.Scale(GetContentScale().x, GetContentScale().y);
1561 builder.Translate(100, 100);
1562 // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
1563 // +300 translation applied by a SaveLayer image filter.
1564
1565 DlPaint paint;
1567 DlMatrix::MakeTranslation({300, 0}) * DlMatrix::MakeScale({2, 2, 1}),
1568 DlImageSampling::kNearestNeighbor));
1569 builder.SaveLayer(std::nullopt, &paint);
1570
1571 DlPaint circle_paint;
1572 circle_paint.setColor(DlColor::kGreen());
1573 builder.DrawCircle(DlPoint(-150, 0), 50, circle_paint);
1574 builder.Restore();
1575
1576 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1577}
1578
1579// This should be solid red, if you see a little red box this is broken.
1580TEST_P(AiksTest, ClearColorOptimizationWhenSubpassIsBiggerThanParentPass) {
1581 SetWindowSize({400, 400});
1582 DisplayListBuilder builder;
1583
1584 builder.Scale(GetContentScale().x, GetContentScale().y);
1585
1586 DlPaint paint;
1587 paint.setColor(DlColor::kRed());
1588 builder.DrawRect(DlRect::MakeLTRB(200, 200, 300, 300), paint);
1589
1591 DlImageSampling::kLinear));
1592 builder.SaveLayer(std::nullopt, &paint);
1593 // Draw a rectangle that would fully cover the parent pass size, but not
1594 // the subpass that it is rendered in.
1595 paint.setColor(DlColor::kGreen());
1596 builder.DrawRect(DlRect::MakeLTRB(0, 0, 400, 400), paint);
1597 // Draw a bigger rectangle to force the subpass to be bigger.
1598
1599 paint.setColor(DlColor::kRed());
1600 builder.DrawRect(DlRect::MakeLTRB(0, 0, 800, 800), paint);
1601 builder.Restore();
1602
1603 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1604}
1605
1606TEST_P(AiksTest, EmptySaveLayerIgnoresPaint) {
1607 DisplayListBuilder builder;
1608 builder.Scale(GetContentScale().x, GetContentScale().y);
1609
1610 DlPaint paint;
1611 paint.setColor(DlColor::kRed());
1612 builder.DrawPaint(paint);
1613 builder.ClipRect(DlRect::MakeXYWH(100, 100, 200, 200));
1614 paint.setColor(DlColor::kBlue());
1615 builder.SaveLayer(std::nullopt, &paint);
1616 builder.Restore();
1617
1618 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1619}
1620
1621TEST_P(AiksTest, EmptySaveLayerRendersWithClear) {
1622 DisplayListBuilder builder;
1623 builder.Scale(GetContentScale().x, GetContentScale().y);
1624 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
1625 builder.DrawImage(image, DlPoint(10, 10), {});
1626 builder.ClipRect(DlRect::MakeXYWH(100, 100, 200, 200));
1627
1628 DlPaint paint;
1629 paint.setBlendMode(DlBlendMode::kClear);
1630 builder.SaveLayer(std::nullopt, &paint);
1631 builder.Restore();
1632
1633 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1634}
1635
1637 CanPerformSaveLayerWithBoundsAndLargerIntermediateIsNotAllocated) {
1638 DisplayListBuilder builder;
1639
1640 DlPaint red;
1641 red.setColor(DlColor::kRed());
1642
1643 DlPaint green;
1644 green.setColor(DlColor::kGreen());
1645
1646 DlPaint blue;
1647 blue.setColor(DlColor::kBlue());
1648
1649 DlPaint save;
1650 save.setColor(DlColor::kBlack().modulateOpacity(0.5));
1651
1652 DlRect huge_bounds = DlRect::MakeXYWH(0, 0, 100000, 100000);
1653 builder.SaveLayer(huge_bounds, &save);
1654
1655 builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), red);
1656 builder.DrawRect(DlRect::MakeXYWH(10, 10, 100, 100), green);
1657 builder.DrawRect(DlRect::MakeXYWH(20, 20, 100, 100), blue);
1658
1659 builder.Restore();
1660
1661 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1662}
1663
1664// This makes sure the WideGamut named tests use 16bit float pixel format.
1665TEST_P(AiksTest, FormatWideGamut) {
1666 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
1668}
1669
1670TEST_P(AiksTest, FormatSRGB) {
1671 PixelFormat pixel_format =
1672 GetContext()->GetCapabilities()->GetDefaultColorFormat();
1673 EXPECT_TRUE(pixel_format == PixelFormat::kR8G8B8A8UNormInt ||
1674 pixel_format == PixelFormat::kB8G8R8A8UNormInt)
1675 << "pixel format: " << PixelFormatToString(pixel_format);
1676}
1677
1678TEST_P(AiksTest, CoordinateConversionsAreCorrect) {
1679 DisplayListBuilder builder;
1680
1681 // Render a texture directly.
1682 {
1683 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
1684
1685 builder.Save();
1686 builder.Translate(100, 200);
1687 builder.Scale(0.5, 0.5);
1688 builder.DrawImage(image, DlPoint(100.0, 100.0),
1689 DlImageSampling::kNearestNeighbor);
1690 builder.Restore();
1691 }
1692
1693 // Render an offscreen rendered texture.
1694 {
1695 DlPaint alpha;
1696 alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
1697
1698 builder.SaveLayer(std::nullopt, &alpha);
1699
1700 DlPaint paint;
1701 paint.setColor(DlColor::kRed());
1702 builder.DrawRect(DlRect::MakeXYWH(000, 000, 100, 100), paint);
1703 paint.setColor(DlColor::kGreen());
1704 builder.DrawRect(DlRect::MakeXYWH(020, 020, 100, 100), paint);
1705 paint.setColor(DlColor::kBlue());
1706 builder.DrawRect(DlRect::MakeXYWH(040, 040, 100, 100), paint);
1707
1708 builder.Restore();
1709 }
1710
1711 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1712}
1713
1714TEST_P(AiksTest, CanPerformFullScreenMSAA) {
1715 DisplayListBuilder builder;
1716
1717 DlPaint paint;
1718 paint.setColor(DlColor::kRed());
1719 builder.DrawCircle(DlPoint(250, 250), 125, paint);
1720
1721 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1722}
1723
1724TEST_P(AiksTest, CanPerformSkew) {
1725 DisplayListBuilder builder;
1726
1727 DlPaint red;
1728 red.setColor(DlColor::kRed());
1729 builder.Skew(2, 5);
1730 builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), red);
1731
1732 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1733}
1734
1735TEST_P(AiksTest, CanPerformSaveLayerWithBounds) {
1736 DisplayListBuilder builder;
1737
1738 DlPaint save;
1739 save.setColor(DlColor::kBlack());
1740
1741 DlRect save_bounds = DlRect::MakeXYWH(0, 0, 50, 50);
1742 builder.SaveLayer(save_bounds, &save);
1743
1744 DlPaint paint;
1745 paint.setColor(DlColor::kRed());
1746 builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), paint);
1747 paint.setColor(DlColor::kGreen());
1748 builder.DrawRect(DlRect::MakeXYWH(10, 10, 100, 100), paint);
1749 paint.setColor(DlColor::kBlue());
1750 builder.DrawRect(DlRect::MakeXYWH(20, 20, 100, 100), paint);
1751
1752 builder.Restore();
1753
1754 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1755}
1756
1757TEST_P(AiksTest, FilledRoundRectPathsRenderCorrectly) {
1758 DisplayListBuilder builder;
1759 builder.Scale(GetContentScale().x, GetContentScale().y);
1760
1761 DlPaint paint;
1762 const int color_count = 3;
1763 DlColor colors[color_count] = {
1766 DlColor::ARGB(1.0, 220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f),
1767 };
1768
1769 paint.setColor(DlColor::kWhite());
1770 builder.DrawPaint(paint);
1771
1772 auto draw_rrect_as_path = [&builder](const DlRect& rect, Scalar x, Scalar y,
1773 const DlPaint& paint) {
1774 builder.DrawPath(DlPath::MakeRoundRectXY(rect, x, y), paint);
1775 };
1776
1777 int c_index = 0;
1778 for (int i = 0; i < 4; i++) {
1779 for (int j = 0; j < 4; j++) {
1780 paint.setColor(colors[(c_index++) % color_count]);
1781 draw_rrect_as_path(DlRect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80),
1782 i * 5 + 10, j * 5 + 10, paint);
1783 }
1784 }
1785 paint.setColor(colors[(c_index++) % color_count]);
1786 draw_rrect_as_path(DlRect::MakeXYWH(10, 420, 380, 80), 40, 40, paint);
1787 paint.setColor(colors[(c_index++) % color_count]);
1788 draw_rrect_as_path(DlRect::MakeXYWH(410, 20, 80, 380), 40, 40, paint);
1789
1790 std::vector<DlColor> gradient_colors = {
1791 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
1792 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
1793 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
1794 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
1795 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
1796 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
1797 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0)};
1798 std::vector<Scalar> stops = {
1799 0.0,
1800 (1.0 / 6.0) * 1,
1801 (1.0 / 6.0) * 2,
1802 (1.0 / 6.0) * 3,
1803 (1.0 / 6.0) * 4,
1804 (1.0 / 6.0) * 5,
1805 1.0,
1806 };
1808 CreateTextureForFixture("airplane.jpg",
1809 /*enable_mipmapping=*/true));
1810
1811 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1813 /*center=*/DlPoint(550, 550),
1814 /*radius=*/75,
1815 /*stop_count=*/gradient_colors.size(),
1816 /*colors=*/gradient_colors.data(),
1817 /*stops=*/stops.data(),
1818 /*tile_mode=*/DlTileMode::kMirror));
1819 for (int i = 1; i <= 10; i++) {
1820 int j = 11 - i;
1821 draw_rrect_as_path(DlRect::MakeLTRB(550 - i * 20, 550 - j * 20, //
1822 550 + i * 20, 550 + j * 20),
1823 i * 10, j * 10, paint);
1824 }
1825 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1827 /*center=*/DlPoint(200, 650),
1828 /*radius=*/75,
1829 /*stop_count=*/gradient_colors.size(),
1830 /*colors=*/gradient_colors.data(),
1831 /*stops=*/stops.data(),
1832 /*tile_mode=*/DlTileMode::kMirror));
1833 draw_rrect_as_path(DlRect::MakeLTRB(100, 610, 300, 690), 40, 40, paint);
1834 draw_rrect_as_path(DlRect::MakeLTRB(160, 550, 240, 750), 40, 40, paint);
1835
1836 auto matrix = DlMatrix::MakeTranslation({520, 20});
1837 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1839 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1840 DlImageSampling::kMipmapLinear, &matrix));
1841 for (int i = 1; i <= 10; i++) {
1842 int j = 11 - i;
1843 draw_rrect_as_path(DlRect::MakeLTRB(720 - i * 20, 220 - j * 20, //
1844 720 + i * 20, 220 + j * 20),
1845 i * 10, j * 10, paint);
1846 }
1847 matrix = DlMatrix::MakeTranslation({800, 300});
1848 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1850 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1851 DlImageSampling::kMipmapLinear, &matrix));
1852
1853 draw_rrect_as_path(DlRect::MakeLTRB(800, 410, 1000, 490), 40, 40, paint);
1854 draw_rrect_as_path(DlRect::MakeLTRB(860, 350, 940, 550), 40, 40, paint);
1855
1856 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1857}
1858
1859TEST_P(AiksTest, CoverageOriginShouldBeAccountedForInSubpasses) {
1860 auto callback = [&]() -> sk_sp<DisplayList> {
1861 DisplayListBuilder builder;
1862 builder.Scale(GetContentScale().x, GetContentScale().y);
1863
1864 DlPaint alpha;
1866
1867 auto current = Point{25, 25};
1868 const auto offset = Point{25, 25};
1869 const auto size = Size(100, 100);
1870
1871 static PlaygroundPoint point_a(Point(40, 40), 10, Color::White());
1872 static PlaygroundPoint point_b(Point(160, 160), 10, Color::White());
1873 auto [b0, b1] = DrawPlaygroundLine(point_a, point_b);
1874 DlRect bounds = DlRect::MakeLTRB(b0.x, b0.y, b1.x, b1.y);
1875
1876 DlPaint stroke_paint;
1877 stroke_paint.setColor(DlColor::kYellow());
1878 stroke_paint.setStrokeWidth(5);
1879 stroke_paint.setDrawStyle(DlDrawStyle::kStroke);
1880 builder.DrawRect(bounds, stroke_paint);
1881
1882 builder.SaveLayer(bounds, &alpha);
1883
1884 DlPaint paint;
1885 paint.setColor(DlColor::kRed());
1886 builder.DrawRect(
1887 DlRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
1888
1889 paint.setColor(DlColor::kGreen());
1890 current += offset;
1891 builder.DrawRect(
1892 DlRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
1893
1894 paint.setColor(DlColor::kBlue());
1895 current += offset;
1896 builder.DrawRect(
1897 DlRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
1898
1899 builder.Restore();
1900
1901 return builder.Build();
1902 };
1903
1904 ASSERT_TRUE(OpenPlaygroundHere(callback));
1905}
1906
1907TEST_P(AiksTest, SaveLayerDrawsBehindSubsequentEntities) {
1908 // Compare with https://fiddle.skia.org/c/9e03de8567ffb49e7e83f53b64bcf636
1909 DisplayListBuilder builder;
1910 DlPaint paint;
1911
1912 paint.setColor(DlColor::kBlack());
1913 DlRect rect = DlRect::MakeXYWH(25, 25, 25, 25);
1914 builder.DrawRect(rect, paint);
1915
1916 builder.Translate(10, 10);
1917
1918 DlPaint save_paint;
1919 builder.SaveLayer(std::nullopt, &save_paint);
1920
1921 paint.setColor(DlColor::kGreen());
1922 builder.DrawRect(rect, paint);
1923
1924 builder.Restore();
1925
1926 builder.Translate(10, 10);
1927 paint.setColor(DlColor::kRed());
1928 builder.DrawRect(rect, paint);
1929
1930 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1931}
1932
1933TEST_P(AiksTest, SiblingSaveLayerBoundsAreRespected) {
1934 DisplayListBuilder builder;
1935 DlPaint paint;
1936 DlRect rect = DlRect::MakeXYWH(0, 0, 1000, 1000);
1937
1938 // Black, green, and red squares offset by [10, 10].
1939 {
1940 DlPaint save_paint;
1941 DlRect bounds = DlRect::MakeXYWH(25, 25, 25, 25);
1942 builder.SaveLayer(bounds, &save_paint);
1943 paint.setColor(DlColor::kBlack());
1944 builder.DrawRect(rect, paint);
1945 builder.Restore();
1946 }
1947
1948 {
1949 DlPaint save_paint;
1950 DlRect bounds = DlRect::MakeXYWH(35, 35, 25, 25);
1951 builder.SaveLayer(bounds, &save_paint);
1952 paint.setColor(DlColor::kGreen());
1953 builder.DrawRect(rect, paint);
1954 builder.Restore();
1955 }
1956
1957 {
1958 DlPaint save_paint;
1959 DlRect bounds = DlRect::MakeXYWH(45, 45, 25, 25);
1960 builder.SaveLayer(bounds, &save_paint);
1961 paint.setColor(DlColor::kRed());
1962 builder.DrawRect(rect, paint);
1963 builder.Restore();
1964 }
1965
1966 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1967}
1968
1969TEST_P(AiksTest, CanRenderClippedLayers) {
1970 DisplayListBuilder builder;
1971
1972 DlPaint paint;
1973 paint.setColor(DlColor::kWhite());
1974 builder.DrawPaint(paint);
1975
1976 // Draw a green circle on the screen.
1977 {
1978 // Increase the clip depth for the savelayer to contend with.
1979 DlPath path = DlPath::MakeCircle(DlPoint(100, 100), 50);
1980 builder.ClipPath(path);
1981
1982 DlRect bounds = DlRect::MakeXYWH(50, 50, 100, 100);
1983 DlPaint save_paint;
1984 builder.SaveLayer(bounds, &save_paint);
1985
1986 // Fill the layer with white.
1987 paint.setColor(DlColor::kWhite());
1988 builder.DrawRect(DlRect::MakeSize(DlSize(400, 400)), paint);
1989 // Fill the layer with green, but do so with a color blend that can't be
1990 // collapsed into the parent pass.
1991 paint.setColor(DlColor::kGreen());
1992 paint.setBlendMode(DlBlendMode::kHardLight);
1993 builder.DrawRect(DlRect::MakeSize(DlSize(400, 400)), paint);
1994 }
1995
1996 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1997}
1998
1999TEST_P(AiksTest, SaveLayerFiltersScaleWithTransform) {
2000 DisplayListBuilder builder;
2001
2002 builder.Scale(GetContentScale().x, GetContentScale().y);
2003 builder.Translate(100, 100);
2004
2005 auto texture = DlImageImpeller::Make(CreateTextureForFixture("boston.jpg"));
2006 auto draw_image_layer = [&builder, &texture](const DlPaint& paint) {
2007 builder.SaveLayer(std::nullopt, &paint);
2008 builder.DrawImage(texture, DlPoint(), DlImageSampling::kLinear);
2009 builder.Restore();
2010 };
2011
2012 DlPaint effect_paint;
2013 effect_paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 6));
2014 draw_image_layer(effect_paint);
2015
2016 builder.Translate(300, 300);
2017 builder.Scale(3, 3);
2018 draw_image_layer(effect_paint);
2019
2020 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2021}
2022
2023TEST_P(AiksTest, FastEllipticalRRectMaskBlursRenderCorrectly) {
2024 DisplayListBuilder builder;
2025
2026 builder.Scale(GetContentScale().x, GetContentScale().y);
2027 DlPaint paint;
2028 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 1));
2029
2030 DlPaint save_paint;
2031 save_paint.setColor(DlColor::kWhite());
2032 builder.DrawPaint(save_paint);
2033
2034 paint.setColor(DlColor::kBlue());
2035 for (int i = 0; i < 5; i++) {
2036 Scalar y = i * 125;
2037 Scalar y_radius = i * 15;
2038 for (int j = 0; j < 5; j++) {
2039 Scalar x = j * 125;
2040 Scalar x_radius = j * 15;
2041 builder.DrawRoundRect(
2043 DlRect::MakeXYWH(x + 50, y + 50, 100.0f, 100.0f), //
2044 x_radius, y_radius),
2045 paint);
2046 }
2047 }
2048
2049 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2050}
2051
2052TEST_P(AiksTest, PipelineBlendSingleParameter) {
2053 DisplayListBuilder builder;
2054
2055 // Should render a green square in the middle of a blue circle.
2056 DlPaint paint;
2057 builder.SaveLayer(std::nullopt, &paint);
2058 {
2059 builder.Translate(100, 100);
2060 paint.setColor(DlColor::kBlue());
2061 builder.DrawCircle(DlPoint(200, 200), 200, paint);
2062 builder.ClipRect(DlRect::MakeXYWH(100, 100, 200, 200));
2063
2064 paint.setColor(DlColor::kGreen());
2065 paint.setBlendMode(DlBlendMode::kSrcOver);
2067 DlColorFilter::MakeBlend(DlColor::kWhite(), DlBlendMode::kDst)));
2068 builder.DrawCircle(DlPoint(200, 200), 200, paint);
2069 builder.Restore();
2070 }
2071
2072 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2073}
2074
2075// Creates an image matrix filter that scales large content such that it would
2076// exceed the max texture size. See
2077// https://github.com/flutter/flutter/issues/128912
2078TEST_P(AiksTest, MassiveScalingMatrixImageFilter) {
2079 if (GetBackend() == PlaygroundBackend::kVulkan) {
2080 GTEST_SKIP() << "Swiftshader is running out of memory on this example.";
2081 }
2082 DisplayListBuilder builder(DlRect::MakeSize(DlSize(1000, 1000)));
2083
2084 auto filter = DlImageFilter::MakeMatrix(
2085 DlMatrix::MakeScale({0.001, 0.001, 1}), DlImageSampling::kLinear);
2086
2087 DlPaint paint;
2088 paint.setImageFilter(filter);
2089 builder.SaveLayer(std::nullopt, &paint);
2090 {
2091 DlPaint paint;
2092 paint.setColor(DlColor::kRed());
2093 builder.DrawRect(DlRect::MakeLTRB(0, 0, 100000, 100000), paint);
2094 }
2095 builder.Restore();
2096
2097 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2098}
2099
2100TEST_P(AiksTest, NoDimplesInRRectPath) {
2101 Scalar width = 200.f;
2102 Scalar height = 60.f;
2103 Scalar corner = 1.f;
2104 auto callback = [&]() -> sk_sp<DisplayList> {
2105 if (AiksTest::ImGuiBegin("Controls", nullptr,
2106 ImGuiWindowFlags_AlwaysAutoResize)) {
2107 ImGui::SliderFloat("width", &width, 0, 200);
2108 ImGui::SliderFloat("height", &height, 0, 200);
2109 ImGui::SliderFloat("corner", &corner, 0, 1);
2110 ImGui::End();
2111 }
2112
2113 DisplayListBuilder builder;
2114 builder.Scale(GetContentScale().x, GetContentScale().y);
2115
2116 DlPaint background_paint;
2117 background_paint.setColor(DlColor(1, 0.1, 0.1, 0.1, DlColorSpace::kSRGB));
2118 builder.DrawPaint(background_paint);
2119
2120 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue()};
2121 std::vector<Scalar> stops = {0.0, 1.0};
2122
2123 DlPaint paint;
2124 auto gradient = DlColorSource::MakeLinear(DlPoint(0, 0), DlPoint(200, 200),
2125 2, colors.data(), stops.data(),
2126 DlTileMode::kClamp);
2127 paint.setColorSource(gradient);
2128 paint.setColor(DlColor::kWhite());
2129 paint.setDrawStyle(DlDrawStyle::kStroke);
2130 paint.setStrokeWidth(20);
2131
2132 builder.Save();
2133 builder.Translate(100, 100);
2134
2135 Scalar corner_x = ((1 - corner) * 50) + 50;
2136 Scalar corner_y = corner * 50 + 50;
2138 DlRect::MakeXYWH(0, 0, width, height), corner_x, corner_y);
2139 builder.DrawRoundRect(rrect, paint);
2140 builder.Restore();
2141 return builder.Build();
2142 };
2143 ASSERT_TRUE(OpenPlaygroundHere(callback));
2144}
2145
2146TEST_P(AiksTest, BackdropFilterOverUnclosedClip) {
2147 DisplayListBuilder builder;
2148
2149 builder.DrawPaint(DlPaint().setColor(DlColor::kWhite()));
2150 builder.Save();
2151 {
2152 builder.ClipRect(DlRect::MakeLTRB(100, 100, 800, 800));
2153
2154 builder.Save();
2155 {
2156 builder.ClipRect(DlRect::MakeLTRB(600, 600, 800, 800));
2157 builder.DrawPaint(DlPaint().setColor(DlColor::kRed()));
2158 builder.DrawPaint(DlPaint().setColor(DlColor::kBlue().withAlphaF(0.5)));
2159 builder.ClipRect(DlRect::MakeLTRB(700, 700, 750, 800));
2160 builder.DrawPaint(DlPaint().setColor(DlColor::kRed().withAlphaF(0.5)));
2161 }
2162 builder.Restore();
2163
2164 auto image_filter = DlImageFilter::MakeBlur(10, 10, DlTileMode::kDecal);
2165 builder.SaveLayer(std::nullopt, nullptr, image_filter.get());
2166 }
2167 builder.Restore();
2168 builder.DrawCircle(DlPoint(100, 100), 100,
2169 DlPaint().setColor(DlColor::kAqua()));
2170
2171 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2172}
2173
2174} // namespace testing
2175} // namespace impeller
bool full_circles
Scalar vertical_scale
bool sweeps_over_360
void DrawOval(const DlRect &bounds, const DlPaint &paint) override
void ClipRect(const DlRect &rect, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false) override
void DrawImageRect(const sk_sp< DlImage > &image, const DlRect &src, const DlRect &dst, DlImageSampling sampling, const DlPaint *paint=nullptr, DlSrcRectConstraint constraint=DlSrcRectConstraint::kFast) override
void DrawRoundRect(const DlRoundRect &rrect, const DlPaint &paint) override
void DrawArc(const DlRect &bounds, DlScalar start, DlScalar sweep, bool useCenter, const DlPaint &paint) override
void DrawImage(const sk_sp< DlImage > &image, const DlPoint &point, DlImageSampling sampling, const DlPaint *paint=nullptr) override
void DrawColor(DlColor color, DlBlendMode mode) override
void DrawCircle(const DlPoint &center, DlScalar radius, const DlPaint &paint) override
void SaveLayer(const std::optional< DlRect > &bounds, const DlPaint *paint=nullptr, const DlImageFilter *backdrop=nullptr, std::optional< int64_t > backdrop_id=std::nullopt) override
void ClipRoundRect(const DlRoundRect &rrect, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false) override
void Rotate(DlScalar degrees) override
void Scale(DlScalar sx, DlScalar sy) override
void Skew(DlScalar sx, DlScalar sy) override
void Translate(DlScalar tx, DlScalar ty) override
void DrawPaint(const DlPaint &paint) override
sk_sp< DisplayList > Build()
Definition dl_builder.cc:66
void DrawPath(const DlPath &path, const DlPaint &paint) override
void ClipPath(const DlPath &path, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false) override
void ClipOval(const DlRect &bounds, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false) override
void Transform(const DlMatrix &matrix) override
void DrawRect(const DlRect &rect, const DlPaint &paint) override
static std::shared_ptr< DlMaskFilter > Make(DlBlurStyle style, SkScalar sigma, bool respect_ctm=true)
Developer-facing API for rendering anything within the engine.
Definition dl_canvas.h:32
static std::shared_ptr< const DlColorFilter > MakeBlend(DlColor color, DlBlendMode mode)
static std::shared_ptr< DlColorSource > MakeImage(const sk_sp< const DlImage > &image, DlTileMode horizontal_tile_mode, DlTileMode vertical_tile_mode, DlImageSampling sampling=DlImageSampling::kLinear, const DlMatrix *matrix=nullptr)
static std::shared_ptr< DlColorSource > MakeLinear(const DlPoint start_point, const DlPoint end_point, uint32_t stop_count, const DlColor *colors, const float *stops, DlTileMode tile_mode, const DlMatrix *matrix=nullptr)
static std::shared_ptr< DlColorSource > MakeRadial(DlPoint center, DlScalar radius, uint32_t stop_count, const DlColor *colors, const float *stops, DlTileMode tile_mode, const DlMatrix *matrix=nullptr)
static std::shared_ptr< DlImageFilter > MakeBlur(DlScalar sigma_x, DlScalar sigma_y, DlTileMode tile_mode)
static std::shared_ptr< DlImageFilter > MakeColorFilter(const std::shared_ptr< const DlColorFilter > &filter)
static std::shared_ptr< DlImageFilter > MakeMatrix(const DlMatrix &matrix, DlImageSampling sampling)
DlPaint & setColor(DlColor color)
Definition dl_paint.h:70
DlPaint & setInvertColors(bool isInvertColors)
Definition dl_paint.h:64
DlPaint & setStrokeCap(DlStrokeCap cap)
Definition dl_paint.h:101
DlPaint & setStrokeWidth(float width)
Definition dl_paint.h:115
DlPaint & setStrokeMiter(float miter)
Definition dl_paint.h:121
DlPaint & setBlendMode(DlBlendMode mode)
Definition dl_paint.h:85
DlPaint & setImageFilter(std::nullptr_t filter)
Definition dl_paint.h:167
DlPaint & setMaskFilter(std::nullptr_t filter)
Definition dl_paint.h:185
DlPaint & setDrawStyle(DlDrawStyle style)
Definition dl_paint.h:93
DlPaint & setStrokeJoin(DlStrokeJoin join)
Definition dl_paint.h:109
DlPaint & setColorFilter(std::nullptr_t filter)
Definition dl_paint.h:149
DlPaint & setColorSource(std::nullptr_t source)
Definition dl_paint.h:131
DlPathBuilder & MoveTo(DlPoint p2)
Start a new contour that will originate at the indicated point p2.
const DlPath TakePath()
Returns the path constructed by this path builder and resets its internal state to the default state ...
DlPathBuilder & AddCircle(DlPoint center, DlScalar radius)
Append a closed circular contour to the path centered on the provided point at the provided radius.
DlPathBuilder & AddRoundRect(const DlRoundRect &round_rect)
Append a closed rounded rect contour to the path.
static DlPath MakeCircle(const DlPoint center, DlScalar radius)
Definition dl_path.cc:68
static DlPath MakeRectXYWH(DlScalar x, DlScalar y, DlScalar width, DlScalar height)
Definition dl_path.cc:50
static DlPath MakeRect(const DlRect &rect)
Definition dl_path.cc:39
static DlPath MakeRoundRectXY(const DlRect &rect, DlScalar x_radius, DlScalar y_radius, bool counter_clock_wise=false)
Definition dl_path.cc:76
static bool ImGuiBegin(const char *name, bool *p_open, ImGuiWindowFlags flags)
static sk_sp< DlImageImpeller > Make(std::shared_ptr< Texture > texture, OwningContext owning_context=OwningContext::kIO)
int32_t x
FlutterVulkanImage * image
FlutterDesktopBinaryReply callback
FlTexture * texture
double y
impeller::Scalar DlScalar
impeller::ISize32 DlISize
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
impeller::Size DlSize
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition switch_defs.h:52
static constexpr DlScalar kEhCloseEnough
impeller::Point DlPoint
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set profile Make the profiler discard new samples once the profiler sample buffer is full When this flag is not the profiler sample buffer is used as a ring buffer
Definition switch_defs.h:98
AiksPlayground AiksTest
TEST_P(AiksTest, DrawAtlasNoColor)
float Scalar
Definition scalar.h:19
std::tuple< Point, Point > DrawPlaygroundLine(PlaygroundPoint &point_a, PlaygroundPoint &point_b)
Definition widgets.cc:51
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition formats.h:99
constexpr float kSqrt2
Definition constants.h:47
void Close(PathBuilder *builder)
constexpr const char * PixelFormatToString(PixelFormat format)
Definition formats.h:140
int32_t height
int32_t width
static constexpr DlColor kWhite()
Definition dl_color.h:70
static constexpr DlColor kBlue()
Definition dl_color.h:73
static constexpr DlColor RGBA(DlScalar r, DlScalar g, DlScalar b, DlScalar a)
Construct a 32 bit color from floating point R, G, B, and A color channels.
Definition dl_color.h:48
static constexpr DlColor kBlack()
Definition dl_color.h:69
static constexpr DlColor ARGB(DlScalar a, DlScalar r, DlScalar g, DlScalar b)
Construct a 32 bit color from floating point A, R, G, and B color channels.
Definition dl_color.h:57
static constexpr DlColor kAqua()
Definition dl_color.h:86
static constexpr DlColor kYellow()
Definition dl_color.h:76
static constexpr DlColor kPurple()
Definition dl_color.h:88
static constexpr DlColor kMidGrey()
Definition dl_color.h:78
static constexpr DlColor kTransparent()
Definition dl_color.h:68
static constexpr DlColor kRed()
Definition dl_color.h:71
static constexpr DlColor kGreen()
Definition dl_color.h:72
static constexpr DlColor kOrange()
Definition dl_color.h:87
constexpr DlColor modulateOpacity(DlScalar opacity) const
Definition dl_color.h:150
static constexpr Color White()
Definition color.h:264
A 4x4 matrix using column-major storage.
Definition matrix.h:37
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition matrix.h:95
static Matrix MakeRotationY(Radians r)
Definition matrix.h:208
static Matrix MakePerspective(Radians fov_y, Scalar aspect_ratio, Scalar z_near, Scalar z_far)
Definition matrix.h:642
static constexpr Matrix MakeScale(const Vector3 &s)
Definition matrix.h:104
static RoundRect MakeRectRadii(const Rect &rect, const RoundingRadii &radii)
Definition round_rect.cc:9
static RoundRect MakeRectXY(const Rect &rect, Scalar x_radius, Scalar y_radius)
Definition round_rect.h:31
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition rect.h:136
static constexpr TRect MakeSize(const TSize< U > &size)
Definition rect.h:150
constexpr TRect< T > Expand(T left, T top, T right, T bottom) const
Returns a rectangle with expanded edges. Negative expansion results in shrinking.
Definition rect.h:618
constexpr TRect< T > Shift(T dx, T dy) const
Returns a new rectangle translated by the given offset.
Definition rect.h:602
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition rect.h:129
Type height
Definition size.h:29
Type width
Definition size.h:28
const size_t start