| Flutter Impeller |

glyph_atlas.h
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 #ifndef FLUTTER_IMPELLER_TYPOGRAPHER_GLYPH_ATLAS_H_
6 #define FLUTTER_IMPELLER_TYPOGRAPHER_GLYPH_ATLAS_H_
7
8 #include <functional>
9 #include <memory>
10 #include <optional>
11
12 #include "flutter/fml/build_config.h"
13
14 #if defined(OS_FUCHSIA)
15 // TODO(gaaclarke): Migrate to use absl. I couldn't get it working since absl
16 // has special logic in its GN files for Fuchsia that I couldn't sort out.
17 #define IMPELLER_TYPOGRAPHER_USE_STD_HASH
18 #else
19 #include "flutter/third_party/abseil-cpp/absl/container/flat_hash_map.h"
20 #endif
21
22 #include "impeller/core/texture.h"
23 #include "impeller/geometry/rect.h"
24 #include "impeller/typographer/font_glyph_pair.h"
25 #include "impeller/typographer/rectangle_packer.h"
26
27 namespace impeller {
28
29 class FontGlyphAtlas;
30
31 /// Helper for AbslHashAdapter. Tallies a hash value with fml::HashCombine.
32 template <typename T>
33 struct AbslHashAdapterCombiner {
34 std::size_t value = 0;
35
36 template <typename... Args>
37 static AbslHashAdapterCombiner combine(AbslHashAdapterCombiner combiner,
38 const Args&... args) {
39 combiner.value = fml::HashCombine(combiner.value, args...);
40 return combiner;
41 }
42 };
43
44 /// Adapts AbslHashValue functions to be used with std::unordered_map and the
45 /// fml hash functions.
46 template <typename T>
47 struct AbslHashAdapter {
48 constexpr std::size_t operator()(const T& element) const {
49 AbslHashAdapterCombiner<T> combiner;
50 combiner = AbslHashValue(std::move(combiner), element);
51 return combiner.value;
52 }
53 };
54
55 struct FrameBounds {
56 /// The bounds of the glyph within the glyph atlas.
57 Rect atlas_bounds;
58 /// The local glyph bounds.
59 Rect glyph_bounds;
60 /// Whether [atlas_bounds] are still a placeholder and have
61 /// not yet been computed.
62 bool is_placeholder = true;
63 };
64
65 //------------------------------------------------------------------------------
66 /// @brief A texture containing the bitmap representation of glyphs in
67 /// different fonts along with the ability to query the location of
68 /// specific font glyphs within the texture.
69 ///
70 class GlyphAtlas {
71 public:
72 //----------------------------------------------------------------------------
73 /// @brief Describes how the glyphs are represented in the texture.
74 enum class Type {
75 //--------------------------------------------------------------------------
76 /// The glyphs are reprsented at their requested size using only an 8-bit
77 /// color channel.
78 ///
79 /// This might be backed by a grey or red single channel texture, depending
80 /// on the backend capabilities.
81 kAlphaBitmap,
82
83 //--------------------------------------------------------------------------
84 /// The glyphs are reprsented at their requested size using N32 premul
85 /// colors.
86 ///
87 kColorBitmap,
88 };
89
90 //----------------------------------------------------------------------------
91 /// @brief Create an empty glyph atlas.
92 ///
93 /// @param[in] type How the glyphs are represented in the texture.
94 /// @param[in] initial_generation the atlas generation.
95 ///
96 GlyphAtlas(Type type, size_t initial_generation);
97
98 ~GlyphAtlas();
99
100 bool IsValid() const;
101
102 //----------------------------------------------------------------------------
103 /// @brief Describes how the glyphs are represented in the texture.
104 ///
105 Type GetType() const;
106
107 //----------------------------------------------------------------------------
108 /// @brief Set the texture for the glyph atlas.
109 ///
110 /// @param[in] texture The texture
111 ///
112 void SetTexture(std::shared_ptr<Texture> texture);
113
114 //----------------------------------------------------------------------------
115 /// @brief Get the texture for the glyph atlas.
116 ///
117 /// @return The texture.
118 ///
119 const std::shared_ptr<Texture>& GetTexture() const;
120
121 //----------------------------------------------------------------------------
122 /// @brief Record the location of a specific font-glyph pair within the
123 /// atlas.
124 ///
125 /// @param[in] pair The font-glyph pair
126 /// @param[in] rect The position in the atlas
127 /// @param[in] bounds The bounds of the glyph at scale
128 ///
129 void AddTypefaceGlyphPositionAndBounds(const FontGlyphPair& pair,
130 Rect position,
131 Rect bounds);
132
133 //----------------------------------------------------------------------------
134 /// @brief Get the number of unique font-glyph pairs in this atlas.
135 ///
136 /// @return The glyph count.
137 ///
138 size_t GetGlyphCount() const;
139
140 //----------------------------------------------------------------------------
141 /// @brief Iterate of all the glyphs along with their locations in the
142 /// atlas.
143 ///
144 /// @param[in] iterator The iterator. Return `false` from the iterator to
145 /// stop iterating.
146 ///
147 /// @return The number of glyphs iterated over.
148 ///
149 size_t IterateGlyphs(
150 const std::function<bool(const ScaledFont& scaled_font,
151 const SubpixelGlyph& glyph,
152 const Rect& rect)>& iterator) const;
153
154 //----------------------------------------------------------------------------
155 /// @brief Find the location of a specific font-glyph pair in the atlas.
156 ///
157 /// @param[in] pair The font-glyph pair
158 ///
159 /// @return The location of the font-glyph pair in the atlas.
160 /// `std::nullopt` if the pair is not in the atlas.
161 ///
162 std::optional<FrameBounds> FindFontGlyphBounds(
163 const FontGlyphPair& pair) const;
164
165 //----------------------------------------------------------------------------
166 /// @brief Obtain an interface for querying the location of glyphs in the
167 /// atlas for the given font and scale. This provides a more
168 /// efficient way to look up a run of glyphs in the same font.
169 ///
170 /// @param[in] font The font
171 /// @param[in] scale The scale
172 ///
173 /// @return A pointer to a FontGlyphAtlas, or nullptr if the font and
174 /// scale are not available in the atlas. The pointer is only
175 /// valid for the lifetime of the GlyphAtlas.
176 ///
177 FontGlyphAtlas* GetOrCreateFontGlyphAtlas(const ScaledFont& scaled_font);
178
179 //----------------------------------------------------------------------------
180 /// @brief Retrieve the generation id for this glyph atlas.
181 ///
182 /// The generation id is used to match with a TextFrame to
183 /// determine if the frame is guaranteed to already be populated
184 /// in the atlas.
185 size_t GetAtlasGeneration() const;
186
187 //----------------------------------------------------------------------------
188 /// @brief Update the atlas generation.
189 void SetAtlasGeneration(size_t value);
190
191 private:
192 const Type type_;
193 std::shared_ptr<Texture> texture_;
194 size_t generation_ = 0;
195
196 #if defined(IMPELLER_TYPOGRAPHER_USE_STD_HASH)
197 using FontAtlasMap = std::unordered_map<ScaledFont,
198 FontGlyphAtlas,
199 AbslHashAdapter<ScaledFont>,
200 ScaledFont::Equal>;
201 #else
202 using FontAtlasMap = absl::flat_hash_map<ScaledFont,
203 FontGlyphAtlas,
204 absl::Hash<ScaledFont>,
205 ScaledFont::Equal>;
206 #endif
207
208 FontAtlasMap font_atlas_map_;
209
210 GlyphAtlas(const GlyphAtlas&) = delete;
211
212 GlyphAtlas& operator=(const GlyphAtlas&) = delete;
213 };
214
215 //------------------------------------------------------------------------------
216 /// @brief A container for caching a glyph atlas across frames.
217 ///
218 class GlyphAtlasContext {
219 public:
220 explicit GlyphAtlasContext(GlyphAtlas::Type type);
221
222 virtual ~GlyphAtlasContext();
223
224 //----------------------------------------------------------------------------
225 /// @brief Retrieve the current glyph atlas.
226 std::shared_ptr<GlyphAtlas> GetGlyphAtlas() const;
227
228 //----------------------------------------------------------------------------
229 /// @brief Retrieve the size of the current glyph atlas.
230 const ISize& GetAtlasSize() const;
231
232 //----------------------------------------------------------------------------
233 /// @brief Retrieve the previous (if any) rect packer.
234 std::shared_ptr<RectanglePacker> GetRectPacker() const;
235
236 //----------------------------------------------------------------------------
237 /// @brief A y-coordinate shift that must be applied to glyphs appended
238 /// to
239 /// the atlas.
240 ///
241 /// The rectangle packer is only initialized for unfilled regions
242 /// of the atlas. The area the rectangle packer covers is offset
243 /// from the origin by this height adjustment.
244 int64_t GetHeightAdjustment() const;
245
246 //----------------------------------------------------------------------------
247 /// @brief Update the context with a newly constructed glyph atlas.
248 void UpdateGlyphAtlas(std::shared_ptr<GlyphAtlas> atlas,
249 ISize size,
250 int64_t height_adjustment_);
251
252 void UpdateRectPacker(std::shared_ptr<RectanglePacker> rect_packer);
253
254 private:
255 std::shared_ptr<GlyphAtlas> atlas_;
256 ISize atlas_size_;
257 std::shared_ptr<RectanglePacker> rect_packer_;
258 int64_t height_adjustment_;
259
260 GlyphAtlasContext(const GlyphAtlasContext&) = delete;
261
262 GlyphAtlasContext& operator=(const GlyphAtlasContext&) = delete;
263 };
264
265 //------------------------------------------------------------------------------
266 /// @brief An object that can look up glyph locations within the GlyphAtlas
267 /// for a particular typeface.
268 ///
269 class FontGlyphAtlas {
270 public:
271 FontGlyphAtlas() = default;
272 FontGlyphAtlas(FontGlyphAtlas&&) = default;
273
274 //----------------------------------------------------------------------------
275 /// @brief Find the location of a glyph in the atlas.
276 ///
277 /// @param[in] glyph The glyph
278 ///
279 /// @return The location of the glyph in the atlas.
280 /// `std::nullopt` if the glyph is not in the atlas.
281 ///
282 std::optional<FrameBounds> FindGlyphBounds(const SubpixelGlyph& glyph) const;
283
284 //----------------------------------------------------------------------------
285 /// @brief Append the frame bounds of a glyph to this atlas.
286 ///
287 /// This may indicate a placeholder glyph location to be replaced
288 /// at a later time, as indicated by FrameBounds.placeholder.
289 void AppendGlyph(const SubpixelGlyph& glyph, const FrameBounds& frame_bounds);
290
291 private:
292 friend class GlyphAtlas;
293
294 #if defined(IMPELLER_TYPOGRAPHER_USE_STD_HASH)
295 using PositionsMap = std::unordered_map<SubpixelGlyph,
296 FrameBounds,
297 AbslHashAdapter<SubpixelGlyph>,
298 SubpixelGlyph::Equal>;
299 #else
300 using PositionsMap = absl::flat_hash_map<SubpixelGlyph,
301 FrameBounds,
302 absl::Hash<SubpixelGlyph>,
303 SubpixelGlyph::Equal>;
304 #endif
305
306 PositionsMap positions_;
307 FontGlyphAtlas(const FontGlyphAtlas&) = delete;
308 };
309
310 } // namespace impeller
311
312 #endif // FLUTTER_IMPELLER_TYPOGRAPHER_GLYPH_ATLAS_H_
impeller::GlyphAtlas::FindFontGlyphBounds
std::optional< FrameBounds > FindFontGlyphBounds(const FontGlyphPair &pair) const
Find the location of a specific font-glyph pair in the atlas.
Definition: glyph_atlas.cc:87
impeller::GlyphAtlas::Type::kColorBitmap
@ kColorBitmap
impeller::GlyphAtlas::GetGlyphCount
size_t GetGlyphCount() const
Get the number of unique font-glyph pairs in this atlas.
Definition: glyph_atlas.cc:103
impeller::GlyphAtlasContext::GetRectPacker
std::shared_ptr< RectanglePacker > GetRectPacker() const
Retrieve the previous (if any) rect packer.
Definition: glyph_atlas.cc:32
impeller::GlyphAtlas::Type::kAlphaBitmap
@ kAlphaBitmap
impeller::GlyphAtlasContext::UpdateGlyphAtlas
void UpdateGlyphAtlas(std::shared_ptr< GlyphAtlas > atlas, ISize size, int64_t height_adjustment_)
Update the context with a newly constructed glyph atlas.
Definition: glyph_atlas.cc:36
impeller::GlyphAtlasContext::GetGlyphAtlas
std::shared_ptr< GlyphAtlas > GetGlyphAtlas() const
Retrieve the current glyph atlas.
Definition: glyph_atlas.cc:20
impeller::FontGlyphAtlas::FindGlyphBounds
std::optional< FrameBounds > FindGlyphBounds(const SubpixelGlyph &glyph) const
Find the location of a glyph in the atlas.
Definition: glyph_atlas.cc:131
impeller::FontGlyphAtlas::FontGlyphAtlas
FontGlyphAtlas()=default
impeller::FontGlyphAtlas
An object that can look up glyph locations within the GlyphAtlas for a particular typeface.
Definition: glyph_atlas.h:269
value
int32_t value
Definition: dl_golden_unittests.cc:444
impeller::GlyphAtlas::SetTexture
void SetTexture(std::shared_ptr< Texture > texture)
Set the texture for the glyph atlas.
Definition: glyph_atlas.cc:66
impeller::SubpixelGlyph
A glyph and its subpixel position.
Definition: font_glyph_pair.h:60
impeller::GlyphAtlas::GetOrCreateFontGlyphAtlas
FontGlyphAtlas * GetOrCreateFontGlyphAtlas(const ScaledFont &scaled_font)
Obtain an interface for querying the location of glyphs in the atlas for the given font and scale....
Definition: glyph_atlas.cc:96
impeller::GlyphAtlasContext::~GlyphAtlasContext
virtual ~GlyphAtlasContext()
Definition: glyph_atlas.cc:18
impeller::GlyphAtlasContext::GetHeightAdjustment
int64_t GetHeightAdjustment() const
A y-coordinate shift that must be applied to glyphs appended to the atlas.
Definition: glyph_atlas.cc:28
impeller::FrameBounds::is_placeholder
bool is_placeholder
Definition: glyph_atlas.h:62
impeller::GlyphAtlas::GlyphAtlas
GlyphAtlas(Type type, size_t initial_generation)
Create an empty glyph atlas.
Definition: glyph_atlas.cc:49
impeller::GlyphAtlas::AddTypefaceGlyphPositionAndBounds
void AddTypefaceGlyphPositionAndBounds(const FontGlyphPair &pair, Rect position, Rect bounds)
Record the location of a specific font-glyph pair within the atlas.
Definition: glyph_atlas.cc:78
impeller::AbslHashAdapterCombiner::value
std::size_t value
Definition: glyph_atlas.h:34
impeller::FrameBounds::atlas_bounds
Rect atlas_bounds
The bounds of the glyph within the glyph atlas.
Definition: glyph_atlas.h:57
impeller::TSize
Definition: size.h:25
impeller::FontGlyphAtlas::AppendGlyph
void AppendGlyph(const SubpixelGlyph &glyph, const FrameBounds &frame_bounds)
Append the frame bounds of a glyph to this atlas.
Definition: glyph_atlas.cc:140
impeller::GlyphAtlasContext::GetAtlasSize
const ISize & GetAtlasSize() const
Retrieve the size of the current glyph atlas.
Definition: glyph_atlas.cc:24
rectangle_packer.h
impeller::GlyphAtlas::GetType
Type GetType() const
Describes how the glyphs are represented in the texture.
Definition: glyph_atlas.cc:58
impeller::GlyphAtlas::~GlyphAtlas
~GlyphAtlas()
impeller::AbslHashAdapterCombiner::combine
static AbslHashAdapterCombiner combine(AbslHashAdapterCombiner combiner, const Args &... args)
Definition: glyph_atlas.h:37
impeller::GlyphAtlas::GetTexture
const std::shared_ptr< Texture > & GetTexture() const
Get the texture for the glyph atlas.
Definition: glyph_atlas.cc:62
impeller::GlyphAtlas::Type
Type
Describes how the glyphs are represented in the texture.
Definition: glyph_atlas.h:74
impeller::ScaledFont::Equal
Definition: font_glyph_pair.h:49
font_glyph_pair.h
type
GLenum type
Definition: blit_command_gles.cc:151
impeller::GlyphAtlasContext
A container for caching a glyph atlas across frames.
Definition: glyph_atlas.h:218
impeller::FontGlyphPair
A font along with a glyph in that font rendered at a particular scale and subpixel position.
Definition: font_glyph_pair.h:110
impeller::GlyphAtlas::SetAtlasGeneration
void SetAtlasGeneration(size_t value)
Update the atlas generation.
Definition: glyph_atlas.cc:74
impeller::GlyphAtlas
A texture containing the bitmap representation of glyphs in different fonts along with the ability to...
Definition: glyph_atlas.h:70
impeller::AbslHashAdapter
Definition: glyph_atlas.h:47
rect.h
impeller::GlyphAtlas::GetAtlasGeneration
size_t GetAtlasGeneration() const
Retrieve the generation id for this glyph atlas.
Definition: glyph_atlas.cc:70
texture.h
impeller::FrameBounds
Definition: glyph_atlas.h:55
impeller::AbslHashAdapterCombiner
Helper for AbslHashAdapter. Tallies a hash value with fml::HashCombine.
Definition: glyph_atlas.h:33
impeller::GlyphAtlas::IsValid
bool IsValid() const
Definition: glyph_atlas.cc:54
impeller::SubpixelGlyph::Equal
Definition: font_glyph_pair.h:85
impeller
Definition: allocation.cc:12
impeller::GlyphAtlasContext::GlyphAtlasContext
GlyphAtlasContext(GlyphAtlas::Type type)
Definition: glyph_atlas.cc:14
impeller::TRect< Scalar >
impeller::GlyphAtlas::IterateGlyphs
size_t IterateGlyphs(const std::function< bool(const ScaledFont &scaled_font, const SubpixelGlyph &glyph, const Rect &rect)> &iterator) const
Iterate of all the glyphs along with their locations in the atlas.
Definition: glyph_atlas.cc:110
impeller::ScaledFont
A font and a scale. Used as a key that represents a typeface within a glyph atlas.
Definition: font_glyph_pair.h:40
impeller::GlyphAtlasContext::UpdateRectPacker
void UpdateRectPacker(std::shared_ptr< RectanglePacker > rect_packer)
Definition: glyph_atlas.cc:44
impeller::AbslHashAdapter::operator()
constexpr std::size_t operator()(const T &element) const
Definition: glyph_atlas.h:48
impeller::FrameBounds::glyph_bounds
Rect glyph_bounds
The local glyph bounds.
Definition: glyph_atlas.h:59