@@ -1,6 +1,6 @@
use crate::{
AbsoluteLength, App, Bounds, DefiniteLength, Edges, Length, Pixels, Point, Size, Style, Window,
- point, size,
+ point, size, util::round_device_pixels_midpoint_down,
};
use collections::{FxHashMap, FxHashSet};
use stacksafe::{StackSafe, stacksafe};
@@ -369,16 +369,8 @@ impl ToTaffy<taffy::style::Style> for Style {
impl ToTaffy<f32> for AbsoluteLength {
fn to_taffy(&self, rem_size: Pixels, scale_factor: f32) -> f32 {
- match self {
- AbsoluteLength::Pixels(pixels) => {
- let pixels: f32 = pixels.into();
- pixels * scale_factor
- }
- AbsoluteLength::Rems(rems) => {
- let pixels: f32 = (*rems * rem_size).into();
- pixels * scale_factor
- }
- }
+ let logical_pixels = self.to_pixels(rem_size).0;
+ round_device_pixels_midpoint_down((logical_pixels * scale_factor).max(0.0))
}
}
@@ -407,16 +399,7 @@ impl ToTaffy<taffy::style::Dimension> for Length {
impl ToTaffy<taffy::style::LengthPercentage> for DefiniteLength {
fn to_taffy(&self, rem_size: Pixels, scale_factor: f32) -> taffy::style::LengthPercentage {
match self {
- DefiniteLength::Absolute(length) => match length {
- AbsoluteLength::Pixels(pixels) => {
- let pixels: f32 = pixels.into();
- taffy::style::LengthPercentage::length(pixels * scale_factor)
- }
- AbsoluteLength::Rems(rems) => {
- let pixels: f32 = (*rems * rem_size).into();
- taffy::style::LengthPercentage::length(pixels * scale_factor)
- }
- },
+ DefiniteLength::Absolute(length) => length.to_taffy(rem_size, scale_factor),
DefiniteLength::Fraction(fraction) => {
taffy::style::LengthPercentage::percent(*fraction)
}
@@ -427,16 +410,7 @@ impl ToTaffy<taffy::style::LengthPercentage> for DefiniteLength {
impl ToTaffy<taffy::style::LengthPercentageAuto> for DefiniteLength {
fn to_taffy(&self, rem_size: Pixels, scale_factor: f32) -> taffy::style::LengthPercentageAuto {
match self {
- DefiniteLength::Absolute(length) => match length {
- AbsoluteLength::Pixels(pixels) => {
- let pixels: f32 = pixels.into();
- taffy::style::LengthPercentageAuto::length(pixels * scale_factor)
- }
- AbsoluteLength::Rems(rems) => {
- let pixels: f32 = (*rems * rem_size).into();
- taffy::style::LengthPercentageAuto::length(pixels * scale_factor)
- }
- },
+ DefiniteLength::Absolute(length) => length.to_taffy(rem_size, scale_factor),
DefiniteLength::Fraction(fraction) => {
taffy::style::LengthPercentageAuto::percent(*fraction)
}
@@ -447,15 +421,7 @@ impl ToTaffy<taffy::style::LengthPercentageAuto> for DefiniteLength {
impl ToTaffy<taffy::style::Dimension> for DefiniteLength {
fn to_taffy(&self, rem_size: Pixels, scale_factor: f32) -> taffy::style::Dimension {
match self {
- DefiniteLength::Absolute(length) => match length {
- AbsoluteLength::Pixels(pixels) => {
- let pixels: f32 = pixels.into();
- taffy::style::Dimension::length(pixels * scale_factor)
- }
- AbsoluteLength::Rems(rems) => {
- taffy::style::Dimension::length((*rems * rem_size * scale_factor).into())
- }
- },
+ DefiniteLength::Absolute(length) => length.to_taffy(rem_size, scale_factor),
DefiniteLength::Fraction(fraction) => taffy::style::Dimension::percent(*fraction),
}
}
@@ -463,16 +429,19 @@ impl ToTaffy<taffy::style::Dimension> for DefiniteLength {
impl ToTaffy<taffy::style::LengthPercentage> for AbsoluteLength {
fn to_taffy(&self, rem_size: Pixels, scale_factor: f32) -> taffy::style::LengthPercentage {
- match self {
- AbsoluteLength::Pixels(pixels) => {
- let pixels: f32 = pixels.into();
- taffy::style::LengthPercentage::length(pixels * scale_factor)
- }
- AbsoluteLength::Rems(rems) => {
- let pixels: f32 = (*rems * rem_size).into();
- taffy::style::LengthPercentage::length(pixels * scale_factor)
- }
- }
+ taffy::style::LengthPercentage::length(self.to_taffy(rem_size, scale_factor))
+ }
+}
+
+impl ToTaffy<taffy::style::LengthPercentageAuto> for AbsoluteLength {
+ fn to_taffy(&self, rem_size: Pixels, scale_factor: f32) -> taffy::style::LengthPercentageAuto {
+ taffy::style::LengthPercentageAuto::length(self.to_taffy(rem_size, scale_factor))
+ }
+}
+
+impl ToTaffy<taffy::style::Dimension> for AbsoluteLength {
+ fn to_taffy(&self, rem_size: Pixels, scale_factor: f32) -> taffy::style::Dimension {
+ taffy::style::Dimension::length(self.to_taffy(rem_size, scale_factor))
}
}
@@ -125,12 +125,32 @@ pub(crate) fn atomic_incr_if_not_zero(counter: &AtomicUsize) -> usize {
}
}
+/// Rounds a device-pixel value to the nearest integer, with .5 ties rounded down.
+#[inline]
+pub(crate) fn round_device_pixels_midpoint_down(value: f32) -> f32 {
+ let floor = value.floor();
+ if value - floor > 0.5 {
+ floor + 1.0
+ } else {
+ floor
+ }
+}
+
#[cfg(test)]
mod tests {
use crate::TestAppContext;
use super::*;
+ #[test]
+ fn test_round_device_pixels_midpoint_down() {
+ assert_eq!(round_device_pixels_midpoint_down(0.5), 0.0);
+ assert_eq!(round_device_pixels_midpoint_down(1.5), 1.0);
+ assert_eq!(round_device_pixels_midpoint_down(2.5), 2.0);
+ assert_eq!(round_device_pixels_midpoint_down(1.5001), 2.0);
+ assert_eq!(round_device_pixels_midpoint_down(-1.5), -2.0);
+ }
+
#[gpui::test]
async fn test_with_timeout(cx: &mut TestAppContext) {
Task::ready(())
@@ -57,7 +57,7 @@ use uuid::Uuid;
mod prompts;
-use crate::util::atomic_incr_if_not_zero;
+use crate::util::{atomic_incr_if_not_zero, round_device_pixels_midpoint_down};
pub use prompts::*;
/// Default window size used when no explicit size is provided.
@@ -2118,6 +2118,12 @@ impl Window {
px((value.0 * scale_factor).round() / scale_factor)
}
+ /// Returns the logical length corresponding to one physical device pixel.
+ #[inline]
+ pub fn one_device_pixel(&self) -> Pixels {
+ px(1.0 / self.scale_factor())
+ }
+
#[inline]
fn round_point_to_device_pixels(&self, position: Point<Pixels>) -> Point<Pixels> {
point(
@@ -2145,11 +2151,16 @@ impl Window {
#[inline]
fn round_bounds_to_device_pixels(&self, bounds: Bounds<Pixels>) -> Bounds<ScaledPixels> {
let scale_factor = self.scale_factor();
- let left = (bounds.left().0 * scale_factor).round();
- let top = (bounds.top().0 * scale_factor).round();
- let right = (bounds.right().0 * scale_factor).round();
- let bottom = (bounds.bottom().0 * scale_factor).round();
- self.bounds_from_device_edges(left, top, right, bottom)
+ Bounds {
+ origin: point(
+ ScaledPixels((bounds.origin.x.0 * scale_factor).round()),
+ ScaledPixels((bounds.origin.y.0 * scale_factor).round()),
+ ),
+ size: size(
+ self.round_length_to_device_pixels(bounds.size.width),
+ self.round_length_to_device_pixels(bounds.size.height),
+ ),
+ }
}
#[inline]
@@ -2174,18 +2185,18 @@ impl Window {
#[inline]
fn round_edges_to_device_pixels(&self, edges: Edges<Pixels>) -> Edges<ScaledPixels> {
- let scale_factor = self.scale_factor();
Edges {
- top: ScaledPixels((edges.top.0 * scale_factor).round()),
- right: ScaledPixels((edges.right.0 * scale_factor).round()),
- bottom: ScaledPixels((edges.bottom.0 * scale_factor).round()),
- left: ScaledPixels((edges.left.0 * scale_factor).round()),
+ top: self.round_nonzero_length_to_device_pixels(edges.top),
+ right: self.round_nonzero_length_to_device_pixels(edges.right),
+ bottom: self.round_nonzero_length_to_device_pixels(edges.bottom),
+ left: self.round_nonzero_length_to_device_pixels(edges.left),
}
}
#[inline]
fn round_length_to_device_pixels(&self, value: Pixels) -> ScaledPixels {
- ScaledPixels((value.0 * self.scale_factor()).round())
+ let scaled = (value.0 * self.scale_factor()).max(0.0);
+ ScaledPixels(round_device_pixels_midpoint_down(scaled))
}
#[inline]