From 9f11809bb753b96bd91debb1ec95709ce645f189 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Wed, 12 Jul 2023 09:29:13 -0700 Subject: [PATCH] [Impeller] Use new SkParagraph APIs for stroked text. (flutter/engine#41735) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ~~Requires https://skia-review.googlesource.com/c/skia/+/692196~~ Landed Fixes https://github.com/flutter/flutter/issues/126010 Looks correct on iOS, renders incorrectly on Android 🤷 . Might be related to all of our text bounds looking off. ### iOS ![flutter_03](https://github.com/flutter/engine/assets/8975114/50897fd0-47fd-4cad-b158-1662aa650092) ### Android ![flutter_04](https://github.com/flutter/engine/assets/8975114/bcefe843-71a0-4b98-956f-039918e9a4cc) --- .../flutter/impeller/display_list/BUILD.gn | 1 + .../impeller/display_list/dl_dispatcher.cc | 20 ++++++++++++++++--- .../impeller/display_list/dl_unittests.cc | 13 ++++++++++++ .../impeller/display_list/skia_conversions.cc | 9 +++++++++ .../impeller/display_list/skia_conversions.h | 3 +++ 5 files changed, 43 insertions(+), 3 deletions(-) diff --git a/engine/src/flutter/impeller/display_list/BUILD.gn b/engine/src/flutter/impeller/display_list/BUILD.gn index a69f63806c6..1b7f13e5d3d 100644 --- a/engine/src/flutter/impeller/display_list/BUILD.gn +++ b/engine/src/flutter/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/engine/src/flutter/impeller/display_list/dl_dispatcher.cc b/engine/src/flutter/impeller/display_list/dl_dispatcher.cc index d1a5ae4f270..9964e9e71ea 100644 --- a/engine/src/flutter/impeller/display_list/dl_dispatcher.cc +++ b/engine/src/flutter/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/engine/src/flutter/impeller/display_list/dl_unittests.cc b/engine/src/flutter/impeller/display_list/dl_unittests.cc index b5ce5c4c9a4..05a0b5d9b07 100644 --- a/engine/src/flutter/impeller/display_list/dl_unittests.cc +++ b/engine/src/flutter/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/engine/src/flutter/impeller/display_list/skia_conversions.cc b/engine/src/flutter/impeller/display_list/skia_conversions.cc index d7af98f6148..29f9ad4eed8 100644 --- a/engine/src/flutter/impeller/display_list/skia_conversions.cc +++ b/engine/src/flutter/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/engine/src/flutter/impeller/display_list/skia_conversions.h b/engine/src/flutter/impeller/display_list/skia_conversions.h index 5f152467424..9406c6d272f 100644 --- a/engine/src/flutter/impeller/display_list/skia_conversions.h +++ b/engine/src/flutter/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