Skip to content

Commit

Permalink
Implement impeller::DisplayListDispatcher::drawTextBlob. (flutter#94)
Browse files Browse the repository at this point in the history
  • Loading branch information
chinmaygarde authored and dnfield committed Apr 27, 2022
1 parent 3235eac commit f2d2351
Show file tree
Hide file tree
Showing 20 changed files with 323 additions and 63 deletions.
11 changes: 1 addition & 10 deletions impeller/aiks/aiks_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -347,19 +347,10 @@ bool RenderTextInCanvas(std::shared_ptr<Context> context,

// Create the Impeller text frame and draw it at the designated baseline.
auto frame = TextFrameFromTextBlob(blob);
TextRenderContextSkia text_context(context);
if (!text_context.IsValid()) {
return false;
}
auto atlas = text_context.CreateGlyphAtlas(frame);
if (!atlas) {
return false;
}

Paint text_paint;
text_paint.color = Color::Yellow();
canvas.DrawTextFrame(std::move(frame), std::move(atlas), text_position,
text_paint);
canvas.DrawTextFrame(std::move(frame), text_position, text_paint);
return true;
}

Expand Down
13 changes: 5 additions & 8 deletions impeller/aiks/canvas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -269,17 +269,14 @@ void Canvas::Save(bool create_subpass) {
xformation_stack_.emplace_back(std::move(entry));
}

void Canvas::DrawTextFrame(TextFrame text_frame,
std::shared_ptr<GlyphAtlas> atlas,
Point position,
Paint paint) {
if (!atlas || !atlas->IsValid()) {
return;
}
void Canvas::DrawTextFrame(TextFrame text_frame, Point position, Paint paint) {
auto lazy_glyph_atlas = GetCurrentPass().GetLazyGlyphAtlas();

lazy_glyph_atlas->AddTextFrame(std::move(text_frame));

auto text_contents = std::make_shared<TextContents>();
text_contents->SetTextFrame(std::move(text_frame));
text_contents->SetGlyphAtlas(std::move(atlas));
text_contents->SetGlyphAtlas(std::move(lazy_glyph_atlas));
text_contents->SetColor(paint.color.Premultiply());

Entity entity;
Expand Down
5 changes: 1 addition & 4 deletions impeller/aiks/canvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,7 @@ class Canvas {

void DrawPicture(Picture picture);

void DrawTextFrame(TextFrame text_frame,
std::shared_ptr<GlyphAtlas> atlas,
Point position,
Paint paint);
void DrawTextFrame(TextFrame text_frame, Point position, Paint paint);

Picture EndRecordingAsPicture();

Expand Down
8 changes: 6 additions & 2 deletions impeller/display_list/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ impeller_component("display_list") {
"display_list_dispatcher.h",
]

deps = [
public_deps = [
"../aiks",
"//flutter/display_list",
"//flutter/fml",
Expand All @@ -21,7 +21,11 @@ impeller_component("display_list") {
impeller_component("display_list_unittests") {
testonly = true

sources = [ "display_list_unittests.cc" ]
sources = [
"display_list_playground.cc",
"display_list_playground.h",
"display_list_unittests.cc",
]

deps = [
":display_list",
Expand Down
8 changes: 6 additions & 2 deletions impeller/display_list/display_list_dispatcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,8 @@ void DisplayListDispatcher::clipPath(const SkPath& path,
}

// |flutter::Dispatcher|
void DisplayListDispatcher::drawColor(SkColor color, flutter::DlBlendMode dl_mode) {
void DisplayListDispatcher::drawColor(SkColor color,
flutter::DlBlendMode dl_mode) {
Paint paint;
paint.color = ToColor(color);
if (auto mode = ToBlendMode(dl_mode); mode.has_value()) {
Expand Down Expand Up @@ -608,7 +609,10 @@ void DisplayListDispatcher::drawDisplayList(
void DisplayListDispatcher::drawTextBlob(const sk_sp<SkTextBlob> blob,
SkScalar x,
SkScalar y) {
UNIMPLEMENTED;
canvas_.DrawTextFrame(TextFrameFromTextBlob(blob), //
impeller::Point{x, y}, //
paint_ //
);
}

// |flutter::Dispatcher|
Expand Down
71 changes: 71 additions & 0 deletions impeller/display_list/display_list_playground.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "impeller/display_list/display_list_playground.h"

#include "flutter/testing/testing.h"
#include "impeller/aiks/aiks_context.h"
#include "impeller/display_list/display_list_dispatcher.h"
#include "third_party/skia/include/core/SkData.h"

namespace impeller {

DisplayListPlayground::DisplayListPlayground() = default;

DisplayListPlayground::~DisplayListPlayground() = default;

bool DisplayListPlayground::OpenPlaygroundHere(
flutter::DisplayListBuilder& builder) {
return OpenPlaygroundHere(builder.Build());
}

bool DisplayListPlayground::OpenPlaygroundHere(
sk_sp<flutter::DisplayList> list) {
if (!Playground::is_enabled()) {
return true;
}

if (!list) {
return false;
}

DisplayListDispatcher dispatcher;
list->Dispatch(dispatcher);
auto picture = dispatcher.EndRecordingAsPicture();

AiksContext context(GetContext());
if (!context.IsValid()) {
return false;
}
return Playground::OpenPlaygroundHere(
[&picture, &context](RenderPass& pass) -> bool {
return context.Render(picture, pass);
});
}

static sk_sp<SkData> OpenFixtureAsSkData(const char* fixture_name) {
auto mapping = flutter::testing::OpenFixtureAsMapping(fixture_name);
if (!mapping) {
return nullptr;
}
return SkData::MakeWithProc(
mapping->GetMapping(), mapping->GetSize(),
[](const void* ptr, void* context) {
delete reinterpret_cast<fml::Mapping*>(context);
},
mapping.release());
}

SkFont DisplayListPlayground::CreateTestFontOfSize(SkScalar scalar) {
static constexpr const char* kTestFontFixture = "Roboto-Regular.ttf";
auto mapping = OpenFixtureAsSkData(kTestFontFixture);
FML_CHECK(mapping);
return SkFont{SkTypeface::MakeFromData(mapping), scalar};
}

SkFont DisplayListPlayground::CreateTestFont() {
return CreateTestFontOfSize(50);
}

} // namespace impeller
33 changes: 33 additions & 0 deletions impeller/display_list/display_list_playground.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#pragma once

#include "flutter/display_list/display_list.h"
#include "flutter/display_list/display_list_builder.h"
#include "flutter/fml/macros.h"
#include "impeller/playground/playground.h"
#include "third_party/skia/include/core/SkFont.h"

namespace impeller {

class DisplayListPlayground : public Playground {
public:
DisplayListPlayground();

~DisplayListPlayground();

bool OpenPlaygroundHere(flutter::DisplayListBuilder& builder);

bool OpenPlaygroundHere(sk_sp<flutter::DisplayList> list);

SkFont CreateTestFontOfSize(SkScalar scalar);

SkFont CreateTestFont();

private:
FML_DISALLOW_COPY_AND_ASSIGN(DisplayListPlayground);
};

} // namespace impeller
19 changes: 18 additions & 1 deletion impeller/display_list/display_list_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,29 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/display_list/display_list_builder.h"
#include "flutter/testing/testing.h"
#include "impeller/display_list/display_list_playground.h"

namespace impeller {
namespace testing {

TEST(DisplayListTest, CanCreateDisatcher) {}
using DisplayListTest = DisplayListPlayground;

TEST_F(DisplayListTest, CanDrawRect) {
flutter::DisplayListBuilder builder;
builder.setColor(SK_ColorBLUE);
builder.drawRect(SkRect::MakeXYWH(10, 10, 100, 100));
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}

TEST_F(DisplayListTest, CanDrawTextBlob) {
flutter::DisplayListBuilder builder;
builder.setColor(SK_ColorBLUE);
builder.drawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()),
100, 100);
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}

} // namespace testing
} // namespace impeller
33 changes: 27 additions & 6 deletions impeller/entity/contents/text_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "text_contents.h"
#include "impeller/entity/contents/text_contents.h"

#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/entity.h"
Expand All @@ -11,8 +11,10 @@
#include "impeller/renderer/sampler_library.h"
#include "impeller/tessellator/tessellator.h"
#include "impeller/typographer/glyph_atlas.h"
#include "impeller/typographer/lazy_glyph_atlas.h"

namespace impeller {

TextContents::TextContents() = default;

TextContents::~TextContents() = default;
Expand All @@ -25,6 +27,23 @@ void TextContents::SetGlyphAtlas(std::shared_ptr<GlyphAtlas> atlas) {
atlas_ = std::move(atlas);
}

void TextContents::SetGlyphAtlas(std::shared_ptr<LazyGlyphAtlas> atlas) {
atlas_ = std::move(atlas);
}

std::shared_ptr<GlyphAtlas> TextContents::ResolveAtlas(
std::shared_ptr<Context> context) const {
if (auto lazy_atlas = std::get_if<std::shared_ptr<LazyGlyphAtlas>>(&atlas_)) {
return lazy_atlas->get()->CreateOrGetGlyphAtlas(context);
}

if (auto atlas = std::get_if<std::shared_ptr<GlyphAtlas>>(&atlas_)) {
return *atlas;
}

return nullptr;
}

void TextContents::SetColor(Color color) {
color_ = color;
}
Expand All @@ -36,7 +55,9 @@ bool TextContents::Render(const ContentContext& renderer,
return true;
}

if (!atlas_ || !atlas_->IsValid()) {
auto atlas = ResolveAtlas(renderer.GetContext());

if (!atlas || !atlas->IsValid()) {
VALIDATION_LOG << "Cannot render glyphs without prepared atlas.";
return false;
}
Expand All @@ -57,15 +78,15 @@ bool TextContents::Render(const ContentContext& renderer,
frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
entity.GetTransformation();
frame_info.atlas_size =
Point{static_cast<Scalar>(atlas_->GetTexture()->GetSize().width),
static_cast<Scalar>(atlas_->GetTexture()->GetSize().height)};
Point{static_cast<Scalar>(atlas->GetTexture()->GetSize().width),
static_cast<Scalar>(atlas->GetTexture()->GetSize().height)};
frame_info.text_color = ToVector(color_);
VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info));

// Common fragment uniforms for all glyphs.
FS::BindGlyphAtlasSampler(
cmd, // command
atlas_->GetTexture(), // texture
atlas->GetTexture(), // texture
renderer.GetContext()->GetSamplerLibrary()->GetSampler({}) // sampler
);

Expand Down Expand Up @@ -107,7 +128,7 @@ bool TextContents::Render(const ContentContext& renderer,
// Draw each glyph individually. This should probably be batched.
for (const auto& glyph_position : run.GetGlyphPositions()) {
FontGlyphPair font_glyph_pair{font, glyph_position.glyph};
auto atlas_glyph_pos = atlas_->FindFontGlyphPosition(font_glyph_pair);
auto atlas_glyph_pos = atlas->FindFontGlyphPosition(font_glyph_pair);
if (!atlas_glyph_pos.has_value()) {
VALIDATION_LOG << "Could not find glyph position in the atlas.";
return false;
Expand Down
12 changes: 11 additions & 1 deletion impeller/entity/contents/text_contents.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <functional>
#include <memory>
#include <variant>
#include <vector>

#include "flutter/fml/macros.h"
Expand All @@ -16,6 +17,8 @@
namespace impeller {

class GlyphAtlas;
class LazyGlyphAtlas;
class Context;

class TextContents final : public Contents {
public:
Expand All @@ -27,6 +30,8 @@ class TextContents final : public Contents {

void SetGlyphAtlas(std::shared_ptr<GlyphAtlas> atlas);

void SetGlyphAtlas(std::shared_ptr<LazyGlyphAtlas> atlas);

void SetColor(Color color);

// |Contents|
Expand All @@ -37,7 +42,12 @@ class TextContents final : public Contents {
private:
TextFrame frame_;
Color color_;
std::shared_ptr<GlyphAtlas> atlas_;
mutable std::variant<std::shared_ptr<GlyphAtlas>,
std::shared_ptr<LazyGlyphAtlas>>
atlas_;

std::shared_ptr<GlyphAtlas> ResolveAtlas(
std::shared_ptr<Context> context) const;

FML_DISALLOW_COPY_AND_ASSIGN(TextContents);
};
Expand Down
4 changes: 4 additions & 0 deletions impeller/entity/entity_pass.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ size_t EntityPass::GetSubpassesDepth() const {
return max_subpass_depth + 1u;
}

const std::shared_ptr<LazyGlyphAtlas>& EntityPass::GetLazyGlyphAtlas() const {
return lazy_glyph_atlas_;
}

std::optional<Rect> EntityPass::GetEntitiesCoverage() const {
std::optional<Rect> result;
for (const auto& entity : entities_) {
Expand Down
5 changes: 5 additions & 0 deletions impeller/entity/entity_pass.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "impeller/entity/entity.h"
#include "impeller/entity/entity_pass_delegate.h"
#include "impeller/renderer/render_target.h"
#include "impeller/typographer/lazy_glyph_atlas.h"

namespace impeller {

Expand Down Expand Up @@ -41,6 +42,8 @@ class EntityPass {

const Subpasses& GetSubpasses() const;

const std::shared_ptr<LazyGlyphAtlas>& GetLazyGlyphAtlas() const;

EntityPass* AddSubpass(std::unique_ptr<EntityPass> pass);

EntityPass* GetSuperpass() const;
Expand All @@ -61,6 +64,8 @@ class EntityPass {
size_t stencil_depth_ = 0u;
std::unique_ptr<EntityPassDelegate> delegate_ =
EntityPassDelegate::MakeDefault();
std::shared_ptr<LazyGlyphAtlas> lazy_glyph_atlas_ =
std::make_shared<LazyGlyphAtlas>();

std::optional<Rect> GetSubpassCoverage(const EntityPass& subpass) const;

Expand Down
Loading

0 comments on commit f2d2351

Please sign in to comment.