10#include "flutter/fml/logging.h"
11#include "flutter/fml/trace_event.h"
21#define DISABLE_COLOR_FONT_SUPPORT 1
22#ifdef DISABLE_COLOR_FONT_SUPPORT
33 return std::make_unique<TypographerContextSTB>();
40std::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) {
109 if (!rect_packer || atlas_size.
IsEmpty()) {
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;
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)) {
194 }
while (current_size.
width <= max_texture_size.
width &&
202 const Rect& location,
207 auto typeface =
font.GetTypeface();
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;
218 auto output =
bitmap->GetPixelAddress({
static_cast<size_t>(location.
GetX()),
219 static_cast<size_t>(location.
GetY())});
223 stbtt_MakeGlyphBitmap(typeface_stb->GetFontInfo(),
output,
225 bitmap->GetRowBytes(), scale_x, scale_y, glyph.
index);
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) {
281 auto pos =
atlas.FindFontGlyphBounds(pair);
282 if (!
pos.has_value()) {
286 pos.value().first, has_color);
292 const ISize& atlas_size) {
307 const Rect& location) ->
bool {
317 const std::shared_ptr<Allocator>& allocator,
318 std::shared_ptr<BlitPass>& blit_pass,
319 const std::shared_ptr<Texture>&
texture) {
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,
356 texture_descriptor.
size = atlas_size;
363 auto texture = allocator->CreateTexture(texture_descriptor);
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 =
389 std::reinterpret_pointer_cast<TypefaceSTB>(
font.font.GetTypeface());
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,
410 std::shared_ptr<GlyphAtlas> last_atlas = atlas_context->GetGlyphAtlas();
412 if (font_glyph_map.empty()) {
417 std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
427 std::vector<FontGlyphPair> new_glyphs;
428 std::vector<Rect> new_sizes;
429 for (
const auto& font_value : font_glyph_map) {
430 const ScaledFont& scaled_font = font_value.first;
432 last_atlas->GetFontGlyphAtlas(scaled_font.
font, scaled_font.
scale);
433 if (font_glyph_atlas) {
436 new_glyphs.emplace_back(scaled_font, glyph);
442 new_glyphs.emplace_back(scaled_font, glyph);
447 if (last_atlas->GetType() ==
type && new_glyphs.size() == 0) {
456 std::vector<Rect> glyph_positions;
457 if (last_atlas->GetType() ==
type &&
459 atlas_context->GetAtlasSize(),
460 atlas_context->GetRectPacker())) {
468 for (
size_t i = 0,
count = glyph_positions.size();
i <
count;
i++) {
469 last_atlas->AddTypefaceGlyphPositionAndBounds(
470 new_glyphs[
i], glyph_positions[
i], new_sizes[
i]);
477 auto bitmap = atlas_context_stb.GetBitmap();
486 blit_pass, last_atlas->GetTexture())) {
496 std::vector<FontGlyphPair> font_glyph_pairs;
497 font_glyph_pairs.reserve(std::accumulate(
498 font_glyph_map.begin(), font_glyph_map.end(), 0,
499 [](
const int a,
const auto&
b) { return a + b.second.size(); }));
500 for (
const auto& font_value : font_glyph_map) {
501 const ScaledFont& scaled_font = font_value.first;
503 font_glyph_pairs.push_back({scaled_font, glyph});
506 auto glyph_atlas = std::make_shared<GlyphAtlas>(
type);
515 atlas_context->UpdateGlyphAtlas(glyph_atlas, atlas_size, 0);
516 if (atlas_size.IsEmpty()) {
526 if (glyph_positions.size() != font_glyph_pairs.size()) {
535 for (
auto it = font_glyph_pairs.begin(); it != font_glyph_pairs.end();
537 glyph_atlas->AddTypefaceGlyphPositionAndBounds(*it, glyph_positions[
i],
549 atlas_context_stb.UpdateBitmap(
bitmap);
574 glyph_atlas->SetTexture(std::move(
texture));
Wraps a closure that is invoked in the destructor unless released by the caller.
static uint32_t NextPowerOfTwoSize(uint32_t x)
static GlyphAtlasContextSTB & Cast(GlyphAtlasContext &base)
To do anything rendering related with Impeller, you need a context.
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 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.
static BufferView AsBufferView(std::shared_ptr< DeviceBuffer > buffer)
Create a buffer view of this entire buffer.
An object that can look up glyph locations within the GlyphAtlas for a particular typeface.
std::optional< std::pair< Rect, Rect > > FindGlyphBounds(const SubpixelGlyph &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::shared_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< 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
~TypographerContextSTB() override
The graphics context necessary to render text.
virtual bool IsValid() const
uint32_t uint32_t * format
#define FML_DCHECK(condition)
static float max(float r, float g, float b)
static float min(float r, float g, float b)
sk_sp< const SkImage > atlas
std::function< void()> closure
font
Font Metadata and Metrics.
static void DrawGlyph(SkCanvas *canvas, const ScaledFont &scaled_font, const SubpixelGlyph &glyph, const Rect &scaled_bounds, const GlyphProperties &prop, bool has_color)
static Rect ComputeGlyphSize(const SkFont &font, const SubpixelGlyph &glyph, Scalar scale)
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)
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
static std::shared_ptr< BitmapSTB > CreateAtlasBitmap(const GlyphAtlas &atlas, const ISize &atlas_size)
std::unordered_map< ScaledFont, std::unordered_set< SubpixelGlyph > > FontGlyphMap
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< BitmapSTB > &bitmap, const std::shared_ptr< Allocator > &allocator, std::shared_ptr< BlitPass > &blit_pass, const std::shared_ptr< Texture > &texture)
static std::shared_ptr< Texture > UploadGlyphTextureAtlas(const std::shared_ptr< Allocator > &allocator, std::shared_ptr< BlitPass > &blit_pass, std::shared_ptr< BitmapSTB > &bitmap, const ISize &atlas_size, PixelFormat format)
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)
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)
SIN Vec< N, float > ceil(const Vec< N, float > &x)
static size_t bytes_per_pixel(skcms_PixelFormat fmt)
A font along with a glyph in that font rendered at a particular scale and subpixel position.
const SubpixelGlyph & glyph
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.
A glyph and its subpixel position.
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 TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
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