ocornut / imgui

Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies
MIT License
57.95k stars 9.93k forks source link

Build font textures with overlapping utf8 code points (LaTeX fonts) #5647

Open jokteur opened 1 year ago

jokteur commented 1 year ago

Version/Branch of Dear ImGui:

Version: 1.87 Branch: docking

Back-end/Renderer/Compiler/OS

GLFW + OpenGL Operating System: Windows 10

My Issue/Question:

Hello, I've been trying to integrate MicroTeX into ImGui. So far, I have had some success, but I've stumbled into a particular problem with utf8 codepoints and glyph indices.

MicroTeX is a library that takes as an input LaTex formatting, and outputs a bunch of draw calls (like AddLine, AddRect, drawGlyph, ...). The problem I encounter is when I use a math fonts: sometimes there are multiple variations of the same character. One character can be regular or italic. For example when drawing the latex equation $\sin s$, the s from sin will be regular (glyph index 116), and the other s will be italic (glyph index 2519), but both have the same utf-8 codepoint: 115.

Here is an example on what I managed to render with ImGui, vs what I expect it to render (not using exactly the same fonts, but it is just for illustration): image vs image

When building the math font with AddFontFromFileTTF and the ImFontGlyphRangesBuilder, I can't really specify glyph indices, only utf8 codepoints. This means that the regular / italic character variations within the same font won't be taken into account.

Is there any way to solve this problem without rewriting the font texture builder entirely ?

Alternate solution I'm aware of the XY problem, but I didn't want to open a separate issue. MicroTeX offers an alternative, where the fonts are directly drawn with draw calls (cubics, quads, lines, rect, ...) and a font altas is never used. I know I can use the draw calls in imgui, but I am wondering about performance. So maybe I have a second question: if the first solution doesn't work, is there any way to use the convenient imgui draw calls, and rasterizing them ? Here ideally I wouldn't want to rewrite a whole rasterizer.

Thanks for the answers

ocornut commented 1 year ago

Our font support is rather lackluster but it also seems that for many fonts the Italic variation are in a separate font file. So you would need to load the normal and italic fonts.

If you use imgui_freetype there’s a flag to turn a font into Italic.

jokteur commented 1 year ago

For normal text, I would normally have separate fonts. But these latex math fonts are build like this: variations of characters are within the same fonts (for e.g. you can have little parenthesis, medium parenthesis, big parenthesis), and there is another file (.clm) that keeps track of these variations. MicroTex is reading both the .otf and .clm files, and sends glyph indices to indicate what to draw.

I would need to basically write a tool to split the variations into multiple fonts, and modify the MicroTeX library to take this into account.

So maybe I would need to take the second approach: draw the fonts directly. Should I open another issue (how to rasterize draw calls), or is there already a solution that I missed ?

thedmd commented 1 year ago

You can try to patch imgui_freetype, so you can request particular style of the font. ImGui pass flags to generator so you use few bits to represent style. That will allow you to generate multiple instances of ImFont for every style. You then can switch between them while constructing equation. All glyphs will land on single atlas, which will not increase draw calls.

Drawing directly is more tricky. You could use FreeType directly to rasterize glyphs, manually blit them to larger bitmap and convert to texture at the end. Use of the cache will be necessary I think.

NanoMichael commented 1 year ago

But these latex math fonts are build like this: variations of characters are within the same fonts (for e.g. you can have little parenthesis, medium parenthesis, big parenthesis)

@jokteur Actually, the math variations are not like the other "font variations" (like italic, bold, condensed, and so on), the "variations" are Unicode specific. For example, a bold math symbol "A" (Unicode code point: U+1D400) has a different Unicode code point from the regular letter "A" (Unicode code point: U+0041). And typically a math font contains all the variations for math symbols, including these "extensible delimiters (like the brace {})", many of them even do not have a Unicode, take the font XITSMath-Regular.otf as an example, the glyph {, its taller variation actually does not have a Unicode. So we can't use the code point to render glyphs, but with the glyph id in the font file.