mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[Impeller] add support for Skia concept of RRect::isSimple needed for DL dispatching (flutter/engine#47736)
Fixes https://github.com/flutter/flutter/issues/133793
This commit is contained in:
parent
81faa02060
commit
0080fdec3c
@ -2407,9 +2407,9 @@ TEST_P(AiksTest, DrawRectAbsorbsClears) {
|
||||
|
||||
TEST_P(AiksTest, DrawRectAbsorbsClearsNegativeRRect) {
|
||||
Canvas canvas;
|
||||
canvas.DrawRRect(Rect::MakeXYWH(0, 0, 300, 300), 5.0,
|
||||
canvas.DrawRRect(Rect::MakeXYWH(0, 0, 300, 300), {5.0, 5.0},
|
||||
{.color = Color::Red(), .blend_mode = BlendMode::kSource});
|
||||
canvas.DrawRRect(Rect::MakeXYWH(0, 0, 300, 300), 5.0,
|
||||
canvas.DrawRRect(Rect::MakeXYWH(0, 0, 300, 300), {5.0, 5.0},
|
||||
{.color = Color::CornflowerBlue().WithAlpha(0.75),
|
||||
.blend_mode = BlendMode::kSourceOver});
|
||||
|
||||
@ -3077,7 +3077,7 @@ TEST_P(AiksTest, CanRenderBackdropBlurInteractive) {
|
||||
canvas.DrawCircle({300, 200}, 100, {.color = Color::GreenYellow()});
|
||||
canvas.DrawCircle({140, 170}, 75, {.color = Color::DarkMagenta()});
|
||||
canvas.DrawCircle({180, 120}, 100, {.color = Color::OrangeRed()});
|
||||
canvas.ClipRRect(Rect::MakeLTRB(a.x, a.y, b.x, b.y), 20);
|
||||
canvas.ClipRRect(Rect::MakeLTRB(a.x, a.y, b.x, b.y), {20, 20});
|
||||
canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
|
||||
ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
@ -3096,7 +3096,7 @@ TEST_P(AiksTest, CanRenderBackdropBlur) {
|
||||
canvas.DrawCircle({300, 200}, 100, {.color = Color::GreenYellow()});
|
||||
canvas.DrawCircle({140, 170}, 75, {.color = Color::DarkMagenta()});
|
||||
canvas.DrawCircle({180, 120}, 100, {.color = Color::OrangeRed()});
|
||||
canvas.ClipRRect(Rect::MakeLTRB(75, 50, 375, 275), 20);
|
||||
canvas.ClipRRect(Rect::MakeLTRB(75, 50, 375, 275), {20, 20});
|
||||
canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
|
||||
ImageFilter::MakeBlur(Sigma(30.0), Sigma(30.0),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
@ -3202,7 +3202,7 @@ TEST_P(AiksTest, CanRenderClippedRuntimeEffects) {
|
||||
|
||||
Canvas canvas;
|
||||
canvas.Save();
|
||||
canvas.ClipRRect(Rect::MakeXYWH(0, 0, 400, 400), 10.0,
|
||||
canvas.ClipRRect(Rect::MakeXYWH(0, 0, 400, 400), {10.0, 10.0},
|
||||
Entity::ClipOperation::kIntersect);
|
||||
canvas.DrawRect(Rect::MakeXYWH(0, 0, 400, 400), paint);
|
||||
canvas.Restore();
|
||||
@ -3480,7 +3480,7 @@ TEST_P(AiksTest, DrawPictureWithText) {
|
||||
|
||||
TEST_P(AiksTest, DrawPictureClipped) {
|
||||
Canvas subcanvas;
|
||||
subcanvas.ClipRRect(Rect::MakeLTRB(100, 100, 400, 400), 15);
|
||||
subcanvas.ClipRRect(Rect::MakeLTRB(100, 100, 400, 400), {15, 15});
|
||||
subcanvas.DrawPaint({.color = Color::Red()});
|
||||
auto picture = subcanvas.EndRecordingAsPicture();
|
||||
|
||||
@ -3492,7 +3492,7 @@ TEST_P(AiksTest, DrawPictureClipped) {
|
||||
|
||||
// Draw over the picture with a larger green rectangle, completely covering it
|
||||
// up.
|
||||
canvas.ClipRRect(Rect::MakeLTRB(100, 100, 400, 400).Expand(20), 15);
|
||||
canvas.ClipRRect(Rect::MakeLTRB(100, 100, 400, 400).Expand(20), {15, 15});
|
||||
canvas.DrawPaint({.color = Color::Green()});
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
|
||||
@ -246,13 +246,14 @@ void Canvas::DrawRect(Rect rect, const Paint& paint) {
|
||||
GetCurrentPass().AddEntity(entity);
|
||||
}
|
||||
|
||||
void Canvas::DrawRRect(Rect rect, Scalar corner_radius, const Paint& paint) {
|
||||
if (AttemptDrawBlurredRRect(rect, corner_radius, paint)) {
|
||||
void Canvas::DrawRRect(Rect rect, Point corner_radii, const Paint& paint) {
|
||||
if (corner_radii.x == corner_radii.y &&
|
||||
AttemptDrawBlurredRRect(rect, corner_radii.x, paint)) {
|
||||
return;
|
||||
}
|
||||
auto path = PathBuilder{}
|
||||
.SetConvexity(Convexity::kConvex)
|
||||
.AddRoundedRect(rect, corner_radius)
|
||||
.AddRoundedRect(rect, corner_radii)
|
||||
.SetBounds(rect)
|
||||
.TakePath();
|
||||
if (paint.style == Paint::Style::kFill) {
|
||||
@ -318,20 +319,20 @@ void Canvas::ClipRect(const Rect& rect, Entity::ClipOperation clip_op) {
|
||||
}
|
||||
|
||||
void Canvas::ClipRRect(const Rect& rect,
|
||||
Scalar corner_radius,
|
||||
Point corner_radii,
|
||||
Entity::ClipOperation clip_op) {
|
||||
auto path = PathBuilder{}
|
||||
.SetConvexity(Convexity::kConvex)
|
||||
.AddRoundedRect(rect, corner_radius)
|
||||
.AddRoundedRect(rect, corner_radii)
|
||||
.SetBounds(rect)
|
||||
.TakePath();
|
||||
|
||||
auto size = rect.GetSize();
|
||||
// Does the rounded rect have a flat part on the top/bottom or left/right?
|
||||
bool flat_on_TB = corner_radius * 2 < size.width;
|
||||
bool flat_on_LR = corner_radius * 2 < size.height;
|
||||
bool flat_on_TB = corner_radii.x * 2 < size.width;
|
||||
bool flat_on_LR = corner_radii.y * 2 < size.height;
|
||||
std::optional<Rect> inner_rect = (flat_on_LR && flat_on_TB)
|
||||
? rect.Expand(-corner_radius)
|
||||
? rect.Expand(-corner_radii)
|
||||
: std::make_optional<Rect>();
|
||||
auto geometry = Geometry::MakeFillPath(path, inner_rect);
|
||||
auto& cull_rect = xformation_stack_.back().cull_rect;
|
||||
@ -348,7 +349,7 @@ void Canvas::ClipRRect(const Rect& rect,
|
||||
IntersectCulling(rect);
|
||||
break;
|
||||
case Entity::ClipOperation::kDifference:
|
||||
if (corner_radius <= 0) {
|
||||
if (corner_radii.x <= 0.0 || corner_radii.y <= 0) {
|
||||
SubtractCulling(rect);
|
||||
} else {
|
||||
// We subtract the inner "tall" and "wide" rectangle pieces
|
||||
@ -357,14 +358,10 @@ void Canvas::ClipRRect(const Rect& rect,
|
||||
// Since this is a subtract operation, we can subtract each
|
||||
// rectangle piece individually without fear of interference.
|
||||
if (flat_on_TB) {
|
||||
SubtractCulling(Rect::MakeLTRB(
|
||||
rect.GetLeft() + corner_radius, rect.GetTop(),
|
||||
rect.GetRight() - corner_radius, rect.GetBottom()));
|
||||
SubtractCulling(rect.Expand({-corner_radii.x, 0.0}));
|
||||
}
|
||||
if (flat_on_LR) {
|
||||
SubtractCulling(Rect::MakeLTRB(
|
||||
rect.GetLeft(), rect.GetTop() + corner_radius, //
|
||||
rect.GetRight(), rect.GetBottom() - corner_radius));
|
||||
SubtractCulling(rect.Expand({0.0, -corner_radii.y}));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -105,7 +105,7 @@ class Canvas {
|
||||
|
||||
void DrawRect(Rect rect, const Paint& paint);
|
||||
|
||||
void DrawRRect(Rect rect, Scalar corner_radius, const Paint& paint);
|
||||
void DrawRRect(Rect rect, Point corner_radii, const Paint& paint);
|
||||
|
||||
void DrawCircle(Point center, Scalar radius, const Paint& paint);
|
||||
|
||||
@ -135,7 +135,7 @@ class Canvas {
|
||||
|
||||
void ClipRRect(
|
||||
const Rect& rect,
|
||||
Scalar corner_radius,
|
||||
Point corner_radii,
|
||||
Entity::ClipOperation clip_op = Entity::ClipOperation::kIntersect);
|
||||
|
||||
void DrawPicture(const Picture& picture);
|
||||
|
||||
@ -182,9 +182,9 @@ class CanvasRecorder {
|
||||
paint);
|
||||
}
|
||||
|
||||
void DrawRRect(Rect rect, Scalar corner_radius, const Paint& paint) {
|
||||
void DrawRRect(Rect rect, Point corner_radii, const Paint& paint) {
|
||||
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawRRect), rect,
|
||||
corner_radius, paint);
|
||||
corner_radii, paint);
|
||||
}
|
||||
|
||||
void DrawCircle(Point center, Scalar radius, const Paint& paint) {
|
||||
@ -233,10 +233,10 @@ class CanvasRecorder {
|
||||
|
||||
void ClipRRect(
|
||||
const Rect& rect,
|
||||
Scalar corner_radius,
|
||||
Point corner_radii,
|
||||
Entity::ClipOperation clip_op = Entity::ClipOperation::kIntersect) {
|
||||
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(ClipRRect), rect,
|
||||
corner_radius, clip_op);
|
||||
corner_radii, clip_op);
|
||||
}
|
||||
|
||||
void DrawPicture(const Picture& picture) {
|
||||
|
||||
@ -160,7 +160,7 @@ TEST(CanvasRecorder, DrawRect) {
|
||||
|
||||
TEST(CanvasRecorder, DrawRRect) {
|
||||
CanvasRecorder<Serializer> recorder;
|
||||
recorder.DrawRRect(Rect(), 0, Paint());
|
||||
recorder.DrawRRect(Rect(), {}, Paint());
|
||||
ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::DrawRRect);
|
||||
}
|
||||
|
||||
@ -202,7 +202,7 @@ TEST(CanvasRecorder, ClipRect) {
|
||||
|
||||
TEST(CanvasRecorder, ClipRRect) {
|
||||
CanvasRecorder<Serializer> recorder;
|
||||
recorder.ClipRRect({}, 0);
|
||||
recorder.ClipRRect({}, {});
|
||||
ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::ClipRRect);
|
||||
}
|
||||
|
||||
|
||||
@ -170,7 +170,7 @@ TEST(AiksCanvasTest, RRectClipIntersectAgainstEmptyCullRect) {
|
||||
Rect rect_clip = Rect::MakeXYWH(5, 5, 10, 10);
|
||||
|
||||
Canvas canvas;
|
||||
canvas.ClipRRect(rect_clip, 1, Entity::ClipOperation::kIntersect);
|
||||
canvas.ClipRRect(rect_clip, {1, 1}, Entity::ClipOperation::kIntersect);
|
||||
|
||||
ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
|
||||
ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), rect_clip);
|
||||
@ -180,7 +180,7 @@ TEST(AiksCanvasTest, RRectClipDiffAgainstEmptyCullRect) {
|
||||
Rect rect_clip = Rect::MakeXYWH(5, 5, 10, 10);
|
||||
|
||||
Canvas canvas;
|
||||
canvas.ClipRRect(rect_clip, 1, Entity::ClipOperation::kDifference);
|
||||
canvas.ClipRRect(rect_clip, {1, 1}, Entity::ClipOperation::kDifference);
|
||||
|
||||
ASSERT_FALSE(canvas.GetCurrentLocalCullingBounds().has_value());
|
||||
}
|
||||
@ -191,7 +191,7 @@ TEST(AiksCanvasTest, RRectClipIntersectAgainstCullRect) {
|
||||
Rect result_cull = Rect::MakeXYWH(5, 5, 5, 5);
|
||||
|
||||
Canvas canvas(initial_cull);
|
||||
canvas.ClipRRect(rect_clip, 1, Entity::ClipOperation::kIntersect);
|
||||
canvas.ClipRRect(rect_clip, {1, 1}, Entity::ClipOperation::kIntersect);
|
||||
|
||||
ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
|
||||
ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
|
||||
@ -203,7 +203,7 @@ TEST(AiksCanvasTest, RRectClipDiffAgainstNonCoveredCullRect) {
|
||||
Rect result_cull = Rect::MakeXYWH(0, 0, 10, 10);
|
||||
|
||||
Canvas canvas(initial_cull);
|
||||
canvas.ClipRRect(rect_clip, 1, Entity::ClipOperation::kDifference);
|
||||
canvas.ClipRRect(rect_clip, {1, 1}, Entity::ClipOperation::kDifference);
|
||||
|
||||
ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
|
||||
ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
|
||||
@ -215,7 +215,7 @@ TEST(AiksCanvasTest, RRectClipDiffAgainstVPartiallyCoveredCullRect) {
|
||||
Rect result_cull = Rect::MakeXYWH(0, 0, 6, 10);
|
||||
|
||||
Canvas canvas(initial_cull);
|
||||
canvas.ClipRRect(rect_clip, 1, Entity::ClipOperation::kDifference);
|
||||
canvas.ClipRRect(rect_clip, {1, 1}, Entity::ClipOperation::kDifference);
|
||||
|
||||
ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
|
||||
ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
|
||||
@ -227,7 +227,7 @@ TEST(AiksCanvasTest, RRectClipDiffAgainstVFullyCoveredCullRect) {
|
||||
Rect result_cull = Rect::MakeXYWH(0, 0, 5, 10);
|
||||
|
||||
Canvas canvas(initial_cull);
|
||||
canvas.ClipRRect(rect_clip, 1, Entity::ClipOperation::kDifference);
|
||||
canvas.ClipRRect(rect_clip, {1, 1}, Entity::ClipOperation::kDifference);
|
||||
|
||||
ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
|
||||
ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
|
||||
@ -239,7 +239,7 @@ TEST(AiksCanvasTest, RRectClipDiffAgainstHPartiallyCoveredCullRect) {
|
||||
Rect result_cull = Rect::MakeXYWH(0, 0, 10, 6);
|
||||
|
||||
Canvas canvas(initial_cull);
|
||||
canvas.ClipRRect(rect_clip, 1, Entity::ClipOperation::kDifference);
|
||||
canvas.ClipRRect(rect_clip, {1, 1}, Entity::ClipOperation::kDifference);
|
||||
|
||||
ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
|
||||
ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
|
||||
@ -251,7 +251,7 @@ TEST(AiksCanvasTest, RRectClipDiffAgainstHFullyCoveredCullRect) {
|
||||
Rect result_cull = Rect::MakeXYWH(0, 0, 10, 5);
|
||||
|
||||
Canvas canvas(initial_cull);
|
||||
canvas.ClipRRect(rect_clip, 1, Entity::ClipOperation::kDifference);
|
||||
canvas.ClipRRect(rect_clip, {1, 1}, Entity::ClipOperation::kDifference);
|
||||
|
||||
ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
|
||||
ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
|
||||
|
||||
@ -726,9 +726,13 @@ void DlDispatcher::clipRect(const SkRect& rect, ClipOp clip_op, bool is_aa) {
|
||||
|
||||
// |flutter::DlOpReceiver|
|
||||
void DlDispatcher::clipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) {
|
||||
if (rrect.isSimple()) {
|
||||
if (rrect.isRect()) {
|
||||
canvas_.ClipRect(skia_conversions::ToRect(rrect.rect()),
|
||||
ToClipOperation(clip_op));
|
||||
} else if (rrect.isSimple()) {
|
||||
canvas_.ClipRRect(skia_conversions::ToRect(rrect.rect()),
|
||||
rrect.getSimpleRadii().fX, ToClipOperation(clip_op));
|
||||
skia_conversions::ToPoint(rrect.getSimpleRadii()),
|
||||
ToClipOperation(clip_op));
|
||||
} else {
|
||||
canvas_.ClipPath(skia_conversions::ToPath(rrect), ToClipOperation(clip_op));
|
||||
}
|
||||
@ -793,7 +797,8 @@ void DlDispatcher::drawCircle(const SkPoint& center, SkScalar radius) {
|
||||
void DlDispatcher::drawRRect(const SkRRect& rrect) {
|
||||
if (rrect.isSimple()) {
|
||||
canvas_.DrawRRect(skia_conversions::ToRect(rrect.rect()),
|
||||
rrect.getSimpleRadii().fX, paint_);
|
||||
skia_conversions::ToPoint(rrect.getSimpleRadii()),
|
||||
paint_);
|
||||
} else {
|
||||
canvas_.DrawPath(skia_conversions::ToPath(rrect), paint_);
|
||||
}
|
||||
@ -809,30 +814,36 @@ void DlDispatcher::drawDRRect(const SkRRect& outer, const SkRRect& inner) {
|
||||
|
||||
// |flutter::DlOpReceiver|
|
||||
void DlDispatcher::drawPath(const SkPath& path) {
|
||||
SimplifyOrDrawPath(canvas_, path, paint_);
|
||||
}
|
||||
|
||||
void DlDispatcher::SimplifyOrDrawPath(CanvasType& canvas,
|
||||
const SkPath& path,
|
||||
const Paint& paint) {
|
||||
SkRect rect;
|
||||
|
||||
// We can't "optimize" a path into a rectangle if it's open.
|
||||
bool closed;
|
||||
if (path.isRect(&rect, &closed) && closed) {
|
||||
canvas_.DrawRect(skia_conversions::ToRect(rect), paint_);
|
||||
canvas.DrawRect(skia_conversions::ToRect(rect), paint);
|
||||
return;
|
||||
}
|
||||
|
||||
SkRRect rrect;
|
||||
if (path.isRRect(&rrect) && rrect.isSimple()) {
|
||||
canvas_.DrawRRect(skia_conversions::ToRect(rrect.rect()),
|
||||
rrect.getSimpleRadii().fX, paint_);
|
||||
canvas.DrawRRect(skia_conversions::ToRect(rrect.rect()),
|
||||
skia_conversions::ToPoint(rrect.getSimpleRadii()), paint);
|
||||
return;
|
||||
}
|
||||
|
||||
SkRect oval;
|
||||
if (path.isOval(&oval) && oval.width() == oval.height()) {
|
||||
canvas_.DrawCircle(skia_conversions::ToPoint(oval.center()),
|
||||
oval.width() * 0.5, paint_);
|
||||
canvas.DrawCircle(skia_conversions::ToPoint(oval.center()),
|
||||
oval.width() * 0.5, paint);
|
||||
return;
|
||||
}
|
||||
|
||||
canvas_.DrawPath(skia_conversions::ToPath(path), paint_);
|
||||
canvas.DrawPath(skia_conversions::ToPath(path), paint);
|
||||
}
|
||||
|
||||
// |flutter::DlOpReceiver|
|
||||
@ -1100,20 +1111,7 @@ void DlDispatcher::drawShadow(const SkPath& path,
|
||||
canvas_.PreConcat(
|
||||
Matrix::MakeTranslation(Vector2(0, -occluder_z * light_position.y)));
|
||||
|
||||
SkRect rect;
|
||||
SkRRect rrect;
|
||||
SkRect oval;
|
||||
if (path.isRect(&rect)) {
|
||||
canvas_.DrawRect(skia_conversions::ToRect(rect), paint);
|
||||
} else if (path.isRRect(&rrect) && rrect.isSimple()) {
|
||||
canvas_.DrawRRect(skia_conversions::ToRect(rrect.rect()),
|
||||
rrect.getSimpleRadii().fX, paint);
|
||||
} else if (path.isOval(&oval) && oval.width() == oval.height()) {
|
||||
canvas_.DrawCircle(skia_conversions::ToPoint(oval.center()),
|
||||
oval.width() * 0.5, paint);
|
||||
} else {
|
||||
canvas_.DrawPath(skia_conversions::ToPath(path), paint);
|
||||
}
|
||||
SimplifyOrDrawPath(canvas_, path, paint);
|
||||
|
||||
canvas_.Restore();
|
||||
}
|
||||
|
||||
@ -226,6 +226,10 @@ class DlDispatcher final : public flutter::DlOpReceiver {
|
||||
CanvasType canvas_;
|
||||
Matrix initial_matrix_;
|
||||
|
||||
static void SimplifyOrDrawPath(CanvasType& canvas,
|
||||
const SkPath& path,
|
||||
const Paint& paint);
|
||||
|
||||
DlDispatcher(const DlDispatcher&) = delete;
|
||||
|
||||
DlDispatcher& operator=(const DlDispatcher&) = delete;
|
||||
|
||||
@ -1591,6 +1591,68 @@ TEST_P(DisplayListTest, DrawShapes) {
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
TEST_P(DisplayListTest, ClipDrawRRectWithNonCircularRadii) {
|
||||
flutter::DisplayListBuilder builder;
|
||||
|
||||
flutter::DlPaint fill_paint = //
|
||||
flutter::DlPaint() //
|
||||
.setColor(flutter::DlColor::kBlue()) //
|
||||
.setDrawStyle(flutter::DlDrawStyle::kFill) //
|
||||
.setStrokeWidth(10);
|
||||
flutter::DlPaint stroke_paint = //
|
||||
flutter::DlPaint() //
|
||||
.setColor(flutter::DlColor::kGreen()) //
|
||||
.setDrawStyle(flutter::DlDrawStyle::kStroke) //
|
||||
.setStrokeWidth(10);
|
||||
|
||||
builder.DrawRRect(
|
||||
SkRRect::MakeRectXY(SkRect::MakeXYWH(500, 100, 300, 300), 120, 40),
|
||||
fill_paint);
|
||||
builder.DrawRRect(
|
||||
SkRRect::MakeRectXY(SkRect::MakeXYWH(500, 100, 300, 300), 120, 40),
|
||||
stroke_paint);
|
||||
|
||||
builder.DrawRRect(
|
||||
SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 500, 300, 300), 40, 120),
|
||||
fill_paint);
|
||||
builder.DrawRRect(
|
||||
SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 500, 300, 300), 40, 120),
|
||||
stroke_paint);
|
||||
|
||||
flutter::DlPaint reference_paint = //
|
||||
flutter::DlPaint() //
|
||||
.setColor(flutter::DlColor::kMidGrey()) //
|
||||
.setDrawStyle(flutter::DlDrawStyle::kFill) //
|
||||
.setStrokeWidth(10);
|
||||
|
||||
builder.DrawRRect(
|
||||
SkRRect::MakeRectXY(SkRect::MakeXYWH(500, 500, 300, 300), 40, 40),
|
||||
reference_paint);
|
||||
builder.DrawRRect(
|
||||
SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 100, 300, 300), 120, 120),
|
||||
reference_paint);
|
||||
|
||||
flutter::DlPaint clip_fill_paint = //
|
||||
flutter::DlPaint() //
|
||||
.setColor(flutter::DlColor::kCyan()) //
|
||||
.setDrawStyle(flutter::DlDrawStyle::kFill) //
|
||||
.setStrokeWidth(10);
|
||||
|
||||
builder.Save();
|
||||
builder.ClipRRect(
|
||||
SkRRect::MakeRectXY(SkRect::MakeXYWH(900, 100, 300, 300), 120, 40));
|
||||
builder.DrawPaint(clip_fill_paint);
|
||||
builder.Restore();
|
||||
|
||||
builder.Save();
|
||||
builder.ClipRRect(
|
||||
SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 900, 300, 300), 40, 120));
|
||||
builder.DrawPaint(clip_fill_paint);
|
||||
builder.Restore();
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
TEST_P(DisplayListTest, DrawVerticesBlendModes) {
|
||||
std::vector<const char*> blend_mode_names;
|
||||
std::vector<flutter::DlBlendMode> blend_mode_values;
|
||||
|
||||
@ -201,7 +201,13 @@ PathBuilder& PathBuilder::AddCircle(const Point& c, Scalar r) {
|
||||
|
||||
PathBuilder& PathBuilder::AddRoundedRect(Rect rect, Scalar radius) {
|
||||
return radius <= 0.0 ? AddRect(rect)
|
||||
: AddRoundedRect(rect, {radius, radius, radius, radius});
|
||||
: AddRoundedRect(rect, RoundingRadii(radius));
|
||||
}
|
||||
|
||||
PathBuilder& PathBuilder::AddRoundedRect(Rect rect, Point radii) {
|
||||
return radii.x <= 0 || radii.y <= 0
|
||||
? AddRect(rect)
|
||||
: AddRoundedRect(rect, RoundingRadii(radii));
|
||||
}
|
||||
|
||||
PathBuilder& PathBuilder::AddRoundedRect(Rect rect, RoundingRadii radii) {
|
||||
|
||||
@ -122,6 +122,18 @@ class PathBuilder {
|
||||
top_right(p_top_right, p_top_right),
|
||||
bottom_right(p_bottom_right, p_bottom_right) {}
|
||||
|
||||
explicit RoundingRadii(Scalar radius)
|
||||
: top_left(radius, radius),
|
||||
bottom_left(radius, radius),
|
||||
top_right(radius, radius),
|
||||
bottom_right(radius, radius) {}
|
||||
|
||||
explicit RoundingRadii(Point radii)
|
||||
: top_left(radii),
|
||||
bottom_left(radii),
|
||||
top_right(radii),
|
||||
bottom_right(radii) {}
|
||||
|
||||
bool AreAllZero() const {
|
||||
return top_left.IsZero() && //
|
||||
bottom_left.IsZero() && //
|
||||
@ -132,6 +144,8 @@ class PathBuilder {
|
||||
|
||||
PathBuilder& AddRoundedRect(Rect rect, RoundingRadii radii);
|
||||
|
||||
PathBuilder& AddRoundedRect(Rect rect, Point radii);
|
||||
|
||||
PathBuilder& AddRoundedRect(Rect rect, Scalar radius);
|
||||
|
||||
PathBuilder& AddPath(const Path& path);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user