From d0b04cffd5361b4ccbf1203a129e7b6e4ec638c9 Mon Sep 17 00:00:00 2001 From: Jason Simmons Date: Thu, 1 Sep 2022 11:12:52 -0700 Subject: [PATCH] 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. --- display_list/display_list_builder.cc | 7 + display_list/display_list_builder.h | 5 +- display_list/display_list_mask_filter.h | 18 +- display_list/display_list_test_utils.cc | 10 +- lib/ui/painting/canvas.h | 8 +- lib/ui/text/paragraph.cc | 10 +- lib/ui/text/paragraph_builder.cc | 6 + third_party/txt/BUILD.gn | 1 + .../txt/src/skia/paragraph_builder_skia.cc | 116 ++++++----- .../txt/src/skia/paragraph_builder_skia.h | 7 + third_party/txt/src/skia/paragraph_skia.cc | 187 ++++++++++++++---- third_party/txt/src/skia/paragraph_skia.h | 7 +- third_party/txt/src/txt/paragraph.h | 4 + third_party/txt/src/txt/paragraph_txt.h | 5 + third_party/txt/src/txt/text_style.h | 3 + 15 files changed, 291 insertions(+), 103 deletions(-) diff --git a/display_list/display_list_builder.cc b/display_list/display_list_builder.cc index ccef2769aeaaf..81c06b08b1be0 100644 --- a/display_list/display_list_builder.cc +++ b/display_list/display_list_builder.cc @@ -1071,6 +1071,13 @@ void DisplayListBuilder::drawTextBlob(const sk_sp blob, Push(0, 1, blob, x, y); CheckLayerOpacityCompatibility(); } +void DisplayListBuilder::drawTextBlob(const sk_sp& blob, + SkScalar x, + SkScalar y, + const DlPaint& paint) { + setAttributesFromDlPaint(paint, DisplayListOpFlags::kDrawTextBlobFlags); + drawTextBlob(blob, x, y); +} void DisplayListBuilder::drawShadow(const SkPath& path, const DlColor color, const SkScalar elevation, diff --git a/display_list/display_list_builder.h b/display_list/display_list_builder.h index 8bcc3ffa56db6..5be4146b14e45 100644 --- a/display_list/display_list_builder.h +++ b/display_list/display_list_builder.h @@ -334,6 +334,10 @@ class DisplayListBuilder final : public virtual Dispatcher, void drawTextBlob(const sk_sp blob, SkScalar x, SkScalar y) override; + void drawTextBlob(const sk_sp& blob, + SkScalar x, + SkScalar y, + const DlPaint& paint); void drawShadow(const SkPath& path, const DlColor color, const SkScalar elevation, @@ -503,7 +507,6 @@ class DisplayListBuilder final : public virtual Dispatcher, void onSetColorFilter(const DlColorFilter* filter); void onSetPathEffect(const DlPathEffect* effect); void onSetMaskFilter(const DlMaskFilter* filter); - void onSetMaskBlurFilter(SkBlurStyle style, SkScalar sigma); DlPaint current_; // If |current_blender_| is set then ignore |current_.getBlendMode()| diff --git a/display_list/display_list_mask_filter.h b/display_list/display_list_mask_filter.h index 56233421a9638..336d7c58e74fd 100644 --- a/display_list/display_list_mask_filter.h +++ b/display_list/display_list_mask_filter.h @@ -58,12 +58,13 @@ class DlMaskFilter // filter is then used to combine those colors. class DlBlurMaskFilter final : public DlMaskFilter { public: - DlBlurMaskFilter(SkBlurStyle style, SkScalar sigma) - : style_(style), sigma_(sigma) {} + DlBlurMaskFilter(SkBlurStyle style, SkScalar sigma, bool respect_ctm = true) + : style_(style), sigma_(sigma), respect_ctm_(respect_ctm) {} DlBlurMaskFilter(const DlBlurMaskFilter& filter) - : DlBlurMaskFilter(filter.style_, filter.sigma_) {} + : DlBlurMaskFilter(filter.style_, filter.sigma_, filter.respect_ctm_) {} DlBlurMaskFilter(const DlBlurMaskFilter* filter) - : DlBlurMaskFilter(filter->style_, filter->sigma_) {} + : DlBlurMaskFilter(filter->style_, filter->sigma_, filter->respect_ctm_) { + } DlMaskFilterType type() const override { return DlMaskFilterType::kBlur; } size_t size() const override { return sizeof(*this); } @@ -73,24 +74,29 @@ class DlBlurMaskFilter final : public DlMaskFilter { } sk_sp skia_object() const override { - return SkMaskFilter::MakeBlur(style_, sigma_); + return SkMaskFilter::MakeBlur(style_, sigma_, respect_ctm_); } const DlBlurMaskFilter* asBlur() const override { return this; } SkBlurStyle style() const { return style_; } SkScalar sigma() const { return sigma_; } + bool respectCTM() const { return respect_ctm_; } protected: bool equals_(DlMaskFilter const& other) const override { FML_DCHECK(other.type() == DlMaskFilterType::kBlur); auto that = static_cast(&other); - return style_ == that->style_ && sigma_ == that->sigma_; + return style_ == that->style_ && sigma_ == that->sigma_ && + respect_ctm_ == that->respect_ctm_; } private: SkBlurStyle style_; SkScalar sigma_; + // Added for backward compatibility with Flutter text shadow rendering which + // uses Skia blur filters with this flag set to false. + bool respect_ctm_; }; // A wrapper class for a Skia MaskFilter of unknown type. The above 4 types diff --git a/display_list/display_list_test_utils.cc b/display_list/display_list_test_utils.cc index 74e9c9ed4ee2e..144fe140d7490 100644 --- a/display_list/display_list_test_utils.cc +++ b/display_list/display_list_test_utils.cc @@ -284,15 +284,15 @@ std::vector CreateAllAttributesOps() { }}, {"SetMaskFilter", { - {0, 24, 0, 0, + {0, 32, 0, 0, [](DisplayListBuilder& b) { b.setMaskFilter(&kTestMaskFilter1); }}, - {0, 24, 0, 0, + {0, 32, 0, 0, [](DisplayListBuilder& b) { b.setMaskFilter(&kTestMaskFilter2); }}, - {0, 24, 0, 0, + {0, 32, 0, 0, [](DisplayListBuilder& b) { b.setMaskFilter(&kTestMaskFilter3); }}, - {0, 24, 0, 0, + {0, 32, 0, 0, [](DisplayListBuilder& b) { b.setMaskFilter(&kTestMaskFilter4); }}, - {0, 24, 0, 0, + {0, 32, 0, 0, [](DisplayListBuilder& b) { b.setMaskFilter(&kTestMaskFilter5); }}, {0, 0, 0, 0, [](DisplayListBuilder& b) { b.setMaskFilter(nullptr); }}, diff --git a/lib/ui/painting/canvas.h b/lib/ui/painting/canvas.h index 22ef44315ca09..0855c52c20f8c 100644 --- a/lib/ui/painting/canvas.h +++ b/lib/ui/painting/canvas.h @@ -190,6 +190,11 @@ class Canvas : public RefCountedDartWrappable, DisplayListOpFlags { SkCanvas* canvas() const { return canvas_; } void Invalidate(); + DisplayListBuilder* builder() { + return display_list_recorder_ ? display_list_recorder_->builder().get() + : nullptr; + } + private: explicit Canvas(SkCanvas* canvas); @@ -205,9 +210,6 @@ class Canvas : public RefCountedDartWrappable, DisplayListOpFlags { // paint attributes from an SkPaint and an operation type as well as access // to the raw DisplayListBuilder for emitting custom rendering operations. sk_sp display_list_recorder_; - DisplayListBuilder* builder() { - return display_list_recorder_->builder().get(); - } }; } // namespace flutter diff --git a/lib/ui/text/paragraph.cc b/lib/ui/text/paragraph.cc index 6b4bb3610bc50..4b3df6439186d 100644 --- a/lib/ui/text/paragraph.cc +++ b/lib/ui/text/paragraph.cc @@ -64,11 +64,15 @@ void Paragraph::paint(Canvas* canvas, double x, double y) { return; } - SkCanvas* sk_canvas = canvas->canvas(); - if (!sk_canvas) { + DisplayListBuilder* builder = canvas->builder(); + if (builder && m_paragraph->Paint(builder, x, y)) { return; } - m_paragraph->Paint(sk_canvas, x, y); + // Fall back to SkCanvas if painting to DisplayListBuilder is not supported. + SkCanvas* sk_canvas = canvas->canvas(); + if (sk_canvas) { + m_paragraph->Paint(sk_canvas, x, y); + } } static tonic::Float32List EncodeTextBoxes( diff --git a/lib/ui/text/paragraph_builder.cc b/lib/ui/text/paragraph_builder.cc index 03daf9358452c..82881ede24eda 100644 --- a/lib/ui/text/paragraph_builder.cc +++ b/lib/ui/text/paragraph_builder.cc @@ -472,6 +472,9 @@ void ParagraphBuilder::pushStyle(const tonic::Int32List& encoded, SkPaint sk_paint; style.has_background = true; style.background = *background.paint(sk_paint); + DlPaint dl_paint; + background.toDlPaint(dl_paint); + style.background_dl = dl_paint; } } @@ -481,6 +484,9 @@ void ParagraphBuilder::pushStyle(const tonic::Int32List& encoded, SkPaint sk_paint; style.has_foreground = true; style.foreground = *foreground.paint(sk_paint); + DlPaint dl_paint; + foreground.toDlPaint(dl_paint); + style.foreground_dl = dl_paint; } } diff --git a/third_party/txt/BUILD.gn b/third_party/txt/BUILD.gn index 98327626ec2aa..3060859fe4773 100644 --- a/third_party/txt/BUILD.gn +++ b/third_party/txt/BUILD.gn @@ -143,6 +143,7 @@ source_set("txt") { configs += [ ":define_skshaper" ] public_deps = [ + "//flutter/display_list", "//flutter/fml", "//third_party/harfbuzz", "//third_party/icu", diff --git a/third_party/txt/src/skia/paragraph_builder_skia.cc b/third_party/txt/src/skia/paragraph_builder_skia.cc index 79b7a65adb413..272b6e09cb21e 100644 --- a/third_party/txt/src/skia/paragraph_builder_skia.cc +++ b/third_party/txt/src/skia/paragraph_builder_skia.cc @@ -42,10 +42,68 @@ SkFontStyle MakeSkFontStyle(txt::FontWeight font_weight, : SkFontStyle::Slant::kItalic_Slant); } -skt::ParagraphStyle TxtToSkia(const ParagraphStyle& txt) { +} // anonymous namespace + +ParagraphBuilderSkia::ParagraphBuilderSkia( + const ParagraphStyle& style, + std::shared_ptr font_collection) + : base_style_(style.GetTextStyle()) { + builder_ = skt::ParagraphBuilder::make( + TxtToSkia(style), font_collection->CreateSktFontCollection()); +} + +ParagraphBuilderSkia::~ParagraphBuilderSkia() = default; + +void ParagraphBuilderSkia::PushStyle(const TextStyle& style) { + builder_->pushStyle(TxtToSkia(style)); + txt_style_stack_.push(style); +} + +void ParagraphBuilderSkia::Pop() { + builder_->pop(); + txt_style_stack_.pop(); +} + +const TextStyle& ParagraphBuilderSkia::PeekStyle() { + return txt_style_stack_.empty() ? base_style_ : txt_style_stack_.top(); +} + +void ParagraphBuilderSkia::AddText(const std::u16string& text) { + builder_->addText(text); +} + +void ParagraphBuilderSkia::AddPlaceholder(PlaceholderRun& span) { + skt::PlaceholderStyle placeholder_style; + placeholder_style.fHeight = span.height; + placeholder_style.fWidth = span.width; + placeholder_style.fBaseline = static_cast(span.baseline); + placeholder_style.fBaselineOffset = span.baseline_offset; + placeholder_style.fAlignment = + static_cast(span.alignment); + + builder_->addPlaceholder(placeholder_style); +} + +std::unique_ptr ParagraphBuilderSkia::Build() { + return std::make_unique(builder_->Build(), + std::move(dl_paints_)); +} + +skt::ParagraphPainter::PaintID ParagraphBuilderSkia::CreatePaintID( + const flutter::DlPaint& dl_paint) { + dl_paints_.push_back(dl_paint); + return dl_paints_.size() - 1; +} + +skt::ParagraphStyle ParagraphBuilderSkia::TxtToSkia(const ParagraphStyle& txt) { skt::ParagraphStyle skia; skt::TextStyle text_style; + // Convert the default color of an SkParagraph text style into a DlPaint. + flutter::DlPaint dl_paint; + dl_paint.setColor(text_style.getColor()); + text_style.setForegroundPaintID(CreatePaintID(dl_paint)); + text_style.setFontStyle(MakeSkFontStyle(txt.font_weight, txt.font_style)); text_style.setFontSize(SkDoubleToScalar(txt.font_size)); text_style.setHeight(SkDoubleToScalar(txt.height)); @@ -84,7 +142,7 @@ skt::ParagraphStyle TxtToSkia(const ParagraphStyle& txt) { return skia; } -skt::TextStyle TxtToSkia(const TextStyle& txt) { +skt::TextStyle ParagraphBuilderSkia::TxtToSkia(const TextStyle& txt) { skt::TextStyle skia; skia.setColor(txt.color); @@ -112,10 +170,14 @@ skt::TextStyle TxtToSkia(const TextStyle& txt) { skia.setLocale(SkString(txt.locale.c_str())); if (txt.has_background) { - skia.setBackgroundColor(txt.background); + skia.setBackgroundPaintID(CreatePaintID(txt.background_dl)); } if (txt.has_foreground) { - skia.setForegroundColor(txt.foreground); + skia.setForegroundPaintID(CreatePaintID(txt.foreground_dl)); + } else { + flutter::DlPaint dl_paint; + dl_paint.setColor(txt.color); + skia.setForegroundPaintID(CreatePaintID(dl_paint)); } skia.resetFontFeatures(); @@ -153,50 +215,4 @@ skt::TextStyle TxtToSkia(const TextStyle& txt) { return skia; } -} // anonymous namespace - -ParagraphBuilderSkia::ParagraphBuilderSkia( - const ParagraphStyle& style, - std::shared_ptr font_collection) - : builder_(skt::ParagraphBuilder::make( - TxtToSkia(style), - font_collection->CreateSktFontCollection())), - base_style_(style.GetTextStyle()) {} - -ParagraphBuilderSkia::~ParagraphBuilderSkia() = default; - -void ParagraphBuilderSkia::PushStyle(const TextStyle& style) { - builder_->pushStyle(TxtToSkia(style)); - txt_style_stack_.push(style); -} - -void ParagraphBuilderSkia::Pop() { - builder_->pop(); - txt_style_stack_.pop(); -} - -const TextStyle& ParagraphBuilderSkia::PeekStyle() { - return txt_style_stack_.empty() ? base_style_ : txt_style_stack_.top(); -} - -void ParagraphBuilderSkia::AddText(const std::u16string& text) { - builder_->addText(text); -} - -void ParagraphBuilderSkia::AddPlaceholder(PlaceholderRun& span) { - skt::PlaceholderStyle placeholder_style; - placeholder_style.fHeight = span.height; - placeholder_style.fWidth = span.width; - placeholder_style.fBaseline = static_cast(span.baseline); - placeholder_style.fBaselineOffset = span.baseline_offset; - placeholder_style.fAlignment = - static_cast(span.alignment); - - builder_->addPlaceholder(placeholder_style); -} - -std::unique_ptr ParagraphBuilderSkia::Build() { - return std::make_unique(builder_->Build()); -} - } // namespace txt diff --git a/third_party/txt/src/skia/paragraph_builder_skia.h b/third_party/txt/src/skia/paragraph_builder_skia.h index 06b00caf43c52..58869cfa0a58b 100644 --- a/third_party/txt/src/skia/paragraph_builder_skia.h +++ b/third_party/txt/src/skia/paragraph_builder_skia.h @@ -19,6 +19,7 @@ #include "txt/paragraph_builder.h" +#include "flutter/display_list/display_list_paint.h" #include "third_party/skia/modules/skparagraph/include/ParagraphBuilder.h" namespace txt { @@ -39,9 +40,15 @@ class ParagraphBuilderSkia : public ParagraphBuilder { virtual std::unique_ptr Build() override; private: + skia::textlayout::ParagraphPainter::PaintID CreatePaintID( + const flutter::DlPaint& dl_paint); + skia::textlayout::ParagraphStyle TxtToSkia(const ParagraphStyle& txt); + skia::textlayout::TextStyle TxtToSkia(const TextStyle& txt); + std::shared_ptr builder_; TextStyle base_style_; std::stack txt_style_stack_; + std::vector dl_paints_; }; } // namespace txt diff --git a/third_party/txt/src/skia/paragraph_skia.cc b/third_party/txt/src/skia/paragraph_skia.cc index 2bf3fbeead623..359a0880de218 100644 --- a/third_party/txt/src/skia/paragraph_skia.cc +++ b/third_party/txt/src/skia/paragraph_skia.cc @@ -22,6 +22,9 @@ namespace txt { namespace skt = skia::textlayout; +using PaintID = skt::ParagraphPainter::PaintID; + +using namespace flutter; namespace { @@ -40,54 +43,108 @@ txt::FontStyle GetTxtFontStyle(SkFontStyle::Slant font_slant) { : txt::FontStyle::italic; } -TextStyle SkiaToTxt(const skt::TextStyle& skia) { - TextStyle txt; +class DisplayListParagraphPainter : public skt::ParagraphPainter { + public: + DisplayListParagraphPainter(DisplayListBuilder* builder, + const std::vector& dl_paints) + : builder_(builder), dl_paints_(dl_paints) {} + + DlPaint toDlPaint(const DecorationStyle& decor_style, + DlDrawStyle draw_style = DlDrawStyle::kStroke) { + DlPaint paint; + paint.setDrawStyle(draw_style); + paint.setAntiAlias(true); + paint.setColor(decor_style.getColor()); + paint.setStrokeWidth(decor_style.getStrokeWidth()); + std::optional dash_path_effect = + decor_style.getDashPathEffect(); + if (dash_path_effect) { + std::array intervals{dash_path_effect->fOnLength, + dash_path_effect->fOffLength}; + paint.setPathEffect( + DlDashPathEffect::Make(intervals.data(), intervals.size(), 0)); + } + return paint; + } - txt.color = skia.getColor(); - txt.decoration = static_cast(skia.getDecorationType()); - txt.decoration_color = skia.getDecorationColor(); - txt.decoration_style = - static_cast(skia.getDecorationStyle()); - txt.decoration_thickness_multiplier = - SkScalarToDouble(skia.getDecorationThicknessMultiplier()); - txt.font_weight = GetTxtFontWeight(skia.getFontStyle().weight()); - txt.font_style = GetTxtFontStyle(skia.getFontStyle().slant()); + void drawTextBlob(const sk_sp& blob, + SkScalar x, + SkScalar y, + const SkPaintOrID& paint) override { + if (!blob) { + return; + } + size_t paint_id = std::get(paint); + FML_DCHECK(paint_id < dl_paints_.size()); + builder_->drawTextBlob(blob, x, y, dl_paints_[paint_id]); + } - txt.text_baseline = static_cast(skia.getTextBaseline()); + void drawTextShadow(const sk_sp& blob, + SkScalar x, + SkScalar y, + SkColor color, + SkScalar blur_sigma) override { + if (!blob) { + return; + } + DlPaint paint; + paint.setColor(color); + if (blur_sigma > 0.0) { + DlBlurMaskFilter filter(SkBlurStyle::kNormal_SkBlurStyle, blur_sigma, + false); + paint.setMaskFilter(&filter); + } + builder_->drawTextBlob(blob, x, y, paint); + } - for (const SkString& font_family : skia.getFontFamilies()) { - txt.font_families.emplace_back(font_family.c_str()); + void drawRect(const SkRect& rect, const SkPaintOrID& paint) override { + size_t paint_id = std::get(paint); + FML_DCHECK(paint_id < dl_paints_.size()); + builder_->drawRect(rect, dl_paints_[paint_id]); } - txt.font_size = SkScalarToDouble(skia.getFontSize()); - txt.letter_spacing = SkScalarToDouble(skia.getLetterSpacing()); - txt.word_spacing = SkScalarToDouble(skia.getWordSpacing()); - txt.height = SkScalarToDouble(skia.getHeight()); + void drawFilledRect(const SkRect& rect, + const DecorationStyle& decor_style) override { + DlPaint paint = toDlPaint(decor_style, DlDrawStyle::kFill); + builder_->drawRect(rect, paint); + } - txt.locale = skia.getLocale().c_str(); - if (skia.hasBackground()) { - txt.background = skia.getBackground(); + void drawPath(const SkPath& path, + const DecorationStyle& decor_style) override { + builder_->drawPath(path, toDlPaint(decor_style)); } - if (skia.hasForeground()) { - txt.foreground = skia.getForeground(); + + void drawLine(SkScalar x0, + SkScalar y0, + SkScalar x1, + SkScalar y1, + const DecorationStyle& decor_style) override { + builder_->drawLine(SkPoint::Make(x0, y0), SkPoint::Make(x1, y1), + toDlPaint(decor_style)); } - txt.text_shadows.clear(); - for (const skt::TextShadow& skia_shadow : skia.getShadows()) { - txt::TextShadow shadow; - shadow.offset = skia_shadow.fOffset; - shadow.blur_sigma = skia_shadow.fBlurSigma; - shadow.color = skia_shadow.fColor; - txt.text_shadows.emplace_back(shadow); + void clipRect(const SkRect& rect) override { + builder_->clipRect(rect, SkClipOp::kIntersect, false); } - return txt; -} + void translate(SkScalar dx, SkScalar dy) override { + builder_->translate(dx, dy); + } + + void save() override { builder_->save(); } + + void restore() override { builder_->restore(); } + + private: + DisplayListBuilder* builder_; + const std::vector& dl_paints_; +}; } // anonymous namespace -ParagraphSkia::ParagraphSkia(std::unique_ptr paragraph) - : paragraph_(std::move(paragraph)) {} +ParagraphSkia::ParagraphSkia(std::unique_ptr paragraph, + std::vector&& dl_paints) + : paragraph_(std::move(paragraph)), dl_paints_(dl_paints) {} double ParagraphSkia::GetMaxWidth() { return SkScalarToDouble(paragraph_->getMaxWidth()); @@ -170,6 +227,12 @@ void ParagraphSkia::Paint(SkCanvas* canvas, double x, double y) { paragraph_->paint(canvas, x, y); } +bool ParagraphSkia::Paint(DisplayListBuilder* builder, double x, double y) { + DisplayListParagraphPainter painter(builder, dl_paints_); + paragraph_->paint(&painter, x, y); + return true; +} + std::vector ParagraphSkia::GetRectsForRange( size_t start, size_t end, @@ -215,4 +278,60 @@ Paragraph::Range ParagraphSkia::GetWordBoundary(size_t offset) { return Paragraph::Range(range.start, range.end); } +TextStyle ParagraphSkia::SkiaToTxt(const skt::TextStyle& skia) { + TextStyle txt; + + txt.color = skia.getColor(); + txt.decoration = static_cast(skia.getDecorationType()); + txt.decoration_color = skia.getDecorationColor(); + txt.decoration_style = + static_cast(skia.getDecorationStyle()); + txt.decoration_thickness_multiplier = + SkScalarToDouble(skia.getDecorationThicknessMultiplier()); + txt.font_weight = GetTxtFontWeight(skia.getFontStyle().weight()); + txt.font_style = GetTxtFontStyle(skia.getFontStyle().slant()); + + txt.text_baseline = static_cast(skia.getTextBaseline()); + + for (const SkString& font_family : skia.getFontFamilies()) { + txt.font_families.emplace_back(font_family.c_str()); + } + + txt.font_size = SkScalarToDouble(skia.getFontSize()); + txt.letter_spacing = SkScalarToDouble(skia.getLetterSpacing()); + txt.word_spacing = SkScalarToDouble(skia.getWordSpacing()); + txt.height = SkScalarToDouble(skia.getHeight()); + + txt.locale = skia.getLocale().c_str(); + if (skia.hasBackground()) { + skt::ParagraphPainter::SkPaintOrID background = + skia.getBackgroundPaintOrID(); + if (std::holds_alternative(background)) { + txt.background = std::get(background); + } else if (std::holds_alternative(background)) { + txt.background_dl = dl_paints_[std::get(background)]; + } + } + if (skia.hasForeground()) { + skt::ParagraphPainter::SkPaintOrID foreground = + skia.getForegroundPaintOrID(); + if (std::holds_alternative(foreground)) { + txt.foreground = std::get(foreground); + } else if (std::holds_alternative(foreground)) { + txt.foreground_dl = dl_paints_[std::get(foreground)]; + } + } + + txt.text_shadows.clear(); + for (const skt::TextShadow& skia_shadow : skia.getShadows()) { + txt::TextShadow shadow; + shadow.offset = skia_shadow.fOffset; + shadow.blur_sigma = skia_shadow.fBlurSigma; + shadow.color = skia_shadow.fColor; + txt.text_shadows.emplace_back(shadow); + } + + return txt; +} + } // namespace txt diff --git a/third_party/txt/src/skia/paragraph_skia.h b/third_party/txt/src/skia/paragraph_skia.h index 286fbe47ca09c..640ab479d41f7 100644 --- a/third_party/txt/src/skia/paragraph_skia.h +++ b/third_party/txt/src/skia/paragraph_skia.h @@ -28,7 +28,8 @@ namespace txt { // Implementation of Paragraph based on Skia's text layout module. class ParagraphSkia : public Paragraph { public: - ParagraphSkia(std::unique_ptr paragraph); + ParagraphSkia(std::unique_ptr paragraph, + std::vector&& dl_paints); virtual ~ParagraphSkia() = default; @@ -53,6 +54,7 @@ class ParagraphSkia : public Paragraph { void Layout(double width) override; void Paint(SkCanvas* canvas, double x, double y) override; + bool Paint(flutter::DisplayListBuilder* builder, double x, double y) override; std::vector GetRectsForRange( size_t start, @@ -68,7 +70,10 @@ class ParagraphSkia : public Paragraph { Range GetWordBoundary(size_t offset) override; private: + TextStyle SkiaToTxt(const skia::textlayout::TextStyle& skia); + std::unique_ptr paragraph_; + std::vector dl_paints_; std::optional> line_metrics_; std::vector line_metrics_styles_; }; diff --git a/third_party/txt/src/txt/paragraph.h b/third_party/txt/src/txt/paragraph.h index 2065a2d1cbd17..db713241d5936 100644 --- a/third_party/txt/src/txt/paragraph.h +++ b/third_party/txt/src/txt/paragraph.h @@ -18,6 +18,7 @@ #ifndef LIB_TXT_SRC_PARAGRAPH_H_ #define LIB_TXT_SRC_PARAGRAPH_H_ +#include "flutter/display_list/display_list_builder.h" #include "line_metrics.h" #include "paragraph_style.h" #include "third_party/skia/include/core/SkRect.h" @@ -146,6 +147,9 @@ class Paragraph { // Paints the laid out text onto the supplied SkCanvas at (x, y) offset from // the origin. Only valid after Layout() is called. virtual void Paint(SkCanvas* canvas, double x, double y) = 0; + virtual bool Paint(flutter::DisplayListBuilder* builder, + double x, + double y) = 0; // Returns a vector of bounding boxes that enclose all text between start and // end glyph indexes, including start and excluding end. diff --git a/third_party/txt/src/txt/paragraph_txt.h b/third_party/txt/src/txt/paragraph_txt.h index b536b40ef9a4f..989fc058bed37 100644 --- a/third_party/txt/src/txt/paragraph_txt.h +++ b/third_party/txt/src/txt/paragraph_txt.h @@ -74,6 +74,11 @@ class ParagraphTxt : public Paragraph { virtual void Layout(double width) override; virtual void Paint(SkCanvas* canvas, double x, double y) override; + virtual bool Paint(flutter::DisplayListBuilder* builder, + double x, + double y) override { + return false; + } // Getter for paragraph_style_. const ParagraphStyle& GetParagraphStyle() const; diff --git a/third_party/txt/src/txt/text_style.h b/third_party/txt/src/txt/text_style.h index 2a63c685c81d2..7fcb30a26117f 100644 --- a/third_party/txt/src/txt/text_style.h +++ b/third_party/txt/src/txt/text_style.h @@ -20,6 +20,7 @@ #include #include +#include "flutter/display_list/display_list_paint.h" #include "font_features.h" #include "font_style.h" #include "font_weight.h" @@ -56,8 +57,10 @@ class TextStyle { std::string locale; bool has_background = false; SkPaint background; + flutter::DlPaint background_dl; bool has_foreground = false; SkPaint foreground; + flutter::DlPaint foreground_dl; // An ordered list of shadows where the first shadow will be drawn first (at // the bottom). std::vector text_shadows;