| Flutter Impeller |

typographer_context_stb.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/stb/typographer_context_stb.h"
6
7 #include <numeric>
8 #include <utility>
9
10 #include "flutter/fml/logging.h"
11 #include "flutter/fml/trace_event.h"
12 #include "fml/closure.h"
13 #include "fml/mapping.h"
14 #include "impeller/base/allocation.h"
15 #include "impeller/core/allocator.h"
16 #include "impeller/core/device_buffer.h"
17 #include "impeller/typographer/backends/stb/glyph_atlas_context_stb.h"
18 #include "impeller/typographer/font_glyph_pair.h"
19 #include "typeface_stb.h"
20
21 #define DISABLE_COLOR_FONT_SUPPORT 1
22 #ifdef DISABLE_COLOR_FONT_SUPPORT
23 constexpr auto kColorFontBitsPerPixel = 1;
24 #else
25 constexpr auto kColorFontBitsPerPixel = 4;
26 #endif
27
28 namespace impeller {
29
30 constexpr size_t kPadding = 1;
31
32 std::unique_ptr<TypographerContext> TypographerContextSTB::Make() {
33 return std::make_unique<TypographerContextSTB>();
34 }
35
36 TypographerContextSTB::TypographerContextSTB() : TypographerContext() {}
37
38 TypographerContextSTB::~TypographerContextSTB() = default;
39
40 std::shared_ptr<GlyphAtlasContext>
41 TypographerContextSTB::CreateGlyphAtlasContext(GlyphAtlas::Type type) const {
42 return std::make_shared<GlyphAtlasContextSTB>(type);
43 }
44
45 // Function returns the count of "remaining pairs" not packed into rect of given
46 // size.
47 static size_t PairsFitInAtlasOfSize(
48 const std::vector<FontGlyphPair>& pairs,
49 const ISize& atlas_size,
50 std::vector<Rect>& glyph_positions,
51 const std::shared_ptr<RectanglePacker>& rect_packer) {
52 if (atlas_size.IsEmpty()) {
53 return false;
54 }
55
56 glyph_positions.clear();
57 glyph_positions.reserve(pairs.size());
58
59 size_t i = 0;
60 for (auto it = pairs.begin(); it != pairs.end(); ++i, ++it) {
61 const auto& pair = *it;
62 const Font& font = pair.scaled_font.font;
63
64 // We downcast to the correct typeface type to access `stb` specific
65 // methods.
66 std::shared_ptr<TypefaceSTB> typeface_stb =
67 std::reinterpret_pointer_cast<TypefaceSTB>(font.GetTypeface());
68 // Conversion factor to scale font size in Points to pixels.
69 // Note this assumes typical DPI.
70 float text_size_pixels =
71 font.GetMetrics().point_size * TypefaceSTB::kPointsToPixels;
72
73 ISize glyph_size;
74 {
75 int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
76 float scale = stbtt_ScaleForMappingEmToPixels(typeface_stb->GetFontInfo(),
77 text_size_pixels);
78 stbtt_GetGlyphBitmapBox(typeface_stb->GetFontInfo(),
79 pair.glyph.glyph.index, scale, scale, &x0, &y0,
80 &x1, &y1);
81
82 glyph_size = ISize(x1 - x0, y1 - y0);
83 }
84
85 IPoint16 location_in_atlas;
86 if (!rect_packer->AddRect(glyph_size.width + kPadding, //
87 glyph_size.height + kPadding, //
88 &location_in_atlas //
89 )) {
90 return pairs.size() - i;
91 }
92 glyph_positions.emplace_back(Rect::MakeXYWH(location_in_atlas.x(), //
93 location_in_atlas.y(), //
94 glyph_size.width, //
95 glyph_size.height //
96 ));
97 }
98
99 return 0;
100 }
101
102 static bool CanAppendToExistingAtlas(
103 const std::shared_ptr<GlyphAtlas>& atlas,
104 const std::vector<FontGlyphPair>& extra_pairs,
105 std::vector<Rect>& glyph_positions,
106 ISize atlas_size,
107 const std::shared_ptr<RectanglePacker>& rect_packer) {
108 TRACE_EVENT0("impeller", __FUNCTION__);
109 if (!rect_packer || atlas_size.IsEmpty()) {
110 return false;
111 }
112
113 // We assume that all existing glyphs will fit. After all, they fit before.
114 // The glyph_positions only contains the values for the additional glyphs
115 // from extra_pairs.
116 FML_DCHECK(glyph_positions.size() == 0);
117 glyph_positions.reserve(extra_pairs.size());
118 for (size_t i = 0; i < extra_pairs.size(); i++) {
119 const FontGlyphPair& pair = extra_pairs[i];
120 const Font& font = pair.scaled_font.font;
121
122 // We downcast to the correct typeface type to access `stb` specific methods
123 std::shared_ptr<TypefaceSTB> typeface_stb =
124 std::reinterpret_pointer_cast<TypefaceSTB>(font.GetTypeface());
125 // Conversion factor to scale font size in Points to pixels.
126 // Note this assumes typical DPI.
127 float text_size_pixels =
128 font.GetMetrics().point_size * TypefaceSTB::kPointsToPixels;
129
130 ISize glyph_size;
131 {
132 int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
133 float scale_y = stbtt_ScaleForMappingEmToPixels(
134 typeface_stb->GetFontInfo(), text_size_pixels);
135 float scale_x = scale_y;
136 stbtt_GetGlyphBitmapBox(typeface_stb->GetFontInfo(),
137 pair.glyph.glyph.index, scale_x, scale_y, &x0,
138 &y0, &x1, &y1);
139
140 glyph_size = ISize(x1 - x0, y1 - y0);
141 }
142
143 IPoint16 location_in_atlas;
144 if (!rect_packer->AddRect(glyph_size.width + kPadding, //
145 glyph_size.height + kPadding, //
146 &location_in_atlas //
147 )) {
148 return false;
149 }
150 glyph_positions.emplace_back(Rect::MakeXYWH(location_in_atlas.x(), //
151 location_in_atlas.y(), //
152 glyph_size.width, //
153 glyph_size.height //
154 ));
155 }
156
157 return true;
158 }
159
160 static ISize OptimumAtlasSizeForFontGlyphPairs(
161 const std::vector<FontGlyphPair>& pairs,
162 std::vector<Rect>& glyph_positions,
163 const std::shared_ptr<GlyphAtlasContext>& atlas_context,
164 GlyphAtlas::Type type,
165 const ISize& max_texture_size) {
166 static constexpr auto kMinAtlasSize = 8u;
167 static constexpr auto kMinAlphaBitmapSize = 1024u;
168
169 TRACE_EVENT0("impeller", __FUNCTION__);
170
171 ISize current_size = type == GlyphAtlas::Type::kAlphaBitmap
172 ? ISize(kMinAlphaBitmapSize, kMinAlphaBitmapSize)
173 : ISize(kMinAtlasSize, kMinAtlasSize);
174 size_t total_pairs = pairs.size() + 1;
175 do {
176 auto rect_packer = std::shared_ptr<RectanglePacker>(
177 RectanglePacker::Factory(current_size.width, current_size.height));
178
179 auto remaining_pairs = PairsFitInAtlasOfSize(pairs, current_size,
180 glyph_positions, rect_packer);
181 if (remaining_pairs == 0) {
182 atlas_context->UpdateRectPacker(rect_packer);
183 return current_size;
184 } else if (remaining_pairs < std::ceil(total_pairs / 2)) {
185 current_size = ISize::MakeWH(
186 std::max(current_size.width, current_size.height),
187 Allocation::NextPowerOfTwoSize(
188 std::min(current_size.width, current_size.height) + 1));
189 } else {
190 current_size = ISize::MakeWH(
191 Allocation::NextPowerOfTwoSize(current_size.width + 1),
192 Allocation::NextPowerOfTwoSize(current_size.height + 1));
193 }
194 } while (current_size.width <= max_texture_size.width &&
195 current_size.height <= max_texture_size.height);
196 return ISize{0, 0};
197 }
198
199 static void DrawGlyph(BitmapSTB* bitmap,
200 const ScaledFont& scaled_font,
201 const Glyph& glyph,
202 const Rect& location,
203 bool has_color) {
204 const auto& metrics = scaled_font.font.GetMetrics();
205
206 const impeller::Font& font = scaled_font.font;
207 auto typeface = font.GetTypeface();
208 // We downcast to the correct typeface type to access `stb` specific methods
209 std::shared_ptr<TypefaceSTB> typeface_stb =
210 std::reinterpret_pointer_cast<TypefaceSTB>(typeface);
211 // Conversion factor to scale font size in Points to pixels.
212 // Note this assumes typical DPI.
213 float text_size_pixels = metrics.point_size * TypefaceSTB::kPointsToPixels;
214 float scale_y = stbtt_ScaleForMappingEmToPixels(typeface_stb->GetFontInfo(),
215 text_size_pixels);
216 float scale_x = scale_y;
217
218 auto output = bitmap->GetPixelAddress({static_cast<size_t>(location.GetX()),
219 static_cast<size_t>(location.GetY())});
220 // For Alpha and Signed Distance field bitmaps we can use STB to draw the
221 // Glyph in place
222 if (!has_color || DISABLE_COLOR_FONT_SUPPORT) {
223 stbtt_MakeGlyphBitmap(typeface_stb->GetFontInfo(), output,
224 location.GetWidth(), location.GetHeight(),
225 bitmap->GetRowBytes(), scale_x, scale_y, glyph.index);
226 } else {
227 // But for color bitmaps we need to get the glyph pixels and then carry all
228 // channels into the atlas bitmap. This may not be performant but I'm unsure
229 // of any other approach currently.
230 int glyph_bitmap_width = 0;
231 int glyph_bitmap_height = 0;
232 int glyph_bitmap_xoff = 0;
233 int glyph_bitmap_yoff = 0;
234 auto glyph_pixels = stbtt_GetGlyphBitmap(
235 typeface_stb->GetFontInfo(), scale_x, scale_y, glyph.index,
236 &glyph_bitmap_width, &glyph_bitmap_height, &glyph_bitmap_xoff,
237 &glyph_bitmap_yoff);
238
239 uint8_t* write_pos = output;
240 for (auto y = 0; y < glyph_bitmap_height; ++y) {
241 for (auto x = 0; x < glyph_bitmap_width; ++x) {
242 // Color bitmaps write as White (i.e. what is 0 in an alpha bitmap is
243 // 255 in a color bitmap) But not alpha. Alpha still carries
244 // transparency info in the normal way.
245 // There's some issue with color fonts, in that if the pixel color is
246 // nonzero, the alpha is ignored during rendering. That is, partially
247 // (or fully) transparent pixels with nonzero color are rendered as
248 // fully opaque.
249 uint8_t a = glyph_pixels[x + y * glyph_bitmap_width];
250 uint8_t c = 255 - a;
251
252 // Red channel
253 *write_pos = c;
254 write_pos++;
255 // Green channel
256 *write_pos = c;
257 write_pos++;
258 // Blue channel
259 *write_pos = c;
260 write_pos++;
261 // Alpha channel
262 *write_pos = a;
263 write_pos++;
264 }
265 // next row
266 write_pos = output + (y * bitmap->GetRowBytes());
267 }
268 stbtt_FreeBitmap(glyph_pixels, nullptr);
269 }
270 }
271
272 static bool UpdateAtlasBitmap(const GlyphAtlas& atlas,
273 const std::shared_ptr<BitmapSTB>& bitmap,
274 const std::vector<FontGlyphPair>& new_pairs) {
275 TRACE_EVENT0("impeller", __FUNCTION__);
276 FML_DCHECK(bitmap != nullptr);
277
278 bool has_color = atlas.GetType() == GlyphAtlas::Type::kColorBitmap;
279
280 for (const FontGlyphPair& pair : new_pairs) {
281 auto pos = atlas.FindFontGlyphBounds(pair);
282 if (!pos.has_value()) {
283 continue;
284 }
285 DrawGlyph(bitmap.get(), pair.scaled_font, pair.glyph.glyph,
286 pos.value().first, has_color);
287 }
288 return true;
289 }
290
291 static std::shared_ptr<BitmapSTB> CreateAtlasBitmap(const GlyphAtlas& atlas,
292 const ISize& atlas_size) {
293 TRACE_EVENT0("impeller", __FUNCTION__);
294
295 size_t bytes_per_pixel = 1;
296 if (atlas.GetType() == GlyphAtlas::Type::kColorBitmap &&
297 !DISABLE_COLOR_FONT_SUPPORT) {
298 bytes_per_pixel = kColorFontBitsPerPixel;
299 }
300 auto bitmap = std::make_shared<BitmapSTB>(atlas_size.width, atlas_size.height,
301 bytes_per_pixel);
302
303 bool has_color = atlas.GetType() == GlyphAtlas::Type::kColorBitmap;
304
305 atlas.IterateGlyphs([&bitmap, has_color](const ScaledFont& scaled_font,
306 const SubpixelGlyph& glyph,
307 const Rect& location) -> bool {
308 DrawGlyph(bitmap.get(), scaled_font, glyph.glyph, location, has_color);
309 return true;
310 });
311
312 return bitmap;
313 }
314
315 // static bool UpdateGlyphTextureAtlas(std::shared_ptr<SkBitmap> bitmap,
316 static bool UpdateGlyphTextureAtlas(std::shared_ptr<BitmapSTB>& bitmap,
317 const std::shared_ptr<Allocator>& allocator,
318 std::shared_ptr<BlitPass>& blit_pass,
319 const std::shared_ptr<Texture>& texture) {
320 TRACE_EVENT0("impeller", __FUNCTION__);
321
322 FML_DCHECK(bitmap != nullptr);
323
324 auto texture_descriptor = texture->GetTextureDescriptor();
325
326 auto mapping = std::make_shared<fml::NonOwnedMapping>(
327 reinterpret_cast<const uint8_t*>(bitmap->GetPixels()), // data
328 texture_descriptor.GetByteSizeOfBaseMipLevel() // size
329 // As the bitmap is static in this module I believe we don't need to
330 // specify a release proc.
331 );
332
333 std::shared_ptr<DeviceBuffer> device_buffer =
334 allocator->CreateBufferWithCopy(*mapping);
335 blit_pass->AddCopy(DeviceBuffer::AsBufferView(device_buffer), texture);
336
337 return blit_pass->EncodeCommands(allocator);
338 }
339
340 static std::shared_ptr<Texture> UploadGlyphTextureAtlas(
341 const std::shared_ptr<Allocator>& allocator,
342 std::shared_ptr<BlitPass>& blit_pass,
343 std::shared_ptr<BitmapSTB>& bitmap,
344 const ISize& atlas_size,
345 PixelFormat format) {
346 TRACE_EVENT0("impeller", __FUNCTION__);
347 if (!allocator) {
348 return nullptr;
349 }
350
351 FML_DCHECK(bitmap != nullptr);
352
353 TextureDescriptor texture_descriptor;
354 texture_descriptor.storage_mode = StorageMode::kDevicePrivate;
355 texture_descriptor.format = format;
356 texture_descriptor.size = atlas_size;
357
358 if (bitmap->GetRowBytes() * bitmap->GetHeight() !=
359 texture_descriptor.GetByteSizeOfBaseMipLevel()) {
360 return nullptr;
361 }
362
363 auto texture = allocator->CreateTexture(texture_descriptor);
364 if (!texture || !texture->IsValid()) {
365 return nullptr;
366 }
367 texture->SetLabel("GlyphAtlas");
368
369 std::shared_ptr<fml::NonOwnedMapping> mapping =
370 std::make_shared<fml::NonOwnedMapping>(
371 reinterpret_cast<const uint8_t*>(bitmap->GetPixels()), // data
372 texture_descriptor.GetByteSizeOfBaseMipLevel() // size
373 // As the bitmap is static in this module I believe we don't need to
374 // specify a release proc.
375 );
376 std::shared_ptr<DeviceBuffer> device_buffer =
377 allocator->CreateBufferWithCopy(*mapping);
378 blit_pass->AddCopy(DeviceBuffer::AsBufferView(device_buffer), texture);
379 if (!blit_pass->EncodeCommands(allocator)) {
380 return nullptr;
381 }
382
383 return texture;
384 }
385
386 static Rect ComputeGlyphSize(const ScaledFont& font,
387 const SubpixelGlyph& glyph) {
388 std::shared_ptr<TypefaceSTB> typeface_stb =
389 std::reinterpret_pointer_cast<TypefaceSTB>(font.font.GetTypeface());
390 float scale = stbtt_ScaleForMappingEmToPixels(
391 typeface_stb->GetFontInfo(),
392 font.font.GetMetrics().point_size * TypefaceSTB::kPointsToPixels);
393 int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
394 stbtt_GetGlyphBitmapBox(typeface_stb->GetFontInfo(), glyph.glyph.index, scale,
395 scale, &x0, &y0, &x1, &y1);
396 return Rect::MakeLTRB(0, 0, x1 - x0, y1 - y0);
397 }
398
399 std::shared_ptr<GlyphAtlas> TypographerContextSTB::CreateGlyphAtlas(
400 Context& context,
401 GlyphAtlas::Type type,
402 HostBuffer& host_buffer,
403 const std::shared_ptr<GlyphAtlasContext>& atlas_context,
404 const FontGlyphMap& font_glyph_map) const {
405 TRACE_EVENT0("impeller", __FUNCTION__);
406 if (!IsValid()) {
407 return nullptr;
408 }
409 auto& atlas_context_stb = GlyphAtlasContextSTB::Cast(*atlas_context);
410 std::shared_ptr<GlyphAtlas> last_atlas = atlas_context->GetGlyphAtlas();
411
412 if (font_glyph_map.empty()) {
413 return last_atlas;
414 }
415
416 std::shared_ptr<CommandBuffer> cmd_buffer = context.CreateCommandBuffer();
417 std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
418
419 fml::ScopedCleanupClosure closure([&cmd_buffer, &context]() {
420 context.GetCommandQueue()->Submit({std::move(cmd_buffer)});
421 });
422
423 // ---------------------------------------------------------------------------
424 // Step 1: Determine if the atlas type and font glyph pairs are compatible
425 // with the current atlas and reuse if possible.
426 // ---------------------------------------------------------------------------
427 std::vector<FontGlyphPair> new_glyphs;
428 std::vector<Rect> new_sizes;
429 for (const auto& font_value : font_glyph_map) {
430 const ScaledFont& scaled_font = font_value.first;
431 const FontGlyphAtlas* font_glyph_atlas =
432 last_atlas->GetFontGlyphAtlas(scaled_font.font, scaled_font.scale);
433 if (font_glyph_atlas) {
434 for (const SubpixelGlyph& glyph : font_value.second) {
435 if (!font_glyph_atlas->FindGlyphBounds(glyph)) {
436 new_glyphs.emplace_back(scaled_font, glyph);
437 new_sizes.push_back(ComputeGlyphSize(scaled_font, glyph));
438 }
439 }
440 } else {
441 for (const SubpixelGlyph& glyph : font_value.second) {
442 new_glyphs.emplace_back(scaled_font, glyph);
443 new_sizes.push_back(ComputeGlyphSize(scaled_font, glyph));
444 }
445 }
446 }
447 if (last_atlas->GetType() == type && new_glyphs.size() == 0) {
448 return last_atlas;
449 }
450
451 // ---------------------------------------------------------------------------
452 // Step 2: Determine if the additional missing glyphs can be appended to the
453 // existing bitmap without recreating the atlas. This requires that
454 // the type is identical.
455 // ---------------------------------------------------------------------------
456 std::vector<Rect> glyph_positions;
457 if (last_atlas->GetType() == type &&
458 CanAppendToExistingAtlas(last_atlas, new_glyphs, glyph_positions,
459 atlas_context->GetAtlasSize(),
460 atlas_context->GetRectPacker())) {
461 // The old bitmap will be reused and only the additional glyphs will be
462 // added.
463
464 // ---------------------------------------------------------------------------
465 // Step 3a: Record the positions in the glyph atlas of the newly added
466 // glyphs.
467 // ---------------------------------------------------------------------------
468 for (size_t i = 0, count = glyph_positions.size(); i < count; i++) {
469 last_atlas->AddTypefaceGlyphPositionAndBounds(
470 new_glyphs[i], glyph_positions[i], new_sizes[i]);
471 }
472
473 // ---------------------------------------------------------------------------
474 // Step 4a: Draw new font-glyph pairs into the existing bitmap.
475 // ---------------------------------------------------------------------------
476 // auto bitmap = atlas_context->GetBitmap();
477 auto bitmap = atlas_context_stb.GetBitmap();
478 if (!UpdateAtlasBitmap(*last_atlas, bitmap, new_glyphs)) {
479 return nullptr;
480 }
481
482 // ---------------------------------------------------------------------------
483 // Step 5a: Update the existing texture with the updated bitmap.
484 // ---------------------------------------------------------------------------
485 if (!UpdateGlyphTextureAtlas(bitmap, context.GetResourceAllocator(),
486 blit_pass, last_atlas->GetTexture())) {
487 return nullptr;
488 }
489 return last_atlas;
490 }
491 // A new glyph atlas must be created.
492
493 // ---------------------------------------------------------------------------
494 // Step 3b: Get the optimum size of the texture atlas.
495 // ---------------------------------------------------------------------------
496 std::vector<FontGlyphPair> font_glyph_pairs;
497 font_glyph_pairs.reserve(std::accumulate(
498 font_glyph_map.begin(), font_glyph_map.end(), 0,
499 [](const int a, const auto& b) { return a + b.second.size(); }));
500 for (const auto& font_value : font_glyph_map) {
501 const ScaledFont& scaled_font = font_value.first;
502 for (const SubpixelGlyph& glyph : font_value.second) {
503 font_glyph_pairs.push_back({scaled_font, glyph});
504 }
505 }
506 auto glyph_atlas = std::make_shared<GlyphAtlas>(type);
507 auto atlas_size = OptimumAtlasSizeForFontGlyphPairs(
508 font_glyph_pairs, //
509 glyph_positions, //
510 atlas_context, //
511 type, //
512 context.GetResourceAllocator()->GetMaxTextureSizeSupported() //
513 );
514
515 atlas_context->UpdateGlyphAtlas(glyph_atlas, atlas_size, 0);
516 if (atlas_size.IsEmpty()) {
517 return nullptr;
518 }
519
520 // ---------------------------------------------------------------------------
521 // Step 4b: Find location of font-glyph pairs in the atlas. We have this from
522 // the last step. So no need to do create another rect packer. But just do a
523 // sanity check of counts. This could also be just an assertion as only a
524 // construction issue would cause such a failure.
525 // ---------------------------------------------------------------------------
526 if (glyph_positions.size() != font_glyph_pairs.size()) {
527 return nullptr;
528 }
529
530 // ---------------------------------------------------------------------------
531 // Step 5b: Record the positions in the glyph atlas.
532 // ---------------------------------------------------------------------------
533 {
534 size_t i = 0;
535 for (auto it = font_glyph_pairs.begin(); it != font_glyph_pairs.end();
536 ++i, ++it) {
537 glyph_atlas->AddTypefaceGlyphPositionAndBounds(*it, glyph_positions[i],
538 new_sizes[i]);
539 }
540 }
541
542 // ---------------------------------------------------------------------------
543 // Step 6b: Draw font-glyph pairs in the correct spot in the atlas.
544 // ---------------------------------------------------------------------------
545 auto bitmap = CreateAtlasBitmap(*glyph_atlas, atlas_size);
546 if (!bitmap) {
547 return nullptr;
548 }
549 atlas_context_stb.UpdateBitmap(bitmap);
550
551 // ---------------------------------------------------------------------------
552 // Step 7b: Upload the atlas as a texture.
553 // ---------------------------------------------------------------------------
554 PixelFormat format;
555 switch (type) {
556 case GlyphAtlas::Type::kAlphaBitmap:
557 format = context.GetCapabilities()->GetDefaultGlyphAtlasFormat();
558 break;
559 case GlyphAtlas::Type::kColorBitmap:
560 format = DISABLE_COLOR_FONT_SUPPORT
561 ? context.GetCapabilities()->GetDefaultGlyphAtlasFormat()
562 : PixelFormat::kR8G8B8A8UNormInt;
563 break;
564 }
565 auto texture = UploadGlyphTextureAtlas(context.GetResourceAllocator(),
566 blit_pass, bitmap, atlas_size, format);
567 if (!texture) {
568 return nullptr;
569 }
570
571 // ---------------------------------------------------------------------------
572 // Step 8b: Record the texture in the glyph atlas.
573 // ---------------------------------------------------------------------------
574 glyph_atlas->SetTexture(std::move(texture));
575
576 return glyph_atlas;
577 }
578
579 } // namespace impeller
impeller::DeviceBuffer::AsBufferView
static BufferView AsBufferView(std::shared_ptr< DeviceBuffer > buffer)
Create a buffer view of this entire buffer.
Definition: device_buffer.cc:18
impeller::ISize
ISize64 ISize
Definition: size.h:140
impeller::CreateAtlasBitmap
static std::shared_ptr< BitmapSTB > CreateAtlasBitmap(const GlyphAtlas &atlas, const ISize &atlas_size)
Definition: typographer_context_stb.cc:291
impeller::GlyphAtlas::Type::kColorBitmap
@ kColorBitmap
typeface_stb.h
impeller::TypographerContextSTB::CreateGlyphAtlasContext
std::shared_ptr< GlyphAtlasContext > CreateGlyphAtlasContext(GlyphAtlas::Type type) const override
Definition: typographer_context_stb.cc:41
impeller::TypographerContext
The graphics context necessary to render text.
Definition: typographer_context.h:22
impeller::Font
Describes a typeface along with any modifications to its intrinsic properties.
Definition: font.h:35
impeller::UpdateGlyphTextureAtlas
static bool UpdateGlyphTextureAtlas(std::shared_ptr< BitmapSTB > &bitmap, const std::shared_ptr< Allocator > &allocator, std::shared_ptr< BlitPass > &blit_pass, const std::shared_ptr< Texture > &texture)
Definition: typographer_context_stb.cc:316
impeller::GlyphAtlas::Type::kAlphaBitmap
@ kAlphaBitmap
impeller::UpdateAtlasBitmap
static bool UpdateAtlasBitmap(const GlyphAtlas &atlas, std::shared_ptr< BlitPass > &blit_pass, HostBuffer &host_buffer, const std::shared_ptr< Texture > &texture, const std::vector< FontGlyphPair > &new_pairs, size_t start_index, size_t end_index)
Definition: typographer_context_skia.cc:252
allocation.h
impeller::TRect< Scalar >::MakeXYWH
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:136
device_buffer.h
impeller::FontGlyphAtlas
An object that can look up glyph locations within the GlyphAtlas for a particular typeface.
Definition: glyph_atlas.h:200
impeller::TypographerContextSTB::TypographerContextSTB
TypographerContextSTB()
Definition: typographer_context_stb.cc:36
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::HostBuffer
Definition: host_buffer.h:28
impeller::TextureDescriptor::format
PixelFormat format
Definition: texture_descriptor.h:41
impeller::ScaledFont::font
Font font
Definition: font_glyph_pair.h:33
impeller::PixelFormat::kR8G8B8A8UNormInt
@ kR8G8B8A8UNormInt
impeller::SubpixelGlyph
A glyph and its subpixel position.
Definition: font_glyph_pair.h:40
impeller::UploadGlyphTextureAtlas
static std::shared_ptr< Texture > UploadGlyphTextureAtlas(const std::shared_ptr< Allocator > &allocator, std::shared_ptr< BlitPass > &blit_pass, std::shared_ptr< BitmapSTB > &bitmap, const ISize &atlas_size, PixelFormat format)
Definition: typographer_context_stb.cc:340
impeller::IPoint16::x
int16_t x() const
Definition: rectangle_packer.h:16
impeller::TRect::GetX
constexpr Type GetX() const
Returns the X coordinate of the upper left corner, equivalent to |GetOrigin().x|.
Definition: rect.h:323
impeller::BitmapSTB::GetPixelAddress
uint8_t * GetPixelAddress(TPoint< size_t > coords)
Definition: glyph_atlas_context_stb.cc:23
impeller::BitmapSTB
Definition: glyph_atlas_context_stb.h:13
impeller::TRect::GetHeight
constexpr Type GetHeight() const
Returns the height of the rectangle, equivalent to |GetSize().height|.
Definition: rect.h:337
kColorFontBitsPerPixel
constexpr auto kColorFontBitsPerPixel
Definition: typographer_context_stb.cc:23
impeller::IPoint16::y
int16_t y() const
Definition: rectangle_packer.h:17
impeller::TypographerContextSTB::CreateGlyphAtlas
std::shared_ptr< GlyphAtlas > CreateGlyphAtlas(Context &context, GlyphAtlas::Type type, HostBuffer &host_buffer, const std::shared_ptr< GlyphAtlasContext > &atlas_context, const FontGlyphMap &font_glyph_map) const override
Definition: typographer_context_stb.cc:399
impeller::PixelFormat
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition: formats.h:99
impeller::Font::GetTypeface
const std::shared_ptr< Typeface > & GetTypeface() const
The typeface whose intrinsic properties this font modifies.
Definition: font.cc:27
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_stb.cc:102
impeller::Glyph
The glyph index in the typeface.
Definition: glyph.h:16
impeller::TSize
Definition: size.h:19
impeller::FontGlyphPair::glyph
const SubpixelGlyph & glyph
Definition: font_glyph_pair.h:64
impeller::TypographerContextSTB::~TypographerContextSTB
~TypographerContextSTB() override
impeller::BitmapSTB::GetRowBytes
size_t GetRowBytes() const
Definition: glyph_atlas_context_stb.cc:30
impeller::FontGlyphPair::scaled_font
const ScaledFont & scaled_font
Definition: font_glyph_pair.h:63
impeller::GlyphAtlas::GetType
Type GetType() const
Describes how the glyphs are represented in the texture.
Definition: glyph_atlas.cc:54
impeller::StorageMode::kDevicePrivate
@ kDevicePrivate
impeller::TRect::GetWidth
constexpr Type GetWidth() const
Returns the width of the rectangle, equivalent to |GetSize().width|.
Definition: rect.h:331
glyph_atlas_context_stb.h
impeller::GlyphAtlas::Type
Type
Describes how the glyphs are represented in the texture.
Definition: glyph_atlas.h:31
impeller::FontGlyphMap
std::unordered_map< ScaledFont, std::unordered_set< SubpixelGlyph > > FontGlyphMap
Definition: font_glyph_pair.h:54
font_glyph_pair.h
impeller::TypographerContextSTB::Make
static std::unique_ptr< TypographerContext > Make()
Definition: typographer_context_stb.cc:32
type
GLenum type
Definition: blit_command_gles.cc:126
impeller::SubpixelGlyph::glyph
Glyph glyph
Definition: font_glyph_pair.h:41
impeller::Font::Metrics::point_size
Scalar point_size
Definition: font.h:48
impeller::RectanglePacker::Factory
static std::shared_ptr< RectanglePacker > Factory(int width, int height)
Return an empty packer with area specified by width and height.
Definition: rectangle_packer.cc:174
impeller::Glyph::index
uint16_t index
Definition: glyph.h:22
impeller::Context::CreateCommandBuffer
virtual std::shared_ptr< CommandBuffer > CreateCommandBuffer() const =0
Create a new command buffer. Command buffers can be used to encode graphics, blit,...
impeller::Context::GetCommandQueue
virtual std::shared_ptr< CommandQueue > GetCommandQueue() const =0
Return the graphics queue for submitting command buffers.
impeller::FontGlyphPair
A font along with a glyph in that font rendered at a particular scale and subpixel position.
Definition: font_glyph_pair.h:60
impeller::Font::GetMetrics
const Metrics & GetMetrics() const
Definition: font.cc:45
impeller::kPadding
constexpr auto kPadding
Definition: typographer_context_skia.cc:50
impeller::TSize::width
Type width
Definition: size.h:22
impeller::TextureDescriptor::size
ISize size
Definition: texture_descriptor.h:42
impeller::ScaledFont::scale
Scalar scale
Definition: font_glyph_pair.h:34
allocator.h
impeller::GlyphAtlas
A texture containing the bitmap representation of glyphs in different fonts along with the ability to...
Definition: glyph_atlas.h:27
impeller::FontGlyphAtlas::FindGlyphBounds
std::optional< std::pair< Rect, Rect > > FindGlyphBounds(const SubpixelGlyph &glyph) const
Find the location of a glyph in the atlas.
Definition: glyph_atlas.cc:119
impeller::Context
To do anything rendering related with Impeller, you need a context.
Definition: context.h:45
impeller::TextureDescriptor::GetByteSizeOfBaseMipLevel
constexpr size_t GetByteSizeOfBaseMipLevel() const
Definition: texture_descriptor.h:48
impeller::TypefaceSTB::kPointsToPixels
static constexpr float kPointsToPixels
Definition: typeface_stb.h:20
impeller::GlyphAtlas::FindFontGlyphBounds
std::optional< std::pair< Rect, Rect > > FindFontGlyphBounds(const FontGlyphPair &pair) const
Find the location of a specific font-glyph pair in the atlas.
Definition: glyph_atlas.cc:73
DISABLE_COLOR_FONT_SUPPORT
#define DISABLE_COLOR_FONT_SUPPORT
Definition: typographer_context_stb.cc:21
impeller::saturated::b
SI b
Definition: saturated_math.h:87
impeller::BackendCast< GlyphAtlasContextSTB, GlyphAtlasContext >::Cast
static GlyphAtlasContextSTB & Cast(GlyphAtlasContext &base)
Definition: backend_cast.h:13
impeller::IPoint16
Definition: rectangle_packer.h:15
scale
const Scalar scale
Definition: stroke_path_geometry.cc:308
impeller::DrawGlyph
static void DrawGlyph(SkCanvas *canvas, const ScaledFont &scaled_font, const SubpixelGlyph &glyph, const Rect &scaled_bounds, const GlyphProperties &prop, bool has_color)
Definition: typographer_context_skia.cc:209
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_stb.cc:160
impeller::ComputeGlyphSize
static Rect ComputeGlyphSize(const SkFont &font, const SubpixelGlyph &glyph, Scalar scale)
Definition: typographer_context_skia.cc:322
impeller::TextureDescriptor::storage_mode
StorageMode storage_mode
Definition: texture_descriptor.h:39
impeller::TSize::height
Type height
Definition: size.h:23
typographer_context_stb.h
impeller::TRect< Scalar >::MakeLTRB
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129
impeller::TextureDescriptor
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
Definition: texture_descriptor.h:38
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::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:327
impeller
Definition: aiks_blend_unittests.cc:18
impeller::Context::GetResourceAllocator
virtual std::shared_ptr< Allocator > GetResourceAllocator() const =0
Returns the allocator used to create textures and buffers on the device.
impeller::PairsFitInAtlasOfSize
static size_t PairsFitInAtlasOfSize(const std::vector< FontGlyphPair > &pairs, const ISize &atlas_size, std::vector< Rect > &glyph_positions, const std::vector< Rect > &glyph_sizes, int64_t height_adjustment, const std::shared_ptr< RectanglePacker > &rect_packer, size_t start_index)
Definition: typographer_context_skia.cc:138
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:98
impeller::ScaledFont
A font and a scale. Used as a key that represents a typeface within a glyph atlas.
Definition: font_glyph_pair.h:32
impeller::TypographerContext::IsValid
virtual bool IsValid() const
Definition: typographer_context.cc:17