Skip to content

Commit

Permalink
Compute text coverage; use blend mode in savelayer; conservative pass…
Browse files Browse the repository at this point in the history
… collapse/elision behavior (flutter#129)
  • Loading branch information
bdero authored and dnfield committed Apr 27, 2022
1 parent a4599bf commit 8b881c6
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 5 deletions.
21 changes: 21 additions & 0 deletions impeller/aiks/aiks_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,27 @@ TEST_F(AiksTest, CanRenderEmojiTextFrame) {
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}

TEST_F(AiksTest, CanRenderTextInSaveLayer) {
Canvas canvas;
canvas.DrawPaint({.color = Color::White()});
canvas.Translate({100, 100});
canvas.Scale(Vector2{0.5, 0.5});

// Blend the layer with the parent pass using kClear to expose the coverage.
canvas.SaveLayer({.blend_mode = Entity::BlendMode::kClear});
ASSERT_TRUE(RenderTextInCanvas(
GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
"Roboto-Regular.ttf"));
canvas.Restore();

// Render the text again over the cleared coverage rect.
ASSERT_TRUE(RenderTextInCanvas(
GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
"Roboto-Regular.ttf"));

ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}

TEST_F(AiksTest, CanDrawPaint) {
Paint paint;
paint.color = Color::MediumTurquoise();
Expand Down
3 changes: 2 additions & 1 deletion impeller/aiks/canvas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,10 @@ void Canvas::DrawCircle(Point center, Scalar radius, Paint paint) {

void Canvas::SaveLayer(Paint paint, std::optional<Rect> bounds) {
GetCurrentPass().SetDelegate(
std::make_unique<PaintPassDelegate>(std::move(paint), bounds));
std::make_unique<PaintPassDelegate>(paint, bounds));

Save(true);
GetCurrentPass().SetBlendMode(paint.blend_mode);

if (bounds.has_value()) {
// Render target switches due to a save layer can be elided. In such cases
Expand Down
4 changes: 2 additions & 2 deletions impeller/aiks/paint_pass_delegate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ std::optional<Rect> PaintPassDelegate::GetCoverageRect() {

// |EntityPassDelgate|
bool PaintPassDelegate::CanElide() {
return paint_.color.IsTransparent();
return paint_.blend_mode == Entity::BlendMode::kDestination;
}

// |EntityPassDelgate|
bool PaintPassDelegate::CanCollapseIntoParentPass() {
return paint_.color.IsOpaque();
return false;
}

// |EntityPassDelgate|
Expand Down
10 changes: 10 additions & 0 deletions impeller/entity/contents/text_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

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

#include <optional>

#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/entity.h"
#include "impeller/geometry/path_builder.h"
Expand Down Expand Up @@ -48,6 +50,14 @@ void TextContents::SetColor(Color color) {
color_ = color;
}

std::optional<Rect> TextContents::GetCoverage(const Entity& entity) const {
auto bounds = frame_.GetBounds();
if (!bounds.has_value()) {
return std::nullopt;
}
return bounds->TransformBounds(entity.GetTransformation());
}

bool TextContents::Render(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
Expand Down
3 changes: 3 additions & 0 deletions impeller/entity/contents/text_contents.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ class TextContents final : public Contents {

void SetColor(Color color);

// |Contents|
std::optional<Rect> GetCoverage(const Entity& entity) const override;

// |Contents|
bool Render(const ContentContext& renderer,
const Entity& entity,
Expand Down
5 changes: 5 additions & 0 deletions impeller/entity/entity_pass.cc
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ bool EntityPass::Render(ContentContext& renderer,
.TakePath());
entity.SetContents(std::move(offscreen_texture_contents));
entity.SetStencilDepth(stencil_depth_);
entity.SetBlendMode(subpass->blend_mode_);
// Once we have filters being applied for SaveLayer, some special sauce
// may be needed here (or in PaintPassDelegate) to ensure the filter
// parameters are transformed by the `xformation_` matrix, while continuing
Expand Down Expand Up @@ -257,4 +258,8 @@ void EntityPass::SetStencilDepth(size_t stencil_depth) {
stencil_depth_ = stencil_depth;
}

void EntityPass::SetBlendMode(Entity::BlendMode blend_mode) {
blend_mode_ = blend_mode;
}

} // namespace impeller
3 changes: 3 additions & 0 deletions impeller/entity/entity_pass.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,15 @@ class EntityPass {

void SetStencilDepth(size_t stencil_depth);

void SetBlendMode(Entity::BlendMode blend_mode);

private:
Entities entities_;
Subpasses subpasses_;
EntityPass* superpass_ = nullptr;
Matrix xformation_;
size_t stencil_depth_ = 0u;
Entity::BlendMode blend_mode_ = Entity::BlendMode::kSourceOver;
std::unique_ptr<EntityPassDelegate> delegate_ =
EntityPassDelegate::MakeDefault();
std::shared_ptr<LazyGlyphAtlas> lazy_glyph_atlas_ =
Expand Down
3 changes: 1 addition & 2 deletions impeller/typographer/backends/skia/text_frame_skia.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ static Font ToFont(const SkFont& font, Scalar scale) {
return Font{std::move(typeface), std::move(metrics)};
}

TextFrame TextFrameFromTextBlob(sk_sp<SkTextBlob> blob,
Scalar scale) {
TextFrame TextFrameFromTextBlob(sk_sp<SkTextBlob> blob, Scalar scale) {
if (!blob) {
return {};
}
Expand Down
15 changes: 15 additions & 0 deletions impeller/typographer/text_frame.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,21 @@ TextFrame::TextFrame() = default;

TextFrame::~TextFrame() = default;

std::optional<Rect> TextFrame::GetBounds() const {
std::optional<Rect> result;

for (const auto& run : runs_) {
const auto glyph_bounds = run.GetFont().GetMetrics().GetBoundingBox();
for (const auto& glyph_position : run.GetGlyphPositions()) {
Vector2 position = glyph_position.position * Vector2();
Rect glyph_rect = Rect(position + glyph_bounds.origin, glyph_bounds.size);
result = result.has_value() ? result->Union(glyph_rect) : glyph_rect;
}
}

return result;
}

bool TextFrame::AddTextRun(TextRun run) {
if (!run.IsValid()) {
return false;
Expand Down
8 changes: 8 additions & 0 deletions impeller/typographer/text_frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ class TextFrame {

~TextFrame();

//----------------------------------------------------------------------------
/// @brief The conservative bounding box for this text frame.
///
/// @return The bounds rectangle. If there are no glyphs in this text
/// frame, std::nullopt is returned.
///
std::optional<Rect> GetBounds() const;

//----------------------------------------------------------------------------
/// @brief The number of runs in this text frame.
///
Expand Down

0 comments on commit 8b881c6

Please sign in to comment.