fractional-scale: implement accurate rounding
This commit is contained in:
parent
cc426a0a4a
commit
e2806a6337
5 changed files with 41 additions and 14 deletions
|
|
@ -30,8 +30,7 @@ impl RendererBase<'_> {
|
|||
|
||||
pub fn scale_point(&self, mut x: i32, mut y: i32) -> (i32, i32) {
|
||||
if self.scaled {
|
||||
x = (x as f64 * self.scalef).round() as _;
|
||||
y = (y as f64 * self.scalef).round() as _;
|
||||
[x, y] = self.scale.pixel_size([x, y]);
|
||||
}
|
||||
(x, y)
|
||||
}
|
||||
|
|
@ -46,10 +45,9 @@ impl RendererBase<'_> {
|
|||
|
||||
pub fn scale_rect(&self, mut rect: Rect) -> Rect {
|
||||
if self.scaled {
|
||||
let x1 = (rect.x1() as f64 * self.scalef).round() as _;
|
||||
let y1 = (rect.y1() as f64 * self.scalef).round() as _;
|
||||
let x2 = (rect.x2() as f64 * self.scalef).round() as _;
|
||||
let y2 = (rect.y2() as f64 * self.scalef).round() as _;
|
||||
let [x1, y1, x2, y2] =
|
||||
self.scale
|
||||
.pixel_size([rect.x1(), rect.y1(), rect.x2(), rect.y2()]);
|
||||
rect = Rect::new(x1, y1, x2, y2).unwrap();
|
||||
}
|
||||
rect
|
||||
|
|
|
|||
13
src/scale.rs
13
src/scale.rs
|
|
@ -1,6 +1,7 @@
|
|||
use std::fmt::{Debug, Display, Formatter};
|
||||
|
||||
const BASE: u32 = 120;
|
||||
const BASE64: i64 = BASE as i64;
|
||||
const BASEF: f64 = BASE as f64;
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
|
|
@ -38,15 +39,13 @@ impl Scale {
|
|||
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() {
|
||||
return (width, height);
|
||||
return v;
|
||||
}
|
||||
let scale = self.to_f64();
|
||||
(
|
||||
(width as f64 * scale).round() as i32,
|
||||
(height as f64 * scale).round() as i32,
|
||||
)
|
||||
let scale = self.0 as i64;
|
||||
v.map(|v| ((v as i64 * scale + BASE64 / 2) / BASE64) as i32)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ use {
|
|||
PlaceholderNode, WorkspaceNode,
|
||||
},
|
||||
utils::{
|
||||
array_to_tuple::ArrayToTuple,
|
||||
clonecell::CloneCell,
|
||||
copyhashmap::CopyHashMap,
|
||||
hash_map_ext::HashMapExt,
|
||||
|
|
@ -608,7 +609,7 @@ impl ToplevelData {
|
|||
let (dw, dh) = self.desired_extents.get().size();
|
||||
if let Some(ws) = self.workspace.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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
pub mod activation_token;
|
||||
pub mod array;
|
||||
pub mod array_to_tuple;
|
||||
pub mod asyncevent;
|
||||
pub mod bindings;
|
||||
pub mod bitfield;
|
||||
|
|
|
|||
28
src/utils/array_to_tuple.rs
Normal file
28
src/utils/array_to_tuple.rs
Normal 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,);
|
||||
Loading…
Add table
Add a link
Reference in a new issue