better text rendering
This commit is contained in:
@@ -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 crate::{
|
||||
@@ -79,7 +81,7 @@ impl TextData {
|
||||
// should probably do texture packing and things if possible.
|
||||
// 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
|
||||
let mut pixels = HashMap::default();
|
||||
let mut pixels = HashMap::<_, [u8; 4]>::default();
|
||||
let mut min_x = 0;
|
||||
let mut min_y = 0;
|
||||
let mut max_x = 0;
|
||||
@@ -99,20 +101,46 @@ impl TextData {
|
||||
None => cosmic_color,
|
||||
};
|
||||
|
||||
self.swash_cache.with_pixels(
|
||||
&mut self.font_system,
|
||||
physical_glyph.cache_key,
|
||||
glyph_color,
|
||||
|x, y, color| {
|
||||
let x = physical_glyph.x + x;
|
||||
let y = run.line_y as i32 + physical_glyph.y + y;
|
||||
min_x = min_x.min(x);
|
||||
min_y = min_y.min(y);
|
||||
max_x = max_x.max(x);
|
||||
max_y = max_y.max(y);
|
||||
pixels.insert((x, y), Rgba(color.as_rgba()));
|
||||
},
|
||||
);
|
||||
if let Some(img) = self
|
||||
.swash_cache
|
||||
.get_image(&mut self.font_system, physical_glyph.cache_key)
|
||||
{
|
||||
let mut pos = img.placement;
|
||||
pos.left += physical_glyph.x;
|
||||
pos.top = physical_glyph.y + run.line_y as i32 - pos.top;
|
||||
min_x = min_x.min(pos.left);
|
||||
min_y = min_y.min(pos.top);
|
||||
max_x = max_x.max(pos.left + pos.width as i32);
|
||||
max_y = max_y.max(pos.top + pos.height as i32);
|
||||
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);
|
||||
height += run.line_height;
|
||||
@@ -120,10 +148,11 @@ impl TextData {
|
||||
let img_width = (max_x - min_x + 1) as u32;
|
||||
let img_height = (max_y - min_y + 1) as u32;
|
||||
let mut image = RgbaImage::new(img_width, img_height);
|
||||
|
||||
for ((x, y), color) in pixels {
|
||||
let x = (x - min_x) as u32;
|
||||
let y = (y - min_y) as u32;
|
||||
image.put_pixel(x, y, color);
|
||||
image.put_pixel(x, y, Rgba(color));
|
||||
}
|
||||
TextTexture {
|
||||
handle: textures.add(image),
|
||||
|
||||
Reference in New Issue
Block a user