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