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,
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;
218 static_cast<size_t>(location.
GetY())});
222 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, pos.value(),
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, location, has_color);
317 const std::shared_ptr<Texture>& texture) {
318 TRACE_EVENT0(
"impeller", __FUNCTION__);
320 FML_DCHECK(bitmap !=
nullptr);
322 auto texture_descriptor = texture->GetTextureDescriptor();
324 auto mapping = std::make_shared<fml::NonOwnedMapping>(
325 reinterpret_cast<const uint8_t*
>(bitmap->GetPixels()),
326 texture_descriptor.GetByteSizeOfBaseMipLevel()
331 return texture->SetContents(mapping);
335 const std::shared_ptr<Allocator>& allocator,
336 std::shared_ptr<BitmapSTB>& bitmap,
337 const ISize& atlas_size,
339 TRACE_EVENT0(
"impeller", __FUNCTION__);
344 FML_DCHECK(bitmap !=
nullptr);
348 texture_descriptor.
format = format;
349 texture_descriptor.
size = atlas_size;
351 if (bitmap->GetRowBytes() * bitmap->GetHeight() !=
356 auto texture = allocator->CreateTexture(texture_descriptor);
357 if (!texture || !texture->IsValid()) {
360 texture->SetLabel(
"GlyphAtlas");
362 auto mapping = std::make_shared<fml::NonOwnedMapping>(
363 reinterpret_cast<const uint8_t*
>(bitmap->GetPixels()),
369 if (!texture->SetContents(mapping)) {
378 const std::shared_ptr<GlyphAtlasContext>& atlas_context,
380 TRACE_EVENT0(
"impeller", __FUNCTION__);
385 std::shared_ptr<GlyphAtlas> last_atlas = atlas_context->GetGlyphAtlas();
387 if (font_glyph_map.empty()) {
395 std::vector<FontGlyphPair> new_glyphs;
396 for (
const auto& font_value : font_glyph_map) {
397 const ScaledFont& scaled_font = font_value.first;
399 last_atlas->GetFontGlyphAtlas(scaled_font.
font, scaled_font.
scale);
400 if (font_glyph_atlas) {
401 for (
const Glyph& glyph : font_value.second) {
403 new_glyphs.emplace_back(scaled_font, glyph);
407 for (
const Glyph& glyph : font_value.second) {
408 new_glyphs.emplace_back(scaled_font, glyph);
412 if (last_atlas->GetType() == type && new_glyphs.size() == 0) {
421 std::vector<Rect> glyph_positions;
422 if (last_atlas->GetType() == type &&
424 atlas_context->GetAtlasSize(),
425 atlas_context->GetRectPacker())) {
433 for (
size_t i = 0, count = glyph_positions.size(); i < count; i++) {
434 last_atlas->AddTypefaceGlyphPosition(new_glyphs[i], glyph_positions[i]);
441 auto bitmap = atlas_context_stb.GetBitmap();
459 std::vector<FontGlyphPair> font_glyph_pairs;
460 font_glyph_pairs.reserve(std::accumulate(
461 font_glyph_map.begin(), font_glyph_map.end(), 0,
462 [](
const int a,
const auto&
b) { return a + b.second.size(); }));
463 for (
const auto& font_value : font_glyph_map) {
464 const ScaledFont& scaled_font = font_value.first;
465 for (
const Glyph& glyph : font_value.second) {
466 font_glyph_pairs.push_back({scaled_font, glyph});
469 auto glyph_atlas = std::make_shared<GlyphAtlas>(type);
478 atlas_context->UpdateGlyphAtlas(glyph_atlas, atlas_size);
479 if (atlas_size.IsEmpty()) {
489 if (glyph_positions.size() != font_glyph_pairs.size()) {
498 for (
auto it = font_glyph_pairs.begin(); it != font_glyph_pairs.end();
500 glyph_atlas->AddTypefaceGlyphPosition(*it, glyph_positions[i]);
511 atlas_context_stb.UpdateBitmap(bitmap);
536 glyph_atlas->SetTexture(std::move(texture));