@@ -1497,6 +1497,101 @@ TEST_P(AiksTest, SolidStrokesRenderCorrectly) {
1497
1497
ASSERT_TRUE (OpenPlaygroundHere (callback));
1498
1498
}
1499
1499
1500
+ TEST_P (AiksTest, GradientStrokesRenderCorrectly) {
1501
+ // Compare with https://fiddle.skia.org/c/027392122bec8ac2b5d5de00a4b9bbe2
1502
+ bool first_frame = true ;
1503
+ auto callback = [&](AiksContext& renderer, RenderTarget& render_target) {
1504
+ if (first_frame) {
1505
+ first_frame = false ;
1506
+ ImGui::SetNextWindowSize ({480 , 100 });
1507
+ ImGui::SetNextWindowPos ({100 , 550 });
1508
+ }
1509
+
1510
+ static float scale = 3 ;
1511
+ static bool add_circle_clip = true ;
1512
+ const char * tile_mode_names[] = {" Clamp" , " Repeat" , " Mirror" , " Decal" };
1513
+ const Entity::TileMode tile_modes[] = {
1514
+ Entity::TileMode::kClamp , Entity::TileMode::kRepeat ,
1515
+ Entity::TileMode::kMirror , Entity::TileMode::kDecal };
1516
+ static int selected_tile_mode = 0 ;
1517
+ static float alpha = 1 ;
1518
+
1519
+ ImGui::Begin (" Controls" );
1520
+ ImGui::SliderFloat (" Scale" , &scale, 0 , 6 );
1521
+ ImGui::Checkbox (" Circle clip" , &add_circle_clip);
1522
+ ImGui::SliderFloat (" Alpha" , &alpha, 0 , 1 );
1523
+ ImGui::Combo (" Tile mode" , &selected_tile_mode, tile_mode_names,
1524
+ sizeof (tile_mode_names) / sizeof (char *));
1525
+ ImGui::End ();
1526
+
1527
+ Canvas canvas;
1528
+ canvas.Scale (GetContentScale ());
1529
+ Paint paint;
1530
+ paint.color = Color::White ();
1531
+ canvas.DrawPaint (paint);
1532
+
1533
+ paint.style = Paint::Style ::kStroke ;
1534
+ paint.color = Color (1.0 , 1.0 , 1.0 , alpha);
1535
+ paint.stroke_width = 10 ;
1536
+ auto tile_mode = tile_modes[selected_tile_mode];
1537
+ paint.color_source = [tile_mode]() {
1538
+ std::vector<Color> colors = {Color{0.9568 , 0.2627 , 0.2118 , 1.0 },
1539
+ Color{0.1294 , 0.5882 , 0.9529 , 1.0 }};
1540
+ std::vector<Scalar> stops = {0.0 , 1.0 };
1541
+ Matrix matrix = {
1542
+ 1 , 0 , 0 , 0 , //
1543
+ 0 , 1 , 0 , 0 , //
1544
+ 0 , 0 , 1 , 0 , //
1545
+ 0 , 0 , 0 , 1 //
1546
+ };
1547
+ auto contents = std::make_shared<LinearGradientContents>();
1548
+ contents->SetEndPoints ({0 , 0 }, {50 , 50 });
1549
+ contents->SetColors (std::move (colors));
1550
+ contents->SetStops (std::move (stops));
1551
+ contents->SetTileMode (tile_mode);
1552
+ contents->SetMatrix (matrix);
1553
+ return contents;
1554
+ };
1555
+
1556
+ Path path = PathBuilder{}
1557
+ .MoveTo ({20 , 20 })
1558
+ .QuadraticCurveTo ({60 , 20 }, {60 , 60 })
1559
+ .Close ()
1560
+ .MoveTo ({60 , 20 })
1561
+ .QuadraticCurveTo ({60 , 60 }, {20 , 60 })
1562
+ .TakePath ();
1563
+
1564
+ canvas.Scale (Vector2 (scale, scale));
1565
+
1566
+ if (add_circle_clip) {
1567
+ auto [handle_a, handle_b] = IMPELLER_PLAYGROUND_LINE (
1568
+ Point (60 , 300 ), Point (600 , 300 ), 20 , Color::Red (), Color::Red ());
1569
+
1570
+ auto screen_to_canvas = canvas.GetCurrentTransformation ().Invert ();
1571
+ Point point_a = screen_to_canvas * handle_a * GetContentScale ();
1572
+ Point point_b = screen_to_canvas * handle_b * GetContentScale ();
1573
+
1574
+ Point middle = (point_a + point_b) / 2 ;
1575
+ auto radius = point_a.GetDistance (middle);
1576
+ canvas.ClipPath (PathBuilder{}.AddCircle (middle, radius).TakePath ());
1577
+ }
1578
+
1579
+ for (auto join : {Join::kBevel , Join::kRound , Join::kMiter }) {
1580
+ paint.stroke_join = join;
1581
+ for (auto cap : {Cap::kButt , Cap::kSquare , Cap::kRound }) {
1582
+ paint.stroke_cap = cap;
1583
+ canvas.DrawPath (path, paint);
1584
+ canvas.Translate ({80 , 0 });
1585
+ }
1586
+ canvas.Translate ({-240 , 60 });
1587
+ }
1588
+
1589
+ return renderer.Render (canvas.EndRecordingAsPicture (), render_target);
1590
+ };
1591
+
1592
+ ASSERT_TRUE (OpenPlaygroundHere (callback));
1593
+ }
1594
+
1500
1595
TEST_P (AiksTest, CoverageOriginShouldBeAccountedForInSubpasses) {
1501
1596
auto callback = [&](AiksContext& renderer, RenderTarget& render_target) {
1502
1597
Canvas canvas;
0 commit comments