-
-
Notifications
You must be signed in to change notification settings - Fork 10.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Better fonts rendering / allow to use e.g. FreeType #618
Comments
Hello, Obviously the purpose of Proggy is to provide a default embedded-in-source-code font for quick tools. It isn't meant to cover everything. I don't know what you mean by "lower pixel sizes", although I guess at 12- it won't look amazing. Though you can increase subsampling and it'll look a little better. stb_truetype also doesn't do sub-pixels. This is a good idea but I won't have time to do it myself, I don't have the resources and it isn't a development priority for me. If you want to work on it'd be great. The function to replace is Another possibility that would be more work but also be beneficial to larger number of people would be to improve stb_truetype. |
Looks awesome! |
Looking nice! PS: The sizing/spacing difference seems like a bug and unrelated to auto-hinting. On some pairs it might feel better because it might compensates for the lack of kerning but generally it doesn't look right. As a side note, kerning supports would in theory be nice but in practice I don't know how to do it without affecting performances a lot (text size calculation is a major bottleneck). We could add kerning as an optional per-font option by duplicating some of the ImFont code, however some code here and there (code in InputText) would need to be reworked to be kerning friendly, aka not processing characters in pairs. Gut feeling is that we can ignore kerning for now, rasterizing quality is a much more valuable benefit as you are pointing out. |
Omar, The fork with my experiments is here: https://github.com/Vuhdo/imgui |
Probably should be posted in screenshots thread, but since it's not anything new, but just reskined ImGui demo with FreeType rasterizer, I'll post it here. Here's how my current mockup looks like: |
Screenshot looking good! I have only skimmed through it but ideally it could be done without touching the imgui files, then the code will be easier to share and maintain. Since everything is public/struct you can have a totally extern Build function taking Just call your function prior to calling |
@Vuhdo Any news about taking this code out of imgui_draw.cpp so it can be used as a separate extension? |
@ocornut Yeah, it's here: https://github.com/Vuhdo/imgui_freetype. |
Interested in having support for using FreeType as well even if I like the stb_x libs I like higher quality text more :) |
@Vuhdo It works! And it doesn't need any modification to imgui (even if it's not possible to disable the stb_truetype stuff to reduce memory usage)! Some thoughts: namespace ImGuiFreeType {
IMGUI_API void GetTexDataAsAlpha8(ImFontAtlas* atlas,unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel,unsigned int flags=0) {
using namespace ImGui;
// Build atlas on demand
if (atlas->TexPixelsAlpha8 == NULL)
{
if (atlas->ConfigData.empty())
atlas->AddFontDefault();
BuildFontAtlas(atlas,flags);
}
*out_pixels = atlas->TexPixelsAlpha8;
if (out_width) *out_width = atlas->TexWidth;
if (out_height) *out_height = atlas->TexHeight;
if (out_bytes_per_pixel) *out_bytes_per_pixel = 1;
}
IMGUI_API void GetTexDataAsRGBA32(ImFontAtlas* atlas,unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel,unsigned int flags=0) {
// Convert to RGBA32 format on demand
// Although it is likely to be the most commonly used format, our font rendering is 1 channel / 8 bpp
if (!atlas->TexPixelsRGBA32)
{
unsigned char* pixels;
GetTexDataAsAlpha8(atlas,&pixels, NULL, NULL,NULL,flags);
atlas->TexPixelsRGBA32 = (unsigned int*)ImGui::MemAlloc((size_t)(atlas->TexWidth * atlas->TexHeight * 4));
const unsigned char* src = pixels;
unsigned int* dst = atlas->TexPixelsRGBA32;
for (int n = atlas->TexWidth * atlas->TexHeight; n > 0; n--)
*dst++ = ((unsigned int)(*src++) << 24) | 0x00FFFFFF;
}
*out_pixels = (unsigned char*)atlas->TexPixelsRGBA32;
if (out_width) *out_width = atlas->TexWidth;
if (out_height) *out_height = atlas->TexHeight;
if (out_bytes_per_pixel) *out_bytes_per_pixel = 4;
}
} // namespace ImGuiFreetype Then, instead of calling something like: io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); I call: ImGuiFreeType::GetTexDataAsRGBA32(io.Fonts,&pixels, &width, &height,NULL,flags);
// where flags are the ImGuiFreeType::RasterizationFlags I want to use Do you think it's correct, or there are cases where my approach doesn't work ? P.S. I think I'll merge your code into my branch sooner or later, as an optional feature :) |
Better just add a separate Build function that the user can call, you don't need to create new GetTexDataAsXXX functions. And that code needs not to be part of imgui.cpp file, it can be separate. |
@Flix01 Thanks for the bug report! I've fixed the memory leak, added missing FreeType's binaries and updated README: |
Nice! Now it only needs to be moved outside of an imgui folder into its one folder so zero forking/merging is needed :) I wonder if it would be a good occasion to create an official imgui_extras repo for that sort of stuff, and docking? |
Yeah, official imgui_extras would be great, but will require a lot of attention from you anyway :) |
well I happened to find out that, if you use Freetype and your text looks a little blurry when small, try pow(bitmap_alpha, 1/2.2), accidentally found that this looks pretty good when i'm dealing with sRGB stuff, not a ultimate solution but it's worth trying for freetype users. |
@Vuhdo nice! Is there any specific reason your version doesn't use subpixel rendering/hinting? It's the one thing I'd like most from freetype. |
@ocornut said:
It's about time since say, two years at least. |
Any update on this issue? |
No, but you can freely use @Vuhdo's code if you want to rasterize using freetype for now. |
…s less confusing (nb: we might break compat with forks of Build() like #618)
Tada! https://github.com/ocornut/imgui_club/ The updated imgui_freetype.h code is here: Hopefully with @Vuhdo benediction! |
Awesome, Omar! |
Thanks @Vuhdo. Closing this topic now!. |
Oh cool, this is fantastic. I'll get this version into gpuvis. Thanks Omar! |
- Fixed abnormally high atlas height. (#618) - Fixed support for any values of TexGlyphPadding (not just only 1). (#618) - Atlas width is now properly based on total surface rather than glyph count (unless overridden with TexDesiredWidth). (#618) - Fixed atlas builder so missing glyphs won't influence the atlas texture width. (#2233, #618) - Fixed atlas builder so duplicate glyphs (when merging fonts) won't be included in the rasterized atlas. (#618)
Let me start by saying, Dear ImGui rocks!
In fact, it's so great that I literally want to use it more than I really need to :)
That said, I have some really annoying problem - mediocre text visuals.
Stb_truetype, the underlying font rendering library, is simple and convenient,
but not that great comparing to, say, FreeType's hinting rasterizer.
Proggy font (the built-in one) is crisp, but it's essentially a bitmap font which
doesn't imply anti-aliased rasterizing.
It's a fixed-width font which really looks like some 'programmer's art', that
might be a problem or not (my artists will make fun of me for sure).
Moreover, it contains only basic Latin glyphs which is really a problem in
some environments (for example, we badly need to render russian texts in our tools).
I've tried to use a number of popular outline fonts (Droids, Microsoft's SegoeUI, etc.).
They all look blurry, at least when using lower pixel sizes.
And that is understandable, stb_truetype does no hinting, only anti-alising.
What I propose is to add some interface so a user could plug-in his own font rasterizer.
This way we can more or less easily substitute stb_truetype with FreeType without bloating the library.
One minor feature which I think can be easily implemented is to add shadows to texts.
Another one is to add glyph outlines, but I bet it's too difficult without using an advanced glyph
rasterizer and complicating the library's code.
What do you think?
-- Alexey
The text was updated successfully, but these errors were encountered: