10 #include "flutter/fml/logging.h"
11 #include "flutter/fml/trace_event.h"
18 #define DISABLE_COLOR_FONT_SUPPORT 1
19 #ifdef DISABLE_COLOR_FONT_SUPPORT
30 return std::make_unique<TypographerContextSTB>();
37 std::shared_ptr<GlyphAtlasContext>
39 return std::make_shared<GlyphAtlasContextSTB>();
45 const std::vector<FontGlyphPair>& pairs,
46 const ISize& atlas_size,
47 std::vector<Rect>& glyph_positions,
48 const std::shared_ptr<RectanglePacker>& rect_packer) {
53 glyph_positions.clear();
54 glyph_positions.reserve(pairs.size());
57 for (
auto it = pairs.begin(); it != pairs.end(); ++i, ++it) {
58 const auto& pair = *it;
59 const Font& font = pair.scaled_font.font;
63 std::shared_ptr<TypefaceSTB> typeface_stb =
64 std::reinterpret_pointer_cast<TypefaceSTB>(font.
GetTypeface());
67 float text_size_pixels =
72 int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
75 float scale = stbtt_ScaleForPixelHeight(typeface_stb->GetFontInfo(),
77 stbtt_GetGlyphBitmapBox(typeface_stb->GetFontInfo(), pair.glyph.index,
78 scale, scale, &x0, &y0, &x1, &y1);
80 glyph_size =
ISize(x1 - x0, y1 - y0);
88 return pairs.size() - i;
91 location_in_atlas.
y(),
101 const std::shared_ptr<GlyphAtlas>& atlas,
102 const std::vector<FontGlyphPair>& extra_pairs,
103 std::vector<Rect>& glyph_positions,
105 const std::shared_ptr<RectanglePacker>& rect_packer) {
106 TRACE_EVENT0(
"impeller", __FUNCTION__);
107 if (!rect_packer || atlas_size.
IsEmpty()) {
114 FML_DCHECK(glyph_positions.size() == 0);
115 glyph_positions.reserve(extra_pairs.size());
116 for (
size_t i = 0; i < extra_pairs.size(); i++) {
121 std::shared_ptr<TypefaceSTB> typeface_stb =
122 std::reinterpret_pointer_cast<TypefaceSTB>(font.
GetTypeface());
125 float text_size_pixels =
130 int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
133 float scale_y = stbtt_ScaleForPixelHeight(typeface_stb->GetFontInfo(),
135 float scale_x = scale_y;
136 stbtt_GetGlyphBitmapBox(typeface_stb->GetFontInfo(), pair.
glyph.
index,
137 scale_x, scale_y, &x0, &y0, &x1, &y1);
139 glyph_size =
ISize(x1 - x0, y1 - y0);
150 location_in_atlas.
y(),
160 const std::vector<FontGlyphPair>& pairs,
161 std::vector<Rect>& glyph_positions,
162 const std::shared_ptr<GlyphAtlasContext>& atlas_context,
164 const ISize& max_texture_size) {
165 static constexpr
auto kMinAtlasSize = 8u;
166 static constexpr
auto kMinAlphaBitmapSize = 1024u;
168 TRACE_EVENT0(
"impeller", __FUNCTION__);
171 ?
ISize(kMinAlphaBitmapSize, kMinAlphaBitmapSize)
172 :
ISize(kMinAtlasSize, kMinAtlasSize);
173 size_t total_pairs = pairs.size() + 1;
175 auto rect_packer = std::shared_ptr<RectanglePacker>(
179 glyph_positions, rect_packer);
180 if (remaining_pairs == 0) {
181 atlas_context->UpdateRectPacker(rect_packer);
183 }
else if (remaining_pairs < std::ceil(total_pairs / 2)) {
187 std::min(current_size.
width, current_size.
height) + 1));
193 }
while (current_size.
width <= max_texture_size.
width &&
201 const Rect& location,
208 std::shared_ptr<TypefaceSTB> typeface_stb =
209 std::reinterpret_pointer_cast<TypefaceSTB>(typeface);
214 stbtt_ScaleForPixelHeight(typeface_stb->GetFontInfo(), text_size_pixels);
215 float scale_x = scale_y;
219 static_cast<size_t>(location.
origin.
y)});
223 stbtt_MakeGlyphBitmap(typeface_stb->GetFontInfo(), output,
231 int glyph_bitmap_width = 0;
232 int glyph_bitmap_height = 0;
233 int glyph_bitmap_xoff = 0;
234 int glyph_bitmap_yoff = 0;
235 auto glyph_pixels = stbtt_GetGlyphBitmap(
236 typeface_stb->GetFontInfo(), scale_x, scale_y, glyph.
index,
237 &glyph_bitmap_width, &glyph_bitmap_height, &glyph_bitmap_xoff,
240 uint8_t* write_pos = output;
241 for (
auto y = 0; y < glyph_bitmap_height; ++y) {
242 for (
auto x = 0; x < glyph_bitmap_width; ++x) {
250 uint8_t a = glyph_pixels[x + y * glyph_bitmap_width];
269 stbtt_FreeBitmap(glyph_pixels,
nullptr);
274 const std::shared_ptr<BitmapSTB>& bitmap,
275 const std::vector<FontGlyphPair>& new_pairs) {
276 TRACE_EVENT0(
"impeller", __FUNCTION__);
277 FML_DCHECK(bitmap !=
nullptr);
283 if (!pos.has_value()) {
286 DrawGlyph(bitmap.get(), pair.scaled_font, pair.glyph, pos.value(),
293 const ISize& atlas_size) {
294 TRACE_EVENT0(
"impeller", __FUNCTION__);
296 size_t bytes_per_pixel = 1;
301 auto bitmap = std::make_shared<BitmapSTB>(atlas_size.
width, atlas_size.
height,
308 const Rect& location) ->
bool {
309 DrawGlyph(bitmap.get(), scaled_font, glyph, location, has_color);
318 const std::shared_ptr<Texture>& texture) {
319 TRACE_EVENT0(
"impeller", __FUNCTION__);
321 FML_DCHECK(bitmap !=
nullptr);
323 auto texture_descriptor = texture->GetTextureDescriptor();
325 auto mapping = std::make_shared<fml::NonOwnedMapping>(
326 reinterpret_cast<const uint8_t*
>(bitmap->GetPixels()),
327 texture_descriptor.GetByteSizeOfBaseMipLevel()
332 return texture->SetContents(mapping);
336 const std::shared_ptr<Allocator>& allocator,
337 std::shared_ptr<BitmapSTB>& bitmap,
338 const ISize& atlas_size,
340 TRACE_EVENT0(
"impeller", __FUNCTION__);
345 FML_DCHECK(bitmap !=
nullptr);
349 texture_descriptor.
format = format;
350 texture_descriptor.
size = atlas_size;
352 if (bitmap->GetRowBytes() * bitmap->GetHeight() !=
357 auto texture = allocator->CreateTexture(texture_descriptor);
358 if (!texture || !texture->IsValid()) {
361 texture->SetLabel(
"GlyphAtlas");
363 auto mapping = std::make_shared<fml::NonOwnedMapping>(
364 reinterpret_cast<const uint8_t*
>(bitmap->GetPixels()),
370 if (!texture->SetContents(mapping)) {
379 std::shared_ptr<GlyphAtlasContext> atlas_context,
381 TRACE_EVENT0(
"impeller", __FUNCTION__);
386 std::shared_ptr<GlyphAtlas> last_atlas = atlas_context->GetGlyphAtlas();
388 if (font_glyph_map.empty()) {
396 std::vector<FontGlyphPair> new_glyphs;
397 for (
const auto& font_value : font_glyph_map) {
398 const ScaledFont& scaled_font = font_value.first;
400 last_atlas->GetFontGlyphAtlas(scaled_font.
font, scaled_font.
scale);
401 if (font_glyph_atlas) {
402 for (
const Glyph& glyph : font_value.second) {
404 new_glyphs.emplace_back(scaled_font, glyph);
408 for (
const Glyph& glyph : font_value.second) {
409 new_glyphs.emplace_back(scaled_font, glyph);
413 if (last_atlas->GetType() == type && new_glyphs.size() == 0) {
422 std::vector<Rect> glyph_positions;
423 if (last_atlas->GetType() == type &&
425 atlas_context->GetAtlasSize(),
426 atlas_context->GetRectPacker())) {
434 for (
size_t i = 0, count = glyph_positions.size(); i < count; i++) {
435 last_atlas->AddTypefaceGlyphPosition(new_glyphs[i], glyph_positions[i]);
442 auto bitmap = atlas_context_stb.GetBitmap();
460 std::vector<FontGlyphPair> font_glyph_pairs;
461 font_glyph_pairs.reserve(std::accumulate(
462 font_glyph_map.begin(), font_glyph_map.end(), 0,
463 [](
const int a,
const auto& b) { return a + b.second.size(); }));
464 for (
const auto& font_value : font_glyph_map) {
465 const ScaledFont& scaled_font = font_value.first;
466 for (
const Glyph& glyph : font_value.second) {
467 font_glyph_pairs.push_back({scaled_font, glyph});
470 auto glyph_atlas = std::make_shared<GlyphAtlas>(type);
479 atlas_context->UpdateGlyphAtlas(glyph_atlas, atlas_size);
480 if (atlas_size.IsEmpty()) {
490 if (glyph_positions.size() != font_glyph_pairs.size()) {
499 for (
auto it = font_glyph_pairs.begin(); it != font_glyph_pairs.end();
501 glyph_atlas->AddTypefaceGlyphPosition(*it, glyph_positions[i]);
512 atlas_context_stb.UpdateBitmap(bitmap);
536 glyph_atlas->SetTexture(std::move(texture));