Skip to content
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

Not able to use NotoColorEmoji font #6302

Closed
yiminli opened this issue Apr 5, 2023 · 9 comments
Closed

Not able to use NotoColorEmoji font #6302

yiminli opened this issue Apr 5, 2023 · 9 comments

Comments

@yiminli
Copy link

yiminli commented Apr 5, 2023

Dear ImGui 1.89.5 WIP (18948)
--------------------------------
sizeof(size_t): 8, sizeof(ImDrawIdx): 2, sizeof(ImDrawVert): 20
define: __cplusplus=201703
define: __linux__
define: __GNUC__=9
--------------------------------
io.BackendPlatformName: imgui_impl_sdl2
io.BackendRendererName: imgui_impl_opengl3
io.ConfigFlags: 0x00000003
 NavEnableKeyboard
 NavEnableGamepad
io.ConfigInputTextCursorBlink
io.ConfigWindowsResizeFromEdges
io.ConfigMemoryCompactTimer = 60.0
io.BackendFlags: 0x0000000E
 HasMouseCursors
 HasSetMousePos
 RendererHasVtxOffset
--------------------------------
io.Fonts: 1 fonts, Flags: 0x00000000, TexSize: 512,64
io.DisplaySize: 1959.00,921.00
io.DisplayFramebufferScale: 1.00,1.00
--------------------------------
style.WindowPadding: 8.00,8.00
style.WindowBorderSize: 1.00
style.FramePadding: 4.00,3.00
style.FrameRounding: 0.00
style.FrameBorderSize: 0.00
style.ItemSpacing: 8.00,4.00
style.ItemInnerSpacing: 4.00,4.00

My Issue/Question:
I want to use font NotoColorEmoji_WindowsCompatible.ttf and display a smile face similar to what is shown in:
#4566 (comment)
It seems the font is not loaded correctly.

Screenshots/Video
image

Standalone, minimal, complete and verifiable example: (see )

diff main.cpp build/imgui/examples/example_sdl2_opengl3/main.cpp
6,8c6
< #include <string>
< #include "misc/freetype/imgui_freetype.h"
<
---
> #include "imgui.h"
105,116d102
<     io.Fonts->AddFontDefault();
<     {
<         static ImWchar ranges[] = { 0x1, 0x1FFFF, 0 };
<         static ImFontConfig cfg;
<         cfg.OversampleH = cfg.OversampleV = 1;
<         cfg.MergeMode = true;
<         cfg.FontBuilderFlags |= ImGuiFreeTypeBuilderFlags_LoadColor;
<         const std::string icon_font = "/tmp/NotoColorEmoji_WindowsCompatible.ttf";
<         io.Fonts->AddFontFromFileTTF(icon_font.c_str(), 109.0f, &cfg, ranges);
<         io.Fonts->Build();
<     }
<
161,166d146
<
<             ImGui::Begin("font test");
<             static char str[128] = "😊Hello, world!";
<             ImGui::Text("%s", str);
<             ImGui::InputText("input text", str, IM_ARRAYSIZE(str));
<             ImGui::End();

Full example with CMake (run build_and_run.sh after unzipping):
emoji_font.zip

@ocornut
Copy link
Owner

ocornut commented Apr 5, 2023

Two things you can do to begin debugging this:

  • Browse Fonts->Input 1 (Noto etc) in that debug window and see if the glyph is listed and visible. This is to validate that it has been rendered properly.
  • Call DebugTextEncoding(str) with your string containing an icon. This is to validate that you compiler UTF-8 encoding settings are correct. See what are the decoded value if they match the codepoint of that Emoji. A "😊Hello, world!" literal is NOT standard and requires per-compiler settings to be UTF-8 encoded You can use (const char*)u8"😊Hello, world!" as a more portable way to UTF-8 encode, which is best wrapped into a macro to make things shorter.

@yiminli
Copy link
Author

yiminli commented Apr 6, 2023

Thanks for reminding me about u8 string literal. I updated the code to:
static char str[128] = u8"😊Hello, world!";

😊 is U+1F60A. Seems rendering of the glyph has some problem.
image

@ocornut
Copy link
Owner

ocornut commented Apr 24, 2023

I can confirm this on my side.
I don't know if it is a bug/unsupported feature in FreeType or if we are misusing Freetype.
It works for me with "seguiemj.tff" but not with "NotoColorEmoji.ttf" neither "NotoColorEmoji_WindowsCompatible.ttf".

Some references:
https://stackoverflow.com/questions/54781525/loading-colored-fonts-with-freetype

@ItsBranK
Copy link

ItsBranK commented May 7, 2023

