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 
6 
7 #include <numeric>
8 #include <utility>
9 
10 #include "flutter/fml/logging.h"
11 #include "flutter/fml/trace_event.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 
35 
37 
38 std::shared_ptr<GlyphAtlasContext>
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.size * 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 
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 =
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 
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),
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.origin.x / scaled_font.scale,
162  location.origin.y / scaled_font.scale);
163  SkGlyphID glyph_id = glyph.index;
164 
165  SkFont sk_font(
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()) {
223  image_info = SkImageInfo::MakeA8(atlas_size.width, atlas_size.height);
224  break;
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  // ---------------------------------------------------------------------------
450  // Step 7b: Upload the atlas as a texture.
451  // ---------------------------------------------------------------------------
452  PixelFormat format;
453  switch (type) {
455  format = PixelFormat::kA8UNormInt;
456  break;
459  break;
460  }
461  auto texture = UploadGlyphTextureAtlas(context.GetResourceAllocator(), bitmap,
462  atlas_size, format);
463  if (!texture) {
464  return nullptr;
465  }
466 
467  // ---------------------------------------------------------------------------
468  // Step 8b: Record the texture in the glyph atlas.
469  // ---------------------------------------------------------------------------
470  glyph_atlas->SetTexture(std::move(texture));
471 
472  return glyph_atlas;
473 }
474 
475 } // namespace impeller
impeller::GlyphAtlas::Type::kColorBitmap
@ kColorBitmap
glyph_atlas_context_skia.h
impeller::TRect::size
TSize< Type > size
Definition: rect.h:24
impeller::TPoint::y
Type y
Definition: point.h:24
impeller::TypographerContextSkia::CreateGlyphAtlasContext
std::shared_ptr< GlyphAtlasContext > CreateGlyphAtlasContext() const override
Definition: typographer_context_skia.cc:39
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:47
impeller::FontGlyphAtlas
An object that can look up glyph locations within the GlyphAtlas for a particular typeface.
Definition: glyph_atlas.h:179
impeller::Allocation::NextPowerOfTwoSize
static uint32_t NextPowerOfTwoSize(uint32_t x)
Definition: allocation.cc:42
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:42
impeller::ScaledFont::font
Font font
Definition: font_glyph_pair.h:24
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:91
impeller::FontGlyphMap
std::unordered_map< ScaledFont, std::unordered_set< Glyph > > FontGlyphMap
Definition: font_glyph_pair.h:28
impeller::PixelFormat::kR8G8B8A8UNormInt
@ kR8G8B8A8UNormInt
impeller::IPoint16::x
int16_t x() const
Definition: rectangle_packer.h:14
typographer_context.h
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:15
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:19
impeller::TSize
Definition: size.h:18
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:38
impeller::TRect::GetLeft
constexpr auto GetLeft() const
Definition: rect.h:137
rectangle_packer.h
impeller::FontGlyphPair::scaled_font
const ScaledFont & scaled_font
Definition: font_glyph_pair.h:37
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:272
impeller::TRect::origin
TPoint< Type > origin
Definition: rect.h:23
impeller::Glyph::index
uint16_t index
Definition: glyph.h:25
impeller::FontGlyphPair
A font along with a glyph in that font rendered at a particular scale.
Definition: font_glyph_pair.h:34
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:21
impeller::TPoint::x
Type x
Definition: point.h:23
impeller::ISize
TSize< int64_t > ISize
Definition: size.h:136
impeller::TextureDescriptor::size
ISize size
Definition: texture_descriptor.h:43
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:25
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::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:50
impeller::TypographerContextSkia::~TypographerContextSkia
~TypographerContextSkia() override
impeller::BackendCast< TypefaceSkia, Typeface >::Cast
static TypefaceSkia & Cast(Typeface &base)
Definition: backend_cast.h:14
impeller::IPoint16
Definition: rectangle_packer.h:13
impeller::PixelFormat::kA8UNormInt
@ kA8UNormInt
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:40
impeller::TSize::height
Type height
Definition: size.h:22
impeller::TextureDescriptor
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
Definition: texture_descriptor.h:39
impeller::TSize::IsEmpty
constexpr bool IsEmpty() const
Definition: size.h:105
impeller::PixelFormat
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition: formats.h:94
impeller::TSize< int64_t >::MakeWH
static constexpr TSize MakeWH(Type width, Type height)
Definition: size.h:33
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:144
impeller::Glyph::bounds
Rect bounds
Visibility coverage of the glyph in text run space (relative to the baseline, no scaling applied).
Definition: glyph.h:36
impeller::TypographerContextSkia::Make
static std::shared_ptr< TypographerContext > Make()
Definition: typographer_context_skia.cc:30
impeller::TRect
Definition: rect.h:20
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:23
impeller::TypographerContext::IsValid
virtual bool IsValid() const
Definition: typographer_context.cc:17