From 2bfcfdf8b814b2ed8dabbc2dec7dbd6d5dcc4733 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 14 Mar 2024 20:39:28 -0600 Subject: [PATCH] Improve fractional rendering by finding perfectly scalable size --- src/text_box.rs | 51 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/src/text_box.rs b/src/text_box.rs index bd9f40f..89d4a4f 100644 --- a/src/text_box.rs +++ b/src/text_box.rs @@ -318,28 +318,46 @@ where let mut editor = self.editor.lock().unwrap(); + let cosmic_theme = theme.cosmic(); + let scrollbar_w = cosmic_theme.spacing.space_xxs as i32; + let view_w = cmp::min(viewport.width as i32, layout.bounds().width as i32) - - self.padding.horizontal() as i32; + - self.padding.horizontal() as i32 + - scrollbar_w; let view_h = cmp::min(viewport.height as i32, layout.bounds().height as i32) - self.padding.vertical() as i32; let scale_factor = style.scale_factor as f32; let metrics = self.metrics.scale(scale_factor); - let image_w = (view_w as f32 * scale_factor) as i32; - let image_h = (view_h as f32 * scale_factor) as i32; + let calculate_image_scaled = |view: i32| -> (i32, f32) { + // Get smallest set of physical pixels that fit inside the logical pixels + let image = ((view as f32) * scale_factor).floor() as i32; + // Convert that back into logical pixels + let scaled = (image as f32) / scale_factor; + (image, scaled) + }; + let calculate_ideal = |view_start: i32| -> (i32, f32) { + // Search for a perfect match within 16 pixels + for i in 0..16 { + let view = view_start - i; + let (image, scaled) = calculate_image_scaled(view); + if view == scaled as i32 { + return (image, scaled); + } + } + let (image, scaled) = calculate_image_scaled(view_start); + (image, scaled) + }; - let cosmic_theme = theme.cosmic(); - let scrollbar_w = (cosmic_theme.spacing.space_xxs as f32 * scale_factor) as i32; + let (image_w, scaled_w) = calculate_ideal(view_w); + let (image_h, scaled_h) = calculate_ideal(view_h); - if image_w <= scrollbar_w || image_h <= 0 { + if image_w <= 0 || image_h <= 0 { // Zero sized image return; } - // Adjust image width by scrollbar width - let image_w = image_w - scrollbar_w; - // Lock font system (used throughout) let mut font_system = font_system().write().unwrap(); @@ -587,7 +605,7 @@ where let rect = Rectangle::new( [image_w as f32 / scale_factor, start_y as f32 / scale_factor].into(), Size::new( - scrollbar_w as f32 / scale_factor, + scrollbar_w as f32, (end_y as f32 - start_y as f32) / scale_factor, ), ); @@ -609,17 +627,16 @@ where let image_position = layout.position() + [self.padding.left, self.padding.top].into(); if let Some(ref handle) = *handle_opt { let image_size = image::Renderer::dimensions(renderer, handle); + let scaled_size = Size::new(scaled_w as f32, scaled_h as f32); + log::debug!( + "text_box image {:?} scaled {:?} position {:?}", + image_size, scaled_size, image_position + ); image::Renderer::draw( renderer, handle.clone(), image::FilterMethod::Nearest, - Rectangle::new( - image_position, - Size::new( - image_size.width as f32 / scale_factor, - image_size.height as f32 / scale_factor, - ), - ), + Rectangle::new(image_position, scaled_size), [0.0; 4], ); }