Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
paragraph_unittests.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <memory>
11#include "gtest/gtest.h"
15#include "testing/canvas_test.h"
16
17namespace flutter {
18namespace testing {
19
20//------------------------------------------------------------------------------
21/// @brief A custom |DlOpReceiver| that records some |DlOps| it receives.
22class DlOpRecorder final : public virtual DlOpReceiver,
27 public:
28 int lineCount() const { return lines_.size(); }
29 int rectCount() const { return rects_.size(); }
30 int pathCount() const { return paths_.size(); }
31 int textFrameCount() const { return text_frames_.size(); }
32 int blobCount() const { return blobs_.size(); }
33 bool hasPathEffect() const { return path_effect_ != nullptr; }
34
35 private:
36 void drawLine(const SkPoint& p0, const SkPoint& p1) override {
37 lines_.emplace_back(p0, p1);
38 }
39
40 void drawTextFrame(const std::shared_ptr<impeller::TextFrame>& text_frame,
41 SkScalar x,
42 SkScalar y) override {
43 text_frames_.push_back(text_frame);
44 }
45
47 SkScalar x,
48 SkScalar y) override {
49 blobs_.push_back(blob);
50 }
51
52 void drawRect(const SkRect& rect) override { rects_.push_back(rect); }
53
54 void drawPath(const SkPath& path) override { paths_.push_back(path); }
55
56 void setPathEffect(const DlPathEffect* effect) override {
57 path_effect_ = effect;
58 }
59
60 std::vector<std::shared_ptr<impeller::TextFrame>> text_frames_;
61 std::vector<sk_sp<SkTextBlob>> blobs_;
62 std::vector<std::pair<SkPoint, SkPoint>> lines_;
63 std::vector<SkRect> rects_;
64 std::vector<SkPath> paths_;
65 const DlPathEffect* path_effect_;
66};
67
68template <typename T>
70 public:
71 PainterTestBase() = default;
72
73 void PretendImpellerIsEnabled(bool impeller) { impeller_ = impeller; }
74
75 protected:
77 auto t_style = txt::TextStyle();
78 t_style.color = SK_ColorBLACK; // default
79 t_style.font_weight = txt::FontWeight::w400; // normal
80 t_style.font_size = 14; // default
81 t_style.decoration = txt::TextDecoration::kUnderline;
82 t_style.decoration_style = style;
83 t_style.decoration_color = SK_ColorBLACK;
84 t_style.font_families.push_back("ahem");
85 return t_style;
86 }
87
89 auto t_style = txt::TextStyle();
90 t_style.color = SK_ColorBLACK; // default
91 t_style.font_weight = txt::FontWeight::w400; // normal
92 t_style.font_size = 14; // default
93 t_style.font_families.push_back("ahem");
94 return t_style;
95 }
96
98 auto pb_skia = makeParagraphBuilder();
99 pb_skia.PushStyle(style);
100 pb_skia.AddText(u"Hello World!");
101 pb_skia.Pop();
102
103 auto builder = DisplayListBuilder();
104 auto paragraph = pb_skia.Build();
105 paragraph->Layout(10000);
106 paragraph->Paint(&builder, 0, 0);
107
108 return builder.Build();
109 }
110
111 private:
112 std::shared_ptr<txt::FontCollection> makeFontCollection() const {
113 auto f_collection = std::make_shared<txt::FontCollection>();
114 auto font_provider = std::make_unique<txt::TypefaceFontAssetProvider>();
115 for (auto& font : GetTestFontData()) {
116 font_provider->RegisterTypeface(font);
117 }
118 auto manager = sk_make_sp<txt::AssetFontManager>(std::move(font_provider));
119 f_collection->SetAssetFontManager(manager);
120 return f_collection;
121 }
122
123 txt::ParagraphBuilderSkia makeParagraphBuilder() const {
124 auto p_style = txt::ParagraphStyle();
125 auto f_collection = makeFontCollection();
126 return txt::ParagraphBuilderSkia(p_style, f_collection, impeller_);
127 }
128
129 bool impeller_ = false;
130};
131
133
134TEST_F(PainterTest, DrawsSolidLineSkia) {
135 PretendImpellerIsEnabled(false);
136
137 auto recorder = DlOpRecorder();
138 draw(makeDecoratedStyle(txt::TextDecorationStyle::kSolid))
139 ->Dispatch(recorder);
140
141 // Skia may draw a solid underline as a filled rectangle:
142 // https://skia.googlesource.com/skia/+/refs/heads/main/modules/skparagraph/src/Decorations.cpp#91
143 EXPECT_EQ(recorder.rectCount(), 1);
144 EXPECT_FALSE(recorder.hasPathEffect());
145}
146
147TEST_F(PainterTest, DrawDashedLineSkia) {
148 PretendImpellerIsEnabled(false);
149
150 auto recorder = DlOpRecorder();
151 draw(makeDecoratedStyle(txt::TextDecorationStyle::kDashed))
152 ->Dispatch(recorder);
153
154 // Skia draws a dashed underline as a filled rectangle with a path effect.
155 EXPECT_EQ(recorder.lineCount(), 1);
156 EXPECT_TRUE(recorder.hasPathEffect());
157}
158
159#ifdef IMPELLER_SUPPORTS_RENDERING
160TEST_F(PainterTest, DrawsSolidLineImpeller) {
161 PretendImpellerIsEnabled(true);
162
163 auto recorder = DlOpRecorder();
164 draw(makeDecoratedStyle(txt::TextDecorationStyle::kSolid))
165 ->Dispatch(recorder);
166
167 // Skia may draw a solid underline as a filled rectangle:
168 // https://skia.googlesource.com/skia/+/refs/heads/main/modules/skparagraph/src/Decorations.cpp#91
169 EXPECT_EQ(recorder.rectCount(), 1);
170 EXPECT_FALSE(recorder.hasPathEffect());
171}
172
173TEST_F(PainterTest, DrawDashedLineImpeller) {
174 PretendImpellerIsEnabled(true);
175
176 auto recorder = DlOpRecorder();
177 draw(makeDecoratedStyle(txt::TextDecorationStyle::kDashed))
178 ->Dispatch(recorder);
179
180 // Impeller draws a dashed underline as a path.
181 EXPECT_EQ(recorder.pathCount(), 1);
182 EXPECT_FALSE(recorder.hasPathEffect());
183}
184
185TEST_F(PainterTest, DrawTextFrameImpeller) {
186 PretendImpellerIsEnabled(true);
187
188 auto recorder = DlOpRecorder();
189 draw(makeStyle())->Dispatch(recorder);
190
191 EXPECT_EQ(recorder.textFrameCount(), 1);
192 EXPECT_EQ(recorder.blobCount(), 0);
193}
194
195TEST_F(PainterTest, DrawStrokedTextImpeller) {
196 PretendImpellerIsEnabled(true);
197
198 auto style = makeStyle();
199 // What is your shtyle?
200 DlPaint foreground;
201 foreground.setDrawStyle(DlDrawStyle::kStroke);
202 style.foreground = foreground;
203
204 auto recorder = DlOpRecorder();
205 draw(style)->Dispatch(recorder);
206
207 EXPECT_EQ(recorder.textFrameCount(), 0);
208 EXPECT_EQ(recorder.blobCount(), 0);
209 EXPECT_EQ(recorder.pathCount(), 1);
210}
211
212TEST_F(PainterTest, DrawTextWithGradientImpeller) {
213 PretendImpellerIsEnabled(true);
214
215 auto style = makeStyle();
216 // how do you like my shtyle?
217 DlPaint foreground;
218 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kCyan()};
219 std::vector<float> stops = {0.0, 1.0};
220 foreground.setColorSource(DlColorSource::MakeLinear(
221 SkPoint::Make(0, 0), SkPoint::Make(100, 100), 2, colors.data(),
222 stops.data(), DlTileMode::kClamp));
223 style.foreground = foreground;
224
225 auto recorder = DlOpRecorder();
226 draw(style)->Dispatch(recorder);
227
228 EXPECT_EQ(recorder.textFrameCount(), 0);
229 EXPECT_EQ(recorder.blobCount(), 0);
230 EXPECT_EQ(recorder.pathCount(), 1);
231}
232
233TEST_F(PainterTest, DrawTextBlobNoImpeller) {
234 PretendImpellerIsEnabled(false);
235
236 auto recorder = DlOpRecorder();
237 draw(makeStyle())->Dispatch(recorder);
238
239 EXPECT_EQ(recorder.textFrameCount(), 0);
240 EXPECT_EQ(recorder.blobCount(), 1);
241}
242#endif // IMPELLER_SUPPORTS_RENDERING
243
244} // namespace testing
245} // namespace flutter
constexpr SkColor SK_ColorBLACK
Definition SkColor.h:103
static void draw(SkCanvas *canvas, SkRect &target, int x, int y)
Definition aaclip.cpp:27
static std::shared_ptr< DlLinearGradientColorSource > MakeLinear(const SkPoint start_point, const SkPoint end_point, uint32_t stop_count, const DlColor *colors, const float *stops, DlTileMode tile_mode, const SkMatrix *matrix=nullptr)
Internal API for rendering recorded display lists to backends.
A custom |DlOpReceiver| that records some |DlOps| it receives.
void drawTextFrame(const std::shared_ptr< impeller::TextFrame > &text_frame, SkScalar x, SkScalar y) override
void drawTextBlob(const sk_sp< SkTextBlob > blob, SkScalar x, SkScalar y) override
void drawLine(const SkPoint &p0, const SkPoint &p1) override
void drawRect(const SkRect &rect) override
void setPathEffect(const DlPathEffect *effect) override
void drawPath(const SkPath &path) override
txt::TextStyle makeDecoratedStyle(txt::TextDecorationStyle style)
sk_sp< DisplayList > draw(txt::TextStyle style) const
ParagraphBuilder implementation using Skia's text layout module.
float SkScalar
Definition extension.cpp:12
double y
double x
PODArray< SkColor > colors
Definition SkRecords.h:276
TEST_F(DisplayListTest, Defaults)
PainterTestBase<::testing::Test > PainterTest
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font manager
Definition switches.h:218
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition switches.h:57
@ kStroke
strokes boundary of shapes
std::vector< sk_sp< SkTypeface > > GetTestFontData()
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap The size limit in megabytes for the Dart VM old gen heap space enable impeller
Definition switches.h:266
TextDecorationStyle
static constexpr SkPoint Make(float x, float y)
static constexpr DlColor kRed()
Definition dl_color.h:24
static constexpr DlColor kCyan()
Definition dl_color.h:27
#define EXPECT_TRUE(handle)
Definition unit_test.h:685