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

Support for OpenType SVG fonts #6591

Closed
wants to merge 7 commits into from
Closed

Conversation

sakiodre
Copy link
Contributor

@sakiodre sakiodre commented Jul 10, 2023

Support for OpenType SVG fonts (SVGinOT)

Motivation

  • SVG in Open Type is a standard by Adobe and Mozilla for color OpenType and Open Font Format fonts. It allows font creators to embed complete SVG files within a font enabling full color and even animations.
  • Popular SVGinOT fonts such as twemoji and (a build of) noto-emoji are currently not supported by dear imgui.
  • Using tools like nanoemoji and scfbuild, we can easily make our own custom colorful fonts from SVGs instead of having to use custom glyphs and deal with bitmap and scaling.

How it works

Enable SVG support and install required libraries

  1. Enable FreeType, follow the instructions here, requires v2.12 and above.
  2. Add #define IMGUI_ENABLE_FREETYPE_OTSVG in your imconfig.h.
  3. Install lunasvg v2.3.2 and above. Get the latest lunasvg binaries or build yourself. Under Windows, you may use vcpkg with: vcpkg install lunasvg --triplet=x64-windows.

Preview

  • Here is a preview of twemoji rendered in dear imgui:
    image

@sakiodre
Copy link
Contributor Author

The problem with librsvg on windows is the vcpkg package is deprecated since it has switched to rust which vcpkg toolchain doesn't really support.

This means we couldn't use the proper rsvg_handle_get_intrinsic_dimensions function to get the SVG dimension, making some glyphs appear distorted (shown in the preview image).

I've been struggling to build librsvg on windows, considering how heavy and problematic it is, switching to a more lightweight, easy-to-install library like lunasvg might be ideal.

@sakiodre
Copy link
Contributor Author

This now uses lunasvg instead of librsvg, it is way faster (not measured but maybe ~10x) and renders better than librsvg. I've also updated the vcpkg port to 2.3.8, so installing the dependencies is not a problem anymore, and we don't need to add a bunch of additional include directories like with the librsvg.

@excellentcucumber
Copy link

excellentcucumber commented Jul 13, 2023

Finally, thank you! Now i can use the notoemoji font

image

Note: You may need to cd to vcpkg directory and git pull first before installing lunasvg

@ocornut any chance of merging?

@ocornut
Copy link
Owner

ocornut commented Jul 13, 2023

Thanks for the PR.
This is an unusually well-made PR, I appreciate your sense of details.

I was initially hesitant in the first draft because of the librsvg availability issue you mentioned + the fact it used to be much more code, but switching to lunasvg makes it much saner and shorter.

I'll need to try it and review more carefully, but in the meantime if you don't mind, some quick feedback:

  • What is <memory> for? could the std::unique_ptr<> be removed in favor of a raw pointer?
  • Could you compact some of the code (asserts, hook list) on a single line.
  • I realize the hooks implemented are based on a demo. Since they are slightly massaged already (function names etc.) I would suggest on removing comments and putting an emphasis on referring to the demo for commentary.
  • We might have an issue since technically the hook code coming from that demo is under the Freetype licence. However it is clearly "trivial" code, in the sense that there aren't other way to achieve the same result with the same API, and that kind of stuff tends to not be copyrightable. I think it is fair use but I would add a comment at the top of the #ifdef IMGUI_ENABLE_FREETYPE_OTSVG block about licensing + a comment in the imconfig.h description comment. as well.

Thanks a lot!

@ocornut
Copy link
Owner

ocornut commented Jul 13, 2023

I would also suggest using #define IMGUI_ENABLE_FREETYPE_LUNASVG instead of #define IMGUI_ENABLE_FREETYPE_OTSVG.
I noticed you changed naming strategy when switching from librsvg to lunasvg, but I would argue the existence of varying libs makes a case for naming it this way.

@sakiodre
Copy link
Contributor Author

sakiodre commented Jul 13, 2023

What is <memory> for? could the std::unique_ptr<> be removed in favor of a raw pointer?

