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>();
37std::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;
73 float scale = stbtt_ScaleForMappingEmToPixels(typeface_stb->GetFontInfo(),
75 stbtt_GetGlyphBitmapBox(typeface_stb->GetFontInfo(), pair.glyph.index,
78 glyph_size =
ISize(x1 - x0, y1 - y0);
86 return pairs.size() - i;
89 location_in_atlas.
y(),
99 const std::shared_ptr<GlyphAtlas>& atlas,
100 const std::vector<FontGlyphPair>& extra_pairs,
101 std::vector<Rect>& glyph_positions,
103 const std::shared_ptr<RectanglePacker>& rect_packer) {
105 if (!rect_packer || atlas_size.
IsEmpty()) {
113 glyph_positions.reserve(extra_pairs.size());
114 for (
size_t i = 0; i < extra_pairs.size(); i++) {
119 std::shared_ptr<TypefaceSTB> typeface_stb =
120 std::reinterpret_pointer_cast<TypefaceSTB>(font.GetTypeface());
123 float text_size_pixels =
128 int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
129 float scale_y = stbtt_ScaleForMappingEmToPixels(
130 typeface_stb->GetFontInfo(), text_size_pixels);
131 float scale_x = scale_y;
132 stbtt_GetGlyphBitmapBox(typeface_stb->GetFontInfo(), pair.
glyph.
index,
133 scale_x, scale_y, &x0, &y0, &x1, &y1);
135 glyph_size =
ISize(x1 - x0, y1 - y0);
146 location_in_atlas.
y(),
156 const std::vector<FontGlyphPair>& pairs,
157 std::vector<Rect>& glyph_positions,
158 const std::shared_ptr<GlyphAtlasContext>& atlas_context,
160 const ISize& max_texture_size) {
161 static constexpr auto kMinAtlasSize = 8u;
162 static constexpr auto kMinAlphaBitmapSize = 1024u;
167 ?
ISize(kMinAlphaBitmapSize, kMinAlphaBitmapSize)
168 :
ISize(kMinAtlasSize, kMinAtlasSize);
169 size_t total_pairs = pairs.size() + 1;
171 auto rect_packer = std::shared_ptr<RectanglePacker>(
175 glyph_positions, rect_packer);
176 if (remaining_pairs == 0) {
177 atlas_context->UpdateRectPacker(rect_packer);
179 }
else if (remaining_pairs < std::ceil(total_pairs / 2)) {
183 std::min(current_size.
width, current_size.
height) + 1));
189 }
while (current_size.
width <= max_texture_size.
width &&
197 const Rect& location,
202 auto typeface = font.GetTypeface();
204 std::shared_ptr<TypefaceSTB> typeface_stb =
205 std::reinterpret_pointer_cast<TypefaceSTB>(typeface);
209 float scale_y = stbtt_ScaleForMappingEmToPixels(typeface_stb->GetFontInfo(),
211 float scale_x = scale_y;
213 auto output =
bitmap->GetPixelAddress({
static_cast<size_t>(location.
GetX()),
214 static_cast<size_t>(location.
GetY())});
218 stbtt_MakeGlyphBitmap(typeface_stb->GetFontInfo(), output,
220 bitmap->GetRowBytes(), scale_x, scale_y, glyph.
index);
225 int glyph_bitmap_width = 0;
226 int glyph_bitmap_height = 0;
227 int glyph_bitmap_xoff = 0;
228 int glyph_bitmap_yoff = 0;
229 auto glyph_pixels = stbtt_GetGlyphBitmap(
230 typeface_stb->GetFontInfo(), scale_x, scale_y, glyph.
index,
231 &glyph_bitmap_width, &glyph_bitmap_height, &glyph_bitmap_xoff,
234 uint8_t* write_pos = output;
235 for (
auto y = 0;
y < glyph_bitmap_height; ++
y) {
236 for (
auto x = 0;
x < glyph_bitmap_width; ++
x) {
244 uint8_t
a = glyph_pixels[
x +
y * glyph_bitmap_width];
261 write_pos = output + (
y *
bitmap->GetRowBytes());
263 stbtt_FreeBitmap(glyph_pixels,
nullptr);
268 const std::shared_ptr<BitmapSTB>&
bitmap,
269 const std::vector<FontGlyphPair>& new_pairs) {
276 auto pos = atlas.FindFontGlyphBounds(pair);
277 if (!
pos.has_value()) {
287 const ISize& atlas_size) {
302 const Rect& location) ->
bool {
312 const std::shared_ptr<Texture>&
texture) {
317 auto texture_descriptor =
texture->GetTextureDescriptor();
319 auto mapping = std::make_shared<fml::NonOwnedMapping>(
320 reinterpret_cast<const uint8_t*
>(
bitmap->GetPixels()),
321 texture_descriptor.GetByteSizeOfBaseMipLevel()
326 return texture->SetContents(mapping);
330 const std::shared_ptr<Allocator>& allocator,
331 std::shared_ptr<BitmapSTB>&
bitmap,
332 const ISize& atlas_size,
344 texture_descriptor.
size = atlas_size;
351 auto texture = allocator->CreateTexture(texture_descriptor);
355 texture->SetLabel(
"GlyphAtlas");
357 auto mapping = std::make_shared<fml::NonOwnedMapping>(
358 reinterpret_cast<const uint8_t*
>(
bitmap->GetPixels()),
364 if (!
texture->SetContents(mapping)) {
373 const std::shared_ptr<GlyphAtlasContext>& atlas_context,
380 std::shared_ptr<GlyphAtlas> last_atlas = atlas_context->GetGlyphAtlas();
382 if (font_glyph_map.empty()) {
390 std::vector<FontGlyphPair> new_glyphs;
391 for (
const auto& font_value : font_glyph_map) {
392 const ScaledFont& scaled_font = font_value.first;
394 last_atlas->GetFontGlyphAtlas(scaled_font.
font, scaled_font.
scale);
395 if (font_glyph_atlas) {
396 for (
const Glyph& glyph : font_value.second) {
398 new_glyphs.emplace_back(scaled_font, glyph);
402 for (
const Glyph& glyph : font_value.second) {
403 new_glyphs.emplace_back(scaled_font, glyph);
407 if (last_atlas->GetType() ==
type && new_glyphs.size() == 0) {
416 std::vector<Rect> glyph_positions;
417 if (last_atlas->GetType() ==
type &&
419 atlas_context->GetAtlasSize(),
420 atlas_context->GetRectPacker())) {
428 for (
size_t i = 0,
count = glyph_positions.size(); i <
count; i++) {
429 last_atlas->AddTypefaceGlyphPosition(new_glyphs[i], glyph_positions[i]);
436 auto bitmap = atlas_context_stb.GetBitmap();
454 std::vector<FontGlyphPair> font_glyph_pairs;
455 font_glyph_pairs.reserve(std::accumulate(
456 font_glyph_map.begin(), font_glyph_map.end(), 0,
457 [](
const int a,
const auto&
b) { return a + b.second.size(); }));
458 for (
const auto& font_value : font_glyph_map) {
459 const ScaledFont& scaled_font = font_value.first;
460 for (
const Glyph& glyph : font_value.second) {
461 font_glyph_pairs.push_back({scaled_font, glyph});
464 auto glyph_atlas = std::make_shared<GlyphAtlas>(
type);
473 atlas_context->UpdateGlyphAtlas(glyph_atlas, atlas_size);
474 if (atlas_size.IsEmpty()) {
484 if (glyph_positions.size() != font_glyph_pairs.size()) {
493 for (
auto it = font_glyph_pairs.begin(); it != font_glyph_pairs.end();
495 glyph_atlas->AddTypefaceGlyphPosition(*it, glyph_positions[i]);
506 atlas_context_stb.UpdateBitmap(
bitmap);
531 glyph_atlas->SetTexture(std::move(
texture));
static uint32_t NextPowerOfTwoSize(uint32_t x)
static GlyphAtlasContextSTB & Cast(GlyphAtlasContext &base)
To do anything rendering related with Impeller, you need a context.
virtual const std::shared_ptr< const Capabilities > & GetCapabilities() const =0
Get the capabilities of Impeller context. All optionally supported feature of the platform,...
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.
std::optional< Rect > FindGlyphBounds(const Glyph &glyph) const
Find the location of a glyph in the atlas.
Describes a typeface along with any modifications to its intrinsic properties.
const Metrics & GetMetrics() const
A texture containing the bitmap representation of glyphs in different fonts along with the ability to...
Type
Describes how the glyphs are represented in the texture.
static std::unique_ptr< RectanglePacker > Factory(int width, int height)
Return an empty packer with area specified by width and height.
static constexpr float kPointsToPixels
static std::unique_ptr< TypographerContext > Make()
std::shared_ptr< GlyphAtlasContext > CreateGlyphAtlasContext() const override
std::shared_ptr< GlyphAtlas > CreateGlyphAtlas(Context &context, GlyphAtlas::Type type, const std::shared_ptr< GlyphAtlasContext > &atlas_context, const FontGlyphMap &font_glyph_map) const override
~TypographerContextSTB() override
The graphics context necessary to render text.
virtual bool IsValid() const
uint32_t uint32_t * format
#define FML_DCHECK(condition)
std::unordered_map< ScaledFont, std::unordered_set< Glyph > > FontGlyphMap
static std::shared_ptr< Texture > UploadGlyphTextureAtlas(const std::shared_ptr< Allocator > &allocator, std::shared_ptr< SkBitmap > bitmap, const ISize &atlas_size, PixelFormat format)
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
static std::shared_ptr< SkBitmap > CreateAtlasBitmap(const GlyphAtlas &atlas, const ISize &atlas_size)
static void DrawGlyph(SkCanvas *canvas, const ScaledFont &scaled_font, const Glyph &glyph, const Rect &location, bool has_color)
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)
static bool UpdateGlyphTextureAtlas(std::shared_ptr< SkBitmap > bitmap, const std::shared_ptr< Texture > &texture)
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)
static bool UpdateAtlasBitmap(const GlyphAtlas &atlas, const std::shared_ptr< SkBitmap > &bitmap, const std::vector< FontGlyphPair > &new_pairs)
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)
static size_t bytes_per_pixel(skcms_PixelFormat fmt)
A font along with a glyph in that font rendered at a particular scale.
const ScaledFont & scaled_font
The glyph index in the typeface.
A font and a scale. Used as a key that represents a typeface within a glyph atlas.
constexpr Type GetY() const
Returns the Y coordinate of the upper left corner, equivalent to |GetOrigin().y|.
constexpr Type GetHeight() const
Returns the height of the rectangle, equivalent to |GetSize().height|.
constexpr Type GetX() const
Returns the X coordinate of the upper left corner, equivalent to |GetOrigin().x|.
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
constexpr Type GetWidth() const
Returns the width of the rectangle, equivalent to |GetSize().width|.
static constexpr TSize MakeWH(Type width, Type height)
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
constexpr size_t GetByteSizeOfBaseMipLevel() const
#define TRACE_EVENT0(category_group, name)
#define DISABLE_COLOR_FONT_SUPPORT
constexpr auto kColorFontBitsPerPixel