diff --git a/impeller/display_list/BUILD.gn b/impeller/display_list/BUILD.gn index a69f63806c685..1b7f13e5d3d05 100644 --- a/impeller/display_list/BUILD.gn +++ b/impeller/display_list/BUILD.gn @@ -15,6 +15,7 @@ impeller_component("skia_conversions") { "../geometry", "//flutter/fml", "//third_party/skia", + "//third_party/skia/modules/skparagraph", ] } diff --git a/impeller/display_list/dl_dispatcher.cc b/impeller/display_list/dl_dispatcher.cc index d1a5ae4f27061..9964e9e71eaf9 100644 --- a/impeller/display_list/dl_dispatcher.cc +++ b/impeller/display_list/dl_dispatcher.cc @@ -1104,9 +1104,23 @@ void DlDispatcher::drawDisplayList( void DlDispatcher::drawTextBlob(const sk_sp blob, SkScalar x, SkScalar y) { - canvas_.DrawTextFrame(TextFrameFromTextBlob(blob), // - impeller::Point{x, y}, // - paint_ // + const auto text_frame = TextFrameFromTextBlob(blob); + if (paint_.style == Paint::Style::kStroke) { + auto path = skia_conversions::PathDataFromTextBlob(blob); + auto bounds = text_frame.GetBounds(); + if (!bounds.has_value()) { + return; + } + canvas_.Save(); + canvas_.Translate({x + bounds->origin.x, y + bounds->origin.y, 0.0}); + canvas_.DrawPath(path, paint_); + canvas_.Restore(); + return; + } + + canvas_.DrawTextFrame(text_frame, // + impeller::Point{x, y}, // + paint_ // ); } diff --git a/impeller/display_list/dl_unittests.cc b/impeller/display_list/dl_unittests.cc index b5ce5c4c9a420..05a0b5d9b072b 100644 --- a/impeller/display_list/dl_unittests.cc +++ b/impeller/display_list/dl_unittests.cc @@ -447,6 +447,19 @@ TEST_P(DisplayListTest, CanDrawWithMaskBlur) { ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } +TEST_P(DisplayListTest, CanDrawStrokedText) { + flutter::DisplayListBuilder builder; + flutter::DlPaint paint; + + paint.setDrawStyle(flutter::DlDrawStyle::kStroke); + paint.setColor(flutter::DlColor::kRed()); + builder.DrawTextBlob( + SkTextBlob::MakeFromString("stoked about stroked text", CreateTestFont()), + 250, 250, paint); + + ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); +} + TEST_P(DisplayListTest, IgnoreMaskFilterWhenSavingLayer) { auto texture = CreateTextureForFixture("embarcadero.jpg"); flutter::DisplayListBuilder builder; diff --git a/impeller/display_list/skia_conversions.cc b/impeller/display_list/skia_conversions.cc index d7af98f61484f..29f9ad4eed8ae 100644 --- a/impeller/display_list/skia_conversions.cc +++ b/impeller/display_list/skia_conversions.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "impeller/display_list/skia_conversions.h" +#include "third_party/skia/modules/skparagraph/include/Paragraph.h" namespace impeller { namespace skia_conversions { @@ -159,6 +160,14 @@ std::vector ToRSXForms(const SkRSXform xform[], int count) { return result; } +Path PathDataFromTextBlob(const sk_sp& blob) { + if (!blob) { + return {}; + } + + return ToPath(skia::textlayout::Paragraph::GetPath(blob.get())); +} + std::optional ToPixelFormat(SkColorType type) { switch (type) { case kRGBA_8888_SkColorType: diff --git a/impeller/display_list/skia_conversions.h b/impeller/display_list/skia_conversions.h index 5f1524674240d..9406c6d272f62 100644 --- a/impeller/display_list/skia_conversions.h +++ b/impeller/display_list/skia_conversions.h @@ -16,6 +16,7 @@ #include "third_party/skia/include/core/SkPoint.h" #include "third_party/skia/include/core/SkRRect.h" #include "third_party/skia/include/core/SkRSXform.h" +#include "third_party/skia/include/core/SkTextBlob.h" namespace impeller { namespace skia_conversions { @@ -40,6 +41,8 @@ Path ToPath(const SkPath& path); Path ToPath(const SkRRect& rrect); +Path PathDataFromTextBlob(const sk_sp& blob); + std::optional ToPixelFormat(SkColorType type); } // namespace skia_conversions