@ -235,9 +235,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- pie menus patterns (#434)
- markup: simple markup language for color change? (#902)
!- font: need handling of missing glyphs by not packing/rasterizing glyph 0 of a given font.
- font: MergeMode: flags to select overwriting or not.
- font: MergeMode: duplicate glyphs are stored in the atlas texture which is suboptimal.
- font: MergeMode: flags to select overwriting or not (this is now very easy with refactored ImFontAtlasBuildWithStbTruetype)
- font: free the Alpha buffer if user only requested RGBA.
!- font: better CalcTextSizeA() API, at least for simple use cases. current one is horrible (perhaps have simple vs extended versions).
- font: a CalcTextHeight() helper could run faster than CalcTextSize().y
@ -252,7 +250,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- font/draw: vertical and/or rotated text renderer (#705) - vertical is easier clipping wise
- font/draw: need to be able to specify wrap start position.
- font/draw: better reserve policy for large horizontal block of text (shouldn't reserve for all clipped lines)
- font: imgui_freetype.h alternative renderer (#618)
- font: optimization: for monospace font (like the default one) we can trim IndexXAdvance as long as trailing value is == FallbackXAdvance (need to make sure TAB is still correct).
- font: add support for kerning, probably optional. A) perhaps default to (32..128)^2 matrix ~ 9K entries = 36KB, then hash for non-ascii?. B) or sparse lookup into per-char list?
- font: add a simpler CalcTextSizeA() api? current one ok but not welcome if user needs to call it directly (without going through ImGui::CalcTextSize)
ImFontAtlasFlagsFlags;// Build flags (see ImFontAtlasFlags_)
ImTextureIDTexID;// User data to refer to the texture once it has been uploaded to user's graphic systems. It is passed back to you during rendering via the ImDrawCmd structure.
intTexDesiredWidth;// Texture width desired by user before Build(). Must be a power-of-two. If have many glyphs your graphics API have texture size restrictions you may want to increase texture width to decrease height.
intTexGlyphPadding;// Padding between glyphs within texture in pixels. Defaults to 1.
intTexGlyphPadding;// Padding between glyphs within texture in pixels. Defaults to 1. If your rendering method doesn't rely on bilinear filtering you may set this to 0.
// [Internal]
// NB: Access texture data via GetTexData*() calls! Which will setup a default font for you.
IM_ASSERT(!Fonts.empty());// When using MergeMode make sure that a font has already been added before. You can use ImGui::GetIO().Fonts->AddFontDefault() to add the default imgui font.
IM_ASSERT(!Fonts.empty()&&"Cannot use MergeMode for the first font");// When using MergeMode make sure that a font has already been added before. You can use ImGui::GetIO().Fonts->AddFontDefault() to add the default imgui font.
// We need a width for the skyline algorithm. Using a dumb heuristic here to decide of width. User can override TexDesiredWidth and TexGlyphPadding if they wish.
// Width doesn't really matter much, but some API/GPU have texture size limitations and increasing width can decrease height.
// 2. For every requested codepoint, check for their presence in the font data, and handle redundancy or overlaps between source fonts to avoid unused glyphs.
if(cfg.MergeMode&&dst_tmp.GlyphsSet.GetBit(codepoint))// Don't overwrite existing glyphs. We could make this an option (e.g. MergeOverwrite)
continue;
if(!stbtt_FindGlyphIndex(&src_tmp.FontInfo,codepoint))// It is actually in the font?
continue;
// Add to avail set/counters
src_tmp.GlyphsCount++;
dst_tmp.GlyphsCount++;
src_tmp.GlyphsSet.SetBit(codepoint,true);
if(dst_tmp.SrcCount>1)
dst_tmp.GlyphsSet.SetBit(codepoint,true);
total_glyphs_count++;
}
}
// 3. Unpack our bit map into a flat list (we now have all the Unicode points that we know are requested _and_ available _and_ not overlapping another)
// We need a width for the skyline algorithm, any width!
// The exact width doesn't really matter much, but some API/GPU have texture size limitations and increasing width can decrease height.
// User can override TexDesiredWidth and TexGlyphPadding if they wish, otherwise we use a simple heuristic to select the width based on expected surface.
// Helper: ImPool<>. Basic keyed storage for contiguous instances, slow/amortized insertion, O(1) indexable, O(Log N) queries by ID over a dense/hot buffer,
// Honor constructor/destructor. Add/remove invalidate all pointers. Indexes have the same lifetime as the associated object.
This is an attempt to replace stb_truetype (the default imgui's font rasterizer) with FreeType.
Currently not optimal and probably has some limitations or bugs.
By [Vuhdo](https://github.com/Vuhdo) (Aleksei Skriabin). Improvements by @mikesart. Maintained by @ocornut.
Build font atlases using FreeType instead of stb_truetype (the default imgui's font rasterizer).
<br>by @vuhdo, @mikesart, @ocornut.
**Usage**
1. Get latest FreeType binaries or build yourself.
### Usage
1. Get latest FreeType binaries or build yourself (under Windows you may use vcpkg with `vcpkg install freetype`).
2. Add imgui_freetype.h/cpp alongside your imgui sources.
3. Include imgui_freetype.h after imgui.h.
4. Call ImGuiFreeType::BuildFontAtlas() *BEFORE* calling ImFontAtlas::GetTexDataAsRGBA32() or ImFontAtlas::Build() (so normal Build() won't be called):
4. Call `ImGuiFreeType::BuildFontAtlas()`*BEFORE* calling `ImFontAtlas::GetTexDataAsRGBA32()` or `ImFontAtlas::Build()` (so normal Build() won't be called):
// Wrapper to use Freetype (instead of stb_truetype) for Dear ImGui
// Wrapper to use FreeType (instead of stb_truetype) for Dear ImGui
// Get latest version at https://github.com/ocornut/imgui/tree/master/misc/freetype
// Original code by @Vuhdo (Aleksei Skriabin). Improvements by @mikesart. Maintained by @ocornut
// Original code by @vuhdo (Aleksei Skriabin). Improvements by @mikesart. Maintained and v0.60+ by @ocornut.
// Changelog:
// - v0.50: (2017/08/16) imported from https://github.com/Vuhdo/imgui_freetype into http://www.github.com/ocornut/imgui_club, updated for latest changes in ImFontAtlas, minor tweaks.
@ -10,6 +10,7 @@
// - 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.56: (2018/06/08) added support for ImFontConfig::GlyphMinAdvanceX, GlyphMaxAdvanceX
// - v0.60: (2019/01/10) re-factored to match big update in STB builder. fixed texture height waste. fixed redundant glyphs when merging. support for glyph padding.
// Gamma Correct Blending:
// FreeType assumes blending in linear space rather than gamma space.
@ -17,18 +18,16 @@
// For correct results you need to be using sRGB and convert to linear space in the pixel shader output.
// The default imgui styles will be impacted by this change (alpha values will need tweaking).
// TODO:
// - Output texture has excessive resolution (lots of vertical waste).
// - FreeType's memory allocator is not overridden.
// - cfg.OversampleH, OversampleV are ignored (but perhaps not so necessary with this rasterizer).
// FIXME: FreeType's memory allocator is not overridden.
// FIXME: cfg.OversampleH, OversampleV are not supported (but perhaps not so necessary with this rasterizer).
#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff)
@ -74,15 +73,15 @@ namespace
/// A structure that describe a glyph.
structGlyphInfo
{
float Width;// Glyph's width in pixels.
float Height;// Glyph's height in pixels.
floatOffsetX;// The distance from the origin ("pen position") to the left of the glyph.
floatOffsetY;// The distance from the origin to the top of the glyph. This is usually a value < 0.
floatAdvanceX;// The distance from the origin to the origin of the next glyph. This is usually a value > 0.
int Width;// Glyph's width in pixels.
int Height;// Glyph's height in pixels.
FT_IntOffsetX;// The distance from the origin ("pen position") to the left of the glyph.
FT_IntOffsetY;// The distance from the origin to the top of the glyph. This is usually a value < 0.
floatAdvanceX;// The distance from the origin to the origin of the next glyph. This is usually a value > 0.
};
// Font parameters and metrics.
structFontInfo
structFontInfo
{
uint32_tPixelHeight;// Size this font was generated with.
floatAscender;// The pixel extents above the baseline in pixels (typically positive).
@ -96,82 +95,80 @@ namespace
// NB: No ctor/dtor, explicitly call Init()/Shutdown()
structFreeTypeFont
{
boolInit(constImFontConfig&cfg,unsignedintextra_user_flags);// Initialize from an external data buffer. Doesn't copy data, and you must ensure it stays valid up to this object lifetime.
voidShutdown();
voidSetPixelHeight(intpixel_height);// Change font pixel size. All following calls to RasterizeGlyph() will use this size
boolInitFont(FT_Libraryft_library,constImFontConfig&cfg,unsignedintextra_user_flags);// Initialize from an external data buffer. Doesn't copy data, and you must ensure it stays valid up to this object lifetime.
voidCloseFont();
voidSetPixelHeight(intpixel_height);// Change font pixel size. All following calls to RasterizeGlyph() will use this size
// 2. For every requested codepoint, check for their presence in the font data, and handle redundancy or overlaps between source fonts to avoid unused glyphs.
// 3. Unpack our bit map into a flat list (we now have all the Unicode points that we know are requested _and_ available _and_ not overlapping another)
// We need a width for the skyline algorithm. Using a dumb heuristic here to decide of width. User can override TexDesiredWidth and TexGlyphPadding if they wish.
// Width doesn't really matter much, but some API/GPU have texture size limitations and increasing width can decrease height.
// We need a width for the skyline algorithm, any width!
// The exact width doesn't really matter much, but some API/GPU have texture size limitations and increasing width can decrease height.
// User can override TexDesiredWidth and TexGlyphPadding if they wish, otherwise we use a simple heuristic to select the width based on expected surface.