| Flutter Impeller |

typographer_context_skia.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/backends/skia/typographer_context_skia.h"
6
7 #include <numeric>
8 #include <utility>
9
10 #include "flutter/fml/logging.h"
11 #include "flutter/fml/trace_event.h"
12 #include "impeller/base/allocation.h"
13 #include "impeller/core/allocator.h"
14 #include "impeller/typographer/backends/skia/glyph_atlas_context_skia.h"
15 #include "impeller/typographer/backends/skia/typeface_skia.h"
16 #include "impeller/typographer/rectangle_packer.h"
17 #include "impeller/typographer/typographer_context.h"
18 #include "include/core/SkColor.h"
19 #include "include/core/SkSize.h"
20 #include "third_party/skia/include/core/SkBitmap.h"
21 #include "third_party/skia/include/core/SkCanvas.h"
22 #include "third_party/skia/include/core/SkFont.h"
23 #include "third_party/skia/include/core/SkSurface.h"
24
25 namespace impeller {
26
27 // TODO(bdero): We might be able to remove this per-glyph padding if we fix
28 // the underlying causes of the overlap.
29 // https://github.com/flutter/flutter/issues/114563
30 constexpr auto kPadding = 2;
31
32 std::shared_ptr<TypographerContext> TypographerContextSkia::Make() {
33 return std::make_shared<TypographerContextSkia>();
34 }
35
36 TypographerContextSkia::TypographerContextSkia() = default;
37
38 TypographerContextSkia::~TypographerContextSkia() = default;
39
40 std::shared_ptr<GlyphAtlasContext>
41 TypographerContextSkia::CreateGlyphAtlasContext() const {
42 return std::make_shared<GlyphAtlasContextSkia>();
43 }
44
45 static size_t PairsFitInAtlasOfSize(
46 const std::vector<FontGlyphPair>& pairs,
47 const ISize& atlas_size,
48 std::vector<Rect>& glyph_positions,
49 const std::shared_ptr<RectanglePacker>& rect_packer) {
50 if (atlas_size.IsEmpty()) {
51 return false;
52 }
53
54 glyph_positions.clear();
55 glyph_positions.reserve(pairs.size());
56
57 size_t i = 0;
58 for (auto it = pairs.begin(); it != pairs.end(); ++i, ++it) {
59 const auto& pair = *it;
60
61 const auto glyph_size =
62 ISize::Ceil(pair.glyph.bounds.GetSize() * pair.scaled_font.scale);
63 IPoint16 location_in_atlas;
64 if (!rect_packer->addRect(glyph_size.width + kPadding, //
65 glyph_size.height + kPadding, //
66 &location_in_atlas //
67 )) {
68 return pairs.size() - i;
69 }
70 glyph_positions.emplace_back(Rect::MakeXYWH(location_in_atlas.x(), //
71 location_in_atlas.y(), //
72 glyph_size.width, //
73 glyph_size.height //
74 ));
75 }
76
77 return 0;
78 }
79
80 static bool CanAppendToExistingAtlas(
81 const std::shared_ptr<GlyphAtlas>& atlas,
82 const std::vector<FontGlyphPair>& extra_pairs,
83 std::vector<Rect>& glyph_positions,
84 ISize atlas_size,
85 const std::shared_ptr<RectanglePacker>& rect_packer) {
86 TRACE_EVENT0("impeller", __FUNCTION__);
87 if (!rect_packer || atlas_size.IsEmpty()) {
88 return false;
89 }
90
91 // We assume that all existing glyphs will fit. After all, they fit before.
92 // The glyph_positions only contains the values for the additional glyphs
93 // from extra_pairs.
94 FML_DCHECK(glyph_positions.size() == 0);
95 glyph_positions.reserve(extra_pairs.size());
96 for (size_t i = 0; i < extra_pairs.size(); i++) {
97 const FontGlyphPair& pair = extra_pairs[i];
98
99 const auto glyph_size =
100 ISize::Ceil(pair.glyph.bounds.GetSize() * pair.scaled_font.scale);
101 IPoint16 location_in_atlas;
102 if (!rect_packer->addRect(glyph_size.width + kPadding, //
103 glyph_size.height + kPadding, //
104 &location_in_atlas //
105 )) {
106 return false;
107 }
108 glyph_positions.emplace_back(Rect::MakeXYWH(location_in_atlas.x(), //
109 location_in_atlas.y(), //
110 glyph_size.width, //
111 glyph_size.height //
112 ));
113 }
114
115 return true;
116 }
117
118 static ISize OptimumAtlasSizeForFontGlyphPairs(
119 const std::vector<FontGlyphPair>& pairs,
120 std::vector<Rect>& glyph_positions,
121 const std::shared_ptr<GlyphAtlasContext>& atlas_context,
122 GlyphAtlas::Type type,
123 const ISize& max_texture_size) {
124 static constexpr auto kMinAtlasSize = 8u;
125 static constexpr auto kMinAlphaBitmapSize = 1024u;
126
127 TRACE_EVENT0("impeller", __FUNCTION__);
128
129 ISize current_size = type == GlyphAtlas::Type::kAlphaBitmap
130 ? ISize(kMinAlphaBitmapSize, kMinAlphaBitmapSize)
131 : ISize(kMinAtlasSize, kMinAtlasSize);
132 size_t total_pairs = pairs.size() + 1;
133 do {
134 auto rect_packer = std::shared_ptr<RectanglePacker>(
135 RectanglePacker::Factory(current_size.width, current_size.height));
136
137 auto remaining_pairs = PairsFitInAtlasOfSize(pairs, current_size,
138 glyph_positions, rect_packer);
139 if (remaining_pairs == 0) {
140 atlas_context->UpdateRectPacker(rect_packer);
141 return current_size;
142 } else if (remaining_pairs < std::ceil(total_pairs / 2)) {
143 current_size = ISize::MakeWH(
144 std::max(current_size.width, current_size.height),
145 Allocation::NextPowerOfTwoSize(
146 std::min(current_size.width, current_size.height) + 1));
147 } else {
148 current_size = ISize::MakeWH(
149 Allocation::NextPowerOfTwoSize(current_size.width + 1),
150 Allocation::NextPowerOfTwoSize(current_size.height + 1));
151 }
152 } while (current_size.width <= max_texture_size.width &&
153 current_size.height <= max_texture_size.height);
154 return ISize{0, 0};
155 }
156
157 static void DrawGlyph(SkCanvas* canvas,
158 const ScaledFont& scaled_font,
159 const Glyph& glyph,
160 const Rect& location,
161 bool has_color) {
162 const auto& metrics = scaled_font.font.GetMetrics();
163 const auto position = SkPoint::Make(location.GetX() / scaled_font.scale,
164 location.GetY() / scaled_font.scale);
165 SkGlyphID glyph_id = glyph.index;
166
167 SkFont sk_font(
168 TypefaceSkia::Cast(*scaled_font.font.GetTypeface()).GetSkiaTypeface(),
169 metrics.point_size, metrics.scaleX, metrics.skewX);
170 sk_font.setEdging(SkFont::Edging::kAntiAlias);
171 sk_font.setHinting(SkFontHinting::kSlight);
172 sk_font.setEmbolden(metrics.embolden);
173
174 auto glyph_color = has_color ? SK_ColorWHITE : SK_ColorBLACK;
175
176 SkPaint glyph_paint;
177 glyph_paint.setColor(glyph_color);
178 canvas->resetMatrix();
179 canvas->scale(scaled_font.scale, scaled_font.scale);
180 canvas->drawGlyphs(1u, // count
181 &glyph_id, // glyphs
182 &position, // positions
183 SkPoint::Make(-glyph.bounds.GetLeft(),
184 -glyph.bounds.GetTop()), // origin
185 sk_font, // font
186 glyph_paint // paint
187 );
188 }
189
190 static bool UpdateAtlasBitmap(const GlyphAtlas& atlas,
191 const std::shared_ptr<SkBitmap>& bitmap,
192 const std::vector<FontGlyphPair>& new_pairs) {
193 TRACE_EVENT0("impeller", __FUNCTION__);
194 FML_DCHECK(bitmap != nullptr);
195
196 auto surface = SkSurfaces::WrapPixels(bitmap->pixmap());
197 if (!surface) {
198 return false;
199 }
200 auto canvas = surface->getCanvas();
201 if (!canvas) {
202 return false;
203 }
204
205 bool has_color = atlas.GetType() == GlyphAtlas::Type::kColorBitmap;
206
207 for (const FontGlyphPair& pair : new_pairs) {
208 auto pos = atlas.FindFontGlyphBounds(pair);
209 if (!pos.has_value()) {
210 continue;
211 }
212 DrawGlyph(canvas, pair.scaled_font, pair.glyph, pos.value(), has_color);
213 }
214 return true;
215 }
216
217 static std::shared_ptr<SkBitmap> CreateAtlasBitmap(const GlyphAtlas& atlas,
218 const ISize& atlas_size) {
219 TRACE_EVENT0("impeller", __FUNCTION__);
220 auto bitmap = std::make_shared<SkBitmap>();
221 SkImageInfo image_info;
222
223 switch (atlas.GetType()) {
224 case GlyphAtlas::Type::kAlphaBitmap:
225 image_info =
226 SkImageInfo::MakeA8(SkISize{static_cast<int32_t>(atlas_size.width),
227 static_cast<int32_t>(atlas_size.height)});
228 break;
229 case GlyphAtlas::Type::kColorBitmap:
230 image_info =
231 SkImageInfo::MakeN32Premul(atlas_size.width, atlas_size.height);
232 break;
233 }
234
235 if (!bitmap->tryAllocPixels(image_info)) {
236 return nullptr;
237 }
238
239 auto surface = SkSurfaces::WrapPixels(bitmap->pixmap());
240 if (!surface) {
241 return nullptr;
242 }
243 auto canvas = surface->getCanvas();
244 if (!canvas) {
245 return nullptr;
246 }
247
248 bool has_color = atlas.GetType() == GlyphAtlas::Type::kColorBitmap;
249
250 atlas.IterateGlyphs([canvas, has_color](const ScaledFont& scaled_font,
251 const Glyph& glyph,
252 const Rect& location) -> bool {
253 DrawGlyph(canvas, scaled_font, glyph, location, has_color);
254 return true;
255 });
256
257 return bitmap;
258 }
259
260 static bool UpdateGlyphTextureAtlas(std::shared_ptr<SkBitmap> bitmap,
261 const std::shared_ptr<Texture>& texture) {
262 TRACE_EVENT0("impeller", __FUNCTION__);
263
264 FML_DCHECK(bitmap != nullptr);
265 auto texture_descriptor = texture->GetTextureDescriptor();
266
267 auto mapping = std::make_shared<fml::NonOwnedMapping>(
268 reinterpret_cast<const uint8_t*>(bitmap->getAddr(0, 0)), // data
269 texture_descriptor.GetByteSizeOfBaseMipLevel(), // size
270 [bitmap](auto, auto) mutable { bitmap.reset(); } // proc
271 );
272
273 return texture->SetContents(mapping);
274 }
275
276 static std::shared_ptr<Texture> UploadGlyphTextureAtlas(
277 const std::shared_ptr<Allocator>& allocator,
278 std::shared_ptr<SkBitmap> bitmap,
279 const ISize& atlas_size,
280 PixelFormat format) {
281 TRACE_EVENT0("impeller", __FUNCTION__);
282 if (!allocator) {
283 return nullptr;
284 }
285
286 FML_DCHECK(bitmap != nullptr);
287 const auto& pixmap = bitmap->pixmap();
288
289 TextureDescriptor texture_descriptor;
290 texture_descriptor.storage_mode = StorageMode::kHostVisible;
291 texture_descriptor.format = format;
292 texture_descriptor.size = atlas_size;
293
294 if (pixmap.rowBytes() * pixmap.height() !=
295 texture_descriptor.GetByteSizeOfBaseMipLevel()) {
296 return nullptr;
297 }
298
299 auto texture = allocator->CreateTexture(texture_descriptor);
300 if (!texture || !texture->IsValid()) {
301 return nullptr;
302 }
303 texture->SetLabel("GlyphAtlas");
304
305 auto mapping = std::make_shared<fml::NonOwnedMapping>(
306 reinterpret_cast<const uint8_t*>(bitmap->getAddr(0, 0)), // data
307 texture_descriptor.GetByteSizeOfBaseMipLevel(), // size
308 [bitmap](auto, auto) mutable { bitmap.reset(); } // proc
309 );
310
311 if (!texture->SetContents(mapping)) {
312 return nullptr;
313 }
314 return texture;
315 }
316
317 std::shared_ptr<GlyphAtlas> TypographerContextSkia::CreateGlyphAtlas(
318 Context& context,
319 GlyphAtlas::Type type,
320 const std::shared_ptr<GlyphAtlasContext>& atlas_context,
321 const FontGlyphMap& font_glyph_map) const {
322 TRACE_EVENT0("impeller", __FUNCTION__);
323 if (!IsValid()) {
324 return nullptr;
325 }
326 auto& atlas_context_skia = GlyphAtlasContextSkia::Cast(*atlas_context);
327 std::shared_ptr<GlyphAtlas> last_atlas = atlas_context->GetGlyphAtlas();
328
329 if (font_glyph_map.empty()) {
330 return last_atlas;
331 }
332
333 // ---------------------------------------------------------------------------
334 // Step 1: Determine if the atlas type and font glyph pairs are compatible
335 // with the current atlas and reuse if possible.
336 // ---------------------------------------------------------------------------
337 std::vector<FontGlyphPair> new_glyphs;
338 for (const auto& font_value : font_glyph_map) {
339 const ScaledFont& scaled_font = font_value.first;
340 const FontGlyphAtlas* font_glyph_atlas =
341 last_atlas->GetFontGlyphAtlas(scaled_font.font, scaled_font.scale);
342 if (font_glyph_atlas) {
343 for (const Glyph& glyph : font_value.second) {
344 if (!font_glyph_atlas->FindGlyphBounds(glyph)) {
345 new_glyphs.emplace_back(scaled_font, glyph);
346 }
347 }
348 } else {
349 for (const Glyph& glyph : font_value.second) {
350 new_glyphs.emplace_back(scaled_font, glyph);
351 }
352 }
353 }
354 if (last_atlas->GetType() == type && new_glyphs.size() == 0) {
355 return last_atlas;
356 }
357
358 // ---------------------------------------------------------------------------
359 // Step 2: Determine if the additional missing glyphs can be appended to the
360 // existing bitmap without recreating the atlas. This requires that
361 // the type is identical.
362 // ---------------------------------------------------------------------------
363 std::vector<Rect> glyph_positions;
364 if (last_atlas->GetType() == type &&
365 CanAppendToExistingAtlas(last_atlas, new_glyphs, glyph_positions,
366 atlas_context->GetAtlasSize(),
367 atlas_context->GetRectPacker())) {
368 // The old bitmap will be reused and only the additional glyphs will be
369 // added.
370
371 // ---------------------------------------------------------------------------
372 // Step 3a: Record the positions in the glyph atlas of the newly added
373 // glyphs.
374 // ---------------------------------------------------------------------------
375 for (size_t i = 0, count = glyph_positions.size(); i < count; i++) {
376 last_atlas->AddTypefaceGlyphPosition(new_glyphs[i], glyph_positions[i]);
377 }
378
379 // ---------------------------------------------------------------------------
380 // Step 4a: Draw new font-glyph pairs into the existing bitmap.
381 // ---------------------------------------------------------------------------
382 auto bitmap = atlas_context_skia.GetBitmap();
383 if (!UpdateAtlasBitmap(*last_atlas, bitmap, new_glyphs)) {
384 return nullptr;
385 }
386
387 // ---------------------------------------------------------------------------
388 // Step 5a: Update the existing texture with the updated bitmap.
389 // ---------------------------------------------------------------------------
390 if (!UpdateGlyphTextureAtlas(bitmap, last_atlas->GetTexture())) {
391 return nullptr;
392 }
393 return last_atlas;
394 }
395 // A new glyph atlas must be created.
396
397 // ---------------------------------------------------------------------------
398 // Step 3b: Get the optimum size of the texture atlas.
399 // ---------------------------------------------------------------------------
400 std::vector<FontGlyphPair> font_glyph_pairs;
401 font_glyph_pairs.reserve(std::accumulate(
402 font_glyph_map.begin(), font_glyph_map.end(), 0,
403 [](const int a, const auto& b) { return a + b.second.size(); }));
404 for (const auto& font_value : font_glyph_map) {
405 const ScaledFont& scaled_font = font_value.first;
406 for (const Glyph& glyph : font_value.second) {
407 font_glyph_pairs.push_back({scaled_font, glyph});
408 }
409 }
410 auto glyph_atlas = std::make_shared<GlyphAtlas>(type);
411 auto atlas_size = OptimumAtlasSizeForFontGlyphPairs(
412 font_glyph_pairs, //
413 glyph_positions, //
414 atlas_context, //
415 type, //
416 context.GetResourceAllocator()->GetMaxTextureSizeSupported() //
417 );
418
419 atlas_context->UpdateGlyphAtlas(glyph_atlas, atlas_size);
420 if (atlas_size.IsEmpty()) {
421 return nullptr;
422 }
423 // ---------------------------------------------------------------------------
424 // Step 4b: Find location of font-glyph pairs in the atlas. We have this from
425 // the last step. So no need to do create another rect packer. But just do a
426 // sanity check of counts. This could also be just an assertion as only a
427 // construction issue would cause such a failure.
428 // ---------------------------------------------------------------------------
429 if (glyph_positions.size() != font_glyph_pairs.size()) {
430 return nullptr;
431 }
432
433 // ---------------------------------------------------------------------------
434 // Step 5b: Record the positions in the glyph atlas.
435 // ---------------------------------------------------------------------------
436 {
437 size_t i = 0;
438 for (auto it = font_glyph_pairs.begin(); it != font_glyph_pairs.end();
439 ++i, ++it) {
440 glyph_atlas->AddTypefaceGlyphPosition(*it, glyph_positions[i]);
441 }
442 }
443
444 // ---------------------------------------------------------------------------
445 // Step 6b: Draw font-glyph pairs in the correct spot in the atlas.
446 // ---------------------------------------------------------------------------
447 auto bitmap = CreateAtlasBitmap(*glyph_atlas, atlas_size);
448 if (!bitmap) {
449 return nullptr;
450 }
451 atlas_context_skia.UpdateBitmap(bitmap);
452
453 // ---------------------------------------------------------------------------
454 // Step 7b: Upload the atlas as a texture.
455 // ---------------------------------------------------------------------------
456 PixelFormat format;
457 switch (type) {
458 case GlyphAtlas::Type::kAlphaBitmap:
459 format = context.GetCapabilities()->GetDefaultGlyphAtlasFormat();
460 break;
461 case GlyphAtlas::Type::kColorBitmap:
462 format = PixelFormat::kR8G8B8A8UNormInt;
463 break;
464 }
465 auto texture = UploadGlyphTextureAtlas(context.GetResourceAllocator(), bitmap,
466 atlas_size, format);
467 if (!texture) {
468 return nullptr;
469 }
470
471 // ---------------------------------------------------------------------------
472 // Step 8b: Record the texture in the glyph atlas.
473 // ---------------------------------------------------------------------------
474 glyph_atlas->SetTexture(std::move(texture));
475
476 return glyph_atlas;
477 }
478
479 } // namespace impeller
impeller::GlyphAtlas::Type::kColorBitmap
@ kColorBitmap
glyph_atlas_context_skia.h
impeller::TypographerContextSkia::CreateGlyphAtlasContext
std::shared_ptr< GlyphAtlasContext > CreateGlyphAtlasContext() const override
Definition: typographer_context_skia.cc:41
impeller::GlyphAtlas::Type::kAlphaBitmap
@ kAlphaBitmap
impeller::GlyphAtlas::FindFontGlyphBounds
std::optional< Rect > FindFontGlyphBounds(const FontGlyphPair &pair) const
Find the location of a specific font-glyph pair in the atlas.
Definition: glyph_atlas.cc:66
allocation.h
impeller::TRect< Scalar >::MakeXYWH
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:136
impeller::FontGlyphAtlas
An object that can look up glyph locations within the GlyphAtlas for a particular typeface.
Definition: glyph_atlas.h:185
impeller::Allocation::NextPowerOfTwoSize
static uint32_t NextPowerOfTwoSize(uint32_t x)
Definition: allocation.cc:41
impeller::Context::GetCapabilities
virtual const std::shared_ptr< const Capabilities > & GetCapabilities() const =0
Get the capabilities of Impeller context. All optionally supported feature of the platform,...
impeller::CreateAtlasBitmap
static std::shared_ptr< SkBitmap > CreateAtlasBitmap(const GlyphAtlas &atlas, const ISize &atlas_size)
Definition: typographer_context_skia.cc:217
impeller::TextureDescriptor::format
PixelFormat format
Definition: texture_descriptor.h:40
impeller::ScaledFont::font
Font font
Definition: font_glyph_pair.h:25
impeller::PixelFormat::kR8G8B8A8UNormInt
@ kR8G8B8A8UNormInt
impeller::RectanglePacker::Factory
static std::unique_ptr< RectanglePacker > Factory(int width, int height)
Return an empty packer with area specified by width and height.
Definition: rectangle_packer.cc:169
impeller::PairsFitInAtlasOfSize
static size_t PairsFitInAtlasOfSize(const std::vector< FontGlyphPair > &pairs, const ISize &atlas_size, std::vector< Rect > &glyph_positions, const std::shared_ptr< RectanglePacker > &rect_packer)
Definition: typographer_context_skia.cc:45
impeller::TSize< int64_t >::Ceil
constexpr TSize Ceil() const
Definition: size.h:96
impeller::FontGlyphMap
std::unordered_map< ScaledFont, std::unordered_set< Glyph > > FontGlyphMap
Definition: font_glyph_pair.h:29
impeller::IPoint16::x
int16_t x() const
Definition: rectangle_packer.h:15
typographer_context.h
impeller::TRect::GetX
constexpr Type GetX() const
Returns the X coordinate of the upper left corner, equivalent to |GetOrigin().x|.
Definition: rect.h:300
impeller::UpdateAtlasBitmap
static bool UpdateAtlasBitmap(const GlyphAtlas &atlas, const std::shared_ptr< SkBitmap > &bitmap, const std::vector< FontGlyphPair > &new_pairs)
Definition: typographer_context_skia.cc:190
impeller::StorageMode::kHostVisible
@ kHostVisible
impeller::IPoint16::y
int16_t y() const
Definition: rectangle_packer.h:16
impeller::PixelFormat
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition: formats.h:100
typographer_context_skia.h
impeller::Font::GetTypeface
const std::shared_ptr< Typeface > & GetTypeface() const
The typeface whose intrinsic properties this font modifies.
Definition: font.cc:23
impeller::GlyphAtlas::IterateGlyphs
size_t IterateGlyphs(const std::function< bool(const ScaledFont &scaled_font, const Glyph &glyph, const Rect &rect)> &iterator) const
Iterate of all the glyphs along with their locations in the atlas.
Definition: glyph_atlas.cc:91
impeller::TypefaceSkia::GetSkiaTypeface
const sk_sp< SkTypeface > & GetSkiaTypeface() const
Definition: typeface_skia.cc:31
impeller::CanAppendToExistingAtlas
static bool CanAppendToExistingAtlas(const std::shared_ptr< GlyphAtlas > &atlas, const std::vector< FontGlyphPair > &extra_pairs, std::vector< Rect > &glyph_positions, ISize atlas_size, const std::shared_ptr< RectanglePacker > &rect_packer)
Definition: typographer_context_skia.cc:80
impeller::Glyph
The glyph index in the typeface.
Definition: glyph.h:20
impeller::TSize< int64_t >
impeller::UpdateGlyphTextureAtlas
static bool UpdateGlyphTextureAtlas(std::shared_ptr< SkBitmap > bitmap, const std::shared_ptr< Texture > &texture)
Definition: typographer_context_skia.cc:260
impeller::FontGlyphPair::glyph
const Glyph & glyph
Definition: font_glyph_pair.h:39
impeller::TRect::GetLeft
constexpr auto GetLeft() const
Definition: rect.h:318
impeller::TypographerContextSkia::CreateGlyphAtlas
std::shared_ptr< GlyphAtlas > CreateGlyphAtlas(Context &context, GlyphAtlas::Type type, const std::shared_ptr< GlyphAtlasContext > &atlas_context, const FontGlyphMap &font_glyph_map) const override
Definition: typographer_context_skia.cc:317
rectangle_packer.h
impeller::FontGlyphPair::scaled_font
const ScaledFont & scaled_font
Definition: font_glyph_pair.h:38
impeller::GlyphAtlas::GetType
Type GetType() const
Describes how the glyphs are represented in the texture.
Definition: glyph_atlas.cc:49
impeller::TypographerContextSkia::TypographerContextSkia
TypographerContextSkia()
impeller::GlyphAtlas::Type
Type
Describes how the glyphs are represented in the texture.
Definition: glyph_atlas.h:32
impeller::UploadGlyphTextureAtlas
static std::shared_ptr< Texture > UploadGlyphTextureAtlas(const std::shared_ptr< Allocator > &allocator, std::shared_ptr< SkBitmap > bitmap, const ISize &atlas_size, PixelFormat format)
Definition: typographer_context_skia.cc:276
impeller::Glyph::index
uint16_t index
Definition: glyph.h:26
impeller::FontGlyphPair
A font along with a glyph in that font rendered at a particular scale.
Definition: font_glyph_pair.h:35
impeller::Font::GetMetrics
const Metrics & GetMetrics() const
Definition: font.cc:37
impeller::kPadding
constexpr auto kPadding
Definition: typographer_context_skia.cc:30
impeller::TSize::width
Type width
Definition: size.h:22
impeller::ISize
TSize< int64_t > ISize
Definition: size.h:138
impeller::TextureDescriptor::size
ISize size
Definition: texture_descriptor.h:41
impeller::ScaledFont::scale
Scalar scale
Definition: font_glyph_pair.h:26
typeface_skia.h
allocator.h
impeller::GlyphAtlas
A texture containing the bitmap representation of glyphs in different fonts along with the ability to...
Definition: glyph_atlas.h:28
impeller::TRect::GetSize
constexpr TSize< Type > GetSize() const
Returns the size of the rectangle which may be negative in either width or height and may have been c...
Definition: rect.h:294
impeller::Context
To do anything rendering related with Impeller, you need a context.
Definition: context.h:46
impeller::TextureDescriptor::GetByteSizeOfBaseMipLevel
constexpr size_t GetByteSizeOfBaseMipLevel() const
Definition: texture_descriptor.h:47
impeller::TypographerContextSkia::~TypographerContextSkia
~TypographerContextSkia() override
impeller::saturated::b
SI b
Definition: saturated_math.h:87
impeller::BackendCast< TypefaceSkia, Typeface >::Cast
static TypefaceSkia & Cast(Typeface &base)
Definition: backend_cast.h:13
impeller::IPoint16
Definition: rectangle_packer.h:14
impeller::OptimumAtlasSizeForFontGlyphPairs
static ISize OptimumAtlasSizeForFontGlyphPairs(const std::vector< FontGlyphPair > &pairs, std::vector< Rect > &glyph_positions, const std::shared_ptr< GlyphAtlasContext > &atlas_context, GlyphAtlas::Type type, const ISize &max_texture_size)
Definition: typographer_context_skia.cc:118
impeller::FontGlyphAtlas::FindGlyphBounds
std::optional< Rect > FindGlyphBounds(const Glyph &glyph) const
Find the location of a glyph in the atlas.
Definition: glyph_atlas.cc:111
impeller::TextureDescriptor::storage_mode
StorageMode storage_mode
Definition: texture_descriptor.h:38
impeller::TSize::height
Type height
Definition: size.h:23
impeller::TextureDescriptor
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
Definition: texture_descriptor.h:37
impeller::TSize::IsEmpty
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
Definition: size.h:105
impeller::TSize< int64_t >::MakeWH
static constexpr TSize MakeWH(Type width, Type height)
Definition: size.h:34
impeller::TRect::GetY
constexpr Type GetY() const
Returns the Y coordinate of the upper left corner, equivalent to |GetOrigin().y|.
Definition: rect.h:304
impeller
Definition: aiks_blur_unittests.cc:20
impeller::Context::GetResourceAllocator
virtual std::shared_ptr< Allocator > GetResourceAllocator() const =0
Returns the allocator used to create textures and buffers on the device.
impeller::TRect::GetTop
constexpr auto GetTop() const
Definition: rect.h:320
impeller::Glyph::bounds
Rect bounds
Visibility coverage of the glyph in text run space (relative to the baseline, no scaling applied).
Definition: glyph.h:37
impeller::TypographerContextSkia::Make
static std::shared_ptr< TypographerContext > Make()
Definition: typographer_context_skia.cc:32
impeller::TRect
Definition: rect.h:122
impeller::DrawGlyph
static void DrawGlyph(SkCanvas *canvas, const ScaledFont &scaled_font, const Glyph &glyph, const Rect &location, bool has_color)
Definition: typographer_context_skia.cc:157
impeller::ScaledFont
A font and a scale. Used as a key that represents a typeface within a glyph atlas.
Definition: font_glyph_pair.h:24
impeller::TypographerContext::IsValid
virtual bool IsValid() const
Definition: typographer_context.cc:17