blob: 5e38b68a76729e0facf19e8d083c66505efacef3 [file] [log] [blame]
// 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/typographer/text_frame.h"
namespace impeller {
TextFrame::TextFrame() = default;
TextFrame::TextFrame(std::vector<TextRun>& runs, Rect bounds, bool has_color)
: runs_(std::move(runs)), bounds_(bounds), has_color_(has_color) {}
TextFrame::~TextFrame() = default;
Rect TextFrame::GetBounds() const {
return bounds_;
}
size_t TextFrame::GetRunCount() const {
return runs_.size();
}
const std::vector<TextRun>& TextFrame::GetRuns() const {
return runs_;
}
GlyphAtlas::Type TextFrame::GetAtlasType() const {
return has_color_ ? GlyphAtlas::Type::kColorBitmap
: GlyphAtlas::Type::kAlphaBitmap;
}
bool TextFrame::MaybeHasOverlapping() const {
if (runs_.size() > 1) {
return true;
}
auto glyph_positions = runs_[0].GetGlyphPositions();
if (glyph_positions.size() > 10) {
return true;
}
if (glyph_positions.size() == 1) {
return false;
}
// To avoid quadradic behavior the overlapping is checked against an
// accumulated bounds rect. This gives faster but less precise information
// on text runs.
auto first_position = glyph_positions[0];
auto overlapping_rect = Rect::MakeOriginSize(
first_position.position + first_position.glyph.bounds.GetOrigin(),
first_position.glyph.bounds.GetSize());
for (auto i = 1u; i < glyph_positions.size(); i++) {
auto glyph_position = glyph_positions[i];
auto glyph_rect = Rect::MakeOriginSize(
glyph_position.position + glyph_position.glyph.bounds.GetOrigin(),
glyph_position.glyph.bounds.GetSize());
auto intersection = glyph_rect.Intersection(overlapping_rect);
if (intersection.has_value()) {
return true;
}
overlapping_rect = overlapping_rect.Union(glyph_rect);
}
return false;
}
// static
Scalar TextFrame::RoundScaledFontSize(Scalar scale, Scalar point_size) {
return std::round(scale * 100) / 100;
}
void TextFrame::CollectUniqueFontGlyphPairs(FontGlyphMap& glyph_map,
Scalar scale) const {
for (const TextRun& run : GetRuns()) {
const Font& font = run.GetFont();
auto rounded_scale =
RoundScaledFontSize(scale, font.GetMetrics().point_size);
auto& set = glyph_map[{font, rounded_scale}];
for (const TextRun::GlyphPosition& glyph_position :
run.GetGlyphPositions()) {
#if false
// Glyph size error due to RoundScaledFontSize usage above.
if (rounded_scale != scale) {
auto delta = std::abs(rounded_scale - scale);
FML_LOG(ERROR) << glyph_position.glyph.bounds.size * delta;
}
#endif
set.insert(glyph_position.glyph);
}
}
}
} // namespace impeller