-
Notifications
You must be signed in to change notification settings - Fork 6k
[Impeller] Cache Skia text bounds computation. #45150
Changes from 6 commits
c669dc2
e7d4907
642fde4
bae1005
8b6a21a
273f9a0
dd50c18
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,16 +39,15 @@ static Rect ToRect(const SkRect& rect) { | |
|
|
||
| static constexpr Scalar kScaleSize = 100000.0f; | ||
|
|
||
| TextFrame MakeTextFrameFromTextBlobSkia(const sk_sp<SkTextBlob>& blob) { | ||
| std::optional<TextFrame> MakeTextFrameFromTextBlobSkia( | ||
| const sk_sp<SkTextBlob>& blob) { | ||
| if (!blob) { | ||
| return {}; | ||
| } | ||
|
|
||
| TextFrame frame; | ||
|
|
||
| std::vector<TextRun> runs; | ||
| bool has_color = false; | ||
| for (SkTextBlobRunIterator run(blob.get()); !run.done(); run.next()) { | ||
| TextRun text_run(ToFont(run)); | ||
|
|
||
| // TODO(jonahwilliams): ask Skia for a public API to look this up. | ||
| // https://github.com/flutter/flutter/issues/112005 | ||
| SkStrikeSpec strikeSpec = SkStrikeSpec::MakeWithNoDevice(run.font()); | ||
|
|
@@ -57,12 +56,6 @@ TextFrame MakeTextFrameFromTextBlobSkia(const sk_sp<SkTextBlob>& blob) { | |
| const auto glyph_count = run.glyphCount(); | ||
| const auto* glyphs = run.glyphs(); | ||
| switch (run.positioning()) { | ||
| case SkTextBlobRunIterator::kDefault_Positioning: | ||
| FML_DLOG(ERROR) << "Unimplemented."; | ||
| break; | ||
| case SkTextBlobRunIterator::kHorizontal_Positioning: | ||
| FML_DLOG(ERROR) << "Unimplemented."; | ||
| break; | ||
| case SkTextBlobRunIterator::kFull_Positioning: { | ||
| std::vector<SkRect> glyph_bounds; | ||
| glyph_bounds.resize(glyph_count); | ||
|
|
@@ -75,32 +68,32 @@ TextFrame MakeTextFrameFromTextBlobSkia(const sk_sp<SkTextBlob>& blob) { | |
| font.setSize(kScaleSize); | ||
| font.getBounds(glyphs, glyph_count, glyph_bounds.data(), nullptr); | ||
|
|
||
| std::vector<TextRun::GlyphPosition> positions; | ||
| positions.reserve(glyph_count); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Allocate the right amount of storage once rather than appending. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Put this as a comment in the code instead of in the PR review There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. feels like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤷🏼. My point is if you think it's important enough to call out in the review, it's probably better as a comment :) Defer to you, definitely a micro-nit. |
||
| for (auto i = 0u; i < glyph_count; i++) { | ||
| // kFull_Positioning has two scalars per glyph. | ||
| const SkPoint* glyph_points = run.points(); | ||
| const auto* point = glyph_points + i; | ||
| Glyph::Type type = paths.glyph(glyphs[i])->isColor() | ||
| ? Glyph::Type::kBitmap | ||
| : Glyph::Type::kPath; | ||
| has_color |= type == Glyph::Type::kBitmap; | ||
|
|
||
| text_run.AddGlyph( | ||
| positions.emplace_back(TextRun::GlyphPosition{ | ||
| Glyph{glyphs[i], type, | ||
| ToRect(glyph_bounds[i]).Scale(font_size / kScaleSize)}, | ||
| Point{point->x(), point->y()}); | ||
| Point{point->x(), point->y()}}); | ||
| } | ||
| TextRun text_run(ToFont(run), positions); | ||
| runs.emplace_back(text_run); | ||
| break; | ||
| } | ||
| case SkTextBlobRunIterator::kRSXform_Positioning: | ||
| FML_DLOG(ERROR) << "Unimplemented."; | ||
| break; | ||
| default: | ||
| FML_DLOG(ERROR) << "Unimplemented."; | ||
| continue; | ||
| } | ||
| frame.AddTextRun(std::move(text_run)); | ||
| } | ||
|
|
||
| return frame; | ||
| return TextFrame(runs, ToRect(blob->bounds()), has_color); | ||
| } | ||
|
|
||
| } // namespace impeller | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,7 @@ | |
|
|
||
| namespace impeller { | ||
|
|
||
| TextFrame MakeTextFrameFromTextBlobSkia(const sk_sp<SkTextBlob>& blob); | ||
| std::optional<TextFrame> MakeTextFrameFromTextBlobSkia( | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I made this optional so that we can avoid creating TextContents at all if the textblob is nullptr for some reason. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ditto above, comment in the code :) |
||
| const sk_sp<SkTextBlob>& blob); | ||
|
|
||
| } // namespace impeller | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,30 +8,13 @@ namespace impeller { | |
|
|
||
| TextFrame::TextFrame() = default; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The default constructor is no glyphs, empty bounds, no color. Which should be perfectly safe. |
||
|
|
||
| TextFrame::~TextFrame() = default; | ||
|
|
||
| std::optional<Rect> TextFrame::GetBounds() const { | ||
| std::optional<Rect> result; | ||
|
|
||
| for (const auto& run : runs_) { | ||
| for (const auto& glyph_position : run.GetGlyphPositions()) { | ||
| Rect glyph_rect = | ||
| Rect(glyph_position.position + glyph_position.glyph.bounds.origin, | ||
| glyph_position.glyph.bounds.size); | ||
| result = result.has_value() ? result->Union(glyph_rect) : glyph_rect; | ||
| } | ||
| } | ||
| TextFrame::TextFrame(std::vector<TextRun>& runs, Rect bounds, bool has_color) | ||
| : runs_(std::move(runs)), bounds_(bounds), has_color_(has_color) {} | ||
|
|
||
| return result; | ||
| } | ||
| TextFrame::~TextFrame() = default; | ||
|
|
||
| bool TextFrame::AddTextRun(TextRun&& run) { | ||
| if (!run.IsValid()) { | ||
| return false; | ||
| } | ||
| has_color_ |= run.HasColor(); | ||
| runs_.emplace_back(std::move(run)); | ||
| return true; | ||
| Rect TextFrame::GetBounds() const { | ||
| return bounds_; | ||
| } | ||
|
|
||
| size_t TextFrame::GetRunCount() const { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,11 +13,18 @@ TextRun::TextRun(const Font& font) : font_(font) { | |
| is_valid_ = true; | ||
| } | ||
|
|
||
| TextRun::TextRun(const Font& font, std::vector<GlyphPosition>& glyphs) | ||
| : font_(font), glyphs_(std::move(glyphs)) { | ||
| if (!font_.IsValid()) { | ||
| return; | ||
| } | ||
| is_valid_ = true; | ||
| } | ||
|
|
||
| TextRun::~TextRun() = default; | ||
|
|
||
| bool TextRun::AddGlyph(Glyph glyph, Point position) { | ||
| glyphs_.emplace_back(GlyphPosition{glyph, position}); | ||
| has_color_ |= glyph.type == Glyph::Type::kBitmap; | ||
| return true; | ||
| } | ||
|
|
||
|
|
@@ -37,8 +44,4 @@ const Font& TextRun::GetFont() const { | |
| return font_; | ||
| } | ||
|
|
||
| bool TextRun::HasColor() const { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't need to track this per run. |
||
| return has_color_; | ||
| } | ||
|
|
||
| } // namespace impeller | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we're never going to use these, I deleted them and left it for the default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a slight preference for removing the default so that we know if Skia adds some other value to this that we could be handling.