1
0
Fork 0
forked from wry/wry

Merge pull request #306 from mahkoh/jorth/fractional-scale-rounding

fractional-scale: implement accurate rounding
This commit is contained in:
mahkoh 2024-10-22 11:13:26 +02:00 committed by GitHub
commit eff490a653
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 41 additions and 14 deletions

View file

@ -30,8 +30,7 @@ impl RendererBase<'_> {
pub fn scale_point(&self, mut x: i32, mut y: i32) -> (i32, i32) { pub fn scale_point(&self, mut x: i32, mut y: i32) -> (i32, i32) {
if self.scaled { if self.scaled {
x = (x as f64 * self.scalef).round() as _; [x, y] = self.scale.pixel_size([x, y]);
y = (y as f64 * self.scalef).round() as _;
} }
(x, y) (x, y)
} }
@ -46,10 +45,9 @@ impl RendererBase<'_> {
pub fn scale_rect(&self, mut rect: Rect) -> Rect { pub fn scale_rect(&self, mut rect: Rect) -> Rect {
if self.scaled { if self.scaled {
let x1 = (rect.x1() as f64 * self.scalef).round() as _; let [x1, y1, x2, y2] =
let y1 = (rect.y1() as f64 * self.scalef).round() as _; self.scale
let x2 = (rect.x2() as f64 * self.scalef).round() as _; .pixel_size([rect.x1(), rect.y1(), rect.x2(), rect.y2()]);
let y2 = (rect.y2() as f64 * self.scalef).round() as _;
rect = Rect::new(x1, y1, x2, y2).unwrap(); rect = Rect::new(x1, y1, x2, y2).unwrap();
} }
rect rect

View file

@ -1,6 +1,7 @@
use std::fmt::{Debug, Display, Formatter}; use std::fmt::{Debug, Display, Formatter};
const BASE: u32 = 120; const BASE: u32 = 120;
const BASE64: i64 = BASE as i64;
const BASEF: f64 = BASE as f64; const BASEF: f64 = BASE as f64;
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
@ -38,15 +39,13 @@ impl Scale {
self.0 self.0
} }
pub fn pixel_size(self, width: i32, height: i32) -> (i32, i32) { #[inline(always)]
pub fn pixel_size<const N: usize>(self, v: [i32; N]) -> [i32; N] {
if self == Scale::default() { if self == Scale::default() {
return (width, height); return v;
} }
let scale = self.to_f64(); let scale = self.0 as i64;
( v.map(|v| ((v as i64 * scale + BASE64 / 2) / BASE64) as i32)
(width as f64 * scale).round() as i32,
(height as f64 * scale).round() as i32,
)
} }
} }

View file

@ -17,6 +17,7 @@ use {
PlaceholderNode, WorkspaceNode, PlaceholderNode, WorkspaceNode,
}, },
utils::{ utils::{
array_to_tuple::ArrayToTuple,
clonecell::CloneCell, clonecell::CloneCell,
copyhashmap::CopyHashMap, copyhashmap::CopyHashMap,
hash_map_ext::HashMapExt, hash_map_ext::HashMapExt,
@ -608,7 +609,7 @@ impl ToplevelData {
let (dw, dh) = self.desired_extents.get().size(); let (dw, dh) = self.desired_extents.get().size();
if let Some(ws) = self.workspace.get() { if let Some(ws) = self.workspace.get() {
let scale = ws.output.get().global.persistent.scale.get(); let scale = ws.output.get().global.persistent.scale.get();
return scale.pixel_size(dw, dh); return scale.pixel_size([dw, dh]).to_tuple();
}; };
(0, 0) (0, 0)
} }

View file

@ -1,5 +1,6 @@
pub mod activation_token; pub mod activation_token;
pub mod array; pub mod array;
pub mod array_to_tuple;
pub mod asyncevent; pub mod asyncevent;
pub mod bindings; pub mod bindings;
pub mod bitfield; pub mod bitfield;

View file

@ -0,0 +1,28 @@
pub trait ArrayToTuple {
type Tuple;
fn to_tuple(self) -> Self::Tuple;
}
macro_rules! ignore {
($t:tt) => {
T
};
}
macro_rules! array_to_tuple {
($n:expr, $($field:ident,)*) => {
impl<T> ArrayToTuple for [T; $n] {
type Tuple = ($(ignore!($field),)*);
fn to_tuple(self) -> Self::Tuple {
let [$($field,)*] = self;
#[allow(clippy::allow_attributes)]
#[allow(clippy::unused_unit)]
($($field,)*)
}
}
};
}
array_to_tuple!(2, t1, t2,);