| Flutter Impeller |

text_frame.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "impeller/typographer/text_frame.h"
6 #include "impeller/geometry/scalar.h"
7 #include "impeller/typographer/font.h"
8 #include "impeller/typographer/font_glyph_pair.h"
9
10 namespace impeller {
11
12 namespace {
13 static bool TextPropertiesEquals(const std::optional<GlyphProperties>& a,
14 const std::optional<GlyphProperties>& b) {
15 if (!a.has_value() && !b.has_value()) {
16 return true;
17 }
18 if (a.has_value() && b.has_value()) {
19 return GlyphProperties::Equal{}(a.value(), b.value());
20 }
21 return false;
22 }
23 } // namespace
24
25 TextFrame::TextFrame() = default;
26
27 TextFrame::TextFrame(std::vector<TextRun>& runs, Rect bounds, bool has_color)
28 : runs_(std::move(runs)), bounds_(bounds), has_color_(has_color) {}
29
30 TextFrame::~TextFrame() = default;
31
32 Rect TextFrame::GetBounds() const {
33 return bounds_;
34 }
35
36 size_t TextFrame::GetRunCount() const {
37 return runs_.size();
38 }
39
40 const std::vector<TextRun>& TextFrame::GetRuns() const {
41 return runs_;
42 }
43
44 GlyphAtlas::Type TextFrame::GetAtlasType() const {
45 return has_color_ ? GlyphAtlas::Type::kColorBitmap
46 : GlyphAtlas::Type::kAlphaBitmap;
47 }
48
49 bool TextFrame::HasColor() const {
50 return has_color_;
51 }
52
53 // static
54 Scalar TextFrame::RoundScaledFontSize(Scalar scale) {
55 // An arbitrarily chosen maximum text scale to ensure that regardless of the
56 // CTM, a glyph will fit in the atlas. If we clamp significantly, this may
57 // reduce fidelity but is preferable to the alternative of failing to render.
58 constexpr Scalar kMaximumTextScale = 48;
59 Scalar result = std::round(scale * 200) / 200;
60 return std::clamp(result, 0.0f, kMaximumTextScale);
61 }
62
63 static constexpr Scalar ComputeFractionalPosition(Scalar value) {
64 value += 0.125;
65 value = (value - floorf(value));
66 if (value < 0.25) {
67 return 0;
68 }
69 if (value < 0.5) {
70 return 0.25;
71 }
72 if (value < 0.75) {
73 return 0.5;
74 }
75 return 0.75;
76 }
77
78 // Compute subpixel position for glyphs based on X position and provided
79 // max basis length (scale).
80 // This logic is based on the SkPackedGlyphID logic in SkGlyph.h
81 // static
82 Point TextFrame::ComputeSubpixelPosition(
83 const TextRun::GlyphPosition& glyph_position,
84 AxisAlignment alignment,
85 const Matrix& transform) {
86 Point pos = transform * glyph_position.position;
87 switch (alignment) {
88 case AxisAlignment::kNone:
89 return Point(0, 0);
90 case AxisAlignment::kX:
91 return Point(ComputeFractionalPosition(pos.x), 0);
92 case AxisAlignment::kY:
93 return Point(0, ComputeFractionalPosition(pos.y));
94 case AxisAlignment::kAll:
95 return Point(ComputeFractionalPosition(pos.x),
96 ComputeFractionalPosition(pos.y));
97 }
98 }
99
100 void TextFrame::SetPerFrameData(Scalar scale,
101 Point offset,
102 const Matrix& transform,
103 std::optional<GlyphProperties> properties) {
104 if (!transform_.Equals(transform) || !ScalarNearlyEqual(scale_, scale) ||
105 !ScalarNearlyEqual(offset_.x, offset.x) ||
106 !ScalarNearlyEqual(offset_.y, offset.y) ||
107 !TextPropertiesEquals(properties_, properties)) {
108 bound_values_.clear();
109 }
110 scale_ = scale;
111 offset_ = offset;
112 properties_ = properties;
113 transform_ = transform;
114 }
115
116 Scalar TextFrame::GetScale() const {
117 return scale_;
118 }
119
120 Point TextFrame::GetOffset() const {
121 return offset_;
122 }
123
124 std::optional<GlyphProperties> TextFrame::GetProperties() const {
125 return properties_;
126 }
127
128 void TextFrame::AppendFrameBounds(const FrameBounds& frame_bounds) {
129 bound_values_.push_back(frame_bounds);
130 }
131
132 void TextFrame::ClearFrameBounds() {
133 bound_values_.clear();
134 }
135
136 bool TextFrame::IsFrameComplete() const {
137 size_t run_size = 0;
138 for (const auto& x : runs_) {
139 run_size += x.GetGlyphCount();
140 }
141 return bound_values_.size() == run_size;
142 }
143
144 const FrameBounds& TextFrame::GetFrameBounds(size_t index) const {
145 FML_DCHECK(index < bound_values_.size());
146 return bound_values_[index];
147 }
148
149 std::pair<size_t, intptr_t> TextFrame::GetAtlasGenerationAndID() const {
150 return std::make_pair(generation_, atlas_id_);
151 }
152
153 void TextFrame::SetAtlasGeneration(size_t value, intptr_t atlas_id) {
154 generation_ = value;
155 atlas_id_ = atlas_id;
156 }
157
158 } // namespace impeller
impeller::GlyphAtlas::Type::kColorBitmap
@ kColorBitmap
impeller::TextFrame::HasColor
bool HasColor() const
Returns the paint color this text frame was recorded with.
Definition: text_frame.cc:49
impeller::AxisAlignment::kAll
@ kAll
impeller::Matrix::Equals
bool Equals(const Matrix &matrix, Scalar epsilon=1e-5f) const
Definition: matrix.h:440
impeller::TextFrame::GetAtlasGenerationAndID
std::pair< size_t, intptr_t > GetAtlasGenerationAndID() const
Definition: text_frame.cc:149
impeller::TPoint::y
Type y
Definition: point.h:31
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::GlyphAtlas::Type::kAlphaBitmap
@ kAlphaBitmap
impeller::TextFrame::TextFrame
TextFrame()
value
int32_t value
Definition: dl_golden_unittests.cc:444
impeller::TextFrame::~TextFrame
~TextFrame()
impeller::TextFrame::SetPerFrameData
void SetPerFrameData(Scalar scale, Point offset, const Matrix &transform, std::optional< GlyphProperties > properties)
Store text frame scale, offset, and properties for hashing in th glyph atlas.
Definition: text_frame.cc:100
impeller::TextFrame::GetRuns
const std::vector< TextRun > & GetRuns() const
Returns a reference to all the text runs in this frame.
Definition: text_frame.cc:40
impeller::TextFrame::GetRunCount
size_t GetRunCount() const
The number of runs in this text frame.
Definition: text_frame.cc:36
impeller::TextFrame::GetFrameBounds
const FrameBounds & GetFrameBounds(size_t index) const
Retrieve the frame bounds for the glyph at [index].
Definition: text_frame.cc:144
x
int32_t x
Definition: dl_golden_unittests.cc:443
offset
SeparatedVector2 offset
Definition: stroke_path_geometry.cc:319
impeller::TextFrame::RoundScaledFontSize
static Scalar RoundScaledFontSize(Scalar scale)
Definition: text_frame.cc:54
impeller::Point
TPoint< Scalar > Point
Definition: point.h:327
transform
Matrix transform
Definition: gaussian_blur_filter_contents.cc:214
font.h
impeller::GlyphAtlas::Type
Type
Describes how the glyphs are represented in the texture.
Definition: glyph_atlas.h:74
font_glyph_pair.h
impeller::AxisAlignment
AxisAlignment
Determines the axis along which there is subpixel positioning.
Definition: font.h:20
impeller::AxisAlignment::kX
@ kX
impeller::TextFrame::GetBounds
Rect GetBounds() const
The conservative bounding box for this text frame.
Definition: text_frame.cc:32
impeller::TPoint::x
Type x
Definition: point.h:30
scalar.h
std
Definition: comparable.h:95
impeller::TextFrame::GetAtlasType
GlyphAtlas::Type GetAtlasType() const
The type of atlas this run should be place in.
Definition: text_frame.cc:44
impeller::TPoint< Scalar >
impeller::TextRun::GlyphPosition
Definition: text_run.h:22
impeller::saturated::b
SI b
Definition: saturated_math.h:87
scale
const Scalar scale
Definition: stroke_path_geometry.cc:316
impeller::ScalarNearlyEqual
constexpr bool ScalarNearlyEqual(Scalar x, Scalar y, Scalar tolerance=kEhCloseEnough)
Definition: scalar.h:35
impeller::FrameBounds
Definition: glyph_atlas.h:55
impeller::TextFrame::IsFrameComplete
bool IsFrameComplete() const
Verifies that all glyphs in this text frame have computed bounds information.
Definition: text_frame.cc:136
text_frame.h
impeller::ComputeFractionalPosition
static constexpr Scalar ComputeFractionalPosition(Scalar value)
Definition: text_frame.cc:63
impeller::AxisAlignment::kNone
@ kNone
impeller::TextFrame::ComputeSubpixelPosition
static Point ComputeSubpixelPosition(const TextRun::GlyphPosition &glyph_position, AxisAlignment alignment, const Matrix &transform)
Definition: text_frame.cc:82
impeller
Definition: allocation.cc:12
impeller::TRect< Scalar >
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::TextRun::GlyphPosition::position
Point position
Definition: text_run.h:24
impeller::AxisAlignment::kY
@ kY