From 657143f93a8ded760abd0dfce984fa77067d85bc Mon Sep 17 00:00:00 2001 From: Chinmay Garde Date: Tue, 15 Oct 2024 16:02:24 -0700 Subject: [PATCH] [Impeller] libImpeller: Initialize the base paragraph style lazily. --- impeller/toolkit/interop/impeller.cc | 3 +- .../toolkit/interop/impeller_unittests.cc | 93 +++++++++++++++++++ impeller/toolkit/interop/paragraph_builder.cc | 45 +++++---- impeller/toolkit/interop/paragraph_builder.h | 10 +- impeller/toolkit/interop/paragraph_style.cc | 11 ++- impeller/toolkit/interop/paragraph_style.h | 4 +- 6 files changed, 140 insertions(+), 26 deletions(-) diff --git a/impeller/toolkit/interop/impeller.cc b/impeller/toolkit/interop/impeller.cc index 1484eda55c12d..05d8c035c1f38 100644 --- a/impeller/toolkit/interop/impeller.cc +++ b/impeller/toolkit/interop/impeller.cc @@ -1009,7 +1009,8 @@ void ImpellerDisplayListBuilderDrawParagraph(ImpellerDisplayListBuilder builder, IMPELLER_EXTERN_C ImpellerParagraphBuilder ImpellerParagraphBuilderNew( ImpellerTypographyContext context) { - auto builder = Create(*GetPeer(context)); + auto builder = + Create(Ref(GetPeer(context))); if (!builder->IsValid()) { VALIDATION_LOG << "Could not create valid paragraph builder."; return nullptr; diff --git a/impeller/toolkit/interop/impeller_unittests.cc b/impeller/toolkit/interop/impeller_unittests.cc index c5829444d6545..2a4690e517888 100644 --- a/impeller/toolkit/interop/impeller_unittests.cc +++ b/impeller/toolkit/interop/impeller_unittests.cc @@ -245,4 +245,97 @@ TEST_P(InteropPlaygroundTest, CanCreateParagraphs) { })); } +static void DrawTextFrame(ImpellerTypographyContext tc, + ImpellerDisplayListBuilder builder, + ImpellerParagraphStyle p_style, + ImpellerPaint bg, + ImpellerColor color, + ImpellerTextAlignment align, + float x_offset) { + const char text[] = + "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; + + ImpellerPaint fg = ImpellerPaintNew(); + + // Draw a box. + ImpellerPaintSetColor(fg, &color); + ImpellerPaintSetDrawStyle(fg, kImpellerDrawStyleStroke); + ImpellerRect box_rect = {10 + x_offset, 10, 200, 200}; + ImpellerDisplayListBuilderDrawRect(builder, &box_rect, fg); + + // Draw text. + ImpellerPaintSetDrawStyle(fg, kImpellerDrawStyleFill); + ImpellerParagraphStyleSetForeground(p_style, fg); + ImpellerParagraphStyleSetBackground(p_style, bg); + ImpellerParagraphStyleSetTextAlignment(p_style, align); + ImpellerParagraphBuilder p_builder = ImpellerParagraphBuilderNew(tc); + ImpellerParagraphBuilderPushStyle(p_builder, p_style); + ImpellerParagraphBuilderAddText(p_builder, (const uint8_t*)text, + sizeof(text)); + ImpellerParagraph left_p = ImpellerParagraphBuilderBuildParagraphNew( + p_builder, box_rect.width - 20.0); + ImpellerPoint pt = {20.0f + x_offset, 20.0f}; + float w = ImpellerParagraphGetMaxWidth(left_p); + float h = ImpellerParagraphGetHeight(left_p); + ImpellerDisplayListBuilderDrawParagraph(builder, left_p, &pt); + ImpellerPaintSetDrawStyle(fg, kImpellerDrawStyleStroke); + + // Draw an inner box around the paragraph layout. + ImpellerRect inner_box_rect = {pt.x, pt.y, w, h}; + ImpellerDisplayListBuilderDrawRect(builder, &inner_box_rect, fg); + + ImpellerParagraphRelease(left_p); + ImpellerParagraphBuilderRelease(p_builder); + ImpellerPaintRelease(fg); +} + +TEST_P(InteropPlaygroundTest, CanRenderTextAlignments) { + ImpellerTypographyContext tc = ImpellerTypographyContextNew(); + + ImpellerDisplayList dl = NULL; + + { + ImpellerDisplayListBuilder builder = ImpellerDisplayListBuilderNew(NULL); + ImpellerPaint bg = ImpellerPaintNew(); + ImpellerParagraphStyle p_style = ImpellerParagraphStyleNew(); + ImpellerParagraphStyleSetFontFamily(p_style, "Roboto"); + ImpellerParagraphStyleSetFontSize(p_style, 24.0); + ImpellerParagraphStyleSetFontWeight(p_style, kImpellerFontWeight400); + + // Clear the background to a white color. + ImpellerColor clear_color = {1.0, 1.0, 1.0, 1.0}; + ImpellerPaintSetColor(bg, &clear_color); + ImpellerDisplayListBuilderDrawPaint(builder, bg); + + // Draw red, left-aligned text. + ImpellerColor red = {1.0, 0.0, 0.0, 1.0}; + DrawTextFrame(tc, builder, p_style, bg, red, kImpellerTextAlignmentLeft, + 0.0); + + // Draw green, centered text. + ImpellerColor green = {0.0, 1.0, 0.0, 1.0}; + DrawTextFrame(tc, builder, p_style, bg, green, kImpellerTextAlignmentCenter, + 220.0); + + // Draw blue, right-aligned text. + ImpellerColor blue = {0.0, 0.0, 1.0, 1.0}; + DrawTextFrame(tc, builder, p_style, bg, blue, kImpellerTextAlignmentRight, + 440.0); + + dl = ImpellerDisplayListBuilderCreateDisplayListNew(builder); + + ImpellerPaintRelease(bg); + ImpellerDisplayListBuilderRelease(builder); + } + + ASSERT_TRUE( + OpenPlaygroundHere([&](const auto& context, const auto& surface) -> bool { + ImpellerSurfaceDrawDisplayList(surface.GetC(), dl); + return true; + })); + + ImpellerDisplayListRelease(dl); + ImpellerTypographyContextRelease(tc); +} + } // namespace impeller::interop::testing diff --git a/impeller/toolkit/interop/paragraph_builder.cc b/impeller/toolkit/interop/paragraph_builder.cc index 4997d591f0f25..d983c38b00f79 100644 --- a/impeller/toolkit/interop/paragraph_builder.cc +++ b/impeller/toolkit/interop/paragraph_builder.cc @@ -10,41 +10,29 @@ namespace impeller::interop { -ParagraphBuilder::ParagraphBuilder(const TypographyContext& context) { - if (!context.IsValid()) { - VALIDATION_LOG << "Invalid typography context."; - return; - } - - static txt::ParagraphStyle kBaseStyle; - - builder_ = std::make_unique( - kBaseStyle, // - context.GetFontCollection(), // - true // is impeller enabled - ); -} +ParagraphBuilder::ParagraphBuilder(ScopedObject context) + : context_(std::move(context)) {} ParagraphBuilder::~ParagraphBuilder() = default; bool ParagraphBuilder::IsValid() const { - return !!builder_; + return !!context_; } void ParagraphBuilder::PushStyle(const ParagraphStyle& style) { - builder_->PushStyle(style.CreateTextStyle()); + GetBuilder(style.GetParagraphStyle())->PushStyle(style.CreateTextStyle()); } void ParagraphBuilder::PopStyle() { - builder_->Pop(); + GetBuilder()->Pop(); } void ParagraphBuilder::AddText(const uint8_t* data, size_t byte_length) { - builder_->AddText(data, byte_length); + GetBuilder()->AddText(data, byte_length); } ScopedObject ParagraphBuilder::Build(Scalar width) const { - auto txt_paragraph = builder_->Build(); + auto txt_paragraph = GetBuilder()->Build(); if (!txt_paragraph) { return nullptr; } @@ -52,4 +40,23 @@ ScopedObject ParagraphBuilder::Build(Scalar width) const { return Create(std::move(txt_paragraph)); } +const std::unique_ptr& ParagraphBuilder::GetBuilder( + const txt::ParagraphStyle& style) const { + if (lazy_builder_) { + return lazy_builder_; + } + lazy_builder_ = std::make_unique( + style, // + context_->GetFontCollection(), // + true // is impeller enabled + ); + return lazy_builder_; +} + +const std::unique_ptr& ParagraphBuilder::GetBuilder() + const { + static txt::ParagraphStyle kDefaultStyle; + return GetBuilder(kDefaultStyle); +} + } // namespace impeller::interop diff --git a/impeller/toolkit/interop/paragraph_builder.h b/impeller/toolkit/interop/paragraph_builder.h index 15604460d009a..8ea141ecfa54b 100644 --- a/impeller/toolkit/interop/paragraph_builder.h +++ b/impeller/toolkit/interop/paragraph_builder.h @@ -20,7 +20,7 @@ class ParagraphBuilder final : public Object { public: - explicit ParagraphBuilder(const TypographyContext& context); + explicit ParagraphBuilder(ScopedObject context); ~ParagraphBuilder() override; @@ -39,7 +39,13 @@ class ParagraphBuilder final ScopedObject Build(Scalar width) const; private: - std::unique_ptr builder_; + ScopedObject context_; + mutable std::unique_ptr lazy_builder_; + + const std::unique_ptr& GetBuilder( + const txt::ParagraphStyle& style) const; + + const std::unique_ptr& GetBuilder() const; }; } // namespace impeller::interop diff --git a/impeller/toolkit/interop/paragraph_style.cc b/impeller/toolkit/interop/paragraph_style.cc index 14733dc795576..55a7fcdfdc8fc 100644 --- a/impeller/toolkit/interop/paragraph_style.cc +++ b/impeller/toolkit/interop/paragraph_style.cc @@ -51,18 +51,23 @@ void ParagraphStyle::SetForeground(ScopedObject paint) { } void ParagraphStyle::SetBackground(ScopedObject paint) { - backgrond_ = std::move(paint); + background_ = std::move(paint); } txt::TextStyle ParagraphStyle::CreateTextStyle() const { auto style = style_.GetTextStyle(); + if (foreground_) { style.foreground = foreground_->GetPaint(); } - if (backgrond_) { - style.background = backgrond_->GetPaint(); + if (background_) { + style.background = background_->GetPaint(); } return style; } +const txt::ParagraphStyle& ParagraphStyle::GetParagraphStyle() const { + return style_; +} + } // namespace impeller::interop diff --git a/impeller/toolkit/interop/paragraph_style.h b/impeller/toolkit/interop/paragraph_style.h index 37165e34d88ee..0a3e898ddb1f6 100644 --- a/impeller/toolkit/interop/paragraph_style.h +++ b/impeller/toolkit/interop/paragraph_style.h @@ -48,10 +48,12 @@ class ParagraphStyle final txt::TextStyle CreateTextStyle() const; + const txt::ParagraphStyle& GetParagraphStyle() const; + private: txt::ParagraphStyle style_; ScopedObject foreground_; - ScopedObject backgrond_; + ScopedObject background_; }; } // namespace impeller::interop