Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[DisplayList] Create DrawDashedLine for paragraph code #53411

Merged
merged 4 commits into from
Jun 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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