-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
[WIP] Replace the current text rendering engine with fontdue. #28
Conversation
The reasons why to change to fontdue are simple: * One of the fastest renderer / layout engine. * Very free dependencies. * Also pure Rust. This PR replaces the glyph rendering by rusttype and the custom layout engine by egui.
Interesting! It would certainly be nice if we could have less code in Egui. A quick test showed slightly larger binaries (in particular the |
A bit of a headsup: On thing that I plan to add to Egui in the coming week or two is to be able to continue text on the same line, and then wrap it. This is so that one can mix different widgets etc to e.g. make a markdown viewer. For instance, maybe we first add a button:
And then add text continuing on the same line:
This would be the work of |
Btw, I feel like I should explain the choice of the word "galley": Egui does widget layout using I'm not married to "galley", but it would be nice to avoid using the same word for different things. |
I will keep this branch rebased to master, so that merge should be easy once deemed ready and merge worthy.
What you describe is pretty advance and would most likely need an extension to the upstream project, so for now I would ask you to push back that change for the short term. It's essentially text flow around a keep out zone (it's not even line based).
We could also change the "layout" for the glyphs into something like "typeset" or "typograph". |
It's not quite that advanced – I don't need the text to wrap around an arbitrary keep-out-zone, just the ability to ask for a text layout where the first line wraps at a different maximum width from the following lines. Basically I'm talking about first-line indentation. If fontdue doesn't support it we should open an issue for it, as it really is key to implementing things like changing font or text color in the middle of a text, or embedding a small image in a text. |
But your example with the button is not line based, it's pixel based. The text of the first line might start on the same height of the button, but the text after that has it's own line height, which might not match the height / margin of the button. And once you want to embed images in text, you need keep out zones and the text flowing around it. If you want it to be line based, then a workaround would be to add whitespace before sending the text to the layout engine. It's already possible with fontdue to mix multiple styles in a typeset: let styles = &[&TextStyle::new("Hello ", 35.0, 0), &TextStyle::new("world!", 40.0, 0)];
layout.layout_horizontal(fonts, styles, &settings, &mut output); Complex shaping is on the roadmap. What I'm essentially asking for: Please dont create a moving target right now, since otherwise this PR would stay in perpetual flux. It's defentily possible to extend the upstream projects, since the author is definitly interrested in having more users. |
Issue submitted: mooman219/fontdue#40 |
I feel your concern, but I won't switch text layout engine unless it supports what I need it to support :) That's why I flagged this now: it is something I want very soon, and if it is impossible in fontdue, then you should not waste time with this PR! However, I assume it will be fairly easy to add to fontdue. Mixing multiple font styles using fontdue is not very attractive to me as it is not immediate mode. Just to illustrate the sort of code I'd like to be able to write (details will vary): ui.horizontal_wrapped(|ui|{
ui.label("This example has ");
ui.hyperlink("a hyperlink", "https://github.com/emilk/gui");
ui.label(" and ");
ui.monospace("some monospace text with a tooltip").on_hover_text("I told you");
ui.label(". It is automatically wrapped at some max width.");
}); This example has a hyperlink and |
This produces proper result with HiDPI screens. The font sizes have also been adjusted, so that the final result matches the old sizes.
Another thing I'd like to add to Egui one day is the ability to opt-in to mesh-based font rendering instead of texture based. This is so that Egui could be used in a 3D world without having blurry text as you get close to it (think VR). Do you think Fontdue would make that easier or harder, or no different? |
You don't want to render your UI text as 3D meshes. That would most likely destroy your performance. For VR and resolution independent applications you most likely want to implement SDF (Signed distance field) based font rendering. I know that the author of fontdue did play with the idea to support those, since they are essentialy still bitmap (with more information). But I don't know the current roadmap. |
I actually do know what I want! I want a simple renderer so that Egui is easy to integrate into any engine. Luckily, rendering triangles is something most computers are really good at. Vector based fonts has downsides (especially for aliasing), but so does SDF based fonts (lack of sharp edges). An SDF approach would also pose problems for how to have a single shader that works for all the Egui primitives. It opens up a big can of worms. Anyway, my current idea would be to pre-tesselate each character using e.g. lyon (just like the current code pre-rasterizes each character), but otherwise keep the text layout algorithm mostly the same. This is not something I will get to soon, but I want to keep my options open. |
I'm gonna close this - I'm not sure fontdue is the right fit for Egui, because it is still uncertain exactly what Egui needs. I appreciate the effort, but Egui is evolving fast, and it is helpful to me to keep things simple for now, which means rolling my own text layout. |
This PR is currently WIP.
The reasons why to change to fontdue are simple:
Performance against the master branch:
This PR replaces the glyph rendering by rusttype and the custom layout engine by egui.
TODO
Bugs
Features
Others