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

Commit adad369

Browse files
committed
Add effect_bounds for DlPathEffect; Delete invalid test cases;
1 parent 9aaea6a commit adad369

9 files changed

Lines changed: 92 additions & 162 deletions

display_list/display_list.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ namespace flutter {
7474
\
7575
V(SetBlender) \
7676
V(ClearBlender) \
77+
\
7778
V(SetSkPathEffect) \
7879
V(SetPodPathEffect) \
7980
V(ClearPathEffect) \

display_list/display_list_canvas_unittests.cc

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -387,14 +387,12 @@ class TestParameters {
387387
NotEquals(ref_attr.getColorSource(), attr.getColorSource())) {
388388
return false;
389389
}
390-
auto skia_path_effect =
391-
attr.getPathEffect() ? attr.getPathEffect()->skia_object() : nullptr;
390+
392391
DisplayListSpecialGeometryFlags geo_flags =
393-
flags_.WithPathEffect(skia_path_effect);
392+
flags_.WithPathEffect(attr.getPathEffect().get());
394393
if (flags_.applies_path_effect() && //
395394
ref_attr.getPathEffect() != attr.getPathEffect()) {
396-
SkPathEffect::DashInfo info;
397-
if (skia_path_effect->asADash(&info) != SkPathEffect::kDash_DashType) {
395+
if (attr.getPathEffect()->asDash() == nullptr) {
398396
return false;
399397
}
400398
if (!ignores_dashes()) {
@@ -485,8 +483,10 @@ class TestParameters {
485483
adjust =
486484
half_width * paint.getStrokeMiter() + tolerance.discrete_offset();
487485
}
486+
auto paint_effect = paint.refPathEffect();
487+
488488
DisplayListSpecialGeometryFlags geo_flags =
489-
flags_.WithPathEffect(paint.refPathEffect());
489+
flags_.WithPathEffect(DlPathEffect::From(paint.refPathEffect()).get());
490490
if (paint.getStrokeCap() == SkPaint::kButt_Cap &&
491491
!geo_flags.butt_cap_becomes_square()) {
492492
adjust = std::max(adjust, half_width);
@@ -1465,8 +1465,6 @@ class CanvasCompareTester {
14651465
b.setPathEffect(effect.get());
14661466
}));
14671467
}
1468-
EXPECT_TRUE(testP.is_draw_text_blob() || effect->skia_object()->unique())
1469-
<< "PathEffect == Dash-29-2 Cleanup";
14701468
effect = DlDashPathEffect::Make(TestDashes2, 2, 0.0f);
14711469
{
14721470
RenderWith(testP, stroke_base_env, tolerance,
@@ -1487,8 +1485,6 @@ class CanvasCompareTester {
14871485
b.setPathEffect(effect.get());
14881486
}));
14891487
}
1490-
EXPECT_TRUE(testP.is_draw_text_blob() || effect->skia_object()->unique())
1491-
<< "PathEffect == Dash-17-1.5 Cleanup";
14921488
}
14931489
}
14941490

display_list/display_list_flags.cc

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,28 @@
33
// found in the LICENSE file.
44

55
#include "flutter/display_list/display_list_flags.h"
6-
6+
#include "flutter/display_list/display_list_path_effect.h"
77
namespace flutter {
88

9-
// Just exists to ensure that the header can be cleanly imported.
9+
const DisplayListSpecialGeometryFlags DisplayListAttributeFlags::WithPathEffect(
10+
const DlPathEffect* effect) const {
11+
if (is_geometric() && effect) {
12+
if (effect->asDash()) {
13+
// A dash effect has a very simple impact. It cannot introduce any
14+
// miter joins that weren't already present in the original path
15+
// and it does not grow the bounds of the path, but it can add
16+
// end caps to areas that might not have had them before so all
17+
// we need to do is to indicate the potential for diagonal
18+
// end caps and move on.
19+
return special_flags_.with(kMayHaveCaps_ | kMayHaveDiagonalCaps_);
20+
} else {
21+
// An arbitrary path effect can introduce joins at an arbitrary
22+
// angle and may change the geometry of the end caps
23+
return special_flags_.with(kMayHaveCaps_ | kMayHaveDiagonalCaps_ |
24+
kMayHaveJoins_ | kMayHaveAcuteJoins_);
25+
}
26+
}
27+
return special_flags_;
28+
}
1029

1130
} // namespace flutter

