This commit is contained in:
Will Temple
2026-05-15 16:28:06 -07:00
parent 67400f1499
commit bfda24ad0a
13 changed files with 782 additions and 363 deletions

View File

@@ -170,8 +170,8 @@ struct UploadedAtlasText {
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
struct TextTextureKey {
text: String,
bounds: Option<(u32, u32)>,
clip: Option<(u32, u32, u32, u32)>,
bounds: Option<(i32, i32)>,
clip: Option<(i32, i32, i32, i32)>,
font_size_bits: u32,
line_height_bits: u32,
color: (u8, u8, u8, u8),
@@ -1315,7 +1315,7 @@ fn fs_main(input: VertexOut) -> @location(0) vec4<f32> {
clip: ActiveClip,
) -> Option<UploadedText> {
let raster_clip = text_raster_clip(text, clip, logical_size)?;
let key = text_texture_key(text, raster_clip);
let key = text_texture_key(text, raster_clip, self.scale_factor);
if !self.text_cache.contains_key(&key) {
let rasterized = self.rasterize_text(text, raster_clip)?;
let cached = self.create_cached_text_texture(&rasterized);
@@ -2442,20 +2442,21 @@ fn clip_visible_glyphs(text: &PreparedText, clip: Option<Rect>) -> &[GlyphInstan
&text.glyphs[glyph_start..glyph_end.min(text.glyphs.len())]
}
fn text_texture_key(text: &PreparedText, raster_clip: Option<Rect>) -> TextTextureKey {
fn text_texture_key(
text: &PreparedText,
raster_clip: Option<Rect>,
scale_factor: f32,
) -> TextTextureKey {
TextTextureKey {
text: text.text.clone(),
bounds: text
.bounds
.map(|bounds| (bounds.width.to_bits(), bounds.height.to_bits())),
clip: raster_clip.map(|clip| {
bounds: text.bounds.map(|bounds| {
(
clip.origin.x.to_bits(),
clip.origin.y.to_bits(),
clip.size.width.to_bits(),
clip.size.height.to_bits(),
(bounds.width * scale_factor).ceil() as i32,
(bounds.height * scale_factor).ceil() as i32,
)
}),
clip: raster_clip
.map(|clip| pixel_rect_tuple(scale_rect_to_pixel_rect(clip, scale_factor))),
font_size_bits: text.font_size.to_bits(),
line_height_bits: text.line_height.to_bits(),
color: (
@@ -2479,6 +2480,10 @@ fn text_texture_key(text: &PreparedText, raster_clip: Option<Rect>) -> TextTextu
}
}
fn pixel_rect_tuple(rect: PixelRect) -> (i32, i32, i32, i32) {
(rect.left, rect.top, rect.right, rect.bottom)
}
#[cfg(test)]
mod tests {
use super::{
@@ -2539,11 +2544,30 @@ mod tests {
);
assert_eq!(
text_texture_key(&first, None),
text_texture_key(&second, None)
text_texture_key(&first, None, 1.0),
text_texture_key(&second, None, 1.0)
);
}
#[test]
fn text_texture_key_normalizes_clip_to_device_pixels() {
let text = PreparedText::monospace(
"scrolling text",
Point::new(20.0, 30.0),
16.0,
8.0,
Color::rgb(0xEE, 0xEE, 0xEE),
);
let first = text_texture_key(&text, Some(Rect::new(0.001, 4.001, 80.001, 20.001)), 2.0);
let second = text_texture_key(&text, Some(Rect::new(0.002, 4.002, 80.002, 20.002)), 2.0);
let different_pixel =
text_texture_key(&text, Some(Rect::new(0.6, 4.001, 80.001, 20.001)), 2.0);
assert_eq!(first, second);
assert_ne!(first, different_pixel);
}
#[test]
fn nested_clip_with_empty_intersection_stays_clipped() {
let mut clip_stack = Vec::new();