pub const GUI_ROUNDING: f32 = 1.0 / 32.0;
pub trait GuiRounding {
fn round_ui(self) -> Self;
fn floor_ui(self) -> Self;
fn round_to_pixels(self, pixels_per_point: f32) -> Self;
fn round_to_pixel_center(self, pixels_per_point: f32) -> Self;
}
impl GuiRounding for f32 {
#[inline]
fn round_ui(self) -> Self {
(self / GUI_ROUNDING).round() * GUI_ROUNDING
}
#[inline]
fn floor_ui(self) -> Self {
(self / GUI_ROUNDING).floor() * GUI_ROUNDING
}
#[inline]
fn round_to_pixels(self, pixels_per_point: f32) -> Self {
(self * pixels_per_point).round() / pixels_per_point
}
#[inline]
fn round_to_pixel_center(self, pixels_per_point: f32) -> Self {
((self * pixels_per_point - 0.5).round() + 0.5) / pixels_per_point
}
}
impl GuiRounding for f64 {
#[inline]
fn round_ui(self) -> Self {
(self / GUI_ROUNDING as Self).round() * GUI_ROUNDING as Self
}
#[inline]
fn floor_ui(self) -> Self {
(self / GUI_ROUNDING as Self).floor() * GUI_ROUNDING as Self
}
#[inline]
fn round_to_pixels(self, pixels_per_point: f32) -> Self {
(self * pixels_per_point as Self).round() / pixels_per_point as Self
}
#[inline]
fn round_to_pixel_center(self, pixels_per_point: f32) -> Self {
((self * pixels_per_point as Self - 0.5).round() + 0.5) / pixels_per_point as Self
}
}
impl GuiRounding for crate::Vec2 {
#[inline]
fn round_ui(self) -> Self {
Self::new(self.x.round_ui(), self.y.round_ui())
}
#[inline]
fn floor_ui(self) -> Self {
Self::new(self.x.floor_ui(), self.y.floor_ui())
}
#[inline]
fn round_to_pixels(self, pixels_per_point: f32) -> Self {
Self::new(
self.x.round_to_pixels(pixels_per_point),
self.y.round_to_pixels(pixels_per_point),
)
}
#[inline]
fn round_to_pixel_center(self, pixels_per_point: f32) -> Self {
Self::new(
self.x.round_to_pixel_center(pixels_per_point),
self.y.round_to_pixel_center(pixels_per_point),
)
}
}
impl GuiRounding for crate::Pos2 {
#[inline]
fn round_ui(self) -> Self {
Self::new(self.x.round_ui(), self.y.round_ui())
}
#[inline]
fn floor_ui(self) -> Self {
Self::new(self.x.floor_ui(), self.y.floor_ui())
}
#[inline]
fn round_to_pixels(self, pixels_per_point: f32) -> Self {
Self::new(
self.x.round_to_pixels(pixels_per_point),
self.y.round_to_pixels(pixels_per_point),
)
}
#[inline]
fn round_to_pixel_center(self, pixels_per_point: f32) -> Self {
Self::new(
self.x.round_to_pixel_center(pixels_per_point),
self.y.round_to_pixel_center(pixels_per_point),
)
}
}
impl GuiRounding for crate::Rect {
#[inline]
fn round_ui(self) -> Self {
Self::from_min_max(self.min.round_ui(), self.max.round_ui())
}
#[inline]
fn floor_ui(self) -> Self {
Self::from_min_max(self.min.floor_ui(), self.max.floor_ui())
}
#[inline]
fn round_to_pixels(self, pixels_per_point: f32) -> Self {
Self::from_min_max(
self.min.round_to_pixels(pixels_per_point),
self.max.round_to_pixels(pixels_per_point),
)
}
#[inline]
fn round_to_pixel_center(self, pixels_per_point: f32) -> Self {
Self::from_min_max(
self.min.round_to_pixel_center(pixels_per_point),
self.max.round_to_pixel_center(pixels_per_point),
)
}
}
#[test]
fn test_gui_rounding() {
assert_eq!(0.0_f32.round_ui(), 0.0);
assert_eq!((GUI_ROUNDING * 1.11).round_ui(), GUI_ROUNDING);
assert_eq!((-GUI_ROUNDING * 1.11).round_ui(), -GUI_ROUNDING);
assert_eq!(f32::NEG_INFINITY.round_ui(), f32::NEG_INFINITY);
assert_eq!(f32::INFINITY.round_ui(), f32::INFINITY);
assert_eq!(0.17_f32.round_to_pixel_center(2.0), 0.25);
}