Skip to content

Commit

Permalink
[DisplayList] Create DrawDashedLine for paragraph code (flutter#53411)
Browse files Browse the repository at this point in the history
With this minor addition to the DlCanvas/DisplayList API the code in the paragraph builder no longer needs to worry about PathEffect objects and their varying support on the backends.

At this point all PathEffect code in the engine is obsolete and can be deleted, but I'll leave that for a follow-on PR.

The only PathEffect related thing I did delete was support for rendering primitives with a PathEffect in the DL Rendering tests, both because it is a vestigial attribute and also because it would interfere with the new DrawDashedLine rendering test (a PathEffect on top of a PathEffect...).
  • Loading branch information
flar authored Jun 17, 2024
1 parent c5e0e55 commit 1c4e5e2
Show file tree
Hide file tree
Showing 30 changed files with 408 additions and 118 deletions.
10 changes: 10 additions & 0 deletions display_list/benchmarking/dl_complexity_gl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,16 @@ void DisplayListGLComplexityCalculator::GLHelper::drawLine(const SkPoint& p0,
AccumulateComplexity(complexity);
}

void DisplayListGLComplexityCalculator::GLHelper::drawDashedLine(
const DlPoint& p0,
const DlPoint& p1,
DlScalar on_length,
DlScalar off_length) {
// Dashing is slightly more complex than a regular drawLine, but this
// op is so rare it is not worth measuring the difference.
drawLine(ToSkPoint(p0), ToSkPoint(p1));
}

void DisplayListGLComplexityCalculator::GLHelper::drawRect(const SkRect& rect) {
if (IsComplex()) {
return;
Expand Down
4 changes: 4 additions & 0 deletions display_list/benchmarking/dl_complexity_gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ class DisplayListGLComplexityCalculator
const DlImageFilter* backdrop) override;

void drawLine(const SkPoint& p0, const SkPoint& p1) override;
void drawDashedLine(const DlPoint& p0,
const DlPoint& p1,
DlScalar on_length,
DlScalar off_length) override;
void drawRect(const SkRect& rect) override;
void drawOval(const SkRect& bounds) override;
void drawCircle(const SkPoint& center, SkScalar radius) override;
Expand Down
10 changes: 10 additions & 0 deletions display_list/benchmarking/dl_complexity_metal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,16 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawLine(
AccumulateComplexity(complexity);
}

void DisplayListMetalComplexityCalculator::MetalHelper::drawDashedLine(
const DlPoint& p0,
const DlPoint& p1,
DlScalar on_length,
DlScalar off_length) {
// Dashing is slightly more complex than a regular drawLine, but this
// op is so rare it is not worth measuring the difference.
drawLine(ToSkPoint(p0), ToSkPoint(p1));
}

void DisplayListMetalComplexityCalculator::MetalHelper::drawRect(
const SkRect& rect) {
if (IsComplex()) {
Expand Down
4 changes: 4 additions & 0 deletions display_list/benchmarking/dl_complexity_metal.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ class DisplayListMetalComplexityCalculator
const DlImageFilter* backdrop) override;

void drawLine(const SkPoint& p0, const SkPoint& p1) override;
void drawDashedLine(const DlPoint& p0,
const DlPoint& p1,
DlScalar on_length,
DlScalar off_length) override;
void drawRect(const SkRect& rect) override;
void drawOval(const SkRect& bounds) override;
void drawCircle(const SkPoint& center, SkScalar radius) override;
Expand Down
1 change: 1 addition & 0 deletions display_list/display_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ namespace flutter {
V(DrawColor) \
\
V(DrawLine) \
V(DrawDashedLine) \
V(DrawRect) \
V(DrawOval) \
V(DrawCircle) \
Expand Down
23 changes: 23 additions & 0 deletions display_list/dl_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1099,6 +1099,29 @@ void DisplayListBuilder::DrawLine(const SkPoint& p0,
SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawLineFlags);
drawLine(p0, p1);
}
void DisplayListBuilder::drawDashedLine(const DlPoint& p0,
const DlPoint& p1,
DlScalar on_length,
DlScalar off_length) {
SkRect bounds = SkRect::MakeLTRB(p0.x, p0.y, p1.x, p1.y).makeSorted();
DisplayListAttributeFlags flags =
(bounds.width() > 0.0f && bounds.height() > 0.0f) ? kDrawLineFlags
: kDrawHVLineFlags;
OpResult result = PaintResult(current_, flags);
if (result != OpResult::kNoEffect && AccumulateOpBounds(bounds, flags)) {
Push<DrawDashedLineOp>(0, p0, p1, on_length, off_length);
CheckLayerOpacityCompatibility();
UpdateLayerResult(result);
}
}
void DisplayListBuilder::DrawDashedLine(const DlPoint& p0,
const DlPoint& p1,
DlScalar on_length,
DlScalar off_length,
const DlPaint& paint) {
SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawLineFlags);
drawDashedLine(p0, p1, on_length, off_length);
}
void DisplayListBuilder::drawRect(const SkRect& rect) {
DisplayListAttributeFlags flags = kDrawRectFlags;
OpResult result = PaintResult(current_, flags);
Expand Down
11 changes: 11 additions & 0 deletions display_list/dl_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,12 @@ class DisplayListBuilder final : public virtual DlCanvas,
const SkPoint& p1,
const DlPaint& paint) override;
// |DlCanvas|
void DrawDashedLine(const DlPoint& p0,
const DlPoint& p1,
DlScalar on_length,
DlScalar off_length,
const DlPaint& paint) override;
// |DlCanvas|
void DrawRect(const SkRect& rect, const DlPaint& paint) override;
// |DlCanvas|
void DrawOval(const SkRect& bounds, const DlPaint& paint) override;
Expand Down Expand Up @@ -419,6 +425,11 @@ class DisplayListBuilder final : public virtual DlCanvas,
// |DlOpReceiver|
void drawLine(const SkPoint& p0, const SkPoint& p1) override;
// |DlOpReceiver|
void drawDashedLine(const DlPoint& p0,
const DlPoint& p1,
DlScalar on_length,
DlScalar off_length) override;
// |DlOpReceiver|
void drawRect(const SkRect& rect) override;
// |DlOpReceiver|
void drawOval(const SkRect& bounds) override;
Expand Down
6 changes: 6 additions & 0 deletions display_list/dl_canvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "flutter/display_list/dl_blend_mode.h"
#include "flutter/display_list/dl_paint.h"
#include "flutter/display_list/dl_vertices.h"
#include "flutter/display_list/geometry/dl_geometry_types.h"
#include "flutter/display_list/image/dl_image.h"

#include "third_party/skia/include/core/SkM44.h"
Expand Down Expand Up @@ -132,6 +133,11 @@ class DlCanvas {
virtual void DrawLine(const SkPoint& p0,
const SkPoint& p1,
const DlPaint& paint) = 0;
virtual void DrawDashedLine(const DlPoint& p0,
const DlPoint& p1,
DlScalar on_length,
DlScalar off_length,
const DlPaint& paint) = 0;
virtual void DrawRect(const SkRect& rect, const DlPaint& paint) = 0;
virtual void DrawOval(const SkRect& bounds, const DlPaint& paint) = 0;
virtual void DrawCircle(const SkPoint& center,
Expand Down
4 changes: 4 additions & 0 deletions display_list/dl_op_receiver.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,10 @@ class DlOpReceiver {
virtual void drawColor(DlColor color, DlBlendMode mode) = 0;
virtual void drawPaint() = 0;
virtual void drawLine(const SkPoint& p0, const SkPoint& p1) = 0;
virtual void drawDashedLine(const DlPoint& p0,
const DlPoint& p1,
DlScalar on_length,
DlScalar off_length) = 0;
virtual void drawRect(const SkRect& rect) = 0;
virtual void drawOval(const SkRect& bounds) = 0;
virtual void drawCircle(const SkPoint& center, SkScalar radius) = 0;
Expand Down
22 changes: 22 additions & 0 deletions display_list/dl_op_records.h
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,28 @@ DEFINE_DRAW_2ARG_OP(Circle, SkPoint, center, SkScalar, radius)
DEFINE_DRAW_2ARG_OP(DRRect, SkRRect, outer, SkRRect, inner)
#undef DEFINE_DRAW_2ARG_OP

// 4 byte header + 24 byte payload packs into 32 bytes (4 bytes unused)
struct DrawDashedLineOp final : DrawOpBase {
static constexpr auto kType = DisplayListOpType::kDrawDashedLine;

DrawDashedLineOp(const DlPoint& p0,
const DlPoint& p1,
DlScalar on_length,
DlScalar off_length)
: p0(p0), p1(p1), on_length(on_length), off_length(off_length) {}

const DlPoint p0;
const DlPoint p1;
const SkScalar on_length;
const SkScalar off_length;

void dispatch(DispatchContext& ctx) const {
if (op_needed(ctx)) {
ctx.receiver.drawDashedLine(p0, p1, on_length, off_length);
}
}
};

// 4 byte header + 28 byte payload packs efficiently into 32 bytes
struct DrawArcOp final : DrawOpBase {
static constexpr auto kType = DisplayListOpType::kDrawArc;
Expand Down
11 changes: 11 additions & 0 deletions display_list/skia/dl_sk_canvas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,17 @@ void DlSkCanvasAdapter::DrawLine(const SkPoint& p0,
delegate_->drawLine(p0, p1, ToStrokedSk(paint));
}

void DlSkCanvasAdapter::DrawDashedLine(const DlPoint& p0,
const DlPoint& p1,
DlScalar on_length,
DlScalar off_length,
const DlPaint& paint) {
SkPaint dashed_paint = ToStrokedSk(paint);
SkScalar intervals[2] = {on_length, off_length};
dashed_paint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 0.0f));
delegate_->drawLine(ToSkPoint(p0), ToSkPoint(p1), dashed_paint);
}

void DlSkCanvasAdapter::DrawRect(const SkRect& rect, const DlPaint& paint) {
delegate_->drawRect(rect, ToSk(paint));
}
Expand Down
5 changes: 5 additions & 0 deletions display_list/skia/dl_sk_canvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ class DlSkCanvasAdapter final : public virtual DlCanvas {
void DrawLine(const SkPoint& p0,
const SkPoint& p1,
const DlPaint& paint) override;
void DrawDashedLine(const DlPoint& p0,
const DlPoint& p1,
DlScalar on_length,
DlScalar off_length,
const DlPaint& paint) override;
void DrawRect(const SkRect& rect, const DlPaint& paint) override;
void DrawOval(const SkRect& bounds, const DlPaint& paint) override;
void DrawCircle(const SkPoint& center,
Expand Down
9 changes: 9 additions & 0 deletions display_list/skia/dl_sk_dispatcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,15 @@ void DlSkCanvasDispatcher::drawColor(DlColor color, DlBlendMode mode) {
void DlSkCanvasDispatcher::drawLine(const SkPoint& p0, const SkPoint& p1) {
canvas_->drawLine(p0, p1, paint());
}
void DlSkCanvasDispatcher::drawDashedLine(const DlPoint& p0,
const DlPoint& p1,
DlScalar on_length,
DlScalar off_length) {
SkPaint dash_paint = paint();
SkScalar intervals[] = {on_length, off_length};
dash_paint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 0.0f));
canvas_->drawLine(ToSkPoint(p0), ToSkPoint(p1), dash_paint);
}
void DlSkCanvasDispatcher::drawRect(const SkRect& rect) {
canvas_->drawRect(rect, paint());
}
Expand Down
4 changes: 4 additions & 0 deletions display_list/skia/dl_sk_dispatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ class DlSkCanvasDispatcher : public virtual DlOpReceiver,
void drawPaint() override;
void drawColor(DlColor color, DlBlendMode mode) override;
void drawLine(const SkPoint& p0, const SkPoint& p1) override;
void drawDashedLine(const DlPoint& p0,
const DlPoint& p1,
DlScalar on_length,
DlScalar off_length) override;
void drawRect(const SkRect& rect) override;
void drawOval(const SkRect& bounds) override;
void drawCircle(const SkPoint& center, SkScalar radius) override;
Expand Down
113 changes: 51 additions & 62 deletions display_list/testing/dl_rendering_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1977,68 +1977,6 @@ class CanvasCompareTester {
ctx.paint.setStrokeMiter(0.0);
ctx.paint.setStrokeJoin(DlStrokeJoin::kMiter);
}));

{
const SkScalar test_dashes_1[] = {29.0, 2.0};
const SkScalar test_dashes_2[] = {17.0, 1.5};
auto dl_dash_effect = DlDashPathEffect::Make(test_dashes_1, 2, 0.0f);
auto sk_dash_effect = SkDashPathEffect::Make(test_dashes_1, 2, 0.0f);
{
RenderWith(testP, stroke_base_env, tolerance,
CaseParameters(
"PathEffect without forced stroking == Dash-29-2",
[=](const SkSetupContext& ctx) {
// Provide some non-trivial stroke size to get dashed
ctx.paint.setStrokeWidth(5.0);
ctx.paint.setPathEffect(sk_dash_effect);
},
[=](const DlSetupContext& ctx) {
// Provide some non-trivial stroke size to get dashed
ctx.paint.setStrokeWidth(5.0);
ctx.paint.setPathEffect(dl_dash_effect);
}));
}
{
RenderWith(testP, stroke_base_env, tolerance,
CaseParameters(
"PathEffect == Dash-29-2",
[=](const SkSetupContext& ctx) {
// Need stroke style to see dashing properly
ctx.paint.setStyle(SkPaint::kStroke_Style);
// Provide some non-trivial stroke size to get dashed
ctx.paint.setStrokeWidth(5.0);
ctx.paint.setPathEffect(sk_dash_effect);
},
[=](const DlSetupContext& ctx) {
// Need stroke style to see dashing properly
ctx.paint.setDrawStyle(DlDrawStyle::kStroke);
// Provide some non-trivial stroke size to get dashed
ctx.paint.setStrokeWidth(5.0);
ctx.paint.setPathEffect(dl_dash_effect);
}));
}
dl_dash_effect = DlDashPathEffect::Make(test_dashes_2, 2, 0.0f);
sk_dash_effect = SkDashPathEffect::Make(test_dashes_2, 2, 0.0f);
{
RenderWith(testP, stroke_base_env, tolerance,
CaseParameters(
"PathEffect == Dash-17-1.5",
[=](const SkSetupContext& ctx) {
// Need stroke style to see dashing properly
ctx.paint.setStyle(SkPaint::kStroke_Style);
// Provide some non-trivial stroke size to get dashed
ctx.paint.setStrokeWidth(5.0);
ctx.paint.setPathEffect(sk_dash_effect);
},
[=](const DlSetupContext& ctx) {
// Need stroke style to see dashing properly
ctx.paint.setDrawStyle(DlDrawStyle::kStroke);
// Provide some non-trivial stroke size to get dashed
ctx.paint.setStrokeWidth(5.0);
ctx.paint.setPathEffect(dl_dash_effect);
}));
}
}
}

static void RenderWithTransforms(const TestParameters& testP,
Expand Down Expand Up @@ -3003,6 +2941,57 @@ TEST_F(DisplayListRendering, DrawVerticalLine) {
.set_vertical_line());
}

TEST_F(DisplayListRendering, DrawDiagonalDashedLines) {
SkPoint p1 = SkPoint::Make(kRenderLeft, kRenderTop);
SkPoint p2 = SkPoint::Make(kRenderRight, kRenderBottom);
SkPoint p3 = SkPoint::Make(kRenderLeft, kRenderBottom);
SkPoint p4 = SkPoint::Make(kRenderRight, kRenderTop);
// Adding some edge center to edge center diagonals to better fill
// out the RRect Clip so bounds checking sees less empty bounds space.
SkPoint p5 = SkPoint::Make(kRenderCenterX, kRenderTop);
SkPoint p6 = SkPoint::Make(kRenderRight, kRenderCenterY);
SkPoint p7 = SkPoint::Make(kRenderLeft, kRenderCenterY);
SkPoint p8 = SkPoint::Make(kRenderCenterX, kRenderBottom);

// Full diagonals are 100x100 which are 140 in length
// Dashing them with 25 on, 5 off means that the last
// dash goes from 120 to 145 which means both ends of the
// diagonals will be in an "on" dash for maximum bounds

// Edge to edge diagonals are 50x50 which are 70 in length
// Dashing them with 25 on, 5 off means that the last
// dash goes from 60 to 85 which means both ends of the
// edge diagonals will be in a dash segment

CanvasCompareTester::RenderAll( //
TestParameters(
[=](const SkRenderContext& ctx) { //
// Skia requires kStroke style on horizontal and vertical
// lines to get the bounds correct.
// See https://bugs.chromium.org/p/skia/issues/detail?id=12446
SkPaint p = ctx.paint;
p.setStyle(SkPaint::kStroke_Style);
SkScalar intervals[2] = {25.0f, 5.0f};
p.setPathEffect(SkDashPathEffect::Make(intervals, 2.0f, 0.0f));
ctx.canvas->drawLine(p1, p2, p);
ctx.canvas->drawLine(p3, p4, p);
ctx.canvas->drawLine(p5, p6, p);
ctx.canvas->drawLine(p7, p8, p);
},
[=](const DlRenderContext& ctx) { //
ctx.canvas->DrawDashedLine(ToDlPoint(p1), ToDlPoint(p2), //
25.0f, 5.0f, ctx.paint);
ctx.canvas->DrawDashedLine(ToDlPoint(p3), ToDlPoint(p4), //
25.0f, 5.0f, ctx.paint);
ctx.canvas->DrawDashedLine(ToDlPoint(p5), ToDlPoint(p6), //
25.0f, 5.0f, ctx.paint);
ctx.canvas->DrawDashedLine(ToDlPoint(p7), ToDlPoint(p8), //
25.0f, 5.0f, ctx.paint);
},
kDrawLineFlags)
.set_draw_line());
}

TEST_F(DisplayListRendering, DrawRect) {
// Bounds are offset by 0.5 pixels to induce AA
CanvasCompareTester::RenderAll( //
Expand Down
Loading

0 comments on commit 1c4e5e2

Please sign in to comment.