display_list/display_list_flags.h

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
namespace flutter {
1212

13+
class DlPathEffect;
1314
/// The base class for the classes that maintain a list of
1415
/// attributes that might be important for a number of operations
1516
/// including which rendering attributes need to be set before
@@ -158,26 +159,7 @@ class DisplayListSpecialGeometryFlags : DisplayListFlagsBase {
158159
class DisplayListAttributeFlags : DisplayListFlagsBase {
159160
public:
160161
const DisplayListSpecialGeometryFlags WithPathEffect(
161-
sk_sp<SkPathEffect> effect) const {
162-
if (is_geometric() && effect) {
163-
SkPathEffect::DashInfo info;
164-
if (effect->asADash(&info) == SkPathEffect::kDash_DashType) {
165-
// A dash effect has a very simple impact. It cannot introduce any
166-
// miter joins that weren't already present in the original path
167-
// and it does not grow the bounds of the path, but it can add
168-
// end caps to areas that might not have had them before so all
169-
// we need to do is to indicate the potential for diagonal
170-
// end caps and move on.
171-
return special_flags_.with(kMayHaveCaps_ | kMayHaveDiagonalCaps_);
172-
} else {
173-
// An arbitrary path effect can introduce joins at an arbitrary
174-
// angle and may change the geometry of the end caps
175-
return special_flags_.with(kMayHaveCaps_ | kMayHaveDiagonalCaps_ |
176-
kMayHaveJoins_ | kMayHaveAcuteJoins_);
177-
}
178-
}
179-
return special_flags_;
180-
}
162+
const DlPathEffect* effect) const;
181163

182164
bool ignores_paint() const { return has_any(kIgnoresPaint_); }
183165

display_list/display_list_path_effect.cc

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "flutter/display_list/display_list_path_effect.h"
66

77
#include <memory>
8+
#include <optional>
89
#include <utility>
910

1011
#include "include/core/SkRefCnt.h"
@@ -30,7 +31,7 @@ std::shared_ptr<DlPathEffect> DlPathEffect::From(SkPathEffect* sk_path_effect) {
3031
if (SkPathEffect::DashType::kDash_DashType ==
3132
sk_path_effect->asADash(&info)) {
3233
auto dash_path_effect =
33-
DlDashPathEffect::Make(info.fIntervals, info.fCount, info.fPhase);
34+
DlDashPathEffect::Make(nullptr, info.fCount, info.fPhase);
3435
info.fIntervals =
3536
reinterpret_cast<DlDashPathEffect*>(dash_path_effect.get())
3637
->intervals();
@@ -53,4 +54,22 @@ std::shared_ptr<DlPathEffect> DlDashPathEffect::Make(const SkScalar* intervals,
5354
return std::move(ret);
5455
}
5556

57+
std::optional<SkRect> DlDashPathEffect::effect_bounds(SkRect& rect) const {
58+
// SkDashPathEffect's computeFastBounds is return true which mean it bounds is
59+
// the input value;
60+
return rect;
61+
}
62+
63+
std::optional<SkRect> DlUnknownPathEffect::effect_bounds(SkRect& rect) const {
64+
if (rect.isSorted()) {
65+
return std::nullopt;
66+
}
67+
SkPaint p;
68+
p.setPathEffect(sk_path_effect_);
69+
if (!p.canComputeFastBounds()) {
70+
return std::nullopt;
71+
}
72+
return p.computeFastBounds(rect, &rect);
73+
}
74+
5675
} // namespace flutter

display_list/display_list_path_effect.h

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_PATH_EFFECT_H_
77

88
#include <cstring>
9+
#include <optional>
910
#include "flutter/display_list/display_list_attributes.h"
1011
#include "flutter/display_list/types.h"
1112
#include "flutter/fml/logging.h"
@@ -41,6 +42,8 @@ class DlPathEffect
4142

4243
virtual const DlDashPathEffect* asDash() const { return nullptr; }
4344

45+
virtual std::optional<SkRect> effect_bounds(SkRect&) const = 0;
46+
4447
protected:
4548
DlPathEffect() = default;
4649

@@ -81,36 +84,36 @@ class DlDashPathEffect final : public DlPathEffect {
8184
}
8285

8386
std::shared_ptr<DlPathEffect> shared() const override {
84-
return Make(pods(), count_, phase_);
87+
return Make(intervals(), count_, phase_);
8588
}
8689

8790
const DlDashPathEffect* asDash() const override { return this; }
8891

8992
sk_sp<SkPathEffect> skia_object() const override {
90-
return SkDashPathEffect::Make(pods(), count_, phase_);
93+
return SkDashPathEffect::Make(intervals(), count_, phase_);
9194
}
9295

93-
SkScalar* intervals() { return reinterpret_cast<SkScalar*>(this + 1); }
96+
const SkScalar* intervals() const {
97+
return reinterpret_cast<const SkScalar*>(this + 1);
98+
}
99+
100+
std::optional<SkRect> effect_bounds(SkRect& rect) const override;
94101

95102
protected:
96103
bool equals_(DlPathEffect const& other) const override {
97104
FML_DCHECK(other.type() == DlPathEffectType::kDash);
98105
auto that = static_cast<DlDashPathEffect const*>(&other);
99-
return memcmp(pods(), that->pods(), count_) == 0 &&
100-
count_ == that->count_ && phase_ == that->phase_;
106+
return count_ == that->count_ &&
107+
memcmp(intervals(), that->intervals(), sizeof(SkScalar) * count_) ==
108+
0 &&
109+
phase_ == that->phase_;
101110
}
102111

103112
private:
104-
const SkScalar* pods() const {
105-
return reinterpret_cast<const SkScalar*>(this + 1);
106-
}
107-
108-
bool base_equals_(DlDashPathEffect const* other) const {
109-
// intervals not nullptr, that has value
110-
111-
return true;
112-
}
113-
113+
SkScalar* intervals() { return reinterpret_cast<SkScalar*>(this + 1); }
114+
// DlDashPathEffect constructor assumes the caller has prealloced storage for
115+
// the intervals. If the intervals is nullptr the intervals will
116+
// uninitialized.
114117
DlDashPathEffect(const SkScalar intervals[], int count, SkScalar phase)
115118
: count_(count), phase_(phase) {
116119
if (intervals != nullptr) {
@@ -120,14 +123,15 @@ class DlDashPathEffect final : public DlPathEffect {
120123
}
121124

122125
DlDashPathEffect(const DlDashPathEffect* dash_effect)
123-
: DlDashPathEffect(dash_effect->pods(),
126+
: DlDashPathEffect(dash_effect->intervals(),
124127
dash_effect->count_,
125128
dash_effect->phase_) {}
126129

127130
int count_;
128131
SkScalar phase_;
129132

130133
friend class DisplayListBuilder;
134+
friend class DlPathEffect;
131135

132136
FML_DISALLOW_COPY_ASSIGN_AND_MOVE(DlDashPathEffect);
133137
};
@@ -152,6 +156,8 @@ class DlUnknownPathEffect final : public DlPathEffect {
152156

153157
virtual ~DlUnknownPathEffect() = default;
154158

159+
std::optional<SkRect> effect_bounds(SkRect& rect) const override;
160+
155161
protected:
156162
bool equals_(const DlPathEffect& other) const override {
157163
FML_DCHECK(other.type() == DlPathEffectType::kUnknown);

display_list/display_list_path_effect_unittests.cc

Lines changed: 8 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,18 @@ TEST(DisplayListPathEffect, DashEffectEquals) {
6868
TEST(DisplayListPathEffect, BlurNotEquals) {
6969
const SkScalar TestDashes1[] = {4.0, 2.0};
7070
const SkScalar TestDashes2[] = {1.0, 1.5};
71+
const SkScalar TestDashes3[] = {4.0, 2.5, 2.0};
7172
auto effect1 = DlDashPathEffect::Make(TestDashes1, 2, 0.0);
7273
auto effect2 = DlDashPathEffect::Make(TestDashes2, 2, 0.0);
73-
auto effect3 = DlDashPathEffect::Make(TestDashes2, 2, 1.0);
74+
auto effect3 = DlDashPathEffect::Make(TestDashes3, 3, 1.0);
75+
7476
ASSERT_NE(effect1, effect2);
75-
ASSERT_NE(effect2, effect3);
7677
ASSERT_NE(effect1->shared(), effect2->shared());
78+
79+
ASSERT_NE(effect1, effect3);
80+
ASSERT_NE(effect1->shared(), effect3->shared());
81+
82+
ASSERT_NE(effect2, effect3);
7783
ASSERT_NE(effect2->shared(), effect3->shared());
7884
}
7985

@@ -116,108 +122,5 @@ TEST(DisplayListPathEffect, UnknownNotEquals) {
116122
"SkDashPathEffect instance differs");
117123
}
118124

119-
void testEquals(DlPathEffect* a, DlPathEffect* b) {
120-
// a and b have the same nullness or values
121-
ASSERT_TRUE(Equals(a, b));
122-
ASSERT_FALSE(NotEquals(a, b));
123-
ASSERT_TRUE(Equals(b, a));
124-
ASSERT_FALSE(NotEquals(b, a));
125-
}
126-
127-
void testNotEquals(DlPathEffect* a, DlPathEffect* b) {
128-
// a and b do not have the same nullness or values
129-
ASSERT_FALSE(Equals(a, b));
130-
ASSERT_TRUE(NotEquals(a, b));
131-
ASSERT_FALSE(Equals(b, a));
132-
ASSERT_TRUE(NotEquals(b, a));
133-
}
134-
135-
void testEquals(std::shared_ptr<const DlPathEffect> a, DlPathEffect* b) {
136-
// a and b have the same nullness or values
137-
ASSERT_TRUE(Equals(a, b));
138-
ASSERT_FALSE(NotEquals(a, b));
139-
ASSERT_TRUE(Equals(b, a));
140-
ASSERT_FALSE(NotEquals(b, a));
141-
}
142-
143-
void testNotEquals(std::shared_ptr<const DlPathEffect> a, DlPathEffect* b) {
144-
// a and b do not have the same nullness or values
145-
ASSERT_FALSE(Equals(a, b));
146-
ASSERT_TRUE(NotEquals(a, b));
147-
ASSERT_FALSE(Equals(b, a));
148-
ASSERT_TRUE(NotEquals(b, a));
149-
}
150-
151-
void testEquals(std::shared_ptr<const DlPathEffect> a,
152-
std::shared_ptr<const DlPathEffect> b) {
153-
// a and b have the same nullness or values
154-
ASSERT_TRUE(Equals(a, b));
155-
ASSERT_FALSE(NotEquals(a, b));
156-
ASSERT_TRUE(Equals(b, a));
157-
ASSERT_FALSE(NotEquals(b, a));
158-
}
159-
160-
void testNotEquals(std::shared_ptr<const DlPathEffect> a,
161-
std::shared_ptr<const DlPathEffect> b) {
162-
// a and b do not have the same nullness or values
163-
ASSERT_FALSE(Equals(a, b));
164-
ASSERT_TRUE(NotEquals(a, b));
165-
ASSERT_FALSE(Equals(b, a));
166-
ASSERT_TRUE(NotEquals(b, a));
167-
}
168-
169-
TEST(DisplayListPathEffect, ComparableTemplates) {
170-
const SkScalar TestDashes1[] = {4.0, 2.0};
171-
const SkScalar TestDashes2[] = {1.0, 1.5};
172-
auto effect1 = DlDashPathEffect::Make(TestDashes1, 2, 0.0);
173-
auto effect2 = DlDashPathEffect::Make(TestDashes1, 2, 0.0);
174-
auto effect3 = DlDashPathEffect::Make(TestDashes2, 2, 1.0);
175-
std::shared_ptr<DlPathEffect> shared_null;
176-
177-
// null to null
178-
testEquals(nullptr, nullptr);
179-
testEquals(shared_null, nullptr);
180-
testEquals(shared_null, shared_null);
181-
182-
// ptr to null
183-
testNotEquals(effect1.get(), nullptr);
184-
testNotEquals(effect2.get(), nullptr);
185-
testNotEquals(effect3.get(), nullptr);
186-
187-
// shared_ptr to null and shared_null to ptr
188-
testNotEquals(effect1->shared(), nullptr);
189-
testNotEquals(effect2->shared(), nullptr);
190-
testNotEquals(effect3->shared(), nullptr);
191-
testNotEquals(shared_null, effect1.get());
192-
testNotEquals(shared_null, effect2.get());
193-
testNotEquals(shared_null, effect3.get());
194-
195-
// ptr to ptr
196-
testEquals(effect1, effect1);
197-
testEquals(effect1, effect2);
198-
testEquals(effect3, effect3);
199-
testEquals(effect2, effect2);
200-
201-
// shared_ptr to ptr
202-
testEquals(effect1->shared(), effect1);
203-
testEquals(effect1->shared(), effect2);
204-
testEquals(effect2->shared(), effect2);
205-
testEquals(effect3->shared(), effect3);
206-
testNotEquals(effect1->shared(), effect3);
207-
testNotEquals(effect2->shared(), effect3);
208-
testNotEquals(effect3->shared(), effect1);
209-
testNotEquals(effect3->shared(), effect2);
210-
211-
// shared_ptr to shared_ptr
212-
testEquals(effect1->shared(), effect1->shared());
213-
testEquals(effect1->shared(), effect2->shared());
214-
testEquals(effect2->shared(), effect2->shared());
215-
testEquals(effect3->shared(), effect3->shared());
216-
testNotEquals(effect1->shared(), effect3->shared());
217-
testNotEquals(effect2->shared(), effect3->shared());
218-
testNotEquals(effect3->shared(), effect1->shared());
219-
testNotEquals(effect3->shared(), effect2->shared());
220-
}
221-
222125
} // namespace testing
223126
} // namespace flutter

0 commit comments

Comments
 (0)