lunasvg::Document::loadFromData returns an unique_ptr so I don't know how we could turn it into the underlying pointer without destroying itself.

We might have an issue since technically the hook code coming from that demo is under the Freetype licence.

Sorry I did not think about the licensing issue, but since most of the original code from the demo is replaced, I believe it is fair use.

@sakiodre
Copy link
Contributor Author

@ocornut I'm not really sure how to go about adding information about the demo license, would you mind checking?

imconfig.h
//---- Use lunasvg library to render OpenType SVG fonts (SVGinOT)
// Requires lunasvg headers to be available in the include path. Requires program to be compiled with the lunasvg library (not provided).
// See https://github.com/ocornut/imgui/tree/master/misc/freetype
// Only works in combination with IMGUI_ENABLE_FREETYPE.
+// The implementation is based on the demo https://gitlab.freedesktop.org/freetype/freetype-demos/-/blob/master/src/rsvg-port.c
+// which is licensed under CeCILL-C Free Software License Agreement
//#define IMGUI_ENABLE_FREETYPE_LUNASVG

imgui_freetype.cpp
#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
// For more details, see https://gitlab.freedesktop.org/freetype/freetype-demos/-/blob/master/src/rsvg-port.c
+// The original code from the demo is licensed under CeCILL-C Free Software License Agreement
+// https://gitlab.freedesktop.org/freetype/freetype/-/blob/master/LICENSE.TXT

@excellentcucumber
Copy link

I can finally use my custom icons as a font, this is game-changing!

image

@sakiodre
Copy link
Contributor Author

Lunasvg is a great library but it still lacks some features in comparison with other libraries. For example, it lacks text and image rendering (lunasvg#113), which might be a deal breaker for some users using their own custom fonts (but not an issue with noto-emoji and twemoji).

Ideally, we may want to use resvg which is currently the best svg rendering library that I could find, but again, just like with the librsvg - it is in Rust, hopefully vcpkg#30251 will get merged some day and resvg can be added in the future along with lunasvg.

Although if resvg were to be added in the future, it's a little problematic to have two options doing the exact same thing.

@misuke0
Copy link

misuke0 commented Jul 18, 2023

One question, could we support skin tone?

@ocornut
Copy link
Owner

ocornut commented Jul 18, 2023

One question, could we support skin tone?

Probably not as the modifier depends on a subset of Unicode specs we don't support nor intend to support.

@excellentcucumber
Copy link

@ocornut sorry to rush but could this be merged before the next release? I'd like to use this with vcpkg

// Calculate the bitmap size
slot->bitmap_left = FT_Int(box.x);
slot->bitmap_top = FT_Int(-box.y);
slot->bitmap.rows = unsigned int(ceil(box.h));
Copy link

@iacore iacore Jul 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here should be (unsigned int)(cell(box.h)). Not sure why CI passed, but this is not valid

Copy link
Contributor Author

@sakiodre sakiodre Jul 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is indeed invalid, Explicit type conversion section 2)

The functional-style cast expression consists of a simple type specifier or a typedef specifier (in other words, a single-word type name, that is, cases such as unsigned int(expression) and int*(expression) are not valid), followed by a comma-separated list of expressions in parentheses.

Interestingly, both MSVC compiler and intellisense did not complain about this, godbolt.

image

CI passed because we haven't added the test with IMGUI_ENABLE_FREETYPE_OTSVG enabled.

@ocornut
Copy link
Owner

ocornut commented Aug 1, 2023

Thanks for your work @sakiodre !
I have merged your PR squashed as 2ad8c60 + miscellaneous shallow amends ab490dc (changelogs, centralized freetype version checks, using ImCeil, IM_ROUND, IM_NEW, misc compaction and coding style tweaks).

@ocornut
Copy link
Owner

ocornut commented Jan 3, 2024

See #7187 suggesting that current version of Lunasvg may have performance issues in some situations, hopefully fixed soon.

@TviKo7teaFy
Copy link

Can you upload a copy of your twemoji font? Why did the twemoji I downloaded from GitHub only show a part? I want to know what the reason is

ocornut pushed a commit that referenced this pull request Oct 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants