imgui_freetype: Add support for colored glyphs. Font: add support for untinted glyphs (#3369)

Amend 9499afd with missing static inline.
This commit is contained in:
ocornut
2021-01-28 17:26:41 +01:00
parent 24aa6654df
commit 24be26e00e
6 changed files with 44 additions and 30 deletions

View File

@ -6,6 +6,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2021/01/28: added support for color-layered glyphs via ImGuiFreeTypeBuilderFlags_LoadColor (require Freetype 2.10+).
// 2021/01/26: simplified integration by using '#define IMGUI_ENABLE_FREETYPE'.
// renamed ImGuiFreeType::XXX flags to ImGuiFreeTypeBuilderFlags_XXX for consistency with other API. removed ImGuiFreeType::BuildFontAtlas().
// 2020/06/04: fix for rare case where FT_Get_Char_Index() succeed but FT_Load_Glyph() fails.
@ -96,7 +97,7 @@ namespace
// | |
// |------------- advanceX ----------->|
/// A structure that describe a glyph.
// A structure that describe a glyph.
struct GlyphInfo
{
int Width; // Glyph's width in pixels.
@ -104,6 +105,7 @@ namespace
FT_Int OffsetX; // The distance from the origin ("pen position") to the left of the glyph.
FT_Int OffsetY; // The distance from the origin to the top of the glyph. This is usually a value < 0.
float AdvanceX; // The distance from the origin to the origin of the next glyph. This is usually a value > 0.
bool IsColored;
};
// Font parameters and metrics.
@ -252,6 +254,7 @@ namespace
out_glyph_info->OffsetX = Face->glyph->bitmap_left;
out_glyph_info->OffsetY = -Face->glyph->bitmap_top;
out_glyph_info->AdvanceX = (float)FT_CEIL(slot->advance.x);
out_glyph_info->IsColored = (ft_bitmap->pixel_mode == FT_PIXEL_MODE_BGRA);
return ft_bitmap;
}
@ -271,18 +274,14 @@ namespace
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(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] = IM_COL32(255, 255, 255, multiply_table[src[x]]);
}
}
break;
}
@ -305,33 +304,28 @@ namespace
}
case FT_PIXEL_MODE_BGRA:
{
// FIXME: Converting pre-multiplied alpha to straight. Doesn't smell good.
#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]);
}
{
uint8_t r = src[x * 4 + 2], g = src[x * 4 + 1], b = src[x * 4], a = src[x * 4 + 3];
dst[x] = IM_COL32(DE_MULTIPLY(r, a), DE_MULTIPLY(g, a), DE_MULTIPLY(b, a), a);
}
}
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]]);
{
uint8_t r = src[x * 4 + 2], g = src[x * 4 + 1], b = src[x * 4], a = src[x * 4 + 3];
dst[x] = IM_COL32(multiply_table[DE_MULTIPLY(r, a)], multiply_table[DE_MULTIPLY(g, a)], multiply_table[DE_MULTIPLY(b, a)], multiply_table[a]);
}
}
}
#undef DE_MULTIPLY
break;
}
@ -359,6 +353,8 @@ struct ImFontBuildSrcGlyphFT
GlyphInfo Info;
uint32_t Codepoint;
unsigned int* BitmapData; // Point within one of the dst_tmp_bitmap_buffers[] array
ImFontBuildSrcGlyphFT() { memset(this, 0, sizeof(*this)); }
};
struct ImFontBuildSrcDataFT
@ -396,6 +392,7 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
atlas->ClearTexData();
// Temporary storage for building
bool src_load_color = false;
ImVector<ImFontBuildSrcDataFT> src_tmp_array;
ImVector<ImFontBuildDstDataFT> dst_tmp_array;
src_tmp_array.resize(atlas->ConfigData.Size);
@ -425,6 +422,7 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
return false;
// Measure highest codepoints
src_load_color |= (cfg.FontBuilderFlags & ImGuiFreeTypeBuilderFlags_LoadColor) != 0;
ImFontBuildDstDataFT& dst_tmp = dst_tmp_array[src_tmp.DstIndex];
src_tmp.SrcRanges = cfg.GlyphRanges ? cfg.GlyphRanges : atlas->GetGlyphRangesDefault();
for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2)
@ -476,7 +474,6 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
if (entries_32 & ((ImU32)1 << bit_n))
{
ImFontBuildSrcGlyphFT src_glyph;
memset(&src_glyph, 0, sizeof(src_glyph));
src_glyph.Codepoint = (ImWchar)(((it - it_begin) << 5) + bit_n);
//src_glyph.GlyphIndex = 0; // FIXME-OPT: We had this info in the previous step and lost it..
src_tmp.GlyphsList.push_back(src_glyph);
@ -595,7 +592,7 @@ 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);
if (extra_flags & ImGuiFreeTypeBuilderFlags_LoadColor)
if (src_load_color)
{
atlas->TexPixelsRGBA32 = (unsigned int*)IM_ALLOC(atlas->TexWidth * atlas->TexHeight * 4);
memset(atlas->TexPixelsRGBA32, 0, atlas->TexWidth * atlas->TexHeight * 4);
@ -670,6 +667,10 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
float u1 = (tx + info.Width) / (float)atlas->TexWidth;
float v1 = (ty + info.Height) / (float)atlas->TexHeight;
dst_font->AddGlyph(&cfg, (ImWchar)src_glyph.Codepoint, x0, y0, x1, y1, u0, v0, u1, v1, info.AdvanceX);
IM_ASSERT(dst_font->Glyphs.back().Codepoint == src_glyph.Codepoint);
if (src_glyph.Info.IsColored)
dst_font->Glyphs.back().Colored = true;
}
src_tmp.Rects = NULL;

View File

@ -44,6 +44,6 @@ namespace ImGuiFreeType
// Obsolete names (will be removed soon)
// Prefer using '#define IMGUI_ENABLE_FREETYPE'
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int flags = 0) { atlas->FontBuilderIO = GetBuilderForFreeType(); atlas->FontBuilderFlags = flags; return atlas->Build(); }
static inline bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int flags = 0) { atlas->FontBuilderIO = GetBuilderForFreeType(); atlas->FontBuilderFlags = flags; return atlas->Build(); }
#endif
}