Compare commits

3 Commits

Author SHA1 Message Date
38d7ca3090 todo update 2025-11-18 01:09:58 -05:00
126c442706 todo update 2025-11-18 01:08:17 -05:00
6b7719539e better text rendering 2025-11-18 01:05:51 -05:00
2 changed files with 46 additions and 19 deletions

2
TODO
View File

@@ -4,8 +4,6 @@ images
text text
figure out ways to speed up / what costs the most figure out ways to speed up / what costs the most
resizing (per frame) is really slow (assuming painter isn't griefing) resizing (per frame) is really slow (assuming painter isn't griefing)
bug where x offset doesn't shift texture correctly (eg typing a vs j)
bug (?) where if you spam a key it slows down at a certain point, seems to be line based
masks r just made to bare minimum work masks r just made to bare minimum work

View File

@@ -1,4 +1,6 @@
use cosmic_text::{Attrs, AttrsList, Buffer, Family, FontSystem, Metrics, SwashCache}; use cosmic_text::{
Attrs, AttrsList, Buffer, Family, FontSystem, Metrics, SwashCache, SwashContent,
};
use image::{Rgba, RgbaImage}; use image::{Rgba, RgbaImage};
use crate::{ use crate::{
@@ -79,7 +81,7 @@ impl TextData {
// should probably do texture packing and things if possible. // should probably do texture packing and things if possible.
// very visible if you add just a couple of wrapping texts and resize window // very visible if you add just a couple of wrapping texts and resize window
// should also be timed to figure out exactly what points need to be sped up // should also be timed to figure out exactly what points need to be sped up
let mut pixels = HashMap::default(); let mut pixels = HashMap::<_, [u8; 4]>::default();
let mut min_x = 0; let mut min_x = 0;
let mut min_y = 0; let mut min_y = 0;
let mut max_x = 0; let mut max_x = 0;
@@ -99,20 +101,46 @@ impl TextData {
None => cosmic_color, None => cosmic_color,
}; };
self.swash_cache.with_pixels( if let Some(img) = self
&mut self.font_system, .swash_cache
physical_glyph.cache_key, .get_image(&mut self.font_system, physical_glyph.cache_key)
glyph_color, {
|x, y, color| { let mut pos = img.placement;
let x = physical_glyph.x + x; pos.left += physical_glyph.x;
let y = run.line_y as i32 + physical_glyph.y + y; pos.top = physical_glyph.y + run.line_y as i32 - pos.top;
min_x = min_x.min(x); min_x = min_x.min(pos.left);
min_y = min_y.min(y); min_y = min_y.min(pos.top);
max_x = max_x.max(x); max_x = max_x.max(pos.left + pos.width as i32);
max_y = max_y.max(y); max_y = max_y.max(pos.top + pos.height as i32);
pixels.insert((x, y), Rgba(color.as_rgba())); let mut merge = |i, color: [u8; 4]| {
}, let x = i % pos.width as usize;
); let y = i / pos.width as usize;
let pos = (x as i32 + pos.left, y as i32 + pos.top);
if let Some(pixel) = pixels.get_mut(&pos) {
for i in 0..4 {
pixel[i] = color[i].saturating_add(pixel[i]);
}
} else {
pixels.insert(pos, color);
}
};
match img.content {
SwashContent::Mask => {
for (i, a) in img.data.iter().enumerate() {
let mut color = glyph_color.as_rgba();
color[3] = ((color[3] as u32 * *a as u32) / u8::MAX as u32) as u8;
merge(i, color);
}
}
SwashContent::SubpixelMask => todo!(),
SwashContent::Color => {
let (colors, _) = img.data.as_chunks::<4>();
for (i, color) in colors.iter().enumerate() {
merge(i, *color);
}
}
}
}
} }
max_width = max_width.max(run.line_w); max_width = max_width.max(run.line_w);
height += run.line_height; height += run.line_height;
@@ -120,10 +148,11 @@ impl TextData {
let img_width = (max_x - min_x + 1) as u32; let img_width = (max_x - min_x + 1) as u32;
let img_height = (max_y - min_y + 1) as u32; let img_height = (max_y - min_y + 1) as u32;
let mut image = RgbaImage::new(img_width, img_height); let mut image = RgbaImage::new(img_width, img_height);
for ((x, y), color) in pixels { for ((x, y), color) in pixels {
let x = (x - min_x) as u32; let x = (x - min_x) as u32;
let y = (y - min_y) as u32; let y = (y - min_y) as u32;
image.put_pixel(x, y, color); image.put_pixel(x, y, Rgba(color));
} }
TextTexture { TextTexture {
handle: textures.add(image), handle: textures.add(image),