Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
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
856void RenderArcFarmForOverlappingCapsTest(DisplayListBuilder& builder,
857 const DlPaint& paint) {
858 builder.Save();
859 builder.Translate(40, 30);
860 const Rect arc_bounds = Rect::MakeLTRB(0, 0, 40, 40);
861 for (int stroke_width = 10; stroke_width <= 40; stroke_width += 3) {
862 DlPaint modified_paint = DlPaint(paint);
863 modified_paint.setStrokeWidth(stroke_width);
864 builder.Save();
865 for (int sweep = 160; sweep <= 360; sweep += 20) {
866 builder.DrawArc(arc_bounds, 0, sweep, false, modified_paint);
867 builder.Translate(84, 0);
868 }
869 builder.Restore();
870 builder.Translate(0, 44 + stroke_width);
871 }
872 builder.Restore();
873}
874} // namespace
875
876TEST_P(AiksTest, FilledArcsRenderCorrectly) {
877 DisplayListBuilder builder;
878 builder.Scale(GetContentScale().x, GetContentScale().y);
879 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
880
881 DlPaint paint;
882 paint.setColor(DlColor::kBlue());
883
884 RenderArcFarm(builder, paint,
885 {
886 .use_center = false,
887 .full_circles = false,
888 });
889
890 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
891}
892
893TEST_P(AiksTest, TranslucentFilledArcsRenderCorrectly) {
894 DisplayListBuilder builder;
895 builder.Scale(GetContentScale().x, GetContentScale().y);
896 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
897
898 DlPaint paint;
899 paint.setColor(DlColor::kBlue().modulateOpacity(0.5));
900
901 RenderArcFarm(builder, paint,
902 {
903 .use_center = false,
904 .full_circles = false,
905 });
906
907 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
908}
909
910TEST_P(AiksTest, FilledArcsRenderCorrectlyWithCenter) {
911 DisplayListBuilder builder;
912 builder.Scale(GetContentScale().x, GetContentScale().y);
913 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
914
915 DlPaint paint;
916 paint.setColor(DlColor::kBlue());
917
918 RenderArcFarm(builder, paint,
919 {
920 .use_center = true,
921 .full_circles = false,
922 });
923
924 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
925}
926
927TEST_P(AiksTest, NonSquareFilledArcsRenderCorrectly) {
928 DisplayListBuilder builder;
929 builder.Scale(GetContentScale().x, GetContentScale().y);
930 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
931
932 DlPaint paint;
933 paint.setColor(DlColor::kBlue());
934
935 RenderArcFarm(builder, paint,
936 {
937 .use_center = false,
938 .full_circles = false,
939 .vertical_scale = 0.8f,
940 });
941
942 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
943}
944
945TEST_P(AiksTest, NonSquareFilledArcsRenderCorrectlyWithCenter) {
946 DisplayListBuilder builder;
947 builder.Scale(GetContentScale().x, GetContentScale().y);
948 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
949
950 DlPaint paint;
951 paint.setColor(DlColor::kBlue());
952
953 RenderArcFarm(builder, paint,
954 {
955 .use_center = true,
956 .full_circles = false,
957 .vertical_scale = 0.8f,
958 });
959
960 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
961}
962
963TEST_P(AiksTest, StrokedArcsRenderCorrectlyWithButtEnds) {
964 DisplayListBuilder builder;
965 builder.Scale(GetContentScale().x, GetContentScale().y);
966 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
967
968 DlPaint paint;
969 paint.setDrawStyle(DlDrawStyle::kStroke);
970 paint.setStrokeWidth(6.0f);
971 paint.setStrokeCap(DlStrokeCap::kButt);
972 paint.setColor(DlColor::kBlue());
973
974 RenderArcFarm(builder, paint,
975 {
976 .use_center = false,
977 .full_circles = false,
978 });
979
980 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
981}
982
983TEST_P(AiksTest, StrokedArcsRenderCorrectlyWithSquareEnds) {
984 DisplayListBuilder builder;
985 builder.Scale(GetContentScale().x, GetContentScale().y);
986 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
987
988 DlPaint paint;
989 paint.setDrawStyle(DlDrawStyle::kStroke);
990 paint.setStrokeWidth(6.0f);
991 paint.setStrokeCap(DlStrokeCap::kSquare);
992 paint.setColor(DlColor::kBlue());
993
994 RenderArcFarm(builder, paint,
995 {
996 .use_center = false,
997 .full_circles = false,
998 });
999
1000 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1001}
1002
1003TEST_P(AiksTest, StrokedArcsRenderCorrectlyWithTranslucencyAndSquareEnds) {
1004 DisplayListBuilder builder;
1005 builder.Scale(GetContentScale().x, GetContentScale().y);
1006 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1007
1008 DlPaint paint;
1009 paint.setDrawStyle(DlDrawStyle::kStroke);
1010 paint.setStrokeCap(DlStrokeCap::kSquare);
1011 paint.setColor(DlColor::kBlue().modulateOpacity(0.5));
1012
1013 RenderArcFarmForOverlappingCapsTest(builder, paint);
1014
1015 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1016}
1017
1018TEST_P(AiksTest, StrokedArcsRenderCorrectlyWithRoundEnds) {
1019 DisplayListBuilder builder;
1020 builder.Scale(GetContentScale().x, GetContentScale().y);
1021 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1022
1023 DlPaint paint;
1024 paint.setDrawStyle(DlDrawStyle::kStroke);
1025 paint.setStrokeWidth(6.0f);
1026 paint.setStrokeCap(DlStrokeCap::kRound);
1027 paint.setColor(DlColor::kBlue());
1028
1029 RenderArcFarm(builder, paint,
1030 {
1031 .use_center = false,
1032 .full_circles = false,
1033 });
1034
1035 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1036}
1037
1038TEST_P(AiksTest, StrokedArcsRenderCorrectlyWithTranslucencyAndRoundEnds) {
1039 DisplayListBuilder builder;
1040 builder.Scale(GetContentScale().x, GetContentScale().y);
1041 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1042
1043 DlPaint paint;
1044 paint.setDrawStyle(DlDrawStyle::kStroke);
1045 paint.setStrokeCap(DlStrokeCap::kRound);
1046 paint.setColor(DlColor::kBlue().modulateOpacity(0.5));
1047
1048 RenderArcFarmForOverlappingCapsTest(builder, paint);
1049
1050 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1051}
1052
1053TEST_P(AiksTest, StrokedArcsRenderCorrectlyWithBevelJoinsAndCenter) {
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(6.0f);
1061 paint.setStrokeJoin(DlStrokeJoin::kBevel);
1062 paint.setColor(DlColor::kBlue());
1063
1064 RenderArcFarm(builder, paint,
1065 {
1066 .use_center = true,
1067 .full_circles = false,
1068 .sweeps_over_360 = true,
1069 });
1070
1071 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1072}
1073
1074TEST_P(AiksTest, StrokedArcsRenderCorrectlyWithMiterJoinsAndCenter) {
1075 DisplayListBuilder builder;
1076 builder.Scale(GetContentScale().x, GetContentScale().y);
1077 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1078
1079 DlPaint paint;
1080 paint.setDrawStyle(DlDrawStyle::kStroke);
1081 paint.setStrokeWidth(6.0f);
1082 paint.setStrokeJoin(DlStrokeJoin::kMiter);
1083 // Default miter of 4.0 does a miter on all of the centers, but
1084 // using 3.0 will show some bevels on the widest interior angles...
1085 paint.setStrokeMiter(3.0f);
1086 paint.setColor(DlColor::kBlue());
1087
1088 RenderArcFarm(builder, paint,
1089 {
1090 .use_center = true,
1091 .full_circles = false,
1092 .sweeps_over_360 = true,
1093 });
1094
1095 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1096}
1097
1098TEST_P(AiksTest, StrokedArcsRenderCorrectlyWithRoundJoinsAndCenter) {
1099 DisplayListBuilder builder;
1100 builder.Scale(GetContentScale().x, GetContentScale().y);
1101 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1102
1103 DlPaint paint;
1104 paint.setDrawStyle(DlDrawStyle::kStroke);
1105 paint.setStrokeWidth(6.0f);
1106 paint.setStrokeJoin(DlStrokeJoin::kRound);
1107 paint.setColor(DlColor::kBlue());
1108
1109 RenderArcFarm(builder, paint,
1110 {
1111 .use_center = true,
1112 .full_circles = false,
1113 .sweeps_over_360 = true,
1114 });
1115
1116 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1117}
1118
1119TEST_P(AiksTest, StrokedArcsRenderCorrectlyWithSquareAndButtEnds) {
1120 DisplayListBuilder builder;
1121 builder.Scale(GetContentScale().x, GetContentScale().y);
1122 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1123
1124 DlPaint paint;
1125 paint.setDrawStyle(DlDrawStyle::kStroke);
1126 paint.setStrokeWidth(8.0f);
1127 paint.setStrokeCap(DlStrokeCap::kSquare);
1128 paint.setColor(DlColor::kRed());
1129
1130 RenderArcFarm(builder, paint,
1131 {
1132 .use_center = false,
1133 .full_circles = false,
1134 });
1135
1136 paint.setStrokeCap(DlStrokeCap::kButt);
1137 paint.setColor(DlColor::kBlue());
1138
1139 RenderArcFarm(builder, paint,
1140 {
1141 .use_center = false,
1142 .full_circles = false,
1143 });
1144
1145 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1146}
1147
1148TEST_P(AiksTest, StrokedArcsRenderCorrectlyWithSquareAndButtAndRoundEnds) {
1149 DisplayListBuilder builder;
1150 builder.Scale(GetContentScale().x, GetContentScale().y);
1151 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1152
1153 DlPaint paint;
1154 paint.setDrawStyle(DlDrawStyle::kStroke);
1155 paint.setStrokeWidth(8.0f);
1156 paint.setStrokeCap(DlStrokeCap::kSquare);
1157 paint.setColor(DlColor::kRed());
1158
1159 RenderArcFarm(builder, paint,
1160 {
1161 .use_center = false,
1162 .full_circles = false,
1163 });
1164
1165 paint.setStrokeCap(DlStrokeCap::kRound);
1166 paint.setColor(DlColor::kGreen());
1167
1168 RenderArcFarm(builder, paint,
1169 {
1170 .use_center = false,
1171 .full_circles = false,
1172 });
1173
1174 paint.setStrokeCap(DlStrokeCap::kButt);
1175 paint.setColor(DlColor::kBlue());
1176
1177 RenderArcFarm(builder, paint,
1178 {
1179 .use_center = false,
1180 .full_circles = false,
1181 });
1182
1183 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1184}
1185
1186TEST_P(AiksTest, StrokedArcsCoverFullArcWithButtEnds) {
1187 // This test compares the rendering of a full circle arc against a partial
1188 // arc by drawing a one over the other in high contrast. If the partial
1189 // arc misses any pixels that were drawn by the full arc, there will be
1190 // some "pixel dirt" around the missing "erased" parts of the arcs. This
1191 // case arises while rendering a CircularProgressIndicator with a background
1192 // color where we want the rendering of the background full arc to hit the
1193 // same pixels around the edges as the partial arc that covers it.
1194 //
1195 // In this case we draw a full blue circle and then draw a partial arc
1196 // over it in the background color (white).
1197
1198 DisplayListBuilder builder;
1199 builder.Scale(GetContentScale().x, GetContentScale().y);
1200 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1201
1202 DlPaint paint;
1203 paint.setDrawStyle(DlDrawStyle::kStroke);
1204 paint.setStrokeWidth(6.0f);
1205 paint.setStrokeCap(DlStrokeCap::kButt);
1206 paint.setColor(DlColor::kBlue());
1207
1208 // First draw full circles in blue to establish the pixels to be erased
1209 RenderArcFarm(builder, paint,
1210 {
1211 .use_center = false,
1212 .full_circles = true,
1213 });
1214
1215 paint.setColor(DlColor::kWhite());
1216
1217 // Then draw partial arcs in white over the circles to "erase" them
1218 RenderArcFarm(builder, paint,
1219 {
1220 .use_center = false,
1221 .full_circles = false,
1222 });
1223
1224 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1225}
1226
1227TEST_P(AiksTest, FilledRoundRectsRenderCorrectly) {
1228 DisplayListBuilder builder;
1229 builder.Scale(GetContentScale().x, GetContentScale().y);
1230 DlPaint paint;
1231 const int color_count = 3;
1232 DlColor colors[color_count] = {
1235 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
1236 };
1237
1238 paint.setColor(DlColor::kWhite());
1239 builder.DrawPaint(paint);
1240
1241 int c_index = 0;
1242 for (int i = 0; i < 4; i++) {
1243 for (int j = 0; j < 4; j++) {
1244 paint.setColor(colors[(c_index++) % color_count]);
1245 builder.DrawRoundRect(
1247 DlRect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80), //
1248 i * 5 + 10, j * 5 + 10),
1249 paint);
1250 }
1251 }
1252 paint.setColor(colors[(c_index++) % color_count]);
1253 builder.DrawRoundRect(
1254 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(10, 420, 380, 80), 40, 40),
1255 paint);
1256 paint.setColor(colors[(c_index++) % color_count]);
1257 builder.DrawRoundRect(
1258 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(410, 20, 80, 380), 40, 40),
1259 paint);
1260
1261 DlColor gradient_colors[7] = {
1262 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
1263 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
1264 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
1265 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
1266 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
1267 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
1268 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
1269 };
1270 DlScalar stops[7] = {
1271 0.0,
1272 (1.0 / 6.0) * 1,
1273 (1.0 / 6.0) * 2,
1274 (1.0 / 6.0) * 3,
1275 (1.0 / 6.0) * 4,
1276 (1.0 / 6.0) * 5,
1277 1.0,
1278 };
1279 auto texture = CreateTextureForFixture("airplane.jpg",
1280 /*enable_mipmapping=*/true);
1282
1283 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1285 DlPoint(550, 550), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
1286 for (int i = 1; i <= 10; i++) {
1287 int j = 11 - i;
1288 builder.DrawRoundRect(
1289 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(550 - i * 20, 550 - j * 20, //
1290 550 + i * 20, 550 + j * 20),
1291 i * 10, j * 10),
1292 paint);
1293 }
1294
1295 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1297 DlPoint(200, 650), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
1298 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1299 builder.DrawRoundRect(
1300 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(100, 610, 300, 690), 40, 40),
1301 paint);
1302 builder.DrawRoundRect(
1303 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(160, 550, 240, 750), 40, 40),
1304 paint);
1305
1306 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1307 DlMatrix local_matrix = DlMatrix::MakeTranslation({520, 20});
1309 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
1310 DlImageSampling::kNearestNeighbor, &local_matrix));
1311 for (int i = 1; i <= 10; i++) {
1312 int j = 11 - i;
1313 builder.DrawRoundRect(
1314 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(720 - i * 20, 220 - j * 20, //
1315 720 + i * 20, 220 + j * 20),
1316 i * 10, j * 10),
1317 paint);
1318 }
1319
1320 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1321 local_matrix = DlMatrix::MakeTranslation({800, 300});
1323 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
1324 DlImageSampling::kNearestNeighbor, &local_matrix));
1325 builder.DrawRoundRect(
1326 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(800, 410, 1000, 490), 40, 40),
1327 paint);
1328 builder.DrawRoundRect(
1329 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(860, 350, 940, 550), 40, 40),
1330 paint);
1331
1332 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1333}
1334
1335TEST_P(AiksTest, SolidColorCirclesOvalsRRectsMaskBlurCorrectly) {
1336 DisplayListBuilder builder;
1337 builder.Scale(GetContentScale().x, GetContentScale().y);
1338 DlPaint paint;
1339 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 1.0f));
1340
1341 builder.DrawPaint(DlPaint().setColor(DlColor::kWhite()));
1342
1343 paint.setColor(
1344 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f));
1345 Scalar y = 100.0f;
1346 for (int i = 0; i < 5; i++) {
1347 Scalar x = (i + 1) * 100;
1348 Scalar radius = x / 10.0f;
1349 builder.DrawRect(DlRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
1350 radius, 60.0f - radius),
1351 paint);
1352 }
1353
1354 paint.setColor(DlColor::kBlue());
1355 y += 100.0f;
1356 for (int i = 0; i < 5; i++) {
1357 Scalar x = (i + 1) * 100;
1358 Scalar radius = x / 10.0f;
1359 builder.DrawCircle(DlPoint(x + 25, y + 25), radius, paint);
1360 }
1361
1362 paint.setColor(DlColor::kGreen());
1363 y += 100.0f;
1364 for (int i = 0; i < 5; i++) {
1365 Scalar x = (i + 1) * 100;
1366 Scalar radius = x / 10.0f;
1367 builder.DrawOval(DlRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
1368 radius, 60.0f - radius),
1369 paint);
1370 }
1371
1372 paint.setColor(
1373 DlColor::RGBA(128.0f / 255.0f, 0.0f / 255.0f, 128.0f / 255.0f, 1.0f));
1374 y += 100.0f;
1375 for (int i = 0; i < 5; i++) {
1376 Scalar x = (i + 1) * 100;
1377 Scalar radius = x / 20.0f;
1378 builder.DrawRoundRect(
1379 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(x, y, 60.0f, 60.0f), //
1380 radius, radius),
1381 paint);
1382 }
1383
1384 paint.setColor(
1385 DlColor::RGBA(255.0f / 255.0f, 165.0f / 255.0f, 0.0f / 255.0f, 1.0f));
1386 y += 100.0f;
1387 for (int i = 0; i < 5; i++) {
1388 Scalar x = (i + 1) * 100;
1389 Scalar radius = x / 20.0f;
1390 builder.DrawRoundRect(
1391 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(x, y, 60.0f, 60.0f), //
1392 radius, 5.0f),
1393 paint);
1394 }
1395
1396 auto dl = builder.Build();
1397 ASSERT_TRUE(OpenPlaygroundHere(dl));
1398}
1399
1400TEST_P(AiksTest, CanRenderClippedBackdropFilter) {
1401 DisplayListBuilder builder;
1402
1403 builder.Scale(GetContentScale().x, GetContentScale().y);
1404
1405 // Draw something interesting in the background.
1406 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
1407 DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0)};
1408 std::vector<Scalar> stops = {
1409 0.0,
1410 1.0,
1411 };
1412 DlPaint paint;
1414 /*start_point=*/DlPoint(0, 0), //
1415 /*end_point=*/DlPoint(100, 100), //
1416 /*stop_count=*/2, //
1417 /*colors=*/colors.data(), //
1418 /*stops=*/stops.data(), //
1419 /*tile_mode=*/DlTileMode::kRepeat //
1420 ));
1421
1422 builder.DrawPaint(paint);
1423
1424 DlRect clip_rect = DlRect::MakeLTRB(50, 50, 400, 300);
1425 DlRoundRect clip_rrect = DlRoundRect::MakeRectXY(clip_rect, 100, 100);
1426
1427 // Draw a clipped SaveLayer, where the clip coverage and SaveLayer size are
1428 // the same.
1429 builder.ClipRoundRect(clip_rrect, DlClipOp::kIntersect);
1430
1431 DlPaint save_paint;
1432 auto backdrop_filter = DlImageFilter::MakeColorFilter(
1433 DlColorFilter::MakeBlend(DlColor::kRed(), DlBlendMode::kExclusion));
1434 builder.SaveLayer(clip_rect, &save_paint, backdrop_filter.get());
1435
1436 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1437}
1438
1439TEST_P(AiksTest, CanDrawPerspectiveTransformWithClips) {
1440 // Avoiding `GetSecondsElapsed()` to reduce risk of golden flakiness.
1441 int time = 0;
1442 auto callback = [&]() -> sk_sp<DisplayList> {
1443 DisplayListBuilder builder;
1444
1445 builder.Save();
1446 {
1447 builder.Translate(300, 300);
1448
1449 // 1. Draw/restore a clip before drawing the image, which will get drawn
1450 // to the depth buffer behind the image.
1451 builder.Save();
1452 {
1453 DlPaint paint;
1454 paint.setColor(DlColor::kGreen());
1455 builder.DrawPaint(paint);
1456 builder.ClipRect(DlRect::MakeLTRB(-180, -180, 180, 180),
1457 DlClipOp::kDifference);
1458
1459 paint.setColor(DlColor::kBlack());
1460 builder.DrawPaint(paint);
1461 }
1462 builder.Restore(); // Restore rectangle difference clip.
1463
1464 builder.Save();
1465 {
1466 // 2. Draw an oval clip that applies to the image, which will get drawn
1467 // in front of the image on the depth buffer.
1468 builder.ClipOval(DlRect::MakeLTRB(-200, -200, 200, 200));
1469
1470 Matrix result =
1471 Matrix(1.0, 0.0, 0.0, 0.0, //
1472 0.0, 1.0, 0.0, 0.0, //
1473 0.0, 0.0, 1.0, 0.003, //
1474 0.0, 0.0, 0.0, 1.0) *
1475 Matrix::MakeRotationY({Radians{-1.0f + (time++ / 60.0f)}});
1476
1477 // 3. Draw the rotating image with a perspective transform.
1478 builder.Transform(result);
1479
1480 auto image =
1481 DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
1482 auto position =
1483 -DlPoint(image->GetSize().width, image->GetSize().height) * 0.5;
1484 builder.DrawImage(image, position, {});
1485 }
1486 builder.Restore(); // Restore oval intersect clip.
1487
1488 // 4. Draw a semi-translucent blue circle atop all previous draws.
1489 DlPaint paint;
1490 paint.setColor(DlColor::kBlue().modulateOpacity(0.4));
1491 builder.DrawCircle(DlPoint(), 230, paint);
1492 }
1493 builder.Restore(); // Restore translation.
1494
1495 return builder.Build();
1496 };
1497 ASSERT_TRUE(OpenPlaygroundHere(callback));
1498}
1499
1500TEST_P(AiksTest, ImageColorSourceEffectTransform) {
1501 // Compare with https://fiddle.skia.org/c/6cdc5aefb291fda3833b806ca347a885
1502
1503 DisplayListBuilder builder;
1504 auto texture = DlImageImpeller::Make(CreateTextureForFixture("monkey.png"));
1505
1506 DlPaint paint;
1507 paint.setColor(DlColor::kWhite());
1508 builder.DrawPaint(paint);
1509
1510 // Translation
1511 {
1512 DlMatrix matrix = DlMatrix::MakeTranslation({50, 50});
1513 DlPaint paint;
1515 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1516 DlImageSampling::kNearestNeighbor, &matrix));
1517
1518 builder.DrawRect(DlRect::MakeLTRB(0, 0, 100, 100), paint);
1519 }
1520
1521 // Rotation/skew
1522 {
1523 builder.Save();
1524 builder.Rotate(45);
1525 DlPaint paint;
1526
1527 Matrix matrix(1, -1, 0, 0, //
1528 1, 1, 0, 0, //
1529 0, 0, 1, 0, //
1530 0, 0, 0, 1);
1532 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1533 DlImageSampling::kNearestNeighbor, &matrix));
1534 builder.DrawRect(DlRect::MakeLTRB(100, 0, 200, 100), paint);
1535 builder.Restore();
1536 }
1537
1538 // Scale
1539 {
1540 builder.Save();
1541 builder.Translate(100, 0);
1542 builder.Scale(100, 100);
1543 DlPaint paint;
1544
1545 DlMatrix matrix = DlMatrix::MakeScale({0.005, 0.005, 1});
1547 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1548 DlImageSampling::kNearestNeighbor, &matrix));
1549
1550 builder.DrawRect(DlRect::MakeLTRB(0, 0, 1, 1), paint);
1551 builder.Restore();
1552 }
1553
1554 // Perspective
1555 {
1556 builder.Save();
1557 builder.Translate(150, 150);
1558 DlPaint paint;
1559
1560 DlMatrix matrix =
1561 DlMatrix::MakePerspective(Radians{0.5}, ISize{200, 200}, 0.05, 1);
1563 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1564 DlImageSampling::kNearestNeighbor, &matrix));
1565
1566 builder.DrawRect(DlRect::MakeLTRB(0, 0, 200, 200), paint);
1567 builder.Restore();
1568 }
1569
1570 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1571}
1572
1573TEST_P(AiksTest, SubpassWithClearColorOptimization) {
1574 DisplayListBuilder builder;
1575
1576 // Use a non-srcOver blend mode to ensure that we don't detect this as an
1577 // opacity peephole optimization.
1578 DlPaint paint;
1579 paint.setColor(DlColor::kBlue().modulateOpacity(0.5));
1580 paint.setBlendMode(DlBlendMode::kSrc);
1581
1582 DlRect bounds = DlRect::MakeLTRB(0, 0, 200, 200);
1583 builder.SaveLayer(bounds, &paint);
1584
1586 paint.setBlendMode(DlBlendMode::kSrc);
1587 builder.DrawPaint(paint);
1588 builder.Restore();
1589
1590 paint.setColor(DlColor::kBlue());
1591 paint.setBlendMode(DlBlendMode::kDstOver);
1592 builder.SaveLayer(std::nullopt, &paint);
1593 builder.Restore();
1594
1595 // This playground should appear blank on CI since we are only drawing
1596 // transparent black. If the clear color optimization is broken, the texture
1597 // will be filled with NaNs and may produce a magenta texture on macOS or iOS.
1598 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1599}
1600
1601// Render a white circle at the top left corner of the screen.
1602TEST_P(AiksTest, MatrixImageFilterDoesntCullWhenTranslatedFromOffscreen) {
1603 DisplayListBuilder builder;
1604 builder.Scale(GetContentScale().x, GetContentScale().y);
1605 builder.Translate(100, 100);
1606 // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
1607 // +300 translation applied by a SaveLayer image filter.
1608 DlPaint paint;
1609 DlMatrix translate = DlMatrix::MakeTranslation({300, 0});
1610 paint.setImageFilter(
1611 DlImageFilter::MakeMatrix(translate, DlImageSampling::kLinear));
1612 builder.SaveLayer(std::nullopt, &paint);
1613
1614 DlPaint circle_paint;
1615 circle_paint.setColor(DlColor::kGreen());
1616 builder.DrawCircle(DlPoint(-300, 0), 100, circle_paint);
1617 builder.Restore();
1618
1619 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1620}
1621
1622// Render a white circle at the top left corner of the screen.
1624 MatrixImageFilterDoesntCullWhenScaledAndTranslatedFromOffscreen) {
1625 DisplayListBuilder builder;
1626 builder.Scale(GetContentScale().x, GetContentScale().y);
1627 builder.Translate(100, 100);
1628 // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
1629 // +300 translation applied by a SaveLayer image filter.
1630
1631 DlPaint paint;
1633 DlMatrix::MakeTranslation({300, 0}) * DlMatrix::MakeScale({2, 2, 1}),
1634 DlImageSampling::kNearestNeighbor));
1635 builder.SaveLayer(std::nullopt, &paint);
1636
1637 DlPaint circle_paint;
1638 circle_paint.setColor(DlColor::kGreen());
1639 builder.DrawCircle(DlPoint(-150, 0), 50, circle_paint);
1640 builder.Restore();
1641
1642 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1643}
1644
1645// This should be solid red, if you see a little red box this is broken.
1646TEST_P(AiksTest, ClearColorOptimizationWhenSubpassIsBiggerThanParentPass) {
1647 SetWindowSize({400, 400});
1648 DisplayListBuilder builder;
1649
1650 builder.Scale(GetContentScale().x, GetContentScale().y);
1651
1652 DlPaint paint;
1653 paint.setColor(DlColor::kRed());
1654 builder.DrawRect(DlRect::MakeLTRB(200, 200, 300, 300), paint);
1655
1657 DlImageSampling::kLinear));
1658 builder.SaveLayer(std::nullopt, &paint);
1659 // Draw a rectangle that would fully cover the parent pass size, but not
1660 // the subpass that it is rendered in.
1661 paint.setColor(DlColor::kGreen());
1662 builder.DrawRect(DlRect::MakeLTRB(0, 0, 400, 400), paint);
1663 // Draw a bigger rectangle to force the subpass to be bigger.
1664
1665 paint.setColor(DlColor::kRed());
1666 builder.DrawRect(DlRect::MakeLTRB(0, 0, 800, 800), paint);
1667 builder.Restore();
1668
1669 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1670}
1671
1672TEST_P(AiksTest, EmptySaveLayerIgnoresPaint) {
1673 DisplayListBuilder builder;
1674 builder.Scale(GetContentScale().x, GetContentScale().y);
1675
1676 DlPaint paint;
1677 paint.setColor(DlColor::kRed());
1678 builder.DrawPaint(paint);
1679 builder.ClipRect(DlRect::MakeXYWH(100, 100, 200, 200));
1680 paint.setColor(DlColor::kBlue());
1681 builder.SaveLayer(std::nullopt, &paint);
1682 builder.Restore();
1683
1684 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1685}
1686
1687TEST_P(AiksTest, EmptySaveLayerRendersWithClear) {
1688 DisplayListBuilder builder;
1689 builder.Scale(GetContentScale().x, GetContentScale().y);
1690 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
1691 builder.DrawImage(image, DlPoint(10, 10), {});
1692 builder.ClipRect(DlRect::MakeXYWH(100, 100, 200, 200));
1693
1694 DlPaint paint;
1695 paint.setBlendMode(DlBlendMode::kClear);
1696 builder.SaveLayer(std::nullopt, &paint);
1697 builder.Restore();
1698
1699 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1700}
1701
1703 CanPerformSaveLayerWithBoundsAndLargerIntermediateIsNotAllocated) {
1704 DisplayListBuilder builder;
1705
1706 DlPaint red;
1707 red.setColor(DlColor::kRed());
1708
1709 DlPaint green;
1710 green.setColor(DlColor::kGreen());
1711
1712 DlPaint blue;
1713 blue.setColor(DlColor::kBlue());
1714
1715 DlPaint save;
1716 save.setColor(DlColor::kBlack().modulateOpacity(0.5));
1717
1718 DlRect huge_bounds = DlRect::MakeXYWH(0, 0, 100000, 100000);
1719 builder.SaveLayer(huge_bounds, &save);
1720
1721 builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), red);
1722 builder.DrawRect(DlRect::MakeXYWH(10, 10, 100, 100), green);
1723 builder.DrawRect(DlRect::MakeXYWH(20, 20, 100, 100), blue);
1724
1725 builder.Restore();
1726
1727 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1728}
1729
1730// This makes sure the WideGamut named tests use 16bit float pixel format.
1731TEST_P(AiksTest, FormatWideGamut) {
1732 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
1734}
1735
1736TEST_P(AiksTest, FormatSRGB) {
1737 PixelFormat pixel_format =
1738 GetContext()->GetCapabilities()->GetDefaultColorFormat();
1739 EXPECT_TRUE(pixel_format == PixelFormat::kR8G8B8A8UNormInt ||
1740 pixel_format == PixelFormat::kB8G8R8A8UNormInt)
1741 << "pixel format: " << PixelFormatToString(pixel_format);
1742}
1743
1744TEST_P(AiksTest, CoordinateConversionsAreCorrect) {
1745 DisplayListBuilder builder;
1746
1747 // Render a texture directly.
1748 {
1749 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
1750
1751 builder.Save();
1752 builder.Translate(100, 200);
1753 builder.Scale(0.5, 0.5);
1754 builder.DrawImage(image, DlPoint(100.0, 100.0),
1755 DlImageSampling::kNearestNeighbor);
1756 builder.Restore();
1757 }
1758
1759 // Render an offscreen rendered texture.
1760 {
1761 DlPaint alpha;
1762 alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
1763
1764 builder.SaveLayer(std::nullopt, &alpha);
1765
1766 DlPaint paint;
1767 paint.setColor(DlColor::kRed());
1768 builder.DrawRect(DlRect::MakeXYWH(000, 000, 100, 100), paint);
1769 paint.setColor(DlColor::kGreen());
1770 builder.DrawRect(DlRect::MakeXYWH(020, 020, 100, 100), paint);
1771 paint.setColor(DlColor::kBlue());
1772 builder.DrawRect(DlRect::MakeXYWH(040, 040, 100, 100), paint);
1773
1774 builder.Restore();
1775 }
1776
1777 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1778}
1779
1780TEST_P(AiksTest, CanPerformFullScreenMSAA) {
1781 DisplayListBuilder builder;
1782
1783 DlPaint paint;
1784 paint.setColor(DlColor::kRed());
1785 builder.DrawCircle(DlPoint(250, 250), 125, paint);
1786
1787 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1788}
1789
1790TEST_P(AiksTest, CanPerformSkew) {
1791 DisplayListBuilder builder;
1792
1793 DlPaint red;
1794 red.setColor(DlColor::kRed());
1795 builder.Skew(2, 5);
1796 builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), red);
1797
1798 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1799}
1800
1801TEST_P(AiksTest, CanPerformSaveLayerWithBounds) {
1802 DisplayListBuilder builder;
1803
1804 DlPaint save;
1805 save.setColor(DlColor::kBlack());
1806
1807 DlRect save_bounds = DlRect::MakeXYWH(0, 0, 50, 50);
1808 builder.SaveLayer(save_bounds, &save);
1809
1810 DlPaint paint;
1811 paint.setColor(DlColor::kRed());
1812 builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), paint);
1813 paint.setColor(DlColor::kGreen());
1814 builder.DrawRect(DlRect::MakeXYWH(10, 10, 100, 100), paint);
1815 paint.setColor(DlColor::kBlue());
1816 builder.DrawRect(DlRect::MakeXYWH(20, 20, 100, 100), paint);
1817
1818 builder.Restore();
1819
1820 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1821}
1822
1823TEST_P(AiksTest, FilledRoundRectPathsRenderCorrectly) {
1824 DisplayListBuilder builder;
1825 builder.Scale(GetContentScale().x, GetContentScale().y);
1826
1827 DlPaint paint;
1828 const int color_count = 3;
1829 DlColor colors[color_count] = {
1832 DlColor::ARGB(1.0, 220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f),
1833 };
1834
1835 paint.setColor(DlColor::kWhite());
1836 builder.DrawPaint(paint);
1837
1838 auto draw_rrect_as_path = [&builder](const DlRect& rect, Scalar x, Scalar y,
1839 const DlPaint& paint) {
1840 builder.DrawPath(DlPath::MakeRoundRectXY(rect, x, y), paint);
1841 };
1842
1843 int c_index = 0;
1844 for (int i = 0; i < 4; i++) {
1845 for (int j = 0; j < 4; j++) {
1846 paint.setColor(colors[(c_index++) % color_count]);
1847 draw_rrect_as_path(DlRect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80),
1848 i * 5 + 10, j * 5 + 10, paint);
1849 }
1850 }
1851 paint.setColor(colors[(c_index++) % color_count]);
1852 draw_rrect_as_path(DlRect::MakeXYWH(10, 420, 380, 80), 40, 40, paint);
1853 paint.setColor(colors[(c_index++) % color_count]);
1854 draw_rrect_as_path(DlRect::MakeXYWH(410, 20, 80, 380), 40, 40, paint);
1855
1856 std::vector<DlColor> gradient_colors = {
1857 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
1858 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
1859 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
1860 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
1861 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
1862 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
1863 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0)};
1864 std::vector<Scalar> stops = {
1865 0.0,
1866 (1.0 / 6.0) * 1,
1867 (1.0 / 6.0) * 2,
1868 (1.0 / 6.0) * 3,
1869 (1.0 / 6.0) * 4,
1870 (1.0 / 6.0) * 5,
1871 1.0,
1872 };
1874 CreateTextureForFixture("airplane.jpg",
1875 /*enable_mipmapping=*/true));
1876
1877 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1879 /*center=*/DlPoint(550, 550),
1880 /*radius=*/75,
1881 /*stop_count=*/gradient_colors.size(),
1882 /*colors=*/gradient_colors.data(),
1883 /*stops=*/stops.data(),
1884 /*tile_mode=*/DlTileMode::kMirror));
1885 for (int i = 1; i <= 10; i++) {
1886 int j = 11 - i;
1887 draw_rrect_as_path(DlRect::MakeLTRB(550 - i * 20, 550 - j * 20, //
1888 550 + i * 20, 550 + j * 20),
1889 i * 10, j * 10, paint);
1890 }
1891 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1893 /*center=*/DlPoint(200, 650),
1894 /*radius=*/75,
1895 /*stop_count=*/gradient_colors.size(),
1896 /*colors=*/gradient_colors.data(),
1897 /*stops=*/stops.data(),
1898 /*tile_mode=*/DlTileMode::kMirror));
1899 draw_rrect_as_path(DlRect::MakeLTRB(100, 610, 300, 690), 40, 40, paint);
1900 draw_rrect_as_path(DlRect::MakeLTRB(160, 550, 240, 750), 40, 40, paint);
1901
1902 auto matrix = DlMatrix::MakeTranslation({520, 20});
1903 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1905 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1906 DlImageSampling::kMipmapLinear, &matrix));
1907 for (int i = 1; i <= 10; i++) {
1908 int j = 11 - i;
1909 draw_rrect_as_path(DlRect::MakeLTRB(720 - i * 20, 220 - j * 20, //
1910 720 + i * 20, 220 + j * 20),
1911 i * 10, j * 10, paint);
1912 }
1913 matrix = DlMatrix::MakeTranslation({800, 300});
1914 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1916 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1917 DlImageSampling::kMipmapLinear, &matrix));
1918
1919 draw_rrect_as_path(DlRect::MakeLTRB(800, 410, 1000, 490), 40, 40, paint);
1920 draw_rrect_as_path(DlRect::MakeLTRB(860, 350, 940, 550), 40, 40, paint);
1921
1922 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1923}
1924
1925TEST_P(AiksTest, CoverageOriginShouldBeAccountedForInSubpasses) {
1926 auto callback = [&]() -> sk_sp<DisplayList> {
1927 DisplayListBuilder builder;
1928 builder.Scale(GetContentScale().x, GetContentScale().y);
1929
1930 DlPaint alpha;
1932
1933 auto current = Point{25, 25};
1934 const auto offset = Point{25, 25};
1935 const auto size = Size(100, 100);
1936
1937 static PlaygroundPoint point_a(Point(40, 40), 10, Color::White());
1938 static PlaygroundPoint point_b(Point(160, 160), 10, Color::White());
1939 auto [b0, b1] = DrawPlaygroundLine(point_a, point_b);
1940 DlRect bounds = DlRect::MakeLTRB(b0.x, b0.y, b1.x, b1.y);
1941
1942 DlPaint stroke_paint;
1943 stroke_paint.setColor(DlColor::kYellow());
1944 stroke_paint.setStrokeWidth(5);
1945 stroke_paint.setDrawStyle(DlDrawStyle::kStroke);
1946 builder.DrawRect(bounds, stroke_paint);
1947
1948 builder.SaveLayer(bounds, &alpha);
1949
1950 DlPaint paint;
1951 paint.setColor(DlColor::kRed());
1952 builder.DrawRect(
1953 DlRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
1954
1955 paint.setColor(DlColor::kGreen());
1956 current += offset;
1957 builder.DrawRect(
1958 DlRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
1959
1960 paint.setColor(DlColor::kBlue());
1961 current += offset;
1962 builder.DrawRect(
1963 DlRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
1964
1965 builder.Restore();
1966
1967 return builder.Build();
1968 };
1969
1970 ASSERT_TRUE(OpenPlaygroundHere(callback));
1971}
1972
1973TEST_P(AiksTest, SaveLayerDrawsBehindSubsequentEntities) {
1974 // Compare with https://fiddle.skia.org/c/9e03de8567ffb49e7e83f53b64bcf636
1975 DisplayListBuilder builder;
1976 DlPaint paint;
1977
1978 paint.setColor(DlColor::kBlack());
1979 DlRect rect = DlRect::MakeXYWH(25, 25, 25, 25);
1980 builder.DrawRect(rect, paint);
1981
1982 builder.Translate(10, 10);
1983
1984 DlPaint save_paint;
1985 builder.SaveLayer(std::nullopt, &save_paint);
1986
1987 paint.setColor(DlColor::kGreen());
1988 builder.DrawRect(rect, paint);
1989
1990 builder.Restore();
1991
1992 builder.Translate(10, 10);
1993 paint.setColor(DlColor::kRed());
1994 builder.DrawRect(rect, paint);
1995
1996 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1997}
1998
1999TEST_P(AiksTest, SiblingSaveLayerBoundsAreRespected) {
2000 DisplayListBuilder builder;
2001 DlPaint paint;
2002 DlRect rect = DlRect::MakeXYWH(0, 0, 1000, 1000);
2003
2004 // Black, green, and red squares offset by [10, 10].
2005 {
2006 DlPaint save_paint;
2007 DlRect bounds = DlRect::MakeXYWH(25, 25, 25, 25);
2008 builder.SaveLayer(bounds, &save_paint);
2009 paint.setColor(DlColor::kBlack());
2010 builder.DrawRect(rect, paint);
2011 builder.Restore();
2012 }
2013
2014 {
2015 DlPaint save_paint;
2016 DlRect bounds = DlRect::MakeXYWH(35, 35, 25, 25);
2017 builder.SaveLayer(bounds, &save_paint);
2018 paint.setColor(DlColor::kGreen());
2019 builder.DrawRect(rect, paint);
2020 builder.Restore();
2021 }
2022
2023 {
2024 DlPaint save_paint;
2025 DlRect bounds = DlRect::MakeXYWH(45, 45, 25, 25);
2026 builder.SaveLayer(bounds, &save_paint);
2027 paint.setColor(DlColor::kRed());
2028 builder.DrawRect(rect, paint);
2029 builder.Restore();
2030 }
2031
2032 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2033}
2034
2035TEST_P(AiksTest, CanRenderClippedLayers) {
2036 DisplayListBuilder builder;
2037
2038 DlPaint paint;
2039 paint.setColor(DlColor::kWhite());
2040 builder.DrawPaint(paint);
2041
2042 // Draw a green circle on the screen.
2043 {
2044 // Increase the clip depth for the savelayer to contend with.
2045 DlPath path = DlPath::MakeCircle(DlPoint(100, 100), 50);
2046 builder.ClipPath(path);
2047
2048 DlRect bounds = DlRect::MakeXYWH(50, 50, 100, 100);
2049 DlPaint save_paint;
2050 builder.SaveLayer(bounds, &save_paint);
2051
2052 // Fill the layer with white.
2053 paint.setColor(DlColor::kWhite());
2054 builder.DrawRect(DlRect::MakeSize(DlSize(400, 400)), paint);
2055 // Fill the layer with green, but do so with a color blend that can't be
2056 // collapsed into the parent pass.
2057 paint.setColor(DlColor::kGreen());
2058 paint.setBlendMode(DlBlendMode::kHardLight);
2059 builder.DrawRect(DlRect::MakeSize(DlSize(400, 400)), paint);
2060 }
2061
2062 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2063}
2064
2065TEST_P(AiksTest, SaveLayerFiltersScaleWithTransform) {
2066 DisplayListBuilder builder;
2067
2068 builder.Scale(GetContentScale().x, GetContentScale().y);
2069 builder.Translate(100, 100);
2070
2071 auto texture = DlImageImpeller::Make(CreateTextureForFixture("boston.jpg"));
2072 auto draw_image_layer = [&builder, &texture](const DlPaint& paint) {
2073 builder.SaveLayer(std::nullopt, &paint);
2074 builder.DrawImage(texture, DlPoint(), DlImageSampling::kLinear);
2075 builder.Restore();
2076 };
2077
2078 DlPaint effect_paint;
2079 effect_paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 6));
2080 draw_image_layer(effect_paint);
2081
2082 builder.Translate(300, 300);
2083 builder.Scale(3, 3);
2084 draw_image_layer(effect_paint);
2085
2086 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2087}
2088
2089TEST_P(AiksTest, FastEllipticalRRectMaskBlursRenderCorrectly) {
2090 DisplayListBuilder builder;
2091
2092 builder.Scale(GetContentScale().x, GetContentScale().y);
2093 DlPaint paint;
2094 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 1));
2095
2096 DlPaint save_paint;
2097 save_paint.setColor(DlColor::kWhite());
2098 builder.DrawPaint(save_paint);
2099
2100 paint.setColor(DlColor::kBlue());
2101 for (int i = 0; i < 5; i++) {
2102 Scalar y = i * 125;
2103 Scalar y_radius = i * 15;
2104 for (int j = 0; j < 5; j++) {
2105 Scalar x = j * 125;
2106 Scalar x_radius = j * 15;
2107 builder.DrawRoundRect(
2109 DlRect::MakeXYWH(x + 50, y + 50, 100.0f, 100.0f), //
2110 x_radius, y_radius),
2111 paint);
2112 }
2113 }
2114
2115 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2116}
2117
2118TEST_P(AiksTest, PipelineBlendSingleParameter) {
2119 DisplayListBuilder builder;
2120
2121 // Should render a green square in the middle of a blue circle.
2122 DlPaint paint;
2123 builder.SaveLayer(std::nullopt, &paint);
2124 {
2125 builder.Translate(100, 100);
2126 paint.setColor(DlColor::kBlue());
2127 builder.DrawCircle(DlPoint(200, 200), 200, paint);
2128 builder.ClipRect(DlRect::MakeXYWH(100, 100, 200, 200));
2129
2130 paint.setColor(DlColor::kGreen());
2131 paint.setBlendMode(DlBlendMode::kSrcOver);
2133 DlColorFilter::MakeBlend(DlColor::kWhite(), DlBlendMode::kDst)));
2134 builder.DrawCircle(DlPoint(200, 200), 200, paint);
2135 builder.Restore();
2136 }
2137
2138 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2139}
2140
2141// Creates an image matrix filter that scales large content such that it would
2142// exceed the max texture size. See
2143// https://github.com/flutter/flutter/issues/128912
2144TEST_P(AiksTest, MassiveScalingMatrixImageFilter) {
2145 if (GetBackend() == PlaygroundBackend::kVulkan) {
2146 GTEST_SKIP() << "Swiftshader is running out of memory on this example.";
2147 }
2148 DisplayListBuilder builder(DlRect::MakeSize(DlSize(1000, 1000)));
2149
2150 auto filter = DlImageFilter::MakeMatrix(
2151 DlMatrix::MakeScale({0.001, 0.001, 1}), DlImageSampling::kLinear);
2152
2153 DlPaint paint;
2154 paint.setImageFilter(filter);
2155 builder.SaveLayer(std::nullopt, &paint);
2156 {
2157 DlPaint paint;
2158 paint.setColor(DlColor::kRed());
2159 builder.DrawRect(DlRect::MakeLTRB(0, 0, 100000, 100000), paint);
2160 }
2161 builder.Restore();
2162
2163 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2164}
2165
2166TEST_P(AiksTest, NoDimplesInRRectPath) {
2167 Scalar width = 200.f;
2168 Scalar height = 60.f;
2169 Scalar corner = 1.f;
2170 auto callback = [&]() -> sk_sp<DisplayList> {
2171 if (AiksTest::ImGuiBegin("Controls", nullptr,
2172 ImGuiWindowFlags_AlwaysAutoResize)) {
2173 ImGui::SliderFloat("width", &width, 0, 200);
2174 ImGui::SliderFloat("height", &height, 0, 200);
2175 ImGui::SliderFloat("corner", &corner, 0, 1);
2176 ImGui::End();
2177 }
2178
2179 DisplayListBuilder builder;
2180 builder.Scale(GetContentScale().x, GetContentScale().y);
2181
2182 DlPaint background_paint;
2183 background_paint.setColor(DlColor(1, 0.1, 0.1, 0.1, DlColorSpace::kSRGB));
2184 builder.DrawPaint(background_paint);
2185
2186 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue()};
2187 std::vector<Scalar> stops = {0.0, 1.0};
2188
2189 DlPaint paint;
2190 auto gradient = DlColorSource::MakeLinear(DlPoint(0, 0), DlPoint(200, 200),
2191 2, colors.data(), stops.data(),
2192 DlTileMode::kClamp);
2193 paint.setColorSource(gradient);
2194 paint.setColor(DlColor::kWhite());
2195 paint.setDrawStyle(DlDrawStyle::kStroke);
2196 paint.setStrokeWidth(20);
2197
2198 builder.Save();
2199 builder.Translate(100, 100);
2200
2201 Scalar corner_x = ((1 - corner) * 50) + 50;
2202 Scalar corner_y = corner * 50 + 50;
2204 DlRect::MakeXYWH(0, 0, width, height), corner_x, corner_y);
2205 builder.DrawRoundRect(rrect, paint);
2206 builder.Restore();
2207 return builder.Build();
2208 };
2209 ASSERT_TRUE(OpenPlaygroundHere(callback));
2210}
2211
2212TEST_P(AiksTest, BackdropFilterOverUnclosedClip) {
2213 DisplayListBuilder builder;
2214
2215 builder.DrawPaint(DlPaint().setColor(DlColor::kWhite()));
2216 builder.Save();
2217 {
2218 builder.ClipRect(DlRect::MakeLTRB(100, 100, 800, 800));
2219
2220 builder.Save();
2221 {
2222 builder.ClipRect(DlRect::MakeLTRB(600, 600, 800, 800));
2223 builder.DrawPaint(DlPaint().setColor(DlColor::kRed()));
2224 builder.DrawPaint(DlPaint().setColor(DlColor::kBlue().withAlphaF(0.5)));
2225 builder.ClipRect(DlRect::MakeLTRB(700, 700, 750, 800));
2226 builder.DrawPaint(DlPaint().setColor(DlColor::kRed().withAlphaF(0.5)));
2227 }
2228 builder.Restore();
2229
2230 auto image_filter = DlImageFilter::MakeBlur(10, 10, DlTileMode::kDecal);
2231 builder.SaveLayer(std::nullopt, nullptr, image_filter.get());
2232 }
2233 builder.Restore();
2234 builder.DrawCircle(DlPoint(100, 100), 100,
2235 DlPaint().setColor(DlColor::kAqua()));
2236
2237 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2238}
2239
2240} // namespace testing
2241} // 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:141
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