39#include "imgui_freetype.h"
40#include "imgui_internal.h"
46#include FT_SYNTHESIS_H
48#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
52#if !((FREETYPE_MAJOR >= 2) && (FREETYPE_MINOR >= 12))
53#error IMGUI_ENABLE_FREETYPE_LUNASVG requires FreeType version >= 2.12
59#pragma warning (disable: 4505)
60#pragma warning (disable: 26812)
64#pragma GCC diagnostic push
65#pragma GCC diagnostic ignored "-Wpragmas"
66#pragma GCC diagnostic ignored "-Wunused-function"
68#pragma GCC diagnostic ignored "-Wsubobject-linkage"
77static void* ImGuiFreeTypeDefaultAllocFunc(
size_t size,
void* user_data) { IM_UNUSED(user_data);
return IM_ALLOC(size); }
78static void ImGuiFreeTypeDefaultFreeFunc(
void* ptr,
void* user_data) { IM_UNUSED(user_data); IM_FREE(ptr); }
81static void* (*GImGuiFreeTypeAllocFunc)(
size_t size,
void* user_data) = ImGuiFreeTypeDefaultAllocFunc;
82static void (*GImGuiFreeTypeFreeFunc)(
void* ptr,
void* user_data) = ImGuiFreeTypeDefaultFreeFunc;
83static void* GImGuiFreeTypeAllocatorUserData =
nullptr;
86#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
87static FT_Error ImGuiLunasvgPortInit(FT_Pointer* state);
88static void ImGuiLunasvgPortFree(FT_Pointer* state);
89static FT_Error ImGuiLunasvgPortRender(FT_GlyphSlot slot, FT_Pointer* _state);
90static FT_Error ImGuiLunasvgPortPresetSlot(FT_GlyphSlot slot, FT_Bool cache, FT_Pointer* _state);
144 uint32_t PixelHeight;
149 float MaxAdvanceWidth;
156 bool InitFont(FT_Library ft_library,
const ImFontConfig& cfg,
unsigned int extra_user_flags);
158 void SetPixelHeight(
int pixel_height);
159 const FT_Glyph_Metrics* LoadGlyph(uint32_t in_codepoint);
160 const FT_Bitmap* RenderGlyphAndGetInfo(GlyphInfo* out_glyph_info);
161 void BlitGlyph(
const FT_Bitmap* ft_bitmap, uint32_t* dst, uint32_t dst_pitch,
unsigned char* multiply_table =
nullptr);
162 ~FreeTypeFont() { CloseFont(); }
167 unsigned int UserFlags;
169 FT_Render_Mode RenderMode;
170 float RasterizationDensity;
171 float InvRasterizationDensity;
175 #define FT_CEIL(X) (((X + 63) & -64) / 64)
177 bool FreeTypeFont::InitFont(FT_Library ft_library,
const ImFontConfig& cfg,
unsigned int extra_font_builder_flags)
179 FT_Error error = FT_New_Memory_Face(ft_library, (uint8_t*)cfg.FontData, (uint32_t)cfg.FontDataSize, (uint32_t)cfg.FontNo, &Face);
182 error = FT_Select_Charmap(Face, FT_ENCODING_UNICODE);
187 UserFlags = cfg.FontBuilderFlags | extra_font_builder_flags;
190 if ((UserFlags & ImGuiFreeTypeBuilderFlags_Bitmap) == 0)
191 LoadFlags |= FT_LOAD_NO_BITMAP;
193 if (UserFlags & ImGuiFreeTypeBuilderFlags_NoHinting)
194 LoadFlags |= FT_LOAD_NO_HINTING;
195 if (UserFlags & ImGuiFreeTypeBuilderFlags_NoAutoHint)
196 LoadFlags |= FT_LOAD_NO_AUTOHINT;
197 if (UserFlags & ImGuiFreeTypeBuilderFlags_ForceAutoHint)
198 LoadFlags |= FT_LOAD_FORCE_AUTOHINT;
199 if (UserFlags & ImGuiFreeTypeBuilderFlags_LightHinting)
200 LoadFlags |= FT_LOAD_TARGET_LIGHT;
201 else if (UserFlags & ImGuiFreeTypeBuilderFlags_MonoHinting)
202 LoadFlags |= FT_LOAD_TARGET_MONO;
204 LoadFlags |= FT_LOAD_TARGET_NORMAL;
206 if (UserFlags & ImGuiFreeTypeBuilderFlags_Monochrome)
207 RenderMode = FT_RENDER_MODE_MONO;
209 RenderMode = FT_RENDER_MODE_NORMAL;
211 if (UserFlags & ImGuiFreeTypeBuilderFlags_LoadColor)
212 LoadFlags |= FT_LOAD_COLOR;
214 RasterizationDensity = cfg.RasterizerDensity;
215 InvRasterizationDensity = 1.0f / RasterizationDensity;
217 memset(&Info, 0,
sizeof(Info));
218 SetPixelHeight((uint32_t)cfg.SizePixels);
223 void FreeTypeFont::CloseFont()
232 void FreeTypeFont::SetPixelHeight(
int pixel_height)
237 FT_Size_RequestRec req;
238 req.type = (UserFlags & ImGuiFreeTypeBuilderFlags_Bitmap) ? FT_SIZE_REQUEST_TYPE_NOMINAL : FT_SIZE_REQUEST_TYPE_REAL_DIM;
240 req.height = (uint32_t)(pixel_height * 64 * RasterizationDensity);
241 req.horiResolution = 0;
242 req.vertResolution = 0;
243 FT_Request_Size(Face, &req);
246 FT_Size_Metrics metrics = Face->size->metrics;
247 Info.PixelHeight = (uint32_t)(pixel_height * InvRasterizationDensity);
248 Info.Ascender = (float)
FT_CEIL(metrics.ascender) * InvRasterizationDensity;
249 Info.Descender = (float)
FT_CEIL(metrics.descender) * InvRasterizationDensity;
250 Info.LineSpacing = (float)
FT_CEIL(metrics.height) * InvRasterizationDensity;
251 Info.LineGap = (float)
FT_CEIL(metrics.height - metrics.ascender + metrics.descender) * InvRasterizationDensity;
252 Info.MaxAdvanceWidth = (float)
FT_CEIL(metrics.max_advance) * InvRasterizationDensity;
255 const FT_Glyph_Metrics* FreeTypeFont::LoadGlyph(uint32_t codepoint)
257 uint32_t glyph_index = FT_Get_Char_Index(Face, codepoint);
258 if (glyph_index == 0)
266 FT_Error error = FT_Load_Glyph(Face, glyph_index, LoadFlags);
271 FT_GlyphSlot slot = Face->glyph;
272#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
273 IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE || slot->format == FT_GLYPH_FORMAT_BITMAP || slot->format == FT_GLYPH_FORMAT_SVG);
275#if ((FREETYPE_MAJOR >= 2) && (FREETYPE_MINOR >= 12))
276 IM_ASSERT(slot->format != FT_GLYPH_FORMAT_SVG &&
"The font contains SVG glyphs, you'll need to enable IMGUI_ENABLE_FREETYPE_LUNASVG in imconfig.h and install required libraries in order to use this font");
278 IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE || slot->format == FT_GLYPH_FORMAT_BITMAP);
282 if (UserFlags & ImGuiFreeTypeBuilderFlags_Bold)
283 FT_GlyphSlot_Embolden(slot);
284 if (UserFlags & ImGuiFreeTypeBuilderFlags_Oblique)
286 FT_GlyphSlot_Oblique(slot);
293 return &slot->metrics;
296 const FT_Bitmap* FreeTypeFont::RenderGlyphAndGetInfo(GlyphInfo* out_glyph_info)
298 FT_GlyphSlot slot = Face->glyph;
299 FT_Error error = FT_Render_Glyph(slot, RenderMode);
303 FT_Bitmap* ft_bitmap = &Face->glyph->bitmap;
304 out_glyph_info->Width = (int)ft_bitmap->width;
305 out_glyph_info->Height = (int)ft_bitmap->rows;
306 out_glyph_info->OffsetX = Face->glyph->bitmap_left;
307 out_glyph_info->OffsetY = -Face->glyph->bitmap_top;
308 out_glyph_info->AdvanceX = (float)
FT_CEIL(slot->advance.x);
309 out_glyph_info->IsColored = (ft_bitmap->pixel_mode == FT_PIXEL_MODE_BGRA);
314 void FreeTypeFont::BlitGlyph(
const FT_Bitmap* ft_bitmap, uint32_t* dst, uint32_t dst_pitch,
unsigned char* multiply_table)
316 IM_ASSERT(ft_bitmap !=
nullptr);
317 const uint32_t w = ft_bitmap->width;
318 const uint32_t h = ft_bitmap->rows;
319 const uint8_t* src = ft_bitmap->buffer;
320 const uint32_t src_pitch = ft_bitmap->pitch;
322 switch (ft_bitmap->pixel_mode)
324 case FT_PIXEL_MODE_GRAY:
326 if (multiply_table ==
nullptr)
328 for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
329 for (uint32_t x = 0; x < w; x++)
330 dst[x] = IM_COL32(255, 255, 255, src[x]);
334 for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
335 for (uint32_t x = 0; x < w; x++)
336 dst[x] = IM_COL32(255, 255, 255, multiply_table[src[x]]);
340 case FT_PIXEL_MODE_MONO:
342 uint8_t color0 = multiply_table ? multiply_table[0] : 0;
343 uint8_t color1 = multiply_table ? multiply_table[255] : 255;
344 for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
347 const uint8_t* bits_ptr = src;
348 for (uint32_t x = 0; x < w; x++, bits <<= 1)
352 dst[x] = IM_COL32(255, 255, 255, (bits & 0x80) ? color1 : color0);
357 case FT_PIXEL_MODE_BGRA:
360 #define DE_MULTIPLY(color, alpha) (ImU32)(255.0f * (float)color / (float)alpha + 0.5f)
361 if (multiply_table ==
nullptr)
363 for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
364 for (uint32_t x = 0; x < w; x++)
366 uint8_t r = src[x * 4 + 2],
g = src[x * 4 + 1], b = src[x * 4], a = src[x * 4 + 3];
372 for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
374 for (uint32_t x = 0; x < w; x++)
376 uint8_t r = src[x * 4 + 2],
g = src[x * 4 + 1], b = src[x * 4], a = src[x * 4 + 3];
385 IM_ASSERT(0 &&
"FreeTypeFont::BlitGlyph(): Unknown bitmap pixel mode!");
390#ifndef STB_RECT_PACK_IMPLEMENTATION
391#ifndef IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
392#define STBRP_ASSERT(x) do { IM_ASSERT(x); } while (0)
394#define STB_RECT_PACK_IMPLEMENTATION
396#ifdef IMGUI_STB_RECT_PACK_FILENAME
397#include IMGUI_STB_RECT_PACK_FILENAME
399#include "imstb_rectpack.h"
435 IM_ASSERT(atlas->ConfigData.Size > 0);
441 atlas->TexWidth = atlas->TexHeight = 0;
442 atlas->TexUvScale = ImVec2(0.0f, 0.0f);
443 atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f);
444 atlas->ClearTexData();
447 bool src_load_color =
false;
448 ImVector<ImFontBuildSrcDataFT> src_tmp_array;
449 ImVector<ImFontBuildDstDataFT> dst_tmp_array;
450 src_tmp_array.resize(atlas->ConfigData.Size);
451 dst_tmp_array.resize(atlas->Fonts.Size);
452 memset((
void*)src_tmp_array.Data, 0, (
size_t)src_tmp_array.size_in_bytes());
453 memset((
void*)dst_tmp_array.Data, 0, (
size_t)dst_tmp_array.size_in_bytes());
456 for (
int src_i = 0; src_i < atlas->ConfigData.Size; src_i++)
459 ImFontConfig& cfg = atlas->ConfigData[src_i];
460 FreeTypeFont& font_face = src_tmp.
Font;
461 IM_ASSERT(cfg.DstFont && (!cfg.DstFont->IsLoaded() || cfg.DstFont->ContainerAtlas == atlas));
465 for (
int output_i = 0; output_i < atlas->Fonts.Size && src_tmp.
DstIndex == -1; output_i++)
466 if (cfg.DstFont == atlas->Fonts[output_i])
473 if (!font_face.InitFont(ft_library, cfg, extra_flags))
477 src_load_color |= (cfg.FontBuilderFlags & ImGuiFreeTypeBuilderFlags_LoadColor) != 0;
479 src_tmp.
SrcRanges = cfg.GlyphRanges ? cfg.GlyphRanges : atlas->GetGlyphRangesDefault();
480 for (
const ImWchar* src_range = src_tmp.
SrcRanges; src_range[0] && src_range[1]; src_range += 2)
484 IM_ASSERT(src_range[0] <= src_range[1]);
492 int total_glyphs_count = 0;
493 for (
int src_i = 0; src_i < src_tmp_array.Size; src_i++)
501 for (
const ImWchar* src_range = src_tmp.
SrcRanges; src_range[0] && src_range[1]; src_range += 2)
502 for (
int codepoint = src_range[0]; codepoint <= (int)src_range[1]; codepoint++)
504 if (dst_tmp.
GlyphsSet.TestBit(codepoint))
506 uint32_t glyph_index = FT_Get_Char_Index(src_tmp.
Font.Face, codepoint);
507 if (glyph_index == 0)
515 total_glyphs_count++;
520 for (
int src_i = 0; src_i < src_tmp_array.Size; src_i++)
525 IM_ASSERT(
sizeof(src_tmp.
GlyphsSet.Storage.Data[0]) ==
sizeof(ImU32));
526 const ImU32* it_begin = src_tmp.
GlyphsSet.Storage.begin();
527 const ImU32* it_end = src_tmp.
GlyphsSet.Storage.end();
528 for (
const ImU32* it = it_begin; it < it_end; it++)
529 if (ImU32 entries_32 = *it)
530 for (ImU32 bit_n = 0; bit_n < 32; bit_n++)
531 if (entries_32 & ((ImU32)1 << bit_n))
534 src_glyph.
Codepoint = (ImWchar)(((it - it_begin) << 5) + bit_n);
541 for (
int dst_i = 0; dst_i < dst_tmp_array.Size; dst_i++)
542 dst_tmp_array[dst_i].GlyphsSet.Clear();
543 dst_tmp_array.clear();
547 ImVector<stbrp_rect> buf_rects;
548 buf_rects.resize(total_glyphs_count);
549 memset(buf_rects.Data, 0, (
size_t)buf_rects.size_in_bytes());
555 const int BITMAP_BUFFERS_CHUNK_SIZE = 256 * 1024;
556 int buf_bitmap_current_used_bytes = 0;
557 ImVector<unsigned char*> buf_bitmap_buffers;
558 buf_bitmap_buffers.push_back((
unsigned char*)IM_ALLOC(BITMAP_BUFFERS_CHUNK_SIZE));
562 int total_surface = 0;
563 int buf_rects_out_n = 0;
564 for (
int src_i = 0; src_i < src_tmp_array.Size; src_i++)
567 ImFontConfig& cfg = atlas->ConfigData[src_i];
571 src_tmp.
Rects = &buf_rects[buf_rects_out_n];
575 const bool multiply_enabled = (cfg.RasterizerMultiply != 1.0f);
576 unsigned char multiply_table[256];
577 if (multiply_enabled)
581 const int padding = atlas->TexGlyphPadding;
582 for (
int glyph_i = 0; glyph_i < src_tmp.
GlyphsList.Size; glyph_i++)
586 const FT_Glyph_Metrics* metrics = src_tmp.
Font.LoadGlyph(src_glyph.
Codepoint);
587 if (metrics ==
nullptr)
591 const FT_Bitmap* ft_bitmap = src_tmp.
Font.RenderGlyphAndGetInfo(&src_glyph.
Info);
592 if (ft_bitmap ==
nullptr)
596 const int bitmap_size_in_bytes = src_glyph.
Info.Width * src_glyph.
Info.Height * 4;
597 if (buf_bitmap_current_used_bytes + bitmap_size_in_bytes > BITMAP_BUFFERS_CHUNK_SIZE)
599 buf_bitmap_current_used_bytes = 0;
600 buf_bitmap_buffers.push_back((
unsigned char*)IM_ALLOC(BITMAP_BUFFERS_CHUNK_SIZE));
602 IM_ASSERT(buf_bitmap_current_used_bytes + bitmap_size_in_bytes <= BITMAP_BUFFERS_CHUNK_SIZE);
605 src_glyph.
BitmapData = (
unsigned int*)(buf_bitmap_buffers.back() + buf_bitmap_current_used_bytes);
606 buf_bitmap_current_used_bytes += bitmap_size_in_bytes;
607 src_tmp.
Font.BlitGlyph(ft_bitmap, src_glyph.
BitmapData, src_glyph.
Info.Width, multiply_enabled ? multiply_table :
nullptr);
609 src_tmp.
Rects[glyph_i].w = (stbrp_coord)(src_glyph.
Info.Width + padding);
610 src_tmp.
Rects[glyph_i].h = (stbrp_coord)(src_glyph.
Info.Height + padding);
611 total_surface += src_tmp.
Rects[glyph_i].w * src_tmp.
Rects[glyph_i].h;
618 const int surface_sqrt = (int)ImSqrt((
float)total_surface) + 1;
619 atlas->TexHeight = 0;
620 if (atlas->TexDesiredWidth > 0)
621 atlas->TexWidth = atlas->TexDesiredWidth;
623 atlas->TexWidth = (surface_sqrt >= 4096 * 0.7f) ? 4096 : (surface_sqrt >= 2048 * 0.7f) ? 2048 : (surface_sqrt >= 1024 * 0.7f) ? 1024 : 512;
627 const int TEX_HEIGHT_MAX = 1024 * 32;
628 const int num_nodes_for_packing_algorithm = atlas->TexWidth - atlas->TexGlyphPadding;
629 ImVector<stbrp_node> pack_nodes;
630 pack_nodes.resize(num_nodes_for_packing_algorithm);
631 stbrp_context pack_context;
632 stbrp_init_target(&pack_context, atlas->TexWidth - atlas->TexGlyphPadding, TEX_HEIGHT_MAX - atlas->TexGlyphPadding, pack_nodes.Data, pack_nodes.Size);
636 for (
int src_i = 0; src_i < src_tmp_array.Size; src_i++)
646 for (
int glyph_i = 0; glyph_i < src_tmp.
GlyphsCount; glyph_i++)
647 if (src_tmp.
Rects[glyph_i].was_packed)
648 atlas->TexHeight = ImMax(atlas->TexHeight, src_tmp.
Rects[glyph_i].y + src_tmp.
Rects[glyph_i].h);
652 atlas->TexHeight = (atlas->Flags & ImFontAtlasFlags_NoPowerOfTwoHeight) ? (atlas->TexHeight + 1) : ImUpperPowerOfTwo(atlas->TexHeight);
653 atlas->TexUvScale = ImVec2(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight);
656 size_t tex_size = (size_t)atlas->TexWidth * atlas->TexHeight * 4;
657 atlas->TexPixelsRGBA32 = (
unsigned int*)IM_ALLOC(tex_size);
658 memset(atlas->TexPixelsRGBA32, 0, tex_size);
662 size_t tex_size = (size_t)atlas->TexWidth * atlas->TexHeight * 1;
663 atlas->TexPixelsAlpha8 = (
unsigned char*)IM_ALLOC(tex_size);
664 memset(atlas->TexPixelsAlpha8, 0, tex_size);
669 bool tex_use_colors =
false;
670 for (
int src_i = 0; src_i < src_tmp_array.Size; src_i++)
679 ImFontConfig& cfg = atlas->ConfigData[src_i];
680 ImFont* dst_font = cfg.DstFont;
682 const float ascent = src_tmp.
Font.Info.Ascender;
683 const float descent = src_tmp.
Font.Info.Descender;
685 const float font_off_x = cfg.GlyphOffset.x;
686 const float font_off_y = cfg.GlyphOffset.y + IM_ROUND(dst_font->Ascent);
688 const int padding = atlas->TexGlyphPadding;
689 for (
int glyph_i = 0; glyph_i < src_tmp.
GlyphsCount; glyph_i++)
692 stbrp_rect& pack_rect = src_tmp.
Rects[glyph_i];
693 IM_ASSERT(pack_rect.was_packed);
694 if (pack_rect.w == 0 && pack_rect.h == 0)
697 GlyphInfo& info = src_glyph.
Info;
698 IM_ASSERT(info.Width + padding <= pack_rect.w);
699 IM_ASSERT(info.Height + padding <= pack_rect.h);
700 const int tx = pack_rect.x + padding;
701 const int ty = pack_rect.y + padding;
704 float x0 = info.OffsetX * src_tmp.
Font.InvRasterizationDensity + font_off_x;
705 float y0 = info.OffsetY * src_tmp.
Font.InvRasterizationDensity + font_off_y;
706 float x1 = x0 + info.Width * src_tmp.
Font.InvRasterizationDensity;
707 float y1 = y0 + info.Height * src_tmp.
Font.InvRasterizationDensity;
708 float u0 = (tx) / (
float)atlas->TexWidth;
709 float v0 = (ty) / (
float)atlas->TexHeight;
710 float u1 = (tx + info.Width) / (
float)atlas->TexWidth;
711 float v1 = (ty + info.Height) / (
float)atlas->TexHeight;
712 dst_font->AddGlyph(&cfg, (ImWchar)src_glyph.
Codepoint, x0, y0, x1, y1, u0, v0, u1, v1, info.AdvanceX * src_tmp.
Font.InvRasterizationDensity);
714 ImFontGlyph* dst_glyph = &dst_font->Glyphs.back();
715 IM_ASSERT(dst_glyph->Codepoint == src_glyph.
Codepoint);
716 if (src_glyph.
Info.IsColored)
717 dst_glyph->Colored = tex_use_colors =
true;
720 size_t blit_src_stride = (size_t)src_glyph.
Info.Width;
721 size_t blit_dst_stride = (size_t)atlas->TexWidth;
722 unsigned int* blit_src = src_glyph.
BitmapData;
723 if (atlas->TexPixelsAlpha8 !=
nullptr)
725 unsigned char* blit_dst = atlas->TexPixelsAlpha8 + (ty * blit_dst_stride) + tx;
726 for (
int y = 0; y < info.Height; y++, blit_dst += blit_dst_stride, blit_src += blit_src_stride)
727 for (
int x = 0; x < info.Width; x++)
728 blit_dst[x] = (
unsigned char)((blit_src[x] >> IM_COL32_A_SHIFT) & 0xFF);
732 unsigned int* blit_dst = atlas->TexPixelsRGBA32 + (ty * blit_dst_stride) + tx;
733 for (
int y = 0; y < info.Height; y++, blit_dst += blit_dst_stride, blit_src += blit_src_stride)
734 for (
int x = 0; x < info.Width; x++)
735 blit_dst[x] = blit_src[x];
739 src_tmp.
Rects =
nullptr;
741 atlas->TexPixelsUseColors = tex_use_colors;
744 for (
int buf_i = 0; buf_i < buf_bitmap_buffers.Size; buf_i++)
745 IM_FREE(buf_bitmap_buffers[buf_i]);
746 src_tmp_array.clear_destruct();
754static void* FreeType_Alloc(FT_Memory ,
long size)
756 return GImGuiFreeTypeAllocFunc((
size_t)size, GImGuiFreeTypeAllocatorUserData);
759static void FreeType_Free(FT_Memory ,
void* block)
761 GImGuiFreeTypeFreeFunc(block, GImGuiFreeTypeAllocatorUserData);
764static void* FreeType_Realloc(FT_Memory ,
long cur_size,
long new_size,
void* block)
767 if (block ==
nullptr)
768 return GImGuiFreeTypeAllocFunc((
size_t)new_size, GImGuiFreeTypeAllocatorUserData);
772 GImGuiFreeTypeFreeFunc(block, GImGuiFreeTypeAllocatorUserData);
776 if (new_size > cur_size)
778 void* new_block = GImGuiFreeTypeAllocFunc((
size_t)new_size, GImGuiFreeTypeAllocatorUserData);
779 memcpy(new_block, block, (
size_t)cur_size);
780 GImGuiFreeTypeFreeFunc(block, GImGuiFreeTypeAllocatorUserData);
787static bool ImFontAtlasBuildWithFreeType(ImFontAtlas* atlas)
790 FT_MemoryRec_ memory_rec = {};
791 memory_rec.user =
nullptr;
792 memory_rec.alloc = &FreeType_Alloc;
793 memory_rec.free = &FreeType_Free;
794 memory_rec.realloc = &FreeType_Realloc;
797 FT_Library ft_library;
798 FT_Error error = FT_New_Library(&memory_rec, &ft_library);
803 FT_Add_Default_Modules(ft_library);
805#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
809 SVG_RendererHooks hooks = { ImGuiLunasvgPortInit, ImGuiLunasvgPortFree, ImGuiLunasvgPortRender, ImGuiLunasvgPortPresetSlot };
810 FT_Property_Set(ft_library,
"ot-svg",
"svg-hooks", &hooks);
814 FT_Done_Library(ft_library);
819const ImFontBuilderIO* ImGuiFreeType::GetBuilderForFreeType()
821 static ImFontBuilderIO io;
822 io.FontBuilder_Build = ImFontAtlasBuildWithFreeType;
826void ImGuiFreeType::SetAllocatorFunctions(
void* (*alloc_func)(
size_t sz,
void* user_data),
void (*free_func)(
void* ptr,
void* user_data),
void* user_data)
828 GImGuiFreeTypeAllocFunc = alloc_func;
829 GImGuiFreeTypeFreeFunc = free_func;
830 GImGuiFreeTypeAllocatorUserData = user_data;
833#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
836struct LunasvgPortState
838 FT_Error err = FT_Err_Ok;
839 lunasvg::Matrix matrix;
840 std::unique_ptr<lunasvg::Document> svg =
nullptr;
843static FT_Error ImGuiLunasvgPortInit(FT_Pointer* _state)
845 *_state = IM_NEW(LunasvgPortState)();
849static void ImGuiLunasvgPortFree(FT_Pointer* _state)
851 IM_DELETE(*(LunasvgPortState**)_state);
854static FT_Error ImGuiLunasvgPortRender(FT_GlyphSlot slot, FT_Pointer* _state)
856 LunasvgPortState* state = *(LunasvgPortState**)_state;
859 if (state->err != FT_Err_Ok)
863 lunasvg::Bitmap bitmap((uint8_t*)slot->bitmap.buffer, slot->bitmap.width, slot->bitmap.rows, slot->bitmap.pitch);
864 state->svg->setMatrix(state->svg->matrix().identity());
865 state->svg->render(bitmap, state->matrix);
866 state->err = FT_Err_Ok;
870static FT_Error ImGuiLunasvgPortPresetSlot(FT_GlyphSlot slot, FT_Bool cache, FT_Pointer* _state)
872 FT_SVG_Document document = (FT_SVG_Document)slot->other;
873 LunasvgPortState* state = *(LunasvgPortState**)_state;
874 FT_Size_Metrics& metrics = document->metrics;
881 state->svg = lunasvg::Document::loadFromData((
const char*)document->svg_document, document->svg_document_length);
882 if (state->svg ==
nullptr)
884 state->err = FT_Err_Invalid_SVG_Document;
888 lunasvg::Box box = state->svg->box();
889 double scale = std::min(metrics.x_ppem / box.w, metrics.y_ppem / box.h);
890 double xx = (double)document->transform.xx / (1 << 16);
891 double xy = -(double)document->transform.xy / (1 << 16);
892 double yx = -(double)document->transform.yx / (1 << 16);
893 double yy = (double)document->transform.yy / (1 << 16);
894 double x0 = (double)document->delta.x / 64 * box.w / metrics.x_ppem;
895 double y0 = -(double)document->delta.y / 64 * box.h / metrics.y_ppem;
898 state->matrix.identity();
899 state->matrix.scale(scale, scale);
900 state->matrix.transform(xx, xy, yx, yy, x0, y0);
901 state->svg->setMatrix(state->matrix);
904 state->matrix.translate(-box.x, -box.y);
907 box = state->svg->box();
910 slot->bitmap_left = FT_Int(box.x);
911 slot->bitmap_top = FT_Int(-box.y);
912 slot->bitmap.rows = (
unsigned int)(ImCeil((
float)box.h));
913 slot->bitmap.width = (
unsigned int)(ImCeil((
float)box.w));
914 slot->bitmap.pitch = slot->bitmap.width * 4;
915 slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
918 double metrics_width = box.w;
919 double metrics_height = box.h;
920 double horiBearingX = box.x;
921 double horiBearingY = -box.y;
922 double vertBearingX = slot->metrics.horiBearingX / 64.0 - slot->metrics.horiAdvance / 64.0 / 2.0;
923 double vertBearingY = (slot->metrics.vertAdvance / 64.0 - slot->metrics.height / 64.0) / 2.0;
924 slot->metrics.width = FT_Pos(IM_ROUND(metrics_width * 64.0));
925 slot->metrics.height = FT_Pos(IM_ROUND(metrics_height * 64.0));
926 slot->metrics.horiBearingX = FT_Pos(horiBearingX * 64);
927 slot->metrics.horiBearingY = FT_Pos(horiBearingY * 64);
928 slot->metrics.vertBearingX = FT_Pos(vertBearingX * 64);
929 slot->metrics.vertBearingY = FT_Pos(vertBearingY * 64);
931 if (slot->metrics.vertAdvance == 0)
932 slot->metrics.vertAdvance = FT_Pos(metrics_height * 1.2 * 64.0);
934 state->err = FT_Err_Ok;
943#pragma GCC diagnostic pop
void ImFontAtlasBuildSetupFont(ImFontAtlas *atlas, ImFont *font, ImFontConfig *font_config, float ascent, float descent)
void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_brighten_factor)
void ImFontAtlasBuildInit(ImFontAtlas *atlas)
void ImFontAtlasBuildFinish(ImFontAtlas *atlas)
void ImFontAtlasBuildPackCustomRects(ImFontAtlas *atlas, void *stbrp_context_opaque)
#define DE_MULTIPLY(color, alpha)
bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas *atlas, unsigned int extra_flags)
constexpr mat4 scale(const vec3 &xyz)
size_t size(std::string_view utf8)
ImVector< ImFontBuildSrcGlyphFT > GlyphsList
const ImWchar * SrcRanges
unsigned int * BitmapData