imgui icon indicating copy to clipboard operation
imgui copied to clipboard

Not able to use NotoColorEmoji font

Open yiminli opened this issue 2 years ago • 17 comments

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: https://github.com/ocornut/imgui/issues/4566#issuecomment-924803382 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

yiminli avatar Apr 05 '23 06:04 yiminli

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.

ocornut avatar Apr 05 '23 17:04 ocornut

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

yiminli avatar Apr 06 '23 06:04 yiminli

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

ocornut avatar Apr 24 '23 10:04 ocornut

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

ItsBrank avatar May 07 '23 18:05 ItsBrank

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 🥳

yiminli avatar Jun 20 '23 05:06 yiminli

Any update on this issue?

batcholi avatar Jul 02 '23 21:07 batcholi

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 avatar Jul 13 '23 13:07 sakiodre

@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.

sakiodre avatar Sep 18 '23 16:09 sakiodre

Thank you @sakiodre, closing this indeed!

ocornut avatar Sep 18 '23 16:09 ocornut

Any plans on supporting COLRv1? I'm using the latest FreeType and when I generate a COLRv1 for my project it is all empty (including using the font in the system... but interestingly not if using LibreWriter) but when I generate COLRv0 it works. I would like to use COLRv1 if possible even if it is right now not a show-stopper.

LordOfDragons avatar Aug 29 '25 19:08 LordOfDragons

I don't think this should be closed. Everyone else (eg ff, chrome) can do it too. I do not see why Dear imgui would be special.

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.

I took a quick look at the code, and we currently silently ignore the FT_Request_Size returned error too. But something like this needs to be incorporated.

Green-Sky avatar Oct 14 '25 16:10 Green-Sky

Everyone else (eg ff, chrome) can do it too. I do not see why Dear imgui would be special.

Because Dear ImGui do not use many third-party libraries and is not a web browser.

The project description is "Dear ImGui is designed to enable fast iterations and to empower programmers to create content creation tools and visualization / debug tools (as opposed to UI for the average end-user). "

I closed based on the post above stating that FreeType does not support CBDT & COLRv1 fonts. If you can come with an implementation/fix that either doesn't drag more dependency, either makes them optional, feel free to make a pull request.

ocornut avatar Oct 14 '25 16:10 ocornut

I closed based on the post above stating that FreeType does not support CBDT & COLRv1 fonts. If you can come with an implementation/fix that either doesn't drag more dependency, either makes them optional, feel free to make a pull request.

FreeType does give you an api to extract all the paint instructions, which is then consumed by eg cairo(ff) or skia(chrome). ImGui chose to use plutosvg/plutovg, which I also think would be the place for this to be implemented, so I opend https://github.com/sammycage/plutosvg/issues/40 over there.

I still think "closed" is not the correct state for this issue though, but you do you (: .

Green-Sky avatar Oct 14 '25 20:10 Green-Sky

FreeType does not support CBDT

Now that one is just not true. I think we are just using the api wrong. Like how we have to select the size instead of "request" the size, like I stated before. Bitmaps have the downside to always be the same size, so we will have to decide if we downscale them to the current font size or keep them full sized in vram (probably not).

(relates to https://github.com/ocornut/imgui/issues/8190 and others)

Green-Sky avatar Oct 14 '25 20:10 Green-Sky

I opened https://github.com/sammycage/plutosvg/issues/40 over there.

Thanks. If it can be supported in PlutoSVG then supposedly it wouldn't need an update on dear imgui side?

I still think "closed" is not the correct state for this issue though, but you do you (: .

For semi-fringe features related to tech that are more foreign to me, I am forced to put them aside to help me prioritize on core Dear ImGui features, otherwise it is humanly unmanageable to me.

I'm really not sure what to do with this, I'm not equipped for it and it outside my priority zone. I'm however absolutely OK to merge support/improvements/fixes PR if the code is sensible and well written.

It if end up extracting bitmaps they should be downscaled to current font size probably.

ocornut avatar Oct 15 '25 13:10 ocornut

I opened sammycage/plutosvg#40 over there.

Thanks. If it can be supported in PlutoSVG then supposedly it wouldn't need an update on dear imgui side?

No, there is no simple, preexisting API for this. For svg, freetype has a hook that can be set. So expect a little friction here. But as I state in that issue, there are other downstream projects that would benefit form such an api (I name SDL_ttf there).

I still think "closed" is not the correct state for this issue though, but you do you (: .

For semi-fringe features related to tech that are more foreign to me, I am forced to put them aside to help me prioritize on core Dear ImGui features, otherwise it is humanly unmanageable to me.

I'm really not sure what to do with this, I'm not equipped for it and it outside my priority zone. I'm however absolutely OK to merge support/improvements/fixes PR if the code is sensible and well written.

yay

It if end up extracting bitmaps they should be downscaled to current font size probably.

I think so too. The new font system accounts for dpi stuff, right?

Also to add to this, imgui has had support for CBDT since 2021 https://github.com/ocornut/imgui/pull/3879 , it just only works when the fontsize is exactly one of the font's provided bitmap sizes.

Here is me loading the system provided noto color emojies font at a pixelsize of 109:

Image

edit: Also I have been following https://github.com/ocornut/imgui/pull/8857 , as it tangates this somewhat.

Green-Sky avatar Oct 15 '25 13:10 Green-Sky

There is now a PR that implements bitmap font size selection and downscaling. This should make it possible to use NotoColorEmoji and AppleColorEmoji in most scenarios.

https://github.com/ocornut/imgui/pull/9012

Please test :)


If that PR is merged, I consider this issue done. COLRv1 is a lower priority and depends on external dependencies. A new issue or PR for COLRv1 can be opened when that is ready.

Green-Sky avatar Oct 25 '25 15:10 Green-Sky