10 #include "flutter/fml/logging.h"
11 #include "flutter/fml/trace_event.h"
12 #include "fml/closure.h"
13 #include "fml/mapping.h"
21 #define DISABLE_COLOR_FONT_SUPPORT 1
22 #ifdef DISABLE_COLOR_FONT_SUPPORT
33 return std::make_unique<TypographerContextSTB>();
40 std::shared_ptr<GlyphAtlasContext>
42 return std::make_shared<GlyphAtlasContextSTB>(
type);
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) {
56 glyph_positions.clear();
57 glyph_positions.reserve(pairs.size());
60 for (
auto it = pairs.begin(); it != pairs.end(); ++i, ++it) {
61 const auto& pair = *it;
62 const Font& font = pair.scaled_font.font;
66 std::shared_ptr<TypefaceSTB> typeface_stb =
67 std::reinterpret_pointer_cast<TypefaceSTB>(font.
GetTypeface());
70 float text_size_pixels =
75 int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
76 float scale = stbtt_ScaleForMappingEmToPixels(typeface_stb->GetFontInfo(),
78 stbtt_GetGlyphBitmapBox(typeface_stb->GetFontInfo(),
79 pair.glyph.glyph.index,
scale,
scale, &x0, &y0,
82 glyph_size =
ISize(x1 - x0, y1 - y0);
90 return pairs.size() - i;
93 location_in_atlas.
y(),
103 const std::shared_ptr<GlyphAtlas>& atlas,
104 const std::vector<FontGlyphPair>& extra_pairs,
105 std::vector<Rect>& glyph_positions,
107 const std::shared_ptr<RectanglePacker>& rect_packer) {
108 TRACE_EVENT0(
"impeller", __FUNCTION__);
109 if (!rect_packer || atlas_size.
IsEmpty()) {
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++) {
123 std::shared_ptr<TypefaceSTB> typeface_stb =
124 std::reinterpret_pointer_cast<TypefaceSTB>(font.
GetTypeface());
127 float text_size_pixels =
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(),
140 glyph_size =
ISize(x1 - x0, y1 - y0);
151 location_in_atlas.
y(),
161 const std::vector<FontGlyphPair>& pairs,
162 std::vector<Rect>& glyph_positions,
163 const std::shared_ptr<GlyphAtlasContext>& atlas_context,
165 const ISize& max_texture_size) {
166 static constexpr
auto kMinAtlasSize = 8u;
167 static constexpr
auto kMinAlphaBitmapSize = 1024u;
169 TRACE_EVENT0(
"impeller", __FUNCTION__);
172 ?
ISize(kMinAlphaBitmapSize, kMinAlphaBitmapSize)
173 :
ISize(kMinAtlasSize, kMinAtlasSize);
174 size_t total_pairs = pairs.size() + 1;
176 auto rect_packer = std::shared_ptr<RectanglePacker>(
180 glyph_positions, rect_packer);
181 if (remaining_pairs == 0) {
182 atlas_context->UpdateRectPacker(rect_packer);
184 }
else if (remaining_pairs < std::ceil(total_pairs / 2)) {
188 std::min(current_size.
width, current_size.
height) + 1));
194 }
while (current_size.
width <= max_texture_size.
width &&
202 const Rect& location,
209 std::shared_ptr<TypefaceSTB> typeface_stb =
210 std::reinterpret_pointer_cast<TypefaceSTB>(typeface);
214 float scale_y = stbtt_ScaleForMappingEmToPixels(typeface_stb->GetFontInfo(),
216 float scale_x = scale_y;
219 static_cast<size_t>(location.
GetY())});
223 stbtt_MakeGlyphBitmap(typeface_stb->GetFontInfo(), output,
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,
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) {
249 uint8_t a = glyph_pixels[x + y * glyph_bitmap_width];
268 stbtt_FreeBitmap(glyph_pixels,
nullptr);
273 const std::shared_ptr<BitmapSTB>& bitmap,
274 const std::vector<FontGlyphPair>& new_pairs) {
275 TRACE_EVENT0(
"impeller", __FUNCTION__);
276 FML_DCHECK(bitmap !=
nullptr);
282 if (!pos.has_value()) {
285 DrawGlyph(bitmap.get(), pair.scaled_font, pair.glyph.glyph,
286 pos.value().first, has_color);
292 const ISize& atlas_size) {
293 TRACE_EVENT0(
"impeller", __FUNCTION__);
295 size_t bytes_per_pixel = 1;
300 auto bitmap = std::make_shared<BitmapSTB>(atlas_size.
width, atlas_size.
height,
307 const Rect& location) ->
bool {
308 DrawGlyph(bitmap.get(), scaled_font, glyph.
glyph, location, has_color);
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__);
322 FML_DCHECK(bitmap !=
nullptr);
324 auto texture_descriptor = texture->GetTextureDescriptor();
326 auto mapping = std::make_shared<fml::NonOwnedMapping>(
327 reinterpret_cast<const uint8_t*
>(bitmap->GetPixels()),
328 texture_descriptor.GetByteSizeOfBaseMipLevel()
333 std::shared_ptr<DeviceBuffer> device_buffer =
334 allocator->CreateBufferWithCopy(*mapping);
337 return blit_pass->EncodeCommands(allocator);
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,
346 TRACE_EVENT0(
"impeller", __FUNCTION__);
351 FML_DCHECK(bitmap !=
nullptr);
355 texture_descriptor.
format = format;
356 texture_descriptor.
size = atlas_size;
358 if (bitmap->GetRowBytes() * bitmap->GetHeight() !=
363 auto texture = allocator->CreateTexture(texture_descriptor);
364 if (!texture || !texture->IsValid()) {
367 texture->SetLabel(
"GlyphAtlas");
369 std::shared_ptr<fml::NonOwnedMapping> mapping =
370 std::make_shared<fml::NonOwnedMapping>(
371 reinterpret_cast<const uint8_t*
>(bitmap->GetPixels()),
376 std::shared_ptr<DeviceBuffer> device_buffer =
377 allocator->CreateBufferWithCopy(*mapping);
379 if (!blit_pass->EncodeCommands(allocator)) {
388 std::shared_ptr<TypefaceSTB> typeface_stb =
390 float scale = stbtt_ScaleForMappingEmToPixels(
391 typeface_stb->GetFontInfo(),
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);
403 const std::shared_ptr<GlyphAtlasContext>& atlas_context,
405 TRACE_EVENT0(
"impeller", __FUNCTION__);
410 std::shared_ptr<GlyphAtlas> last_atlas = atlas_context->GetGlyphAtlas();
412 if (font_glyph_map.empty()) {
420 std::vector<FontGlyphPair> new_glyphs;
421 std::vector<Rect> new_sizes;
422 for (
const auto& font_value : font_glyph_map) {
423 const ScaledFont& scaled_font = font_value.first;
425 last_atlas->GetFontGlyphAtlas(scaled_font.
font, scaled_font.
scale);
426 if (font_glyph_atlas) {
429 new_glyphs.emplace_back(scaled_font, glyph);
435 new_glyphs.emplace_back(scaled_font, glyph);
441 if (last_atlas->GetType() ==
type && new_glyphs.size() == 0) {
446 std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
448 fml::ScopedCleanupClosure closure([&cmd_buffer, &context]() {
457 std::vector<Rect> glyph_positions;
458 if (last_atlas->GetType() ==
type &&
460 atlas_context->GetAtlasSize(),
461 atlas_context->GetRectPacker())) {
469 for (
size_t i = 0, count = glyph_positions.size(); i < count; i++) {
470 last_atlas->AddTypefaceGlyphPositionAndBounds(
471 new_glyphs[i], glyph_positions[i], new_sizes[i]);
478 auto bitmap = atlas_context_stb.GetBitmap();
487 blit_pass, last_atlas->GetTexture())) {
497 std::vector<FontGlyphPair> font_glyph_pairs;
498 font_glyph_pairs.reserve(std::accumulate(
499 font_glyph_map.begin(), font_glyph_map.end(), 0,
500 [](
const int a,
const auto&
b) { return a + b.second.size(); }));
501 for (
const auto& font_value : font_glyph_map) {
502 const ScaledFont& scaled_font = font_value.first;
504 font_glyph_pairs.push_back({scaled_font, glyph});
507 auto glyph_atlas = std::make_shared<GlyphAtlas>(
type);
516 atlas_context->UpdateGlyphAtlas(glyph_atlas, atlas_size, 0);
517 if (atlas_size.IsEmpty()) {
527 if (glyph_positions.size() != font_glyph_pairs.size()) {
536 for (
auto it = font_glyph_pairs.begin(); it != font_glyph_pairs.end();
538 glyph_atlas->AddTypefaceGlyphPositionAndBounds(*it, glyph_positions[i],
550 atlas_context_stb.UpdateBitmap(bitmap);
567 blit_pass, bitmap, atlas_size, format);
575 glyph_atlas->SetTexture(std::move(texture));