Man I've been spending the last 3 days trying to get this same font to work, finally found this and saw it was an issue...fml

@yiminli
Copy link
Author

yiminli commented Jun 20, 2023

clfontpng (https://gist.github.com/jokertarot/7583938) can render emoji in NotoColorEmoji_WindowsCompatible.ttf into png file without a problem.
The author used FreeType 2.5. I tested it working with FreeType 2.12.1:
./clfontpng NotoColorEmoji_WindowsCompatible.ttf 🥳

@batcholi
Copy link

batcholi commented Jul 2, 2023

Any update on this issue?

@sakiodre
Copy link
Contributor

sakiodre commented Jul 13, 2023

Apparently, the notoemoji font (CBDT variant) is not scalable (FT_IS_SCALABLE(face) is false), making FT_Request_Size defaults to 0 for width and height, this can be fixed by using FT_Select_Size instead, but that function only selects a fixed size, making the "font size" meaningless.

image

To reproduce
    cfg.FontBuilderFlags |= ImGuiFreeTypeBuilderFlags_LoadColor | ImGuiFreeTypeBuilderFlags_Bitmap;
    bool FreeTypeFont::IsCBDTFont()
    {
        FT_ULong tag = FT_MAKE_TAG('C', 'B', 'D', 'T');
        FT_ULong length = 0;
        FT_Load_Sfnt_Table(Face, tag, 0, nullptr, &length);
        return length > 0;
    }

    void FreeTypeFont::SetPixelHeight(int pixel_height)
    {
        if (IsCBDTFont())
        {
            IM_ASSERT(Face->num_fixed_sizes != 0);
            LoadFlags |= FT_LOAD_COLOR;

            int best_match = 0;
            int diff = std::abs(pixel_height - Face->available_sizes[0].width);
            for (int i = 1; i < Face->num_fixed_sizes; ++i)
            {
                int ndiff = std::abs(pixel_height - Face->available_sizes[i].width);
                if (ndiff < diff)
                {
                    best_match = i;
                    diff = ndiff;
                }
            }

            FT_Select_Size(Face, best_match);
        }
        else
        {
            // Vuhdo: I'm not sure how to deal with font sizes properly. As far as I understand, currently ImGui assumes that the 'pixel_height'
            // is a maximum height of an any given glyph, i.e. it's the sum of font's ascender and descender. Seems strange to me.
            // NB: FT_Set_Pixel_Sizes() doesn't seem to get us the same result.
            FT_Size_RequestRec req;
            req.type = (UserFlags & ImGuiFreeTypeBuilderFlags_Bitmap) ? FT_SIZE_REQUEST_TYPE_NOMINAL : FT_SIZE_REQUEST_TYPE_REAL_DIM;
            req.width = 0;
            req.height = (uint32_t)pixel_height * 64;
            req.horiResolution = 0;
            req.vertResolution = 0;
            FT_Request_Size(Face, &req);
        }

        // Update font info
        FT_Size_Metrics metrics = Face->size->metrics;
        Info.PixelHeight = (uint32_t)pixel_height;
        Info.Ascender = (float)FT_CEIL(metrics.ascender);
        Info.Descender = (float)FT_CEIL(metrics.descender);
        Info.LineSpacing = (float)FT_CEIL(metrics.height);
        Info.LineGap = (float)FT_CEIL(metrics.height - metrics.ascender + metrics.descender);
        Info.MaxAdvanceWidth = (float)FT_CEIL(metrics.max_advance);
    }

Furthermore, with the noto-glyf_colr_1.ttf font, it is scalable and has outlines, but its outline (path) size is 0, making the FT_Outline_Get_CBox function in ftoutln.c returns 0 for x y w h. Maybe this is an issue with nanoemoji which was used to build notoemoji. See why, Although it claims "The 'COLR' v1 API is now considered as stable", but it doesn't handle glyphs in 'COLR' v1 format by itself; you have to extract the outlines and render them manually. and provides no way to actually "render them manually".

I can't figure out how to adjust the scale, given that it's "unscalable" but as a workaround, we can use the SVGinOT font noto-untouchedsvg.ttf with my PR #6591

image

@sakiodre
Copy link
Contributor

@ocornut I think we can close this as this is freetype's lack of support for CBDT & COLRv1 fonts (see the technical details I posted above).

With IMGUI_ENABLE_FREETYPE_OTSVG we can use the noto-untouchedsvg.ttf variant instead.

@ocornut
Copy link
Owner

ocornut commented Sep 18, 2023

Thank you @sakiodre, closing this indeed!

@ocornut ocornut closed this as completed Sep 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants