mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-11-03 22:51:06 +01:00 
			
		
		
		
	imgui_freetype: add support for colored glyphs with ImGuiFreeTypeBuilderFlags_LoadColor (#3369)
(squashed 4 commits)
This commit is contained in:
		@@ -2457,6 +2457,16 @@ void ImFontAtlasBuildRender8bppRectFromString(ImFontAtlas* atlas, int x, int y,
 | 
			
		||||
            out_pixel[off_x] = (in_str[off_x] == in_marker_char) ? in_marker_pixel_value : 0x00;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ImFontAtlasBuildRender32bppRectFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char, unsigned int in_marker_pixel_value)
 | 
			
		||||
{
 | 
			
		||||
    IM_ASSERT(x >= 0 && x + w <= atlas->TexWidth);
 | 
			
		||||
    IM_ASSERT(y >= 0 && y + h <= atlas->TexHeight);
 | 
			
		||||
    unsigned int* out_pixel = atlas->TexPixelsRGBA32 + x + (y * atlas->TexWidth);
 | 
			
		||||
    for (int off_y = 0; off_y < h; off_y++, out_pixel += atlas->TexWidth, in_str += w)
 | 
			
		||||
        for (int off_x = 0; off_x < w; off_x++)
 | 
			
		||||
            out_pixel[off_x] = (in_str[off_x] == in_marker_char) ? in_marker_pixel_value : IM_COL32_BLACK_TRANS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas)
 | 
			
		||||
{
 | 
			
		||||
    ImFontAtlasCustomRect* r = atlas->GetCustomRectByIndex(atlas->PackIdMouseCursors);
 | 
			
		||||
@@ -2469,15 +2479,30 @@ static void ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas)
 | 
			
		||||
        IM_ASSERT(r->Width == FONT_ATLAS_DEFAULT_TEX_DATA_W * 2 + 1 && r->Height == FONT_ATLAS_DEFAULT_TEX_DATA_H);
 | 
			
		||||
        const int x_for_white = r->X;
 | 
			
		||||
        const int x_for_black = r->X + FONT_ATLAS_DEFAULT_TEX_DATA_W + 1;
 | 
			
		||||
        ImFontAtlasBuildRender8bppRectFromString(atlas, x_for_white, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, '.', 0xFF);
 | 
			
		||||
        ImFontAtlasBuildRender8bppRectFromString(atlas, x_for_black, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, 'X', 0xFF);
 | 
			
		||||
        if (atlas->TexPixelsAlpha8 != NULL)
 | 
			
		||||
        {
 | 
			
		||||
            ImFontAtlasBuildRender8bppRectFromString(atlas, x_for_white, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, '.', 0xFF);
 | 
			
		||||
            ImFontAtlasBuildRender8bppRectFromString(atlas, x_for_black, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, 'X', 0xFF);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            ImFontAtlasBuildRender32bppRectFromString(atlas, x_for_white, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, '.', IM_COL32_WHITE);
 | 
			
		||||
            ImFontAtlasBuildRender32bppRectFromString(atlas, x_for_black, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, 'X', IM_COL32_WHITE);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        // Render 4 white pixels
 | 
			
		||||
        IM_ASSERT(r->Width == 2 && r->Height == 2);
 | 
			
		||||
        const int offset = (int)r->X + (int)r->Y * w;
 | 
			
		||||
        atlas->TexPixelsAlpha8[offset] = atlas->TexPixelsAlpha8[offset + 1] = atlas->TexPixelsAlpha8[offset + w] = atlas->TexPixelsAlpha8[offset + w + 1] = 0xFF;
 | 
			
		||||
        if (atlas->TexPixelsAlpha8 != NULL)
 | 
			
		||||
        {
 | 
			
		||||
            atlas->TexPixelsAlpha8[offset] = atlas->TexPixelsAlpha8[offset + 1] = atlas->TexPixelsAlpha8[offset + w] = atlas->TexPixelsAlpha8[offset + w + 1] = 0xFF;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            atlas->TexPixelsRGBA32[offset] = atlas->TexPixelsRGBA32[offset + 1] = atlas->TexPixelsRGBA32[offset + w] = atlas->TexPixelsRGBA32[offset + w + 1] = IM_COL32_WHITE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    atlas->TexUvWhitePixel = ImVec2((r->X + 0.5f) * atlas->TexUvScale.x, (r->Y + 0.5f) * atlas->TexUvScale.y);
 | 
			
		||||
}
 | 
			
		||||
@@ -2500,10 +2525,30 @@ static void ImFontAtlasBuildRenderLinesTexData(ImFontAtlas* atlas)
 | 
			
		||||
 | 
			
		||||
        // Write each slice
 | 
			
		||||
        IM_ASSERT(pad_left + line_width + pad_right == r->Width && y < r->Height); // Make sure we're inside the texture bounds before we start writing pixels
 | 
			
		||||
        unsigned char* write_ptr = &atlas->TexPixelsAlpha8[r->X + ((r->Y + y) * atlas->TexWidth)];
 | 
			
		||||
        memset(write_ptr, 0x00, pad_left);
 | 
			
		||||
        memset(write_ptr + pad_left, 0xFF, line_width);
 | 
			
		||||
        memset(write_ptr + pad_left + line_width, 0x00, pad_right);
 | 
			
		||||
        if (atlas->TexPixelsAlpha8 != NULL)
 | 
			
		||||
        {
 | 
			
		||||
            unsigned char* write_ptr = &atlas->TexPixelsAlpha8[r->X + ((r->Y + y) * atlas->TexWidth)];
 | 
			
		||||
            for (unsigned int i = 0; i < pad_left; i++)
 | 
			
		||||
                *(write_ptr + i) = 0x00;
 | 
			
		||||
            
 | 
			
		||||
            for (unsigned int i = 0; i < line_width; i++)
 | 
			
		||||
                *(write_ptr + pad_left + i) = 0xFF;
 | 
			
		||||
 | 
			
		||||
            for (unsigned int i = 0; i < pad_right; i++)
 | 
			
		||||
                *(write_ptr + pad_left + line_width + i) = 0x00;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            unsigned int* write_ptr = &atlas->TexPixelsRGBA32[r->X + ((r->Y + y) * atlas->TexWidth)];
 | 
			
		||||
            for (unsigned int i = 0; i < pad_left; i++)
 | 
			
		||||
                *(write_ptr + i) = IM_COL32_BLACK_TRANS;
 | 
			
		||||
            
 | 
			
		||||
            for (unsigned int i = 0; i < line_width; i++)
 | 
			
		||||
                *(write_ptr + pad_left + i) = IM_COL32_WHITE;
 | 
			
		||||
 | 
			
		||||
            for (unsigned int i = 0; i < pad_right; i++)
 | 
			
		||||
                *(write_ptr + pad_left + line_width + i) = IM_COL32_BLACK_TRANS;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Calculate UVs for this line
 | 
			
		||||
        ImVec2 uv0 = ImVec2((float)(r->X + pad_left - 1), (float)(r->Y + y)) * atlas->TexUvScale;
 | 
			
		||||
@@ -2538,7 +2583,7 @@ void ImFontAtlasBuildInit(ImFontAtlas* atlas)
 | 
			
		||||
void ImFontAtlasBuildFinish(ImFontAtlas* atlas)
 | 
			
		||||
{
 | 
			
		||||
    // Render into our custom data blocks
 | 
			
		||||
    IM_ASSERT(atlas->TexPixelsAlpha8 != NULL);
 | 
			
		||||
    IM_ASSERT(atlas->TexPixelsAlpha8 != NULL || atlas->TexPixelsRGBA32 != NULL);
 | 
			
		||||
    ImFontAtlasBuildRenderDefaultTexData(atlas);
 | 
			
		||||
    ImFontAtlasBuildRenderLinesTexData(atlas);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -126,7 +126,7 @@ namespace
 | 
			
		||||
        void                    SetPixelHeight(int pixel_height); // Change font pixel size. All following calls to RasterizeGlyph() will use this size
 | 
			
		||||
        const FT_Glyph_Metrics* LoadGlyph(uint32_t in_codepoint);
 | 
			
		||||
        const FT_Bitmap*        RenderGlyphAndGetInfo(GlyphInfo* out_glyph_info);
 | 
			
		||||
        void                    BlitGlyph(const FT_Bitmap* ft_bitmap, uint8_t* dst, uint32_t dst_pitch, unsigned char* multiply_table = NULL);
 | 
			
		||||
        void                    BlitGlyph(const FT_Bitmap* ft_bitmap, uint32_t* dst, uint32_t dst_pitch, unsigned char* multiply_table = NULL);
 | 
			
		||||
        ~FreeTypeFont()         { CloseFont(); }
 | 
			
		||||
 | 
			
		||||
        // [Internals]
 | 
			
		||||
@@ -173,6 +173,9 @@ namespace
 | 
			
		||||
        else
 | 
			
		||||
            RenderMode = FT_RENDER_MODE_NORMAL;
 | 
			
		||||
 | 
			
		||||
        if (UserFlags & ImGuiFreeTypeBuilderFlags_LoadColor)
 | 
			
		||||
            LoadFlags |= FT_LOAD_COLOR;
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -253,7 +256,7 @@ namespace
 | 
			
		||||
        return ft_bitmap;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void FreeTypeFont::BlitGlyph(const FT_Bitmap* ft_bitmap, uint8_t* dst, uint32_t dst_pitch, unsigned char* multiply_table)
 | 
			
		||||
    void FreeTypeFont::BlitGlyph(const FT_Bitmap* ft_bitmap, uint32_t* dst, uint32_t dst_pitch, unsigned char* multiply_table)
 | 
			
		||||
    {
 | 
			
		||||
        IM_ASSERT(ft_bitmap != NULL);
 | 
			
		||||
        const uint32_t w = ft_bitmap->width;
 | 
			
		||||
@@ -268,13 +271,18 @@ namespace
 | 
			
		||||
                if (multiply_table == NULL)
 | 
			
		||||
                {
 | 
			
		||||
                    for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
 | 
			
		||||
                        memcpy(dst, src, w);
 | 
			
		||||
                    {
 | 
			
		||||
                        for (uint32_t x = 0; x < w; x++)
 | 
			
		||||
                            dst[x] = IM_COL32(255, 255, 255, src[x]);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
 | 
			
		||||
                    {
 | 
			
		||||
                        for (uint32_t x = 0; x < w; x++)
 | 
			
		||||
                            dst[x] = multiply_table[src[x]];
 | 
			
		||||
                            dst[x] = IM_COL32(255, 255, 255, multiply_table[src[x]]);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
@@ -290,11 +298,43 @@ namespace
 | 
			
		||||
                    {
 | 
			
		||||
                        if ((x & 7) == 0)
 | 
			
		||||
                            bits = *bits_ptr++;
 | 
			
		||||
                        dst[x] = (bits & 0x80) ? color1 : color0;
 | 
			
		||||
                        dst[x] = IM_COL32(255, 255, 255, (bits & 0x80) ? color1 : color0);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        case FT_PIXEL_MODE_BGRA:
 | 
			
		||||
            {
 | 
			
		||||
                #define DE_MULTIPLY(color, alpha) (ImU32)(255.0f * (float)color / (float)alpha + 0.5f)
 | 
			
		||||
 | 
			
		||||
                if (multiply_table == NULL)
 | 
			
		||||
                {
 | 
			
		||||
                    for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
 | 
			
		||||
                    {
 | 
			
		||||
                        for (uint32_t x = 0; x < w; x++)
 | 
			
		||||
                            dst[x] = IM_COL32(
 | 
			
		||||
                                DE_MULTIPLY(src[x * 4 + 2], src[x * 4 + 3]),
 | 
			
		||||
                                DE_MULTIPLY(src[x * 4 + 1], src[x * 4 + 3]),
 | 
			
		||||
                                DE_MULTIPLY(src[x * 4],     src[x * 4 + 3]),
 | 
			
		||||
                                src[x * 4 + 3]);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
 | 
			
		||||
                    {
 | 
			
		||||
                        for (uint32_t x = 0; x < w; x++)
 | 
			
		||||
                            dst[x] = IM_COL32(
 | 
			
		||||
                                multiply_table[DE_MULTIPLY(src[x * 4 + 2], src[x * 4 + 3])],
 | 
			
		||||
                                multiply_table[DE_MULTIPLY(src[x * 4 + 1], src[x * 4 + 3])],
 | 
			
		||||
                                multiply_table[DE_MULTIPLY(src[x * 4],     src[x * 4 + 3])],
 | 
			
		||||
                                multiply_table[src[x * 4 + 3]]);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                #undef DE_MULTIPLY
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        default:
 | 
			
		||||
            IM_ASSERT(0 && "FreeTypeFont::BlitGlyph(): Unknown bitmap pixel mode!");
 | 
			
		||||
        }
 | 
			
		||||
@@ -318,7 +358,7 @@ struct ImFontBuildSrcGlyphFT
 | 
			
		||||
{
 | 
			
		||||
    GlyphInfo           Info;
 | 
			
		||||
    uint32_t            Codepoint;
 | 
			
		||||
    unsigned char*      BitmapData;         // Point within one of the dst_tmp_bitmap_buffers[] array
 | 
			
		||||
    unsigned int*       BitmapData;         // Point within one of the dst_tmp_bitmap_buffers[] array
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ImFontBuildSrcDataFT
 | 
			
		||||
@@ -498,7 +538,7 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
 | 
			
		||||
            IM_ASSERT(ft_bitmap);
 | 
			
		||||
 | 
			
		||||
            // Allocate new temporary chunk if needed
 | 
			
		||||
            const int bitmap_size_in_bytes = src_glyph.Info.Width * src_glyph.Info.Height;
 | 
			
		||||
            const int bitmap_size_in_bytes = src_glyph.Info.Width * src_glyph.Info.Height * 4;
 | 
			
		||||
            if (buf_bitmap_current_used_bytes + bitmap_size_in_bytes > BITMAP_BUFFERS_CHUNK_SIZE)
 | 
			
		||||
            {
 | 
			
		||||
                buf_bitmap_current_used_bytes = 0;
 | 
			
		||||
@@ -506,9 +546,9 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Blit rasterized pixels to our temporary buffer and keep a pointer to it.
 | 
			
		||||
            src_glyph.BitmapData = buf_bitmap_buffers.back() + buf_bitmap_current_used_bytes;
 | 
			
		||||
            src_glyph.BitmapData = (unsigned int*)(buf_bitmap_buffers.back() + buf_bitmap_current_used_bytes);
 | 
			
		||||
            buf_bitmap_current_used_bytes += bitmap_size_in_bytes;
 | 
			
		||||
            src_tmp.Font.BlitGlyph(ft_bitmap, src_glyph.BitmapData, src_glyph.Info.Width * 1, multiply_enabled ? multiply_table : NULL);
 | 
			
		||||
            src_tmp.Font.BlitGlyph(ft_bitmap, src_glyph.BitmapData, src_glyph.Info.Width, multiply_enabled ? multiply_table : NULL);
 | 
			
		||||
 | 
			
		||||
            src_tmp.Rects[glyph_i].w = (stbrp_coord)(src_glyph.Info.Width + padding);
 | 
			
		||||
            src_tmp.Rects[glyph_i].h = (stbrp_coord)(src_glyph.Info.Height + padding);
 | 
			
		||||
@@ -555,8 +595,16 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
 | 
			
		||||
    // 7. Allocate texture
 | 
			
		||||
    atlas->TexHeight = (atlas->Flags & ImFontAtlasFlags_NoPowerOfTwoHeight) ? (atlas->TexHeight + 1) : ImUpperPowerOfTwo(atlas->TexHeight);
 | 
			
		||||
    atlas->TexUvScale = ImVec2(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight);
 | 
			
		||||
    atlas->TexPixelsAlpha8 = (unsigned char*)IM_ALLOC(atlas->TexWidth * atlas->TexHeight);
 | 
			
		||||
    memset(atlas->TexPixelsAlpha8, 0, atlas->TexWidth * atlas->TexHeight);
 | 
			
		||||
    if (extra_flags & ImGuiFreeTypeBuilderFlags_LoadColor)
 | 
			
		||||
    {
 | 
			
		||||
        atlas->TexPixelsRGBA32 = (unsigned int*)IM_ALLOC(atlas->TexWidth * atlas->TexHeight * 4);
 | 
			
		||||
        memset(atlas->TexPixelsRGBA32, 0, atlas->TexWidth * atlas->TexHeight * 4);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        atlas->TexPixelsAlpha8 = (unsigned char*)IM_ALLOC(atlas->TexWidth * atlas->TexHeight);
 | 
			
		||||
        memset(atlas->TexPixelsAlpha8, 0, atlas->TexWidth * atlas->TexHeight);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 8. Copy rasterized font characters back into the main texture
 | 
			
		||||
    // 9. Setup ImFont and glyphs for runtime
 | 
			
		||||
@@ -596,10 +644,21 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
 | 
			
		||||
            // Blit from temporary buffer to final texture
 | 
			
		||||
            size_t blit_src_stride = (size_t)src_glyph.Info.Width;
 | 
			
		||||
            size_t blit_dst_stride = (size_t)atlas->TexWidth;
 | 
			
		||||
            unsigned char* blit_src = src_glyph.BitmapData;
 | 
			
		||||
            unsigned char* blit_dst = atlas->TexPixelsAlpha8 + (ty * blit_dst_stride) + tx;
 | 
			
		||||
            for (int y = info.Height; y > 0; y--, blit_dst += blit_dst_stride, blit_src += blit_src_stride)
 | 
			
		||||
                memcpy(blit_dst, blit_src, blit_src_stride);
 | 
			
		||||
            unsigned int* blit_src = src_glyph.BitmapData;
 | 
			
		||||
            if (atlas->TexPixelsAlpha8 != NULL)
 | 
			
		||||
            {
 | 
			
		||||
                unsigned char* blit_dst = atlas->TexPixelsAlpha8 + (ty * blit_dst_stride) + tx;
 | 
			
		||||
                for (int y = 0; y < info.Height; y++, blit_dst += blit_dst_stride, blit_src += blit_src_stride)
 | 
			
		||||
                    for (int x = 0; x < info.Width; x++)
 | 
			
		||||
                        blit_dst[x] = (unsigned char)((blit_src[x] >> IM_COL32_A_SHIFT) & 0xFF);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                unsigned int* blit_dst = atlas->TexPixelsRGBA32 + (ty * blit_dst_stride) + tx;
 | 
			
		||||
                for (int y = 0; y < info.Height; y++, blit_dst += blit_dst_stride, blit_src += blit_src_stride)
 | 
			
		||||
                    for (int x = 0; x < info.Width; x++)
 | 
			
		||||
                        blit_dst[x] = blit_src[x];
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Register glyph
 | 
			
		||||
            float x0 = info.OffsetX + font_off_x;
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,8 @@ enum ImGuiFreeTypeBuilderFlags
 | 
			
		||||
    ImGuiFreeTypeBuilderFlags_MonoHinting   = 1 << 4,   // Strong hinting algorithm that should only be used for monochrome output.
 | 
			
		||||
    ImGuiFreeTypeBuilderFlags_Bold          = 1 << 5,   // Styling: Should we artificially embolden the font?
 | 
			
		||||
    ImGuiFreeTypeBuilderFlags_Oblique       = 1 << 6,   // Styling: Should we slant the font, emulating italic style?
 | 
			
		||||
    ImGuiFreeTypeBuilderFlags_Monochrome    = 1 << 7    // Disable anti-aliasing. Combine this with MonoHinting for best results!
 | 
			
		||||
    ImGuiFreeTypeBuilderFlags_Monochrome    = 1 << 7,   // Disable anti-aliasing. Combine this with MonoHinting for best results!
 | 
			
		||||
    ImGuiFreeTypeBuilderFlags_LoadColor     = 1 << 8    // Enable FreeType color-layered glyphs
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
namespace ImGuiFreeType
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user