ImFontConfig: Added GlyphMinAdvanceX/GlyphMaxAdvanceX settings useful to make a font appears monospaced, particularly useful for icon fonts. (#1869)

This commit is contained in:
omar 2018-06-08 12:46:36 +02:00
parent 8e48ab6b19
commit f5bf9f509c
5 changed files with 31 additions and 12 deletions

View File

@ -53,6 +53,7 @@ Other Changes:
- InputTextMultiline(): Fixed double navigation highlight when scrollbar is active. (#787) - InputTextMultiline(): Fixed double navigation highlight when scrollbar is active. (#787)
- InputText(): Fixed Undo after pasting large amount of text (Redo will still fail when undo buffers are exhausted, but text won't be corrupted). - InputText(): Fixed Undo after pasting large amount of text (Redo will still fail when undo buffers are exhausted, but text won't be corrupted).
- SliderFloat(): When using keyboard/gamepad and a zero precision format string (e.g. "%.0f"), always step in integer units. (#1866) - SliderFloat(): When using keyboard/gamepad and a zero precision format string (e.g. "%.0f"), always step in integer units. (#1866)
- ImFontConfig: Added GlyphMinAdvanceX/GlyphMaxAdvanceX settings useful to make a font appears monospaced, particularly useful for icon fonts. (#1869)
- ImFontAtlas: Added GetGlyphRangesChineseSimplifiedCommon() helper that returns a list of ~2500 most common Simplified Chinese characters. (#1859) [@JX-Master, @ocornut] - ImFontAtlas: Added GetGlyphRangesChineseSimplifiedCommon() helper that returns a list of ~2500 most common Simplified Chinese characters. (#1859) [@JX-Master, @ocornut]
- Examples: GLFW: Made it possible to Shutdown/Init the backend again (by reseting the time storage properly). (#1827) [@ice1000] - Examples: GLFW: Made it possible to Shutdown/Init the backend again (by reseting the time storage properly). (#1827) [@ice1000]
- Misc: Updated stb_textedit from 1.09 + patches to 1.12 + minor patches. - Misc: Updated stb_textedit from 1.09 + patches to 1.12 + minor patches.

View File

@ -1699,13 +1699,15 @@ struct ImFontConfig
int FontDataSize; // // TTF/OTF data size int FontDataSize; // // TTF/OTF data size
bool FontDataOwnedByAtlas; // true // TTF/OTF data ownership taken by the container ImFontAtlas (will delete memory itself). bool FontDataOwnedByAtlas; // true // TTF/OTF data ownership taken by the container ImFontAtlas (will delete memory itself).
int FontNo; // 0 // Index of font within TTF/OTF file int FontNo; // 0 // Index of font within TTF/OTF file
float SizePixels; // // Size in pixels for rasterizer. float SizePixels; // // Size in pixels for rasterizer (more or less maps to the resulting font height).
int OversampleH; // 3 // Rasterize at higher quality for sub-pixel positioning. We don't use sub-pixel positions on the Y axis. int OversampleH; // 3 // Rasterize at higher quality for sub-pixel positioning. We don't use sub-pixel positions on the Y axis.
int OversampleV; // 1 // Rasterize at higher quality for sub-pixel positioning. We don't use sub-pixel positions on the Y axis. int OversampleV; // 1 // Rasterize at higher quality for sub-pixel positioning. We don't use sub-pixel positions on the Y axis.
bool PixelSnapH; // false // Align every glyph to pixel boundary. Useful e.g. if you are merging a non-pixel aligned font with the default font. If enabled, you can set OversampleH/V to 1. bool PixelSnapH; // false // Align every glyph to pixel boundary. Useful e.g. if you are merging a non-pixel aligned font with the default font. If enabled, you can set OversampleH/V to 1.
ImVec2 GlyphExtraSpacing; // 0, 0 // Extra spacing (in pixels) between glyphs. Only X axis is supported for now. ImVec2 GlyphExtraSpacing; // 0, 0 // Extra spacing (in pixels) between glyphs. Only X axis is supported for now.
ImVec2 GlyphOffset; // 0, 0 // Offset all glyphs from this font input. ImVec2 GlyphOffset; // 0, 0 // Offset all glyphs from this font input.
const ImWchar* GlyphRanges; // NULL // Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list). THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE. const ImWchar* GlyphRanges; // NULL // Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list). THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE.
float GlyphMinAdvanceX; // 0 // Minimum AdvanceX for glyphs, set Min to align font icons, set both Min/Max to enforce mono-space font
float GlyphMaxAdvanceX; // FLT_MAX // Maximum AdvanceX for glyphs
bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights. bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights.
unsigned int RasterizerFlags; // 0x00 // Settings for custom font rasterizer (e.g. ImGuiFreeType). Leave as zero if you aren't using one. unsigned int RasterizerFlags; // 0x00 // Settings for custom font rasterizer (e.g. ImGuiFreeType). Leave as zero if you aren't using one.
float RasterizerMultiply; // 1.0f // Brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. float RasterizerMultiply; // 1.0f // Brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable.
@ -1787,7 +1789,7 @@ struct ImFontAtlas
void SetBit(int n) { UsedChars[n >> 3] |= 1 << (n & 7); } // Set bit 'c' in the array void SetBit(int n) { UsedChars[n >> 3] |= 1 << (n & 7); } // Set bit 'c' in the array
void AddChar(ImWchar c) { SetBit(c); } // Add character void AddChar(ImWchar c) { SetBit(c); } // Add character
IMGUI_API void AddText(const char* text, const char* text_end = NULL); // Add string (each character of the UTF-8 string are added) IMGUI_API void AddText(const char* text, const char* text_end = NULL); // Add string (each character of the UTF-8 string are added)
IMGUI_API void AddRanges(const ImWchar* ranges); // Add ranges, e.g. builder.AddRanges(ImFontAtlas::GetGlyphRangesDefault) to force add all of ASCII/Latin+Ext IMGUI_API void AddRanges(const ImWchar* ranges); // Add ranges, e.g. builder.AddRanges(ImFontAtlas::GetGlyphRangesDefault()) to force add all of ASCII/Latin+Ext
IMGUI_API void BuildRanges(ImVector<ImWchar>* out_ranges); // Output new ranges IMGUI_API void BuildRanges(ImVector<ImWchar>* out_ranges); // Output new ranges
}; };

View File

@ -1325,6 +1325,8 @@ ImFontConfig::ImFontConfig()
GlyphExtraSpacing = ImVec2(0.0f, 0.0f); GlyphExtraSpacing = ImVec2(0.0f, 0.0f);
GlyphOffset = ImVec2(0.0f, 0.0f); GlyphOffset = ImVec2(0.0f, 0.0f);
GlyphRanges = NULL; GlyphRanges = NULL;
GlyphMinAdvanceX = 0.0f;
GlyphMaxAdvanceX = FLT_MAX;
MergeMode = false; MergeMode = false;
RasterizerFlags = 0x00; RasterizerFlags = 0x00;
RasterizerMultiply = 1.0f; RasterizerMultiply = 1.0f;
@ -1867,8 +1869,8 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
const float ascent = ImFloor(unscaled_ascent * font_scale + ((unscaled_ascent > 0.0f) ? +1 : -1)); const float ascent = ImFloor(unscaled_ascent * font_scale + ((unscaled_ascent > 0.0f) ? +1 : -1));
const float descent = ImFloor(unscaled_descent * font_scale + ((unscaled_descent > 0.0f) ? +1 : -1)); const float descent = ImFloor(unscaled_descent * font_scale + ((unscaled_descent > 0.0f) ? +1 : -1));
ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent); ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent);
const float off_x = cfg.GlyphOffset.x; const float font_off_x = cfg.GlyphOffset.x;
const float off_y = cfg.GlyphOffset.y + (float)(int)(dst_font->Ascent + 0.5f); const float font_off_y = cfg.GlyphOffset.y + (float)(int)(dst_font->Ascent + 0.5f);
for (int i = 0; i < tmp.RangesCount; i++) for (int i = 0; i < tmp.RangesCount; i++)
{ {
@ -1883,10 +1885,16 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
if (cfg.MergeMode && dst_font->FindGlyphNoFallback((unsigned short)codepoint)) if (cfg.MergeMode && dst_font->FindGlyphNoFallback((unsigned short)codepoint))
continue; continue;
float char_advance_x_org = pc.xadvance;
float char_advance_x_mod = ImClamp(char_advance_x_org, cfg.GlyphMinAdvanceX, cfg.GlyphMaxAdvanceX);
float char_off_x = font_off_x;
if (char_advance_x_org != char_advance_x_mod)
char_off_x += cfg.PixelSnapH ? (float)(int)((char_advance_x_mod - char_advance_x_org) * 0.5f) : (char_advance_x_mod - char_advance_x_org) * 0.5f;
stbtt_aligned_quad q; stbtt_aligned_quad q;
float dummy_x = 0.0f, dummy_y = 0.0f; float dummy_x = 0.0f, dummy_y = 0.0f;
stbtt_GetPackedQuad(range.chardata_for_range, atlas->TexWidth, atlas->TexHeight, char_idx, &dummy_x, &dummy_y, &q, 0); stbtt_GetPackedQuad(range.chardata_for_range, atlas->TexWidth, atlas->TexHeight, char_idx, &dummy_x, &dummy_y, &q, 0);
dst_font->AddGlyph((ImWchar)codepoint, q.x0 + off_x, q.y0 + off_y, q.x1 + off_x, q.y1 + off_y, q.s0, q.t0, q.s1, q.t1, pc.xadvance); dst_font->AddGlyph((ImWchar)codepoint, q.x0 + char_off_x, q.y0 + font_off_y, q.x1 + char_off_x, q.y1 + font_off_y, q.s0, q.t0, q.s1, q.t1, char_advance_x_mod);
} }
} }
} }

View File

@ -57,6 +57,7 @@ In this document:
ImFontConfig config; ImFontConfig config;
config.MergeMode = true; config.MergeMode = true;
config.GlyphMinAdvanceX = 13.0f; // Use if you want to make the icon monospaced
static const ImWchar icon_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 }; static const ImWchar icon_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };
io.Fonts->AddFontFromFileTTF("fonts/fontawesome-webfont.ttf", 13.0f, &config, icon_ranges); io.Fonts->AddFontFromFileTTF("fonts/fontawesome-webfont.ttf", 13.0f, &config, icon_ranges);

View File

@ -9,6 +9,7 @@
// - v0.53: (2017/10/22) minor inconsequential change to match change in master (removed an unnecessary statement) // - v0.53: (2017/10/22) minor inconsequential change to match change in master (removed an unnecessary statement)
// - v0.54: (2018/01/22) fix for addition of ImFontAtlas::TexUvscale member // - v0.54: (2018/01/22) fix for addition of ImFontAtlas::TexUvscale member
// - v0.55: (2018/02/04) moved to main imgui repository (away from http://www.github.com/ocornut/imgui_club) // - v0.55: (2018/02/04) moved to main imgui repository (away from http://www.github.com/ocornut/imgui_club)
// - v0.56: (2018/06/08) added support for ImFontConfig::GlyphMinAdvanceX, GlyphMaxAdvanceX
// Gamma Correct Blending: // Gamma Correct Blending:
// FreeType assumes blending in linear space rather than gamma space. // FreeType assumes blending in linear space rather than gamma space.
@ -324,8 +325,8 @@ bool ImGuiFreeType::BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags)
const float ascent = font_face.Info.Ascender; const float ascent = font_face.Info.Ascender;
const float descent = font_face.Info.Descender; const float descent = font_face.Info.Descender;
ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent); ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent);
const float off_x = cfg.GlyphOffset.x; const float font_off_x = cfg.GlyphOffset.x;
const float off_y = cfg.GlyphOffset.y + (float)(int)(dst_font->Ascent + 0.5f); const float font_off_y = cfg.GlyphOffset.y + (float)(int)(dst_font->Ascent + 0.5f);
bool multiply_enabled = (cfg.RasterizerMultiply != 1.0f); bool multiply_enabled = (cfg.RasterizerMultiply != 1.0f);
unsigned char multiply_table[256]; unsigned char multiply_table[256];
@ -356,17 +357,23 @@ bool ImGuiFreeType::BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags)
font_face.BlitGlyph(ft_glyph_bitmap, blit_dst, atlas->TexWidth, multiply_enabled ? multiply_table : NULL); font_face.BlitGlyph(ft_glyph_bitmap, blit_dst, atlas->TexWidth, multiply_enabled ? multiply_table : NULL);
FT_Done_Glyph(ft_glyph); FT_Done_Glyph(ft_glyph);
float char_advance_x_org = glyph_info.AdvanceX;
float char_advance_x_mod = ImClamp(char_advance_x_org, cfg.GlyphMinAdvanceX, cfg.GlyphMaxAdvanceX);
float char_off_x = font_off_x;
if (char_advance_x_org != char_advance_x_mod)
char_off_x += cfg.PixelSnapH ? (float)(int)((char_advance_x_mod - char_advance_x_org) * 0.5f) : (char_advance_x_mod - char_advance_x_org) * 0.5f;
// Register glyph // Register glyph
dst_font->AddGlyph((ImWchar)codepoint, dst_font->AddGlyph((ImWchar)codepoint,
glyph_info.OffsetX + off_x, glyph_info.OffsetX + char_off_x,
glyph_info.OffsetY + off_y, glyph_info.OffsetY + font_off_y,
glyph_info.OffsetX + off_x + glyph_info.Width, glyph_info.OffsetX + char_off_x + glyph_info.Width,
glyph_info.OffsetY + off_y + glyph_info.Height, glyph_info.OffsetY + font_off_y + glyph_info.Height,
rect.x / (float)atlas->TexWidth, rect.x / (float)atlas->TexWidth,
rect.y / (float)atlas->TexHeight, rect.y / (float)atlas->TexHeight,
(rect.x + glyph_info.Width) / (float)atlas->TexWidth, (rect.x + glyph_info.Width) / (float)atlas->TexWidth,
(rect.y + glyph_info.Height) / (float)atlas->TexHeight, (rect.y + glyph_info.Height) / (float)atlas->TexHeight,
glyph_info.AdvanceX); char_advance_x_mod);
} }
} }
} }