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

Commit c2c4046

Browse files
committed
Build display lists from SkParagraph output using the ParagraphPainter interface
SkPaint does not provide APIs for extracting the definitions of some attributes such as filters. The engine will instead use DlPaint to describe how text foregrounds and backgrounds will be painted. The DlPaint objects will be represented as PaintIDs in SkParagraph text styles. The ParagraphPainter will then map the PaintIDs back to the original DlPaint objects.
1 parent ecb5136 commit c2c4046

14 files changed

+241
-70
lines changed

display_list/display_list_builder.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,6 +1086,13 @@ void DisplayListBuilder::drawTextBlob(const sk_sp<SkTextBlob> blob,
10861086
Push<DrawTextBlobOp>(0, 1, blob, x, y);
10871087
CheckLayerOpacityCompatibility();
10881088
}
1089+
void DisplayListBuilder::drawTextBlob(const sk_sp<SkTextBlob> blob,
1090+
SkScalar x,
1091+
SkScalar y,
1092+
const DlPaint& paint) {
1093+
setAttributesFromDlPaint(paint, DisplayListOpFlags::kDrawTextBlobFlags);
1094+
drawTextBlob(blob, x, y);
1095+
}
10891096
void DisplayListBuilder::drawShadow(const SkPath& path,
10901097
const DlColor color,
10911098
const SkScalar elevation,

display_list/display_list_builder.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,10 @@ class DisplayListBuilder final : public virtual Dispatcher,
339339
void drawTextBlob(const sk_sp<SkTextBlob> blob,
340340
SkScalar x,
341341
SkScalar y) override;
342+
void drawTextBlob(const sk_sp<SkTextBlob> blob,
343+
SkScalar x,
344+
SkScalar y,
345+
const DlPaint& paint);
342346
void drawShadow(const SkPath& path,
343347
const DlColor color,
344348
const SkScalar elevation,
@@ -508,7 +512,6 @@ class DisplayListBuilder final : public virtual Dispatcher,
508512
void onSetColorFilter(const DlColorFilter* filter);
509513
void onSetPathEffect(const DlPathEffect* effect);
510514
void onSetMaskFilter(const DlMaskFilter* filter);
511-
void onSetMaskBlurFilter(SkBlurStyle style, SkScalar sigma);
512515

513516
DlPaint current_;
514517
// If |current_blender_| is set then ignore |current_.getBlendMode()|

display_list/display_list_mask_filter.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,13 @@ class DlMaskFilter
5858
// filter is then used to combine those colors.
5959
class DlBlurMaskFilter final : public DlMaskFilter {
6060
public:
61-
DlBlurMaskFilter(SkBlurStyle style, SkScalar sigma)
62-
: style_(style), sigma_(sigma) {}
61+
DlBlurMaskFilter(SkBlurStyle style, SkScalar sigma, bool respect_ctm = true)
62+
: style_(style), sigma_(sigma), respect_ctm_(respect_ctm) {}
6363
DlBlurMaskFilter(const DlBlurMaskFilter& filter)
64-
: DlBlurMaskFilter(filter.style_, filter.sigma_) {}
64+
: DlBlurMaskFilter(filter.style_, filter.sigma_, filter.respect_ctm_) {}
6565
DlBlurMaskFilter(const DlBlurMaskFilter* filter)
66-
: DlBlurMaskFilter(filter->style_, filter->sigma_) {}
66+
: DlBlurMaskFilter(filter->style_, filter->sigma_, filter->respect_ctm_) {
67+
}
6768

6869
DlMaskFilterType type() const override { return DlMaskFilterType::kBlur; }
6970
size_t size() const override { return sizeof(*this); }
@@ -73,24 +74,29 @@ class DlBlurMaskFilter final : public DlMaskFilter {
7374
}
7475

7576
sk_sp<SkMaskFilter> skia_object() const override {
76-
return SkMaskFilter::MakeBlur(style_, sigma_);
77+
return SkMaskFilter::MakeBlur(style_, sigma_, respect_ctm_);
7778
}
7879

7980
const DlBlurMaskFilter* asBlur() const override { return this; }
8081

8182
SkBlurStyle style() const { return style_; }
8283
SkScalar sigma() const { return sigma_; }
84+
bool respectCTM() const { return respect_ctm_; }
8385

8486
protected:
8587
bool equals_(DlMaskFilter const& other) const override {
8688
FML_DCHECK(other.type() == DlMaskFilterType::kBlur);
8789
auto that = static_cast<DlBlurMaskFilter const*>(&other);
88-
return style_ == that->style_ && sigma_ == that->sigma_;
90+
return style_ == that->style_ && sigma_ == that->sigma_ &&
91+
respect_ctm_ == that->respect_ctm_;
8992
}
9093

9194
private:
9295
SkBlurStyle style_;
9396
SkScalar sigma_;
97+
// Added for backward compatibility with Flutter text shadow rendering which
98+
// uses Skia blur filters with this flag set to false.
99+
bool respect_ctm_;
94100
};
95101

96102
// A wrapper class for a Skia MaskFilter of unknown type. The above 4 types

lib/ui/painting/canvas.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,11 @@ class Canvas : public RefCountedDartWrappable<Canvas>, DisplayListOpFlags {
190190
SkCanvas* canvas() const { return canvas_; }
191191
void Invalidate();
192192

193+
DisplayListBuilder* builder() {
194+
return display_list_recorder_ ? display_list_recorder_->builder().get()
195+
: nullptr;
196+
}
197+
193198
private:
194199
explicit Canvas(SkCanvas* canvas);
195200

@@ -205,9 +210,6 @@ class Canvas : public RefCountedDartWrappable<Canvas>, DisplayListOpFlags {
205210
// paint attributes from an SkPaint and an operation type as well as access
206211
// to the raw DisplayListBuilder for emitting custom rendering operations.
207212
sk_sp<DisplayListCanvasRecorder> display_list_recorder_;
208-
DisplayListBuilder* builder() {
209-
return display_list_recorder_->builder().get();
210-
}
211213
};
212214

213215
} // namespace flutter

lib/ui/text/paragraph.cc

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,15 @@ void Paragraph::paint(Canvas* canvas, double x, double y) {
6464
return;
6565
}
6666

67-
SkCanvas* sk_canvas = canvas->canvas();
68-
if (!sk_canvas) {
67+
DisplayListBuilder* builder = canvas->builder();
68+
if (builder && m_paragraph->Paint(builder, x, y)) {
6969
return;
7070
}
71-
m_paragraph->Paint(sk_canvas, x, y);
71+
// Fall back to SkCanvas if painting to DisplayListBuilder is not supported.
72+
SkCanvas* sk_canvas = canvas->canvas();
73+
if (sk_canvas) {
74+
m_paragraph->Paint(sk_canvas, x, y);
75+
}
7276
}
7377

7478
static tonic::Float32List EncodeTextBoxes(

lib/ui/text/paragraph_builder.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,9 @@ void ParagraphBuilder::pushStyle(const tonic::Int32List& encoded,
472472
SkPaint sk_paint;
473473
style.has_background = true;
474474
style.background = *background.paint(sk_paint);
475+
DlPaint dl_paint;
476+
background.toDlPaint(dl_paint);
477+
style.background_dl = dl_paint;
475478
}
476479
}
477480

@@ -481,6 +484,9 @@ void ParagraphBuilder::pushStyle(const tonic::Int32List& encoded,
481484
SkPaint sk_paint;
482485
style.has_foreground = true;
483486
style.foreground = *foreground.paint(sk_paint);
487+
DlPaint dl_paint;
488+
foreground.toDlPaint(dl_paint);
489+
style.foreground_dl = dl_paint;
484490
}
485491
}
486492

third_party/txt/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ source_set("txt") {
143143
configs += [ ":define_skshaper" ]
144144

145145
public_deps = [
146+
"//flutter/display_list",
146147
"//flutter/fml",
147148
"//third_party/harfbuzz",
148149
"//third_party/icu",

third_party/txt/src/skia/paragraph_builder_skia.cc

Lines changed: 64 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,66 @@ SkFontStyle MakeSkFontStyle(txt::FontWeight font_weight,
4242
: SkFontStyle::Slant::kItalic_Slant);
4343
}
4444

45-
skt::ParagraphStyle TxtToSkia(const ParagraphStyle& txt) {
45+
} // anonymous namespace
46+
47+
ParagraphBuilderSkia::ParagraphBuilderSkia(
48+
const ParagraphStyle& style,
49+
std::shared_ptr<FontCollection> font_collection)
50+
: base_style_(style.GetTextStyle()) {
51+
builder_ = skt::ParagraphBuilder::make(
52+
TxtToSkia(style), font_collection->CreateSktFontCollection());
53+
}
54+
55+
ParagraphBuilderSkia::~ParagraphBuilderSkia() = default;
56+
57+
void ParagraphBuilderSkia::PushStyle(const TextStyle& style) {
58+
builder_->pushStyle(TxtToSkia(style));
59+
txt_style_stack_.push(style);
60+
}
61+
62+
void ParagraphBuilderSkia::Pop() {
63+
builder_->pop();
64+
txt_style_stack_.pop();
65+
}
66+
67+
const TextStyle& ParagraphBuilderSkia::PeekStyle() {
68+
return txt_style_stack_.empty() ? base_style_ : txt_style_stack_.top();
69+
}
70+
71+
void ParagraphBuilderSkia::AddText(const std::u16string& text) {
72+
builder_->addText(text);
73+
}
74+
75+
void ParagraphBuilderSkia::AddPlaceholder(PlaceholderRun& span) {
76+
skt::PlaceholderStyle placeholder_style;
77+
placeholder_style.fHeight = span.height;
78+
placeholder_style.fWidth = span.width;
79+
placeholder_style.fBaseline = static_cast<skt::TextBaseline>(span.baseline);
80+
placeholder_style.fBaselineOffset = span.baseline_offset;
81+
placeholder_style.fAlignment =
82+
static_cast<skt::PlaceholderAlignment>(span.alignment);
83+
84+
builder_->addPlaceholder(placeholder_style);
85+
}
86+
87+
std::unique_ptr<Paragraph> ParagraphBuilderSkia::Build() {
88+
return std::make_unique<ParagraphSkia>(builder_->Build(),
89+
std::move(dl_paints_));
90+
}
91+
92+
skt::ParagraphPainter::PaintID ParagraphBuilderSkia::CreatePaintID(
93+
const flutter::DlPaint& dl_paint) {
94+
dl_paints_.push_back(dl_paint);
95+
return dl_paints_.size() - 1;
96+
}
97+
98+
skt::ParagraphStyle ParagraphBuilderSkia::TxtToSkia(const ParagraphStyle& txt) {
4699
skt::ParagraphStyle skia;
47100
skt::TextStyle text_style;
48101

102+
flutter::DlPaint dl_paint;
103+
dl_paint.setColor(text_style.getColor());
104+
text_style.setForegroundPaintID(CreatePaintID(dl_paint));
49105
text_style.setFontStyle(MakeSkFontStyle(txt.font_weight, txt.font_style));
50106
text_style.setFontSize(SkDoubleToScalar(txt.font_size));
51107
text_style.setHeight(SkDoubleToScalar(txt.height));
@@ -84,7 +140,7 @@ skt::ParagraphStyle TxtToSkia(const ParagraphStyle& txt) {
84140
return skia;
85141
}
86142

87-
skt::TextStyle TxtToSkia(const TextStyle& txt) {
143+
skt::TextStyle ParagraphBuilderSkia::TxtToSkia(const TextStyle& txt) {
88144
skt::TextStyle skia;
89145

90146
skia.setColor(txt.color);
@@ -112,10 +168,14 @@ skt::TextStyle TxtToSkia(const TextStyle& txt) {
112168

113169
skia.setLocale(SkString(txt.locale.c_str()));
114170
if (txt.has_background) {
115-
skia.setBackgroundColor(txt.background);
171+
skia.setBackgroundPaintID(CreatePaintID(txt.background_dl));
116172
}
117173
if (txt.has_foreground) {
118-
skia.setForegroundColor(txt.foreground);
174+
skia.setForegroundPaintID(CreatePaintID(txt.foreground_dl));
175+
} else {
176+
flutter::DlPaint dl_paint;
177+
dl_paint.setColor(txt.color);
178+
skia.setForegroundPaintID(CreatePaintID(dl_paint));
119179
}
120180

121181
skia.resetFontFeatures();
@@ -153,50 +213,4 @@ skt::TextStyle TxtToSkia(const TextStyle& txt) {
153213
return skia;
154214
}
155215

156-
} // anonymous namespace
157-
158-
ParagraphBuilderSkia::ParagraphBuilderSkia(
159-
const ParagraphStyle& style,
160-
std::shared_ptr<FontCollection> font_collection)
161-
: builder_(skt::ParagraphBuilder::make(
162-
TxtToSkia(style),
163-
font_collection->CreateSktFontCollection())),
164-
base_style_(style.GetTextStyle()) {}
165-
166-
ParagraphBuilderSkia::~ParagraphBuilderSkia() = default;
167-
168-
void ParagraphBuilderSkia::PushStyle(const TextStyle& style) {
169-
builder_->pushStyle(TxtToSkia(style));
170-
txt_style_stack_.push(style);
171-
}
172-
173-
void ParagraphBuilderSkia::Pop() {
174-
builder_->pop();
175-
txt_style_stack_.pop();
176-
}
177-
178-
const TextStyle& ParagraphBuilderSkia::PeekStyle() {
179-
return txt_style_stack_.empty() ? base_style_ : txt_style_stack_.top();
180-
}
181-
182-
void ParagraphBuilderSkia::AddText(const std::u16string& text) {
183-
builder_->addText(text);
184-
}
185-
186-
void ParagraphBuilderSkia::AddPlaceholder(PlaceholderRun& span) {
187-
skt::PlaceholderStyle placeholder_style;
188-
placeholder_style.fHeight = span.height;
189-
placeholder_style.fWidth = span.width;
190-
placeholder_style.fBaseline = static_cast<skt::TextBaseline>(span.baseline);
191-
placeholder_style.fBaselineOffset = span.baseline_offset;
192-
placeholder_style.fAlignment =
193-
static_cast<skt::PlaceholderAlignment>(span.alignment);
194-
195-
builder_->addPlaceholder(placeholder_style);
196-
}
197-
198-
std::unique_ptr<Paragraph> ParagraphBuilderSkia::Build() {
199-
return std::make_unique<ParagraphSkia>(builder_->Build());
200-
}
201-
202216
} // namespace txt

third_party/txt/src/skia/paragraph_builder_skia.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "txt/paragraph_builder.h"
2121

22+
#include "flutter/display_list/display_list_paint.h"
2223
#include "third_party/skia/modules/skparagraph/include/ParagraphBuilder.h"
2324

2425
namespace txt {
@@ -39,9 +40,15 @@ class ParagraphBuilderSkia : public ParagraphBuilder {
3940
virtual std::unique_ptr<Paragraph> Build() override;
4041

4142
private:
43+
skia::textlayout::ParagraphPainter::PaintID CreatePaintID(
44+
const flutter::DlPaint& dl_paint);
45+
skia::textlayout::ParagraphStyle TxtToSkia(const ParagraphStyle& txt);
46+
skia::textlayout::TextStyle TxtToSkia(const TextStyle& txt);
47+
4248
std::shared_ptr<skia::textlayout::ParagraphBuilder> builder_;
4349
TextStyle base_style_;
4450
std::stack<TextStyle> txt_style_stack_;
51+
std::vector<flutter::DlPaint> dl_paints_;
4552
};
4653

4754
} // namespace txt

0 commit comments

Comments
 (0)