-
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
Cosmic Text for font rendering #3378
Comments
I also experimented with cosmic text but went with hacking some completely inefficient and not really generic code in the pub fn tessellate_text(&mut self, text_shape: &TextShape, out: &mut Mesh) {
let TextShape {
pos: galley_pos,
galley,
underline,
override_text_color,
angle,
} = text_shape;
if galley.is_empty() {
return;
}
if galley.pixels_per_point != self.pixels_per_point {
eprintln!("epaint: WARNING: pixels_per_point (dpi scale) have changed between text layout and tessellation. \
You must recreate your text shapes if pixels_per_point changes.");
}
for row in &galley.rows {
let metrics =
cosmic_text::Metrics::new(galley.job.sections[0].format.font_id.size, row.height());
let mut buffer = cosmic_text::Buffer::new(&mut self.font_system, metrics);
let mut buffer = buffer.borrow_with(&mut self.font_system);
buffer.set_size(row.rect.width(), row.rect.height());
let attrs = cosmic_text::Attrs::new();
buffer.set_text(&row.text(), attrs, cosmic_text::Shaping::Advanced);
buffer.shape_until_scroll();
let text_color = override_text_color
.map(|c| cosmic_text::Color::rgba(c.r(), c.g(), c.b(), c.a()))
.unwrap_or_else(|| cosmic_text::Color::rgb(0xFF, 0xFF, 0xFF));
buffer.draw(&mut self.swash_cache, text_color, |x, y, w, h, color| {
let min_pos = *galley_pos + row.rect.min.to_vec2() + vec2(x as f32, y as f32);
let size = vec2(w as f32, h as f32);
let output_rect = Rect::from_min_size(min_pos, size);
let ecolor =
Color32::from_rgba_unmultiplied(color.r(), color.g(), color.b(), color.a());
out.add_colored_rect(output_rect, ecolor);
});
}
} Using cosmic text would mean to replace the whole pipeline of text layout and not just rendering, which seems to be quite a change, even possible in the public facing API. But it is definitely possible. |
Interesting work! Can you type in some RTL text? e.g. (سلامم) And yes I agree, it'll be a big change. User facing API's could stay the same still in my opinion, but the pipeline will need some change. |
I do not know font rendering, but can't there be a GPU cache of the bitmaps and be reused without having to create a new texture? that should be fast enough. although problem would be the issue in different sizes, could quickly grow in memory size.. hmm I'd say GPUs nowadays are fast enough, and given WebGPU is right around the corner, this could be possible. I wonder how did the ICED achieved it. |
Do you have a link for that issue? |
yes of course! pop-os/cosmic-text#70 |
related issue that explains further: iced-rs/iced#1877 |
maybe this helps as direction for how to solve the caching? pop-os/cosmic-text#26 (comment) |
I'm digging (trying...) into this. It looks like we need to draw textures and not polygons... |
Here are some notes I have while reading the code.
|
interesting, I can hardly understand most of them 😅 |
This might be useful for reference: https://github.com/grovesNL/glyphon |
For people who need this right now, feel free to use this crate I just created https://github.com/StratusFearMe21/egui-glyphon |
I had a talk to the people behind Parley the other day, and I think it is exactly what we want for egui. It is not quite ready yet (lacking docs/examples), but according to the fine folks at linebender, it will be ready for testing in a month or so. Parley promises to solve:
…and with a minimal amount of dependencies. This is very exciting! |
Could someone summarize the issues with cosmic-text that would be blocking its adoption by egui? |
Which is right about now... 👀 |
I fixed pop-os/cosmic-text#70 recently. I'll be doing a new release of cosmic-text soon that includes this change. |
🚀 🚀 🚀 |
For reference, Bevy is working to decide between parley and cosmic-text right now. |
I released a new version of cosmic-text, 0.12.0, with numerous fixes for use by bevy. Please let me know if there is anything I need to do to support egui. |
FWIW, Bevy has just merged Cosmic Text support: bevyengine/bevy#10193 |
@crumblingstatue thanks for linking that Bevy document! I think the reasoning and conclusions in there is sound: Parley is very promising, but not yet ready, while Cosmic Text is ready for production today. I therefor support switching egui to Cosmic Text, if someone coulenteers to do the actual work 😆 The above linked Bevy PR should be a very helpful guide for migrating from One thing that worries me is the added dependencies.
By comparison, we have:
The Still, the build time is only 2x, for quite a lot more features:
So I say as long as the .wasm size doesn't balloon (and I doubt it will), let's go for it 🚀 |
This is a concern for me, as well. On the other hand, The other consideration is that
Footnotes
|
Yes, I am always open to optimizations, and I am tracking some upstream crate issues that cause the duplicate ttf-parser issue. |
How much is this change likely to improve the kerning, and perhaps the vertical alignment of text from two different fonts? (We're evaluating a change from Electron.js to Tauri or egui, resulting in a bit of a beauty context for this sort of thing here). For reference, here's the relevant Rust code, the HTML is a styled let mut format = TextFormat {
font_id: egui::FontId::new(orig_text_height_px, egui::FontFamily::Proportional),
color: Color32::BLACK,
valign: Align::Center,
..Default::default()
};
let mut job = LayoutJob::default();
job.append(text, 0.0, format.clone());
job.append(" ", 0.0, format.clone());
format.font_id.family = egui::FontFamily::Name("icons".into());
job.append(icon, 0.0, format);
let galley = ui.painter().layout_job(job);
let galley_size = galley.size();
let galley_pos = rect.min + padding + (text_size - galley_size) / 2.0;
ui.painter().galley(galley_pos, galley, Color32::WHITE); |
I updated this for 0.30.0 if anyone wants to start hacking on this: works great! |
As discussed in #1016 , I have done some testing on cosmic-text.
First of all, they have some docs that I've been exploring. And I was testing their example. They do have
no_std
andwasm
support too according to theCargo.toml
they have.I've noticed that the way it renders, is by drawing rectangles. Which is something I've seen for the first time to be honest. You can check it here. It gives a x,y,width,height, and color which is usually just color predefined and alpha channel being different for aliasing and stuff.
There is also another method if rectangles aren't possible: Swash Image which basically returns an image bytes to be rendered instead of individually creating rectangles. It requires some things I couldn't implement myself to be honest.
I was able to sort of hack the rectangle method in my engine
It had... not good results to be honest
Although maybe that's on me for having some issues with the engine as their examples do work and work very well. But yeah, that's my findings so far on cosmic text.
The text was updated successfully, but these errors were encountered: