From 87c5356d977a07abfe05dc0fcdbcebcc73eb47dd Mon Sep 17 00:00:00 2001 From: HolyBlackCat Date: Thu, 9 May 2019 22:03:27 +0300 Subject: [PATCH] FreeType: Added RasterizerFlags::Monochrome flag to disable font anti-aliasing. (#2545) Combine with RasterizerFlags::MonoHinting for best results. --- docs/CHANGELOG.txt | 2 ++ misc/freetype/README.md | 1 + misc/freetype/imgui_freetype.cpp | 53 ++++++++++++++++++++++++++------ misc/freetype/imgui_freetype.h | 3 +- 4 files changed, 48 insertions(+), 11 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 1e47efe2..d7f4ca26 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,8 @@ Other Changes: - Separator: Revert 1.70 "Declare its thickness (1.0f) to the layout" change. It's not incorrect but it breaks existing some layout patterns. Will return back to it when we expose Separator flags. - Scrollbar: Very minor bounding box adjustment to cope with various border size. +- ImFontAtlas: FreeType: Added RasterizerFlags::Monochrome flag to disable font anti-aliasing. (#2545) + Combine with RasterizerFlags::MonoHinting for best results. - Examples/Backends: Don't filter characters under 0x10000 before calling io.AddInputCharacter(), the filtering is done in io.AddInputCharacter() itself. This is in prevision for fuller Unicode support. (#2538, #2541) diff --git a/misc/freetype/README.md b/misc/freetype/README.md index 397adec7..b62671ce 100644 --- a/misc/freetype/README.md +++ b/misc/freetype/README.md @@ -120,6 +120,7 @@ struct FreeTypeTest WantRebuild |= ImGui::CheckboxFlags("MonoHinting", &FontsFlags, ImGuiFreeType::MonoHinting); WantRebuild |= ImGui::CheckboxFlags("Bold", &FontsFlags, ImGuiFreeType::Bold); WantRebuild |= ImGui::CheckboxFlags("Oblique", &FontsFlags, ImGuiFreeType::Oblique); + WantRebuild |= ImGui::CheckboxFlags("Monochrome", &FontsFlags, ImGuiFreeType::Monochrome); } ImGui::End(); } diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index 4a579ed2..a184d78b 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -12,6 +12,7 @@ // - 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. // - v0.61: (2019/01/15) added support for imgui allocators + added FreeType only override function SetAllocatorFunctions(). +// - v0.62: (2019/02/09) added RasterizerFlags::Monochrome flag to disable font anti-aliasing (combine with ::MonoHinting for best results!) // Gamma Correct Blending: // FreeType assumes blending in linear space rather than gamma space. @@ -109,6 +110,7 @@ namespace FT_Face Face; unsigned int UserFlags; // = ImFontConfig::RasterizerFlags FT_Int32 LoadFlags; + FT_Render_Mode RenderMode; }; // From SDL_ttf: Handy routines for converting from fixed point @@ -142,6 +144,11 @@ namespace else LoadFlags |= FT_LOAD_TARGET_NORMAL; + if (UserFlags & ImGuiFreeType::Monochrome) + RenderMode = FT_RENDER_MODE_MONO; + else + RenderMode = FT_RENDER_MODE_NORMAL; + return true; } @@ -208,7 +215,7 @@ namespace const FT_Bitmap* FreeTypeFont::RenderGlyphAndGetInfo(GlyphInfo* out_glyph_info) { FT_GlyphSlot slot = Face->glyph; - FT_Error error = FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL); + FT_Error error = FT_Render_Glyph(slot, RenderMode); if (error != 0) return NULL; @@ -230,16 +237,42 @@ namespace const uint8_t* src = ft_bitmap->buffer; const uint32_t src_pitch = ft_bitmap->pitch; - if (multiply_table == NULL) + switch (ft_bitmap->pixel_mode) { - for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch) - memcpy(dst, src, w); - } - 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]]; + case FT_PIXEL_MODE_GRAY: // Grayscale image, 1 byte per pixel. + { + if (multiply_table == NULL) + { + for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch) + memcpy(dst, src, w); + } + 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]]; + } + break; + } + case FT_PIXEL_MODE_MONO: // Monochrome image, 1 bit per pixel. The bits in each byte are ordered from MSB to LSB. + { + uint8_t color0 = multiply_table ? multiply_table[0] : 0; + uint8_t color1 = multiply_table ? multiply_table[255] : 255; + for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch) + { + uint8_t bits = 0; + const uint8_t* bits_ptr = src; + for (uint32_t x = 0; x < w; x++, bits <<= 1) + { + if ((x & 7) == 0) + bits = *bits_ptr++; + dst[x] = (bits & 0x80) ? color1 : color0; + } + } + break; + } + default: + IM_ASSERT(0 && "FreeTypeFont::BlitGlyph(): Unknown bitmap pixel mode!"); } } } diff --git a/misc/freetype/imgui_freetype.h b/misc/freetype/imgui_freetype.h index b4b0fd66..d65c7724 100644 --- a/misc/freetype/imgui_freetype.h +++ b/misc/freetype/imgui_freetype.h @@ -24,7 +24,8 @@ namespace ImGuiFreeType LightHinting = 1 << 3, // A lighter hinting algorithm for gray-level modes. Many generated glyphs are fuzzier but better resemble their original shape. This is achieved by snapping glyphs to the pixel grid only vertically (Y-axis), as is done by Microsoft's ClearType and Adobe's proprietary font renderer. This preserves inter-glyph spacing in horizontal text. MonoHinting = 1 << 4, // Strong hinting algorithm that should only be used for monochrome output. Bold = 1 << 5, // Styling: Should we artificially embolden the font? - Oblique = 1 << 6 // Styling: Should we slant the font, emulating italic style? + Oblique = 1 << 6, // Styling: Should we slant the font, emulating italic style? + Monochrome = 1 << 7 // Disable anti-aliasing. Combine this with MonoHinting for best results! }; IMGUI_API bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags = 0);