Flutter Engine
The Flutter Engine
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 <cstddef>
8#include <memory>
9#include <numeric>
10#include <utility>
11#include <vector>
12
13#include "flutter/fml/logging.h"
14#include "flutter/fml/trace_event.h"
15#include "fml/closure.h"
16
37#include "include/core/SkSize.h"
38
44
45namespace impeller {
46
47// TODO(bdero): We might be able to remove this per-glyph padding if we fix
48// the underlying causes of the overlap.
49// https://github.com/flutter/flutter/issues/114563
50constexpr auto kPadding = 2;
51
52namespace {
53SkPaint::Cap ToSkiaCap(Cap cap) {
54 switch (cap) {
55 case Cap::kButt:
56 return SkPaint::Cap::kButt_Cap;
57 case Cap::kRound:
58 return SkPaint::Cap::kRound_Cap;
59 case Cap::kSquare:
60 return SkPaint::Cap::kSquare_Cap;
61 }
63}
64
65SkPaint::Join ToSkiaJoin(Join join) {
66 switch (join) {
67 case Join::kMiter:
68 return SkPaint::Join::kMiter_Join;
69 case Join::kRound:
70 return SkPaint::Join::kRound_Join;
71 case Join::kBevel:
72 return SkPaint::Join::kBevel_Join;
73 }
75}
76} // namespace
77
78std::shared_ptr<TypographerContext> TypographerContextSkia::Make() {
79 return std::make_shared<TypographerContextSkia>();
80}
81
83
85
86std::shared_ptr<GlyphAtlasContext>
88 return std::make_shared<GlyphAtlasContext>(type);
89}
90
92 switch (atlas.GetType()) {
94 return SkImageInfo::MakeA8(SkISize{static_cast<int32_t>(size.width),
95 static_cast<int32_t>(size.height)});
97 return SkImageInfo::MakeN32Premul(size.width, size.height);
98 }
100}
101
102/// Append as many glyphs to the texture as will fit, and return the first index
103/// of [extra_pairs] that did not fit.
105 const std::shared_ptr<GlyphAtlas>& atlas,
106 const std::vector<FontGlyphPair>& extra_pairs,
107 std::vector<Rect>& glyph_positions,
108 const std::vector<Rect>& glyph_sizes,
109 ISize atlas_size,
110 int64_t height_adjustment,
111 const std::shared_ptr<RectanglePacker>& rect_packer) {
112 TRACE_EVENT0("impeller", __FUNCTION__);
113 if (!rect_packer || atlas_size.IsEmpty()) {
114 return 0;
115 }
116
117 for (size_t i = 0; i < extra_pairs.size(); i++) {
118 ISize glyph_size = ISize::Ceil(glyph_sizes[i].GetSize());
119 IPoint16 location_in_atlas;
120 if (!rect_packer->AddRect(glyph_size.width + kPadding, //
121 glyph_size.height + kPadding, //
122 &location_in_atlas //
123 )) {
124 return i;
125 }
126 // Position the glyph in the center of the 1px padding.
127 glyph_positions.push_back(Rect::MakeXYWH(
128 location_in_atlas.x() + 1, //
129 location_in_atlas.y() + height_adjustment + 1, //
130 glyph_size.width, //
131 glyph_size.height //
132 ));
133 }
134
135 return extra_pairs.size();
136}
137
139 const std::vector<FontGlyphPair>& pairs,
140 const ISize& atlas_size,
141 std::vector<Rect>& glyph_positions,
142 const std::vector<Rect>& glyph_sizes,
143 int64_t height_adjustment,
144 const std::shared_ptr<RectanglePacker>& rect_packer,
145 size_t start_index) {
146 FML_DCHECK(!atlas_size.IsEmpty());
147
148 for (size_t i = start_index; i < pairs.size(); i++) {
149 ISize glyph_size = ISize::Ceil(glyph_sizes[i].GetSize());
150 IPoint16 location_in_atlas;
151 if (!rect_packer->AddRect(glyph_size.width + kPadding, //
152 glyph_size.height + kPadding, //
153 &location_in_atlas //
154 )) {
155 return i;
156 }
157 glyph_positions.push_back(Rect::MakeXYWH(
158 location_in_atlas.x() + 1, //
159 location_in_atlas.y() + height_adjustment + 1, //
160 glyph_size.width, //
161 glyph_size.height //
162 ));
163 }
164
165 return pairs.size();
166}
167
169 const std::shared_ptr<GlyphAtlasContext>& atlas_context,
170 const std::vector<FontGlyphPair>& extra_pairs,
171 std::vector<Rect>& glyph_positions,
172 const std::vector<Rect>& glyph_sizes,
173 size_t glyph_index_start,
174 int64_t max_texture_height) {
175 // Because we can't grow the skyline packer horizontally, pick a reasonable
176 // large width for all atlases.
177 static constexpr int64_t kAtlasWidth = 4096;
178 static constexpr int64_t kMinAtlasHeight = 1024;
179
180 ISize current_size = ISize(kAtlasWidth, kMinAtlasHeight);
181 if (atlas_context->GetAtlasSize().height > current_size.height) {
182 current_size.height = atlas_context->GetAtlasSize().height * 2;
183 }
184
185 auto height_adjustment = atlas_context->GetAtlasSize().height;
186 while (current_size.height <= max_texture_height) {
187 std::shared_ptr<RectanglePacker> rect_packer;
188 if (atlas_context->GetRectPacker() || glyph_index_start) {
189 rect_packer = RectanglePacker::Factory(
190 kAtlasWidth,
191 current_size.height - atlas_context->GetAtlasSize().height);
192 } else {
193 rect_packer = RectanglePacker::Factory(kAtlasWidth, current_size.height);
194 }
195 glyph_positions.erase(glyph_positions.begin() + glyph_index_start,
196 glyph_positions.end());
197 atlas_context->UpdateRectPacker(rect_packer);
198 auto next_index = PairsFitInAtlasOfSize(
199 extra_pairs, current_size, glyph_positions, glyph_sizes,
200 height_adjustment, rect_packer, glyph_index_start);
201 if (next_index == extra_pairs.size()) {
202 return current_size;
203 }
204 current_size = ISize(current_size.width, current_size.height * 2);
205 }
206 return {};
207}
208
209static void DrawGlyph(SkCanvas* canvas,
210 const ScaledFont& scaled_font,
211 const SubpixelGlyph& glyph,
212 const Rect& scaled_bounds,
213 const GlyphProperties& prop,
214 bool has_color) {
215 const auto& metrics = scaled_font.font.GetMetrics();
216 SkPoint position = SkPoint::Make(1, 1);
217 SkGlyphID glyph_id = glyph.glyph.index;
218
219 SkFont sk_font(
221 metrics.point_size, metrics.scaleX, metrics.skewX);
224 sk_font.setEmbolden(metrics.embolden);
225 sk_font.setSubpixel(true);
226 sk_font.setSize(sk_font.getSize() * scaled_font.scale);
227
228 auto glyph_color =
229 has_color ? glyph.properties.color.ToARGB() : SK_ColorBLACK;
230
231 SkPaint glyph_paint;
232 glyph_paint.setColor(glyph_color);
233 glyph_paint.setBlendMode(SkBlendMode::kSrc);
234 if (prop.stroke) {
235 glyph_paint.setStroke(true);
236 glyph_paint.setStrokeWidth(prop.stroke_width * scaled_font.scale);
237 glyph_paint.setStrokeCap(ToSkiaCap(glyph.properties.stroke_cap));
238 glyph_paint.setStrokeJoin(ToSkiaJoin(glyph.properties.stroke_join));
239 glyph_paint.setStrokeMiter(prop.stroke_miter * scaled_font.scale);
240 }
241 canvas->translate(glyph.subpixel_offset.x, glyph.subpixel_offset.y);
242 canvas->drawGlyphs(1u, // count
243 &glyph_id, // glyphs
244 &position, // positions
245 SkPoint::Make(-scaled_bounds.GetLeft(),
246 -scaled_bounds.GetTop()), // origin
247 sk_font, // font
248 glyph_paint // paint
249 );
250}
251
253 std::shared_ptr<BlitPass>& blit_pass,
254 HostBuffer& host_buffer,
255 const std::shared_ptr<Texture>& texture,
256 const std::vector<FontGlyphPair>& new_pairs,
257 size_t start_index,
258 size_t end_index) {
259 TRACE_EVENT0("impeller", __FUNCTION__);
260
261 bool has_color = atlas.GetType() == GlyphAtlas::Type::kColorBitmap;
262
263 for (size_t i = start_index; i < end_index; i++) {
264 const FontGlyphPair& pair = new_pairs[i];
265 auto data = atlas.FindFontGlyphBounds(pair);
266 if (!data.has_value()) {
267 continue;
268 }
269 auto [pos, bounds] = data.value();
270 Size size = pos.GetSize();
271 if (size.IsEmpty()) {
272 continue;
273 }
274 // The uploaded bitmap is expanded by 1px of padding
275 // on each side.
276 size.width += 2;
277 size.height += 2;
278
280 bitmap.setInfo(GetImageInfo(atlas, size));
281 if (!bitmap.tryAllocPixels()) {
282 return false;
283 }
284
285 auto surface = SkSurfaces::WrapPixels(bitmap.pixmap());
286 if (!surface) {
287 return false;
288 }
289 auto canvas = surface->getCanvas();
290 if (!canvas) {
291 return false;
292 }
293
294 DrawGlyph(canvas, pair.scaled_font, pair.glyph, bounds,
295 pair.glyph.properties, has_color);
296
297 // Writing to a malloc'd buffer and then copying to the staging buffers
298 // benchmarks as substantially faster on a number of Android devices.
299 BufferView buffer_view = host_buffer.Emplace(
300 bitmap.getAddr(0, 0),
302 atlas.GetTexture()->GetTextureDescriptor().format),
304
305 // convert_to_read is set to false so that the texture remains in a transfer
306 // dst layout until we finish writing to it below. This only has an impact
307 // on Vulkan where we are responsible for managing image layouts.
308 if (!blit_pass->AddCopy(std::move(buffer_view), //
309 texture, //
310 IRect::MakeXYWH(pos.GetLeft() - 1, pos.GetTop() - 1,
311 size.width, size.height), //
312 /*label=*/"", //
313 /*slice=*/0, //
314 /*convert_to_read=*/false //
315 )) {
316 return false;
317 }
318 }
319 return blit_pass->ConvertTextureToShaderRead(texture);
320}
321
323 const SubpixelGlyph& glyph,
324 Scalar scale) {
325 SkRect scaled_bounds;
326 SkPaint glyph_paint;
327 if (glyph.properties.stroke) {
328 glyph_paint.setStroke(true);
329 glyph_paint.setStrokeWidth(glyph.properties.stroke_width * scale);
330 glyph_paint.setStrokeCap(ToSkiaCap(glyph.properties.stroke_cap));
331 glyph_paint.setStrokeJoin(ToSkiaJoin(glyph.properties.stroke_join));
332 glyph_paint.setStrokeMiter(glyph.properties.stroke_miter * scale);
333 }
334 font.getBounds(&glyph.glyph.index, 1, &scaled_bounds, &glyph_paint);
335
336 // Expand the bounds of glyphs at subpixel offsets by 2 in the x direction.
337 Scalar adjustment = 0.0;
338 if (glyph.subpixel_offset != Point(0, 0)) {
339 adjustment = 1.0;
340 }
341 return Rect::MakeLTRB(scaled_bounds.fLeft - adjustment, scaled_bounds.fTop,
342 scaled_bounds.fRight + adjustment,
343 scaled_bounds.fBottom);
344};
345
347 Context& context,
349 HostBuffer& host_buffer,
350 const std::shared_ptr<GlyphAtlasContext>& atlas_context,
351 const FontGlyphMap& font_glyph_map) const {
352 TRACE_EVENT0("impeller", __FUNCTION__);
353 if (!IsValid()) {
354 return nullptr;
355 }
356 std::shared_ptr<GlyphAtlas> last_atlas = atlas_context->GetGlyphAtlas();
357 FML_DCHECK(last_atlas->GetType() == type);
358
359 if (font_glyph_map.empty()) {
360 return last_atlas;
361 }
362
363 // ---------------------------------------------------------------------------
364 // Step 1: Determine if the atlas type and font glyph pairs are compatible
365 // with the current atlas and reuse if possible. For each new font and
366 // glyph pair, compute the glyph size at scale.
367 // ---------------------------------------------------------------------------
368 std::vector<Rect> glyph_sizes;
369 std::vector<FontGlyphPair> new_glyphs;
370 for (const auto& font_value : font_glyph_map) {
371 const ScaledFont& scaled_font = font_value.first;
372 const FontGlyphAtlas* font_glyph_atlas =
373 last_atlas->GetFontGlyphAtlas(scaled_font.font, scaled_font.scale);
374
375 auto metrics = scaled_font.font.GetMetrics();
376
377 SkFont sk_font(
379 metrics.point_size, metrics.scaleX, metrics.skewX);
382 sk_font.setEmbolden(metrics.embolden);
383 // Rather than computing the bounds at the requested point size and scaling
384 // up the bounds, we scale up the font size and request the bounds. This
385 // seems to give more accurate bounds information.
386 sk_font.setSize(sk_font.getSize() * scaled_font.scale);
387 sk_font.setSubpixel(true);
388
389 if (font_glyph_atlas) {
390 for (const SubpixelGlyph& glyph : font_value.second) {
391 if (!font_glyph_atlas->FindGlyphBounds(glyph)) {
392 new_glyphs.emplace_back(scaled_font, glyph);
393 glyph_sizes.push_back(
394 ComputeGlyphSize(sk_font, glyph, scaled_font.scale));
395 }
396 }
397 } else {
398 for (const SubpixelGlyph& glyph : font_value.second) {
399 new_glyphs.emplace_back(scaled_font, glyph);
400 glyph_sizes.push_back(
401 ComputeGlyphSize(sk_font, glyph, scaled_font.scale));
402 }
403 }
404 }
405 if (new_glyphs.size() == 0) {
406 return last_atlas;
407 }
408
409 // ---------------------------------------------------------------------------
410 // Step 2: Determine if the additional missing glyphs can be appended to the
411 // existing bitmap without recreating the atlas.
412 // ---------------------------------------------------------------------------
413 std::vector<Rect> glyph_positions;
414 glyph_positions.reserve(new_glyphs.size());
415 size_t first_missing_index = 0;
416
417 if (last_atlas->GetTexture()) {
418 // Append all glyphs that fit into the current atlas.
419 first_missing_index = AppendToExistingAtlas(
420 last_atlas, new_glyphs, glyph_positions, glyph_sizes,
421 atlas_context->GetAtlasSize(), atlas_context->GetHeightAdjustment(),
422 atlas_context->GetRectPacker());
423
424 // ---------------------------------------------------------------------------
425 // Step 3a: Record the positions in the glyph atlas of the newly added
426 // glyphs.
427 // ---------------------------------------------------------------------------
428 for (size_t i = 0; i < first_missing_index; i++) {
429 last_atlas->AddTypefaceGlyphPositionAndBounds(
430 new_glyphs[i], glyph_positions[i], glyph_sizes[i]);
431 }
432
433 std::shared_ptr<CommandBuffer> cmd_buffer = context.CreateCommandBuffer();
434 std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
435
437 blit_pass->EncodeCommands(context.GetResourceAllocator());
438 context.GetCommandQueue()->Submit({std::move(cmd_buffer)});
439 });
440
441 // ---------------------------------------------------------------------------
442 // Step 4a: Draw new font-glyph pairs into the a host buffer and encode
443 // the uploads into the blit pass.
444 // ---------------------------------------------------------------------------
445 if (!UpdateAtlasBitmap(*last_atlas, blit_pass, host_buffer,
446 last_atlas->GetTexture(), new_glyphs, 0,
447 first_missing_index)) {
448 return nullptr;
449 }
450
451 // If all glyphs fit, just return the old atlas.
452 if (first_missing_index == new_glyphs.size()) {
453 return last_atlas;
454 }
455 }
456
457 int64_t height_adjustment = atlas_context->GetAtlasSize().height;
458 const int64_t max_texture_height =
459 context.GetResourceAllocator()->GetMaxTextureSizeSupported().height;
460
461 // IF the current atlas size is as big as it can get, then "GC" and create an
462 // atlas with only the required glyphs. OpenGLES cannot reliably perform the
463 // blit required here, as 1) it requires attaching textures as read and write
464 // framebuffers which has substantially smaller size limits that max textures
465 // and 2) is missing a GLES 2.0 implementation and cap check.
466 bool blit_old_atlas = true;
467 std::shared_ptr<GlyphAtlas> new_atlas = last_atlas;
468 if (atlas_context->GetAtlasSize().height >= max_texture_height ||
470 blit_old_atlas = false;
471 first_missing_index = 0;
472 glyph_positions.clear();
473 height_adjustment = 0;
474 new_atlas = std::make_shared<GlyphAtlas>(type);
475 atlas_context->UpdateRectPacker(nullptr);
476 atlas_context->UpdateGlyphAtlas(new_atlas, {0, 0}, 0);
477 }
478
479 // A new glyph atlas must be created.
480 ISize atlas_size = ComputeNextAtlasSize(atlas_context, //
481 new_glyphs, //
482 glyph_positions, //
483 glyph_sizes, //
484 first_missing_index, //
485 max_texture_height //
486 );
487
488 atlas_context->UpdateGlyphAtlas(new_atlas, atlas_size, height_adjustment);
489 if (atlas_size.IsEmpty()) {
490 return nullptr;
491 }
492 FML_DCHECK(new_glyphs.size() == glyph_positions.size());
493
494 TextureDescriptor descriptor;
495 switch (type) {
497 descriptor.format =
498 context.GetCapabilities()->GetDefaultGlyphAtlasFormat();
499 break;
502 break;
503 }
504 descriptor.size = atlas_size;
506 descriptor.usage = TextureUsage::kShaderRead;
507 std::shared_ptr<Texture> new_texture =
508 context.GetResourceAllocator()->CreateTexture(descriptor);
509 if (!new_texture) {
510 return nullptr;
511 }
512
513 new_texture->SetLabel("GlyphAtlas");
514
515 std::shared_ptr<CommandBuffer> cmd_buffer = context.CreateCommandBuffer();
516 std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
517
518 // The R8/A8 textures used for certain glyphs is not supported as color
519 // attachments in most graphics drivers. For other textures, most framebuffer
520 // attachments have a much smaller size limit than the max texture size.
521 {
522 TRACE_EVENT0("flutter", "ClearGlyphAtlas");
523 size_t byte_size =
524 new_texture->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
526 host_buffer.Emplace(nullptr, byte_size, DefaultUniformAlignment());
527
528 ::memset(buffer_view.buffer->OnGetContents() + buffer_view.range.offset, 0,
529 byte_size);
530 buffer_view.buffer->Flush();
531 blit_pass->AddCopy(buffer_view, new_texture);
532 }
533
535 blit_pass->EncodeCommands(context.GetResourceAllocator());
536 context.GetCommandQueue()->Submit({std::move(cmd_buffer)});
537 });
538
539 // Blit the old texture to the top left of the new atlas.
540 if (new_atlas->GetTexture() && blit_old_atlas) {
541 blit_pass->AddCopy(new_atlas->GetTexture(), new_texture,
542 IRect::MakeSize(new_atlas->GetTexture()->GetSize()),
543 {0, 0});
544 }
545
546 // Now append all remaining glyphs. This should never have any missing data...
547 new_atlas->SetTexture(std::move(new_texture));
548
549 // ---------------------------------------------------------------------------
550 // Step 3a: Record the positions in the glyph atlas of the newly added
551 // glyphs.
552 // ---------------------------------------------------------------------------
553 for (size_t i = first_missing_index; i < glyph_positions.size(); i++) {
554 new_atlas->AddTypefaceGlyphPositionAndBounds(
555 new_glyphs[i], glyph_positions[i], glyph_sizes[i]);
556 }
557
558 // ---------------------------------------------------------------------------
559 // Step 4a: Draw new font-glyph pairs into the a host buffer and encode
560 // the uploads into the blit pass.
561 // ---------------------------------------------------------------------------
562 if (!UpdateAtlasBitmap(*new_atlas, blit_pass, host_buffer,
563 new_atlas->GetTexture(), new_glyphs,
564 first_missing_index, new_glyphs.size())) {
565 return nullptr;
566 }
567 // ---------------------------------------------------------------------------
568 // Step 8b: Record the texture in the glyph atlas.
569 // ---------------------------------------------------------------------------
570
571 return new_atlas;
572}
573
574} // namespace impeller
SkPoint pos
constexpr SkColor SK_ColorBLACK
Definition: SkColor.h:103
@ kSlight
minimal modification to improve constrast
uint16_t SkGlyphID
Definition: SkTypes.h:179
GLenum type
BufferView buffer_view
void translate(SkScalar dx, SkScalar dy)
Definition: SkCanvas.cpp:1278
void drawGlyphs(int count, const SkGlyphID glyphs[], const SkPoint positions[], const uint32_t clusters[], int textByteCount, const char utf8text[], SkPoint origin, const SkFont &font, const SkPaint &paint)
Definition: SkFont.h:35
void setSubpixel(bool subpixel)
Definition: SkFont.cpp:109
SkScalar getSize() const
Definition: SkFont.h:217
void setEdging(Edging edging)
Definition: SkFont.cpp:121
void setSize(SkScalar textSize)
Definition: SkFont.cpp:129
void setHinting(SkFontHinting hintingLevel)
Definition: SkFont.cpp:125
@ kAntiAlias
may have transparent pixels on glyph edges
void setEmbolden(bool embolden)
Definition: SkFont.cpp:115
void setColor(SkColor color)
Definition: SkPaint.cpp:119
void setStrokeMiter(SkScalar miter)
Definition: SkPaint.cpp:169
void setStrokeCap(Cap cap)
Definition: SkPaint.cpp:179
void setStrokeJoin(Join join)
Definition: SkPaint.cpp:189
void setBlendMode(SkBlendMode mode)
Definition: SkPaint.cpp:151
void setStroke(bool)
Definition: SkPaint.cpp:115
void setStrokeWidth(SkScalar width)
Definition: SkPaint.cpp:159
Wraps a closure that is invoked in the destructor unless released by the caller.
Definition: closure.h:32
static TypefaceSkia & Cast(Typeface &base)
Definition: backend_cast.h:13
To do anything rendering related with Impeller, you need a context.
Definition: context.h:45
virtual std::shared_ptr< CommandQueue > GetCommandQueue() const =0
Return the graphics queue for submitting command buffers.
virtual const std::shared_ptr< const Capabilities > & GetCapabilities() const =0
Get the capabilities of Impeller context. All optionally supported feature of the platform,...
virtual BackendType GetBackendType() const =0
Get the graphics backend of an Impeller context.
virtual std::shared_ptr< CommandBuffer > CreateCommandBuffer() const =0
Create a new command buffer. Command buffers can be used to encode graphics, blit,...
virtual std::shared_ptr< Allocator > GetResourceAllocator() const =0
Returns the allocator used to create textures and buffers on the device.
An object that can look up glyph locations within the GlyphAtlas for a particular typeface.
Definition: glyph_atlas.h:200
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
const std::shared_ptr< Typeface > & GetTypeface() const
The typeface whose intrinsic properties this font modifies.
Definition: font.cc:27
const Metrics & GetMetrics() const
Definition: font.cc:45
A texture containing the bitmap representation of glyphs in different fonts along with the ability to...
Definition: glyph_atlas.h:27
Type
Describes how the glyphs are represented in the texture.
Definition: glyph_atlas.h:31
BufferView Emplace(const BufferType &buffer, size_t alignment=0)
Emplace non-uniform data (like contiguous vertices) onto the host buffer.
Definition: host_buffer.h:95
static std::shared_ptr< RectanglePacker > Factory(int width, int height)
Return an empty packer with area specified by width and height.
const sk_sp< SkTypeface > & GetSkiaTypeface() const
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
std::shared_ptr< GlyphAtlasContext > CreateGlyphAtlasContext(GlyphAtlas::Type type) const override
static std::shared_ptr< TypographerContext > Make()
VkSurfaceKHR surface
Definition: main.cc:49
#define FML_UNREACHABLE()
Definition: logging.h:109
#define FML_DCHECK(condition)
Definition: logging.h:103
FlTexture * texture
sk_sp< const SkImage > atlas
Definition: SkRecords.h:331
Optional< SkRect > bounds
Definition: SkRecords.h:189
SK_API sk_sp< SkSurface > WrapPixels(const SkImageInfo &imageInfo, void *pixels, size_t rowBytes, const SkSurfaceProps *surfaceProps=nullptr)
Definition: bitmap.py:1
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
std::function< void()> closure
Definition: closure.h:14
font
Font Metadata and Metrics.
constexpr size_t BytesPerPixelForPixelFormat(PixelFormat format)
Definition: formats.h:460
static void DrawGlyph(SkCanvas *canvas, const ScaledFont &scaled_font, const SubpixelGlyph &glyph, const Rect &scaled_bounds, const GlyphProperties &prop, bool has_color)
Join
Definition: path.h:24
static Rect ComputeGlyphSize(const SkFont &font, const SubpixelGlyph &glyph, Scalar scale)
float Scalar
Definition: scalar.h:18
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)
static SkImageInfo GetImageInfo(const GlyphAtlas &atlas, Size size)
Cap
Definition: path.h:18
static size_t AppendToExistingAtlas(const std::shared_ptr< GlyphAtlas > &atlas, const std::vector< FontGlyphPair > &extra_pairs, std::vector< Rect > &glyph_positions, const std::vector< Rect > &glyph_sizes, ISize atlas_size, int64_t height_adjustment, const std::shared_ptr< RectanglePacker > &rect_packer)
static ISize ComputeNextAtlasSize(const std::shared_ptr< GlyphAtlasContext > &atlas_context, const std::vector< FontGlyphPair > &extra_pairs, std::vector< Rect > &glyph_positions, const std::vector< Rect > &glyph_sizes, size_t glyph_index_start, int64_t max_texture_height)
constexpr auto kPadding
std::unordered_map< ScaledFont, std::unordered_set< SubpixelGlyph > > FontGlyphMap
ISize64 ISize
Definition: size.h:140
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)
constexpr size_t DefaultUniformAlignment()
Definition: platform.h:14
static SkScalar prop(SkScalar radius, SkScalar newSize, SkScalar oldSize)
Definition: rrect.cpp:83
static SkString join(const CommandLineFlags::StringArray &)
Definition: skpbench.cpp:741
const Scalar scale
Definition: SkSize.h:16
static SkImageInfo MakeN32Premul(int width, int height)
static SkImageInfo MakeA8(int width, int height)
static constexpr SkPoint Make(float x, float y)
Definition: SkPoint_impl.h:173
SkScalar fBottom
larger y-axis bounds
Definition: extension.cpp:17
SkScalar fLeft
smaller x-axis bounds
Definition: extension.cpp:14
SkScalar fRight
larger x-axis bounds
Definition: extension.cpp:16
SkScalar fTop
smaller y-axis bounds
Definition: extension.cpp:15
constexpr uint32_t ToARGB() const
Convert to ARGB 32 bit color.
Definition: color.h:261
A font along with a glyph in that font rendered at a particular scale and subpixel position.
const SubpixelGlyph & glyph
const ScaledFont & scaled_font
uint16_t index
Definition: glyph.h:22
int16_t y() const
int16_t x() const
A font and a scale. Used as a key that represents a typeface within a glyph atlas.
A glyph and its subpixel position.
GlyphProperties properties
constexpr auto GetTop() const
Definition: rect.h:343
constexpr auto GetLeft() const
Definition: rect.h:341
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:136
static constexpr TRect MakeSize(const TSize< U > &size)
Definition: rect.h:146
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129
Type height
Definition: size.h:23
Type width
Definition: size.h:22
constexpr TSize Ceil() const
Definition: size.h:96
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
Definition: size.h:105
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:131