From f012bd80f2629753a0055ffe2ba760086c4f5279 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Tue, 15 Feb 2022 10:59:23 +0000 Subject: [PATCH 1/4] Update easy-cast to git master --- crates/kas-core/Cargo.toml | 2 +- crates/kas-core/src/prelude.rs | 2 +- crates/kas-widgets/src/view/filter_list.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/kas-core/Cargo.toml b/crates/kas-core/Cargo.toml index a6f054e2b..bd303b3ff 100644 --- a/crates/kas-core/Cargo.toml +++ b/crates/kas-core/Cargo.toml @@ -58,7 +58,7 @@ ron = ["config", "dep_ron"] macros_log = ["kas-macros/log"] [dependencies] -easy-cast = "0.4.2" +easy-cast = { git = "https://github.com/kas-gui/easy-cast.git", rev = "6bf6084bb78f6bd1e781158016916ef103db0b19" } log = "0.4" smallvec = "1.6.1" stack_dst = { version = "0.6", optional = true } diff --git a/crates/kas-core/src/prelude.rs b/crates/kas-core/src/prelude.rs index 41cb6b115..7eb76e0c7 100644 --- a/crates/kas-core/src/prelude.rs +++ b/crates/kas-core/src/prelude.rs @@ -9,7 +9,7 @@ //! this crate's prelude. #[doc(no_inline)] -pub use crate::cast::{Cast, CastFloat, Conv, ConvFloat}; +pub use crate::cast::traits::*; #[doc(no_inline)] pub use crate::class::*; #[doc(no_inline)] diff --git a/crates/kas-widgets/src/view/filter_list.rs b/crates/kas-widgets/src/view/filter_list.rs index ca43bb191..0fbb02a98 100644 --- a/crates/kas-widgets/src/view/filter_list.rs +++ b/crates/kas-widgets/src/view/filter_list.rs @@ -48,7 +48,7 @@ impl> FilteredList { /// Construct and apply filter #[inline] fn new(data: T, filter: F) -> Self { - let len = data.len().cast(); + let len = data.len(); let view = RefCell::new(Vec::with_capacity(len)); let s = FilteredList { data, filter, view }; let _ = s.refresh(); From f3323a508c4969606658b9eba1bcd9d8cd092f3e Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Tue, 15 Feb 2022 14:22:56 +0000 Subject: [PATCH 2/4] Use easy-cast to convert between geometry types --- crates/kas-core/src/draw/draw_shared.rs | 3 +- crates/kas-core/src/event/components.rs | 12 +- crates/kas-core/src/event/manager/mgr_pub.rs | 3 +- .../kas-core/src/event/manager/mgr_shell.rs | 16 +- crates/kas-core/src/geom.rs | 168 +++++++----------- crates/kas-core/src/geom/vector.rs | 106 +++++------ crates/kas-core/src/layout/size_types.rs | 8 +- crates/kas-core/src/layout/sizer.rs | 3 +- crates/kas-core/src/layout/visitor.rs | 3 +- crates/kas-core/src/text.rs | 5 +- crates/kas-resvg/src/canvas.rs | 2 +- crates/kas-resvg/src/svg.rs | 6 +- crates/kas-theme/src/dim.rs | 8 +- crates/kas-theme/src/flat_theme.rs | 53 +++--- crates/kas-theme/src/shaded_theme.rs | 33 ++-- crates/kas-wgpu/src/draw/atlases.rs | 2 +- crates/kas-wgpu/src/draw/draw_pipe.rs | 8 +- crates/kas-wgpu/src/window.rs | 4 +- crates/kas-widgets/src/drag.rs | 2 +- crates/kas-widgets/src/edit_field.rs | 8 +- crates/kas-widgets/src/label.rs | 2 +- crates/kas-widgets/src/scroll_label.rs | 8 +- examples/async-event.rs | 2 +- examples/clock.rs | 12 +- 24 files changed, 228 insertions(+), 249 deletions(-) diff --git a/crates/kas-core/src/draw/draw_shared.rs b/crates/kas-core/src/draw/draw_shared.rs index a63ce9bad..8bff13f11 100644 --- a/crates/kas-core/src/draw/draw_shared.rs +++ b/crates/kas-core/src/draw/draw_shared.rs @@ -7,6 +7,7 @@ use super::color::Rgba; use super::{images, DrawImpl, ImageError, ImageFormat, ImageId, PassId}; +use crate::cast::Cast; use crate::geom::{Quad, Size, Vec2}; use crate::text::{Effect, TextDisplay}; use std::any::Any; @@ -103,7 +104,7 @@ impl DrawShared for SharedState { #[inline] fn image_size(&self, id: ImageId) -> Option { - self.draw.image_size(id).map(|size| size.into()) + self.draw.image_size(id).map(|size| size.cast()) } } diff --git a/crates/kas-core/src/event/components.rs b/crates/kas-core/src/event/components.rs index c707bbe90..63c649bd5 100644 --- a/crates/kas-core/src/event/components.rs +++ b/crates/kas-core/src/event/components.rs @@ -7,7 +7,7 @@ use super::ScrollDelta::{LineDelta, PixelDelta}; use super::{Command, CursorIcon, Event, EventMgr, PressSource, Response, VoidMsg}; -use crate::cast::CastFloat; +use crate::cast::traits::*; use crate::geom::{Coord, Offset, Rect, Size, Vec2}; #[allow(unused)] use crate::text::SelectionHelper; @@ -58,7 +58,7 @@ impl Glide { } } let dur = now - t0; - let v = Vec2::from(delta) / dur.as_secs_f32(); + let v = Vec2::conv(delta) / dur.as_secs_f32(); if dur >= Duration::from_millis(1) && v != Vec2::ZERO { *self = Glide::Glide(now, v, Vec2::ZERO); true @@ -76,8 +76,8 @@ impl Glide { let now = Instant::now(); let dur = (now - *start).as_secs_f32(); let d = *v * dur + *rest; - let rest = d.fract(); - let delta = Offset::from(d.trunc()); + let delta = Offset::conv_approx(d); + let rest = d - Vec2::conv(delta); if v.max_abs_comp() >= 1.0 { let mut v = *v * decay_mul.powf(dur); @@ -144,7 +144,7 @@ impl ScrollComponent { /// change in offset. In practice the caller will likely be performing all /// required updates regardless and the return value can be safely ignored. pub fn set_sizes(&mut self, window_size: Size, content_size: Size) -> TkAction { - self.max_offset = Offset::from(content_size) - Offset::from(window_size); + self.max_offset = Offset::conv(content_size) - Offset::conv(window_size); self.set_offset(self.offset) } @@ -203,7 +203,7 @@ impl ScrollComponent { #[inline] pub fn focus_rect(&mut self, rect: Rect, window_rect: Rect) -> (Rect, TkAction) { let v = rect.pos - window_rect.pos; - let off = Offset::from(rect.size) - Offset::from(window_rect.size); + let off = Offset::conv(rect.size) - Offset::conv(window_rect.size); let offset = self.offset.max(v + off).min(v); let action = self.set_offset(offset); (rect - self.offset, action) diff --git a/crates/kas-core/src/event/manager/mgr_pub.rs b/crates/kas-core/src/event/manager/mgr_pub.rs index 81a5b8e32..5d994dc5c 100644 --- a/crates/kas-core/src/event/manager/mgr_pub.rs +++ b/crates/kas-core/src/event/manager/mgr_pub.rs @@ -10,6 +10,7 @@ use std::time::{Duration, Instant}; use std::u16; use super::*; +use crate::cast::Conv; use crate::draw::DrawShared; use crate::geom::{Coord, Offset, Vec2}; use crate::layout::SetRectMgr; @@ -154,7 +155,7 @@ impl EventState { #[inline] pub fn config_test_pan_thresh(&self, dist: Offset) -> bool { let thresh = self.config.pan_dist_thresh(); - Vec2::from(dist).sum_square() >= thresh * thresh + Vec2::conv(dist).sum_square() >= thresh * thresh } /// Access the screen's scale factor diff --git a/crates/kas-core/src/event/manager/mgr_shell.rs b/crates/kas-core/src/event/manager/mgr_shell.rs index 520de3e69..1e651c090 100644 --- a/crates/kas-core/src/event/manager/mgr_shell.rs +++ b/crates/kas-core/src/event/manager/mgr_shell.rs @@ -11,8 +11,8 @@ use std::collections::HashMap; use std::time::{Duration, Instant}; use super::*; -use crate::cast::Conv; -use crate::geom::{Coord, DVec2, Offset}; +use crate::cast::traits::*; +use crate::geom::{Coord, DVec2}; use crate::layout::SetRectMgr; #[allow(unused)] use crate::WidgetConfig; // for doc-links @@ -216,7 +216,7 @@ impl EventState { assert!(grab.n > 0); // Terminology: pi are old coordinates, qi are new coords - let (p1, q1) = (DVec2::from(grab.coords[0].0), DVec2::from(grab.coords[0].1)); + let (p1, q1) = (DVec2::conv(grab.coords[0].0), DVec2::conv(grab.coords[0].1)); grab.coords[0].0 = grab.coords[0].1; let alpha; @@ -228,7 +228,7 @@ impl EventState { } else { // We don't use more than two touches: information would be // redundant (although it could be averaged). - let (p2, q2) = (DVec2::from(grab.coords[1].0), DVec2::from(grab.coords[1].1)); + let (p2, q2) = (DVec2::conv(grab.coords[1].0), DVec2::conv(grab.coords[1].1)); grab.coords[1].0 = grab.coords[1].1; let (pd, qd) = (p2 - p1, q2 - q1); @@ -371,7 +371,7 @@ impl<'a> EventMgr<'a> { } CursorMoved { position, .. } => { self.state.last_click_button = FAKE_MOUSE_BUTTON; - let coord = position.into(); + let coord = position.cast_approx(); // Update hovered widget let cur_id = widget.find_id(coord); @@ -427,8 +427,8 @@ impl<'a> EventMgr<'a> { MouseScrollDelta::PixelDelta(pos) => { // The delta is given as a PhysicalPosition, so we need // to convert to our vector type (Offset) here. - let coord = Coord::from(pos); - ScrollDelta::PixelDelta(Offset(coord.0, coord.1)) + let coord = Coord::conv_approx(pos); + ScrollDelta::PixelDelta(coord.cast()) } }); if let Some(id) = self.state.hover.clone() { @@ -493,7 +493,7 @@ impl<'a> EventMgr<'a> { // AxisMotion { axis: AxisId, value: f64, }, Touch(touch) => { let source = PressSource::Touch(touch.id); - let coord = touch.location.into(); + let coord = touch.location.cast_approx(); match touch.phase { TouchPhase::Started => { let start_id = widget.find_id(coord); diff --git a/crates/kas-core/src/geom.rs b/crates/kas-core/src/geom.rs index 8f9e9c468..824e5a1b2 100644 --- a/crates/kas-core/src/geom.rs +++ b/crates/kas-core/src/geom.rs @@ -4,8 +4,20 @@ // https://www.apache.org/licenses/LICENSE-2.0 //! Geometry data types - -use crate::cast::{Cast, Conv}; +//! +//! [`Coord`], [`Size`] and [`Offset`] are all integer (`i32`) types used for +//! widget UI layout, representing positions, sizes and scroll deltas +//! respectively. +//! +//! [`Vec2`] is a floating-point (`f32`) type used mainly for screen-space +//! position during rendering. +//! +//! Conversions types mostly use [`Cast`] and [`Conv`]. [`From`] may be used to +//! simply pack/unpack components. To convert from floating-point types to +//! integer types, use [`CastApprox`] or [`CastFloat`] to specify the rounding +//! mode. + +use crate::cast::{Cast, Conv, Result}; use crate::dir::Directional; mod vector; @@ -222,9 +234,10 @@ impl std::ops::SubAssign for Coord { } } -impl From for kas_text::Vec2 { - fn from(pos: Coord) -> kas_text::Vec2 { - Vec2::from(pos).into() +impl Conv for kas_text::Vec2 { + #[inline] + fn try_conv(pos: Coord) -> Result { + Ok(Vec2::try_conv(pos)?.into()) } } @@ -346,62 +359,55 @@ impl std::ops::Div for Size { } } -impl std::ops::Mul for Size { - type Output = Self; - +impl Conv for Coord { #[inline] - fn mul(self, x: f32) -> Self { - debug_assert!(x >= 0.0); - let v = Vec2::from(self) * x; - v.into() + fn try_conv(v: Offset) -> Result { + debug_assert!(v.0 >= 0 && v.1 >= 0, "Coord::conv({:?}): negative value", v); + Ok(Self(v.0, v.1)) } } -impl std::ops::Div for Size { - type Output = Self; +impl Conv for Size { #[inline] - fn div(self, x: f32) -> Self { - debug_assert!(x >= 0.0); - let v = Vec2::from(self) / x; - v.into() - } -} - -impl From for Size { - fn from(v: Offset) -> Self { - debug_assert!(v.0 >= 0 && v.1 >= 0, "Size::from({:?}): negative value", v); - Self(v.0, v.1) + fn try_conv(v: Offset) -> Result { + debug_assert!(v.0 >= 0 && v.1 >= 0, "Size::conv({:?}): negative value", v); + Ok(Self(v.0, v.1)) } } // used for marigns -impl From for (u16, u16) { - fn from(size: Size) -> (u16, u16) { - (size.0.cast(), size.1.cast()) +impl Conv for (u16, u16) { + #[inline] + fn try_conv(size: Size) -> Result { + Ok((size.0.try_cast()?, size.1.try_cast()?)) } } -impl From<(u16, u16)> for Size { - fn from(v: (u16, u16)) -> Self { - Self(i32::conv(v.0), i32::conv(v.1)) +impl Conv<(u16, u16)> for Size { + #[inline] + fn try_conv(v: (u16, u16)) -> Result { + Ok(Self(i32::try_conv(v.0)?, i32::try_conv(v.1)?)) } } -impl From<(u32, u32)> for Size { - fn from(v: (u32, u32)) -> Self { - Self(i32::conv(v.0), i32::conv(v.1)) +impl Conv<(u32, u32)> for Size { + #[inline] + fn try_conv(v: (u32, u32)) -> Result { + Ok(Self(i32::try_conv(v.0)?, i32::try_conv(v.1)?)) } } -impl From for (u32, u32) { - fn from(size: Size) -> (u32, u32) { - (u32::conv(size.0), u32::conv(size.1)) +impl Conv for (u32, u32) { + #[inline] + fn try_conv(size: Size) -> Result { + Ok((u32::try_conv(size.0)?, u32::try_conv(size.1)?)) } } -impl From for kas_text::Vec2 { - fn from(size: Size) -> kas_text::Vec2 { +impl Conv for kas_text::Vec2 { + #[inline] + fn try_conv(size: Size) -> Result { debug_assert!(size.0 >= 0 && size.1 >= 0); - Vec2::from(size).into() + Ok(Vec2::try_conv(size)?.into()) } } @@ -481,34 +487,24 @@ impl std::ops::Div for Offset { } } -impl std::ops::Mul for Offset { - type Output = Self; - +impl Conv for Offset { #[inline] - fn mul(self, x: f32) -> Self { - let v = Vec2::from(self) * x; - v.into() + fn try_conv(v: Coord) -> Result { + Ok(Self(v.0, v.1)) } } -impl std::ops::Div for Offset { - type Output = Self; +impl Conv for Offset { #[inline] - fn div(self, x: f32) -> Self { - let v = Vec2::from(self) / x; - v.into() - } -} - -impl From for Offset { - fn from(v: Size) -> Self { - Self(v.0, v.1) + fn try_conv(v: Size) -> Result { + Ok(Self(v.0, v.1)) } } -impl From for kas_text::Vec2 { - fn from(size: Offset) -> kas_text::Vec2 { - Vec2::from(size).into() +impl Conv for kas_text::Vec2 { + #[inline] + fn try_conv(v: Offset) -> Result { + Ok(Vec2::try_conv(v)?.into()) } } @@ -556,7 +552,7 @@ impl Rect { let pos = l1.max(r1); let pos2 = l2.min(r2); if pos.le(pos2) { - Some(Rect::new(pos, (pos2 - pos).into())) + Some(Rect::new(pos, (pos2 - pos).cast())) } else { None } @@ -616,56 +612,28 @@ impl std::ops::SubAssign for Rect { #[cfg_attr(doc_cfg, doc(cfg(feature = "winit")))] mod winit_impls { use super::{Coord, Size}; - use winit::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize, Pixel}; - - impl Coord { - /// Convert from a logical position - pub fn from_logical(logical: LogicalPosition, dpi_factor: f64) -> Self { - let pos = PhysicalPosition::::from_logical(logical, dpi_factor); - let pos: (i32, i32) = pos.into(); - Coord(pos.0, pos.1) - } - } - - impl From> for Coord { - #[inline] - fn from(pos: PhysicalPosition) -> Coord { - let pos: (i32, i32) = pos.cast::().into(); - Coord(pos.0, pos.1) - } - } - - impl From for PhysicalPosition { - #[inline] - fn from(coord: Coord) -> PhysicalPosition { - let pos: PhysicalPosition = (coord.0, coord.1).into(); - pos.cast() - } - } + use crate::cast::{Cast, CastApprox, Conv, ConvApprox}; + use winit::dpi::{PhysicalPosition, PhysicalSize}; - impl From> for Size { + impl> ConvApprox> for Coord { #[inline] - fn from(size: PhysicalSize) -> Size { - let size: (i32, i32) = size.cast::().into(); - debug_assert!(size.0 >= 0 && size.1 >= 0); - Size(size.0, size.1) + fn try_conv_approx(pos: PhysicalPosition) -> cast::Result { + Ok(Coord(pos.x.cast_approx(), pos.y.cast_approx())) } } - impl From for PhysicalSize { + impl> Conv> for Size { #[inline] - fn from(size: Size) -> PhysicalSize { - debug_assert!(size.0 >= 0 && size.1 >= 0); - let pos: PhysicalSize = (size.0, size.1).into(); - pos.cast() + fn try_conv(size: PhysicalSize) -> cast::Result { + Ok(Size(size.width.cast(), size.height.cast())) } } impl From for winit::dpi::Size { #[inline] - fn from(size: Size) -> winit::dpi::Size { - debug_assert!(size.0 >= 0 && size.1 >= 0); - winit::dpi::Size::Physical((size.0, size.1).into()) + fn from(size: Size) -> Self { + let (w, h): (u32, u32) = size.cast(); + winit::dpi::Size::Physical(PhysicalSize::new(w, h)) } } } diff --git a/crates/kas-core/src/geom/vector.rs b/crates/kas-core/src/geom/vector.rs index 0bb57012e..01bf86808 100644 --- a/crates/kas-core/src/geom/vector.rs +++ b/crates/kas-core/src/geom/vector.rs @@ -7,7 +7,7 @@ //! //! For drawing operations, all dimensions use the `f32` type. -use crate::cast::{CastFloat, Conv}; +use crate::cast::*; use crate::geom::{Coord, Offset, Rect, Size}; use std::ops::{Add, AddAssign, Div, Mul, Neg, Sub, SubAssign}; @@ -122,12 +122,12 @@ impl SubAssign for Quad { } } -impl From for Quad { +impl Conv for Quad { #[inline] - fn from(rect: Rect) -> Quad { - let a = Vec2::from(rect.pos); - let b = a + Vec2::from(rect.size); - Quad { a, b } + fn try_conv(rect: Rect) -> Result { + let a = Vec2::try_conv(rect.pos)?; + let b = a + Vec2::try_conv(rect.size)?; + Ok(Quad { a, b }) } } @@ -440,72 +440,78 @@ macro_rules! impl_vec2 { (v.0, v.1) } } + }; +} - impl From for $T { - #[inline] - fn from(arg: Coord) -> Self { - $T(<$f>::conv(arg.0), <$f>::conv(arg.1)) - } - } +impl From for Vec2 { + #[inline] + fn from(size: kas_text::Vec2) -> Self { + Vec2(size.0, size.1) + } +} + +impl From for kas_text::Vec2 { + #[inline] + fn from(size: Vec2) -> kas_text::Vec2 { + kas_text::Vec2(size.0, size.1) + } +} - impl From for $T { +impl ConvApprox for Vec2 { + fn try_conv_approx(size: DVec2) -> Result { + Ok(Vec2(size.0.try_cast_approx()?, size.1.try_cast_approx()?)) + } +} + +impl_vec2!(Vec2, f32); +impl_vec2!(DVec2, f64); + +macro_rules! impl_conv_vec2 { + ($S:ty, $T:ty) => { + impl Conv<$S> for $T { #[inline] - fn from(arg: Size) -> Self { - $T(<$f>::conv(arg.0), <$f>::conv(arg.1)) + fn try_conv(arg: $S) -> Result { + Ok(Self(arg.0.try_cast()?, arg.1.try_cast()?)) } } - impl From for $T { + impl ConvApprox<$T> for $S { #[inline] - fn from(arg: Offset) -> Self { - $T(<$f>::conv(arg.0), <$f>::conv(arg.1)) + fn try_conv_approx(arg: $T) -> Result { + Ok(Self(arg.0.try_cast_approx()?, arg.1.try_cast_approx()?)) } } - impl From<$T> for Coord { + impl ConvFloat<$T> for $S { #[inline] - fn from(arg: $T) -> Self { - Coord(arg.0.cast_nearest(), arg.1.cast_nearest()) + fn try_conv_trunc(x: $T) -> Result { + Ok(Self(i32::try_conv_trunc(x.0)?, i32::try_conv_trunc(x.1)?)) } - } - - impl From<$T> for Size { #[inline] - fn from(arg: $T) -> Self { - Offset::from(arg).into() + fn try_conv_nearest(x: $T) -> Result { + Ok(Self( + i32::try_conv_nearest(x.0)?, + i32::try_conv_nearest(x.1)?, + )) } - } - - impl From<$T> for Offset { #[inline] - fn from(arg: $T) -> Self { - Offset(arg.0.cast_nearest(), arg.1.cast_nearest()) + fn try_conv_floor(x: $T) -> Result { + Ok(Self(i32::try_conv_floor(x.0)?, i32::try_conv_floor(x.1)?)) } - } - - impl From for $T { #[inline] - fn from(size: kas_text::Vec2) -> Self { - $T(size.0.into(), size.1.into()) + fn try_conv_ceil(x: $T) -> Result { + Ok(Self(i32::try_conv_ceil(x.0)?, i32::try_conv_ceil(x.1)?)) } } }; } -impl From for kas_text::Vec2 { - fn from(size: Vec2) -> kas_text::Vec2 { - kas_text::Vec2(size.0, size.1) - } -} - -impl From for Vec2 { - fn from(size: DVec2) -> Vec2 { - Vec2(size.0 as f32, size.1 as f32) - } -} - -impl_vec2!(Vec2, f32); -impl_vec2!(DVec2, f64); +impl_conv_vec2!(Coord, Vec2); +impl_conv_vec2!(Size, Vec2); +impl_conv_vec2!(Offset, Vec2); +impl_conv_vec2!(Coord, DVec2); +impl_conv_vec2!(Size, DVec2); +impl_conv_vec2!(Offset, DVec2); /// 3D vector /// diff --git a/crates/kas-core/src/layout/size_types.rs b/crates/kas-core/src/layout/size_types.rs index 5b601b50b..1d6bdc01c 100644 --- a/crates/kas-core/src/layout/size_types.rs +++ b/crates/kas-core/src/layout/size_types.rs @@ -6,7 +6,7 @@ //! Types used by size rules use super::{Align, AlignHints, AxisInfo, SizeRules}; -use crate::cast::{CastFloat, Conv, ConvFloat}; +use crate::cast::traits::*; use crate::dir::Directional; use crate::geom::{Rect, Size, Vec2}; @@ -83,7 +83,7 @@ impl Margins { impl From for Margins { fn from(size: Size) -> Self { - Margins::hv_splat(size.into()) + Margins::hv_splat(size.cast()) } } @@ -224,8 +224,8 @@ impl SpriteDisplay { let ideal = match self.aspect { AspectScaling::None => self.size, AspectScaling::Fixed => { - let size = Vec2::from(self.size); - let ratio = Vec2::from(rect.size) / size; + let size = Vec2::conv(self.size); + let ratio = Vec2::conv(rect.size) / size; // Use smaller ratio, which must be finite if ratio.0 < ratio.1 { Size(rect.size.0, i32::conv_nearest(ratio.0 * size.1)) diff --git a/crates/kas-core/src/layout/sizer.rs b/crates/kas-core/src/layout/sizer.rs index 456bcea38..91dc3fbad 100644 --- a/crates/kas-core/src/layout/sizer.rs +++ b/crates/kas-core/src/layout/sizer.rs @@ -9,6 +9,7 @@ use log::trace; use std::fmt; use super::{AlignHints, AxisInfo, Margins, SetRectMgr, SizeRules}; +use crate::cast::Conv; use crate::geom::{Rect, Size}; use crate::theme::SizeMgr; use crate::{Widget, WidgetConfig}; @@ -212,7 +213,7 @@ impl SolveCache { } if inner_margin { - rect.pos += Size::from((self.margins.horiz.0, self.margins.vert.0)); + rect.pos += Size::conv((self.margins.horiz.0, self.margins.vert.0)); rect.size.0 = width; rect.size.1 -= self.margins.sum_vert(); } diff --git a/crates/kas-core/src/layout/visitor.rs b/crates/kas-core/src/layout/visitor.rs index 63f24c171..115d381cd 100644 --- a/crates/kas-core/src/layout/visitor.rs +++ b/crates/kas-core/src/layout/visitor.rs @@ -11,6 +11,7 @@ use super::{AlignHints, AxisInfo, RulesSetter, RulesSolver, SetRectMgr, SizeRules, Storage}; use super::{DynRowStorage, RowPositionSolver, RowSetter, RowSolver, RowStorage}; use super::{GridChildInfo, GridDimensions, GridSetter, GridSolver, GridStorage}; +use crate::cast::Cast; use crate::draw::color::Rgb; use crate::geom::{Coord, Offset, Rect, Size}; use crate::text::{Align, TextApi, TextApiExt}; @@ -490,7 +491,7 @@ impl<'a> Visitor for Text<'a> { }; self.data.pos = rect.pos; self.text.update_env(|env| { - env.set_bounds(rect.size.into()); + env.set_bounds(rect.size.cast()); env.set_align(align.unwrap_or(halign, Align::Center)); }); } diff --git a/crates/kas-core/src/text.rs b/crates/kas-core/src/text.rs index a9b902a46..8f411a758 100644 --- a/crates/kas-core/src/text.rs +++ b/crates/kas-core/src/text.rs @@ -21,7 +21,8 @@ pub use string::AccelString; /// Utilities integrating `kas-text` functionality pub mod util { - use super::{fonts, format, EditableTextApi, Text, TextApi, Vec2}; + use super::{fonts, format, EditableTextApi, Text, TextApi}; + use crate::cast::Conv; use crate::{geom::Size, TkAction}; use log::trace; @@ -72,7 +73,7 @@ pub mod util { return TkAction::empty(); } if let Some(req) = text.prepare() { - let avail = Vec2::from(avail); + let avail = crate::geom::Vec2::conv(avail); if !(req.0 <= avail.0 && req.1 <= avail.1) { trace!( "set_text_and_prepare triggers RESIZE: req={:?}, avail={:?}", diff --git a/crates/kas-resvg/src/canvas.rs b/crates/kas-resvg/src/canvas.rs index 0af109186..2401b7de8 100644 --- a/crates/kas-resvg/src/canvas.rs +++ b/crates/kas-resvg/src/canvas.rs @@ -118,7 +118,7 @@ widget! { fn set_rect(&mut self, mgr: &mut SetRectMgr, rect: Rect, align: AlignHints) { self.core.rect = self.sprite.align_rect(rect, align); - let size: (u32, u32) = self.core.rect.size.into(); + let size: (u32, u32) = self.core.rect.size.cast(); let pm_size = self.pixmap.as_ref().map(|pm| (pm.width(), pm.height())); if pm_size.unwrap_or((0, 0)) != size { diff --git a/crates/kas-resvg/src/svg.rs b/crates/kas-resvg/src/svg.rs index ef78e2c6a..464daa12b 100644 --- a/crates/kas-resvg/src/svg.rs +++ b/crates/kas-resvg/src/svg.rs @@ -119,8 +119,8 @@ widget! { let size = tree.svg_node().size.to_screen_size().dimensions(); self.tree = Some(tree); let size = Vec2(size.0.cast(), size.1.cast()); - self.min_size = Size::from(size * self.min_size_factor * scale_factor); - self.ideal_size = Size::from(size * self.ideal_size_factor * scale_factor); + self.min_size = Size::conv_nearest(size * self.min_size_factor * scale_factor); + self.ideal_size = Size::conv_nearest(size * self.ideal_size_factor * scale_factor); } } } @@ -151,7 +151,7 @@ widget! { self.core_data_mut().rect = align .complete(Align::Center, Align::Center) .aligned_rect(size, rect); - Into::<(u32, u32)>::into(size) + Cast::<(u32, u32)>::cast(size) } None => { self.core_data_mut().rect = rect; diff --git a/crates/kas-theme/src/dim.rs b/crates/kas-theme/src/dim.rs index 860366ca9..aef272950 100644 --- a/crates/kas-theme/src/dim.rs +++ b/crates/kas-theme/src/dim.rs @@ -11,7 +11,7 @@ use std::f32; use std::rc::Rc; use crate::anim::AnimState; -use kas::cast::{Cast, CastFloat, ConvFloat}; +use kas::cast::traits::*; use kas::geom::{Size, Vec2}; use kas::layout::{AxisInfo, FrameRules, Margins, SizeRules, Stretch}; use kas::text::{fonts::FontId, Align, TextApi, TextApiExt}; @@ -113,9 +113,9 @@ impl Dimensions { button_frame: (params.button_frame * scale_factor).cast_nearest(), checkbox: i32::conv_nearest(params.checkbox_inner * dpp) + 2 * (i32::from(inner_margin) + frame), - scrollbar: Size::from(params.scrollbar_size * scale_factor), - slider: Size::from(params.slider_size * scale_factor), - progress_bar: Size::from(params.progress_bar * scale_factor), + scrollbar: Size::conv_nearest(params.scrollbar_size * scale_factor), + slider: Size::conv_nearest(params.slider_size * scale_factor), + progress_bar: Size::conv_nearest(params.progress_bar * scale_factor), shadow_a: shadow_offset - shadow_size, shadow_b: shadow_offset + shadow_size, } diff --git a/crates/kas-theme/src/flat_theme.rs b/crates/kas-theme/src/flat_theme.rs index 6e4926496..50a6799a4 100644 --- a/crates/kas-theme/src/flat_theme.rs +++ b/crates/kas-theme/src/flat_theme.rs @@ -13,7 +13,7 @@ use std::ops::Range; use std::rc::Rc; use crate::{dim, ColorsLinear, Config, Theme}; -use kas::cast::Cast; +use kas::cast::traits::*; use kas::dir::{Direction, Directional}; use kas::draw::{color::Rgba, *}; use kas::geom::*; @@ -337,18 +337,18 @@ where let mut shadow = Default::default(); let mut outer_rect = inner_rect; if class == PassType::Overlay { - shadow = Quad::from(inner_rect); + shadow = Quad::conv(inner_rect); shadow.a += self.w.dims.shadow_a * SHADOW_POPUP; shadow.b += self.w.dims.shadow_b * SHADOW_POPUP; - let a = shadow.a.floor(); - let b = shadow.b.ceil(); - outer_rect = Rect::new(a.into(), (b - a).into()); + let a = Coord::conv_floor(shadow.a); + let b = Coord::conv_ceil(shadow.b); + outer_rect = Rect::new(a, (b - a).cast()); } let mut draw = self.draw.new_pass(outer_rect, offset, class); if class == PassType::Overlay { - shadow += offset.into(); - let inner = Quad::from(inner_rect + offset).shrink(self.w.dims.frame as f32); + shadow += offset.cast(); + let inner = Quad::conv(inner_rect + offset).shrink(self.w.dims.frame as f32); draw.rounded_frame_2col(shadow, inner, Rgba::BLACK, Rgba::TRANSPARENT); } @@ -365,7 +365,7 @@ where } fn frame(&mut self, rect: Rect, style: FrameStyle, state: InputState) { - let outer = Quad::from(rect); + let outer = Quad::conv(rect); match style { FrameStyle::InnerMargin => (), FrameStyle::Frame => { @@ -405,12 +405,12 @@ where } fn separator(&mut self, rect: Rect) { - let outer = Quad::from(rect); + let outer = Quad::conv(rect); self.draw.rect(outer, self.cols.frame); } fn selection_box(&mut self, rect: Rect) { - let inner = Quad::from(rect); + let inner = Quad::conv(rect); let outer = inner.grow(self.w.dims.inner_margin.into()); // TODO: this should use its own colour and a stippled pattern let col = self.cols.text_sel_bg; @@ -418,13 +418,12 @@ where } fn text(&mut self, pos: Coord, text: &TextDisplay, _: TextClass, state: InputState) { - let pos = pos; let col = if state.disabled() { self.cols.text_disabled } else { self.cols.text }; - self.draw.text(pos.into(), text, col); + self.draw.text(pos.cast(), text, col); } fn text_effects(&mut self, pos: Coord, text: &dyn TextApi, _: TextClass, state: InputState) { @@ -434,7 +433,7 @@ where self.cols.text }; self.draw - .text_col_effects((pos).into(), text.display(), col, text.effect_tokens()); + .text_col_effects(pos.cast(), text.display(), col, text.effect_tokens()); } fn text_accel( @@ -445,7 +444,7 @@ where _: TextClass, state: InputState, ) { - let pos = Vec2::from(pos); + let pos = Vec2::conv(pos); let col = if state.disabled() { self.cols.text_disabled } else { @@ -467,7 +466,7 @@ where _: TextClass, state: InputState, ) { - let pos = Vec2::from(pos); + let pos = Vec2::conv(pos); let col = if state.disabled() { self.cols.text_disabled } else { @@ -509,7 +508,7 @@ where } let width = self.w.dims.font_marker_width; - let pos = Vec2::from(pos); + let pos = Vec2::conv(pos); let mut col = self.cols.nav_focus; for cursor in text.text_glyph_pos(byte).rev() { @@ -537,7 +536,7 @@ where } fn button(&mut self, rect: Rect, col: Option, state: InputState) { - let outer = Quad::from(rect); + let outer = Quad::conv(rect); let col_bg = if state.nav_focus() && !state.disabled() { self.cols.accent_soft @@ -552,7 +551,7 @@ where fn checkbox(&mut self, wid: u64, rect: Rect, checked: bool, state: InputState) { let anim_fade = self.w.anim.fade_bool_1m(self.draw.draw, wid, checked); - let outer = Quad::from(rect); + let outer = Quad::conv(rect); let col_frame = self.cols.nav_region(state).unwrap_or(self.cols.frame); let inner = self.button_frame(outer, col_frame, self.cols.edit_bg(state), state); @@ -569,7 +568,7 @@ where fn radiobox(&mut self, wid: u64, rect: Rect, checked: bool, state: InputState) { let anim_fade = self.w.anim.fade_bool_1m(self.draw.draw, wid, checked); - let outer = Quad::from(rect); + let outer = Quad::conv(rect); let col = self.cols.nav_region(state).unwrap_or(self.cols.frame); if !(state.disabled() || state.depress()) { @@ -605,14 +604,14 @@ where fn scrollbar(&mut self, rect: Rect, h_rect: Rect, _dir: Direction, state: InputState) { // track - let outer = Quad::from(rect); + let outer = Quad::conv(rect); let inner = outer.shrink(outer.size().min_comp() / 2.0); let mut col = self.cols.frame; col.a = 0.5; // HACK self.draw.rounded_frame(outer, inner, 0.0, col); // handle - let outer = Quad::from(h_rect); + let outer = Quad::conv(h_rect); let r = outer.size().min_comp() * 0.125; let outer = outer.shrink(r); let inner = outer.shrink(3.0 * r); @@ -626,8 +625,8 @@ where fn slider(&mut self, rect: Rect, h_rect: Rect, dir: Direction, state: InputState) { // track - let mut outer = Quad::from(rect); - let mid = Vec2::from(h_rect.pos + h_rect.size / 2); + let mut outer = Quad::conv(rect); + let mid = Vec2::conv(h_rect.pos + h_rect.size / 2); let (mut first, mut second); if dir.is_horizontal() { outer = outer.shrink_vec(Vec2(0.0, outer.size().1 * (1.0 / 3.0))); @@ -662,8 +661,8 @@ where // handle; force it to be square let size = Size::splat(h_rect.size.0.min(h_rect.size.1)); - let offset = Offset::from((h_rect.size - size) / 2); - let outer = Quad::from(Rect::new(h_rect.pos + offset, size)); + let offset = Offset::conv((h_rect.size - size) / 2); + let outer = Quad::conv(Rect::new(h_rect.pos + offset, size)); let col = if state.nav_focus() && !state.disabled() { self.cols.accent_soft @@ -693,7 +692,7 @@ where } fn progress_bar(&mut self, rect: Rect, dir: Direction, _: InputState, value: f32) { - let mut outer = Quad::from(rect); + let mut outer = Quad::conv(rect); let inner = outer.shrink(outer.size().min_comp() / 2.0); self.draw.rounded_frame(outer, inner, 0.75, self.cols.frame); @@ -707,7 +706,7 @@ where } fn image(&mut self, id: ImageId, rect: Rect) { - let rect = Quad::from(rect); + let rect = Quad::conv(rect); self.draw.image(id, rect); } } diff --git a/crates/kas-theme/src/shaded_theme.rs b/crates/kas-theme/src/shaded_theme.rs index a2d5017f1..e44af9b83 100644 --- a/crates/kas-theme/src/shaded_theme.rs +++ b/crates/kas-theme/src/shaded_theme.rs @@ -10,6 +10,7 @@ use std::ops::Range; use crate::{dim, ColorsLinear, Config, FlatTheme, Theme}; use crate::{DrawShaded, DrawShadedImpl}; +use kas::cast::traits::*; use kas::dir::{Direction, Directional}; use kas::draw::{color::Rgba, *}; use kas::geom::*; @@ -192,7 +193,7 @@ where /// - `bg_col`: colour of background /// - `nav_col`: colour of navigation highlight, if visible fn draw_edit_box(&mut self, outer: Rect, bg_col: Rgba, nav_col: Option) -> Quad { - let mut outer = Quad::from(outer); + let mut outer = Quad::conv(outer); let mut inner = outer.shrink(self.w.dims.frame as f32); let col = self.cols.background; @@ -211,7 +212,7 @@ where /// Draw a handle (for slider, scrollbar) fn draw_handle(&mut self, rect: Rect, state: InputState) { - let outer = Quad::from(rect); + let outer = Quad::conv(rect); let thickness = outer.size().min_comp() / 2.0; let inner = outer.shrink(thickness); let col = self.cols.accent_soft_state(state); @@ -246,18 +247,18 @@ where let mut shadow = Default::default(); let mut outer_rect = inner_rect; if class == PassType::Overlay { - shadow = Quad::from(inner_rect); + shadow = Quad::conv(inner_rect); shadow.a += self.w.dims.shadow_a; shadow.b += self.w.dims.shadow_b; - let a = shadow.a.floor(); - let b = shadow.b.ceil(); - outer_rect = Rect::new(a.into(), (b - a).into()); + let a = Coord::conv_floor(shadow.a); + let b = Coord::conv_ceil(shadow.b); + outer_rect = Rect::new(a, (b - a).cast()); } let mut draw = self.draw.new_pass(outer_rect, offset, class); if class == PassType::Overlay { - shadow += offset.into(); - let inner = Quad::from(inner_rect + offset); + shadow += offset.cast(); + let inner = Quad::conv(inner_rect + offset); draw.rounded_frame_2col(shadow, inner, Rgba::BLACK, Rgba::TRANSPARENT); } @@ -276,19 +277,19 @@ where fn frame(&mut self, rect: Rect, style: FrameStyle, mut state: InputState) { match style { FrameStyle::Frame => { - let outer = Quad::from(rect); + let outer = Quad::conv(rect); let inner = outer.shrink(self.w.dims.frame as f32); let norm = (0.7, -0.7); let col = self.cols.background; self.draw.shaded_round_frame(outer, inner, norm, col); } FrameStyle::Popup => { - let outer = Quad::from(rect); + let outer = Quad::conv(rect); self.draw.rect(outer, self.cols.background); } FrameStyle::MenuEntry => { if let Some(col) = self.cols.menu_entry(state) { - let outer = Quad::from(rect); + let outer = Quad::conv(rect); self.draw.rect(outer, col); } } @@ -303,7 +304,7 @@ where } fn separator(&mut self, rect: Rect) { - let outer = Quad::from(rect); + let outer = Quad::conv(rect); let inner = outer.shrink(outer.size().min_comp() / 2.0); let norm = (0.0, -0.7); let col = self.cols.background; @@ -363,7 +364,7 @@ where } fn button(&mut self, rect: Rect, col: Option, state: InputState) { - let outer = Quad::from(rect); + let outer = Quad::conv(rect); let inner = outer.shrink(self.w.dims.button_frame as f32); let col = col.map(|c| c.into()).unwrap_or(self.cols.accent_soft); let col = ColorsLinear::adjust_for_state(col, state); @@ -411,7 +412,7 @@ where fn scrollbar(&mut self, rect: Rect, h_rect: Rect, _dir: Direction, state: InputState) { // track - let outer = Quad::from(rect); + let outer = Quad::conv(rect); let inner = outer.shrink(outer.size().min_comp() / 2.0); let norm = (0.0, -0.7); let col = self.cols.background; @@ -423,7 +424,7 @@ where fn slider(&mut self, rect: Rect, h_rect: Rect, dir: Direction, state: InputState) { // track - let mut outer = Quad::from(rect); + let mut outer = Quad::conv(rect); outer = match dir.is_horizontal() { true => outer.shrink_vec(Vec2(0.0, outer.size().1 * (3.0 / 8.0))), false => outer.shrink_vec(Vec2(outer.size().0 * (3.0 / 8.0), 0.0)), @@ -438,7 +439,7 @@ where } fn progress_bar(&mut self, rect: Rect, dir: Direction, _: InputState, value: f32) { - let mut outer = Quad::from(rect); + let mut outer = Quad::conv(rect); let inner = outer.shrink(outer.size().min_comp() / 2.0); let norm = (0.0, -0.7); let col = self.cols.frame; diff --git a/crates/kas-wgpu/src/draw/atlases.rs b/crates/kas-wgpu/src/draw/atlases.rs index 642b6ab20..4f199a1c8 100644 --- a/crates/kas-wgpu/src/draw/atlases.rs +++ b/crates/kas-wgpu/src/draw/atlases.rs @@ -243,7 +243,7 @@ impl Pipeline { let origin = (alloc.rectangle.min.x.cast(), alloc.rectangle.min.y.cast()); - let tex_size = Vec2::from(Size::from(tex_size)); + let tex_size = Vec2::conv(Size::from(tex_size)); let a = to_vec2(alloc.rectangle.min) / tex_size; let b = to_vec2(alloc.rectangle.max) / tex_size; debug_assert!(Vec2::ZERO.le(a) && a.le(b) && b.le(Vec2::splat(1.0))); diff --git a/crates/kas-wgpu/src/draw/draw_pipe.rs b/crates/kas-wgpu/src/draw/draw_pipe.rs index fb75a6822..e1f6cb893 100644 --- a/crates/kas-wgpu/src/draw/draw_pipe.rs +++ b/crates/kas-wgpu/src/draw/draw_pipe.rs @@ -9,7 +9,7 @@ use std::f32::consts::FRAC_PI_2; use wgpu::util::DeviceExt; use super::*; -use kas::cast::Cast; +use kas::cast::traits::*; use kas::draw::color::Rgba; use kas::draw::*; use kas::geom::{Quad, Rect, Size, Vec2}; @@ -119,7 +119,7 @@ impl DrawPipe { pub fn resize(&self, window: &mut DrawWindow, size: Size) { window.clip_regions[0].0.size = size; - let vsize = Vec2::from(size); + let vsize = Vec2::conv(size); let off = vsize * -0.5; let scale = 2.0 / vsize; window.scale = [off.0, off.1, scale.0, -scale.1]; @@ -143,7 +143,7 @@ impl DrawPipe { let mut scale = window.scale; let base_offset = (scale[0], scale[1]); for (region, bg) in window.clip_regions.iter().zip(self.bg_common.iter()) { - let offset = Vec2::from(region.1); + let offset = Vec2::conv(region.1); scale[0] = base_offset.0 - offset.0; scale[1] = base_offset.1 - offset.1; self.queue @@ -155,7 +155,7 @@ impl DrawPipe { let (bgl_common, light_norm_buf) = (&self.bgl_common, &self.light_norm_buf); self.bg_common .extend(window.clip_regions[bg_len..].iter().map(|region| { - let offset = Vec2::from(region.1); + let offset = Vec2::conv(region.1); scale[0] = base_offset.0 - offset.0; scale[1] = base_offset.1 - offset.1; let scale_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { diff --git a/crates/kas-wgpu/src/window.rs b/crates/kas-wgpu/src/window.rs index c22cfc80f..3684e2920 100644 --- a/crates/kas-wgpu/src/window.rs +++ b/crates/kas-wgpu/src/window.rs @@ -82,7 +82,7 @@ impl>> Window { let scale_factor = window.scale_factor(); shared.scale_factor = scale_factor; - let size: Size = window.inner_size().into(); + let size: Size = window.inner_size().cast(); info!("Constucted new window with size {:?}", size); let mut draw = shared.draw.draw.new_window(); @@ -315,7 +315,7 @@ impl>> Window { fn do_resize(&mut self, shared: &mut SharedState, size: PhysicalSize) { let time = Instant::now(); - let size = size.into(); + let size = size.cast(); if size == self.sc_size() { return; } diff --git a/crates/kas-widgets/src/drag.rs b/crates/kas-widgets/src/drag.rs index 2f34dbc3c..d1c41f8dd 100644 --- a/crates/kas-widgets/src/drag.rs +++ b/crates/kas-widgets/src/drag.rs @@ -122,7 +122,7 @@ impl DragHandle { /// This depends on size of the handle and the track. #[inline] pub fn max_offset(&self) -> Offset { - Offset::from(self.track.size) - Offset::from(self.core.rect.size) + Offset::conv(self.track.size) - Offset::conv(self.core.rect.size) } /// Set a new handle offset diff --git a/crates/kas-widgets/src/edit_field.rs b/crates/kas-widgets/src/edit_field.rs index 61a41239d..4cf5d38c9 100644 --- a/crates/kas-widgets/src/edit_field.rs +++ b/crates/kas-widgets/src/edit_field.rs @@ -404,7 +404,7 @@ widget! { .text .update_env(|env| { env.set_align(align.unwrap_or(Align::Default, valign)); - env.set_bounds(size.into()); + env.set_bounds(size.cast()); }) .into(); self.set_view_offset_from_edit_pos(); @@ -576,8 +576,8 @@ widget! { fn max_scroll_offset(&self) -> Offset { let bounds = Vec2::from(self.text.env().bounds); - let max_offset = (self.required - bounds).ceil(); - Offset::from(max_offset).max(Offset::ZERO) + let max_offset = Offset::conv_ceil(self.required - bounds); + max_offset.max(Offset::ZERO) } fn scroll_offset(&self) -> Offset { @@ -1086,7 +1086,7 @@ impl EditField { } fn set_edit_pos_from_coord(&mut self, mgr: &mut EventMgr, coord: Coord) { - let rel_pos = (coord - self.rect().pos + self.view_offset).into(); + let rel_pos = (coord - self.rect().pos + self.view_offset).cast(); self.selection .set_edit_pos(self.text.text_index_nearest(rel_pos)); self.set_view_offset_from_edit_pos(); diff --git a/crates/kas-widgets/src/label.rs b/crates/kas-widgets/src/label.rs index a93671f11..bac489037 100644 --- a/crates/kas-widgets/src/label.rs +++ b/crates/kas-widgets/src/label.rs @@ -30,7 +30,7 @@ widget! { fn set_rect(&mut self, _: &mut SetRectMgr, rect: Rect, align: AlignHints) { self.core.rect = rect; self.label.update_env(|env| { - env.set_bounds(rect.size.into()); + env.set_bounds(rect.size.cast()); env.set_align(align.unwrap_or(Align::Default, Align::Center)); }); } diff --git a/crates/kas-widgets/src/scroll_label.rs b/crates/kas-widgets/src/scroll_label.rs index 7c14c0fe9..3260d4bb3 100644 --- a/crates/kas-widgets/src/scroll_label.rs +++ b/crates/kas-widgets/src/scroll_label.rs @@ -42,7 +42,7 @@ widget! { .text .update_env(|env| { env.set_align(align.unwrap_or(Align::Default, Align::Default)); - env.set_bounds(size.into()); + env.set_bounds(size.cast()); }) .into(); self.set_view_offset_from_edit_pos(); @@ -89,7 +89,7 @@ widget! { } fn set_edit_pos_from_coord(&mut self, mgr: &mut EventMgr, coord: Coord) { - let rel_pos = (coord - self.rect().pos + self.view_offset).into(); + let rel_pos = (coord - self.rect().pos + self.view_offset).cast(); self.selection .set_edit_pos(self.text.text_index_nearest(rel_pos)); self.set_view_offset_from_edit_pos(); @@ -221,8 +221,8 @@ widget! { fn max_scroll_offset(&self) -> Offset { let bounds = Vec2::from(self.text.env().bounds); - let max_offset = (self.required - bounds).ceil(); - Offset::from(max_offset).max(Offset::ZERO) + let max_offset = Offset::conv_ceil(self.required - bounds); + max_offset.max(Offset::ZERO) } fn scroll_offset(&self) -> Offset { diff --git a/examples/async-event.rs b/examples/async-event.rs index a00269328..89dce560f 100644 --- a/examples/async-event.rs +++ b/examples/async-event.rs @@ -66,7 +66,7 @@ widget! { fn draw(&mut self, mut draw: DrawMgr) { let draw = draw.draw_device(); let col = *self.colour.lock().unwrap(); - draw.rect((self.rect()).into(), col); + draw.rect((self.rect()).cast(), col); } } impl Handler for ColourSquare { diff --git a/examples/clock.rs b/examples/clock.rs index 2fa6d5a7e..fcf8aaee7 100644 --- a/examples/clock.rs +++ b/examples/clock.rs @@ -48,7 +48,7 @@ widget! { let size = rect.size.0.min(rect.size.1); let size = Size::splat(size); let excess = rect.size - size; - let pos = rect.pos + (excess * 0.5); + let pos = rect.pos + excess / 2; self.core.rect = Rect { pos, size }; // Note: font size is calculated as dpem = dpp * pt_size. Instead of @@ -56,11 +56,11 @@ widget! { let half_size = Size(size.0, size.1 / 2); self.date.update_env(|env| { env.set_pt_size(size.1 as f32 * 0.12); - env.set_bounds(half_size.into()); + env.set_bounds(half_size.cast()); }); self.time.update_env(|env| { env.set_pt_size(size.1 as f32 * 0.15); - env.set_bounds(half_size.into()); + env.set_bounds(half_size.cast()); }); self.date_pos = pos + Size(0, size.1 - half_size.1); self.time_pos = pos; @@ -81,7 +81,7 @@ widget! { let mut draw = DrawIface::>::downcast_from(draw).unwrap(); let rect = self.core.rect; - let quad = Quad::from(rect); + let quad = Quad::conv(rect); draw.circle(quad, 0.95, col_face); let half = (quad.b.1 - quad.a.1) / 2.0; @@ -97,8 +97,8 @@ widget! { draw.rounded_line(centre + v * (r - l), centre + v * r, w, col_face); } - draw.text(self.date_pos.into(), self.date.as_ref(), col_date); - draw.text(self.time_pos.into(), self.time.as_ref(), col_time); + draw.text(self.date_pos.cast(), self.date.as_ref(), col_date); + draw.text(self.time_pos.cast(), self.time.as_ref(), col_time); // We use a new pass to control the draw order (force in front). let mut draw = draw.new_pass(rect, Offset::ZERO, PassType::Clip); From 896470ac142108ff7d8ee1eafd3c835ad74a3f21 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Tue, 15 Feb 2022 16:36:04 +0000 Subject: [PATCH 3/4] Fix kas-core doc-tests and mandlebrot example --- crates/kas-core/src/event/events.rs | 6 +++--- examples/mandlebrot/mandlebrot.rs | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/kas-core/src/event/events.rs b/crates/kas-core/src/event/events.rs index b1e5f4576..4cfc19bf3 100644 --- a/crates/kas-core/src/event/events.rs +++ b/crates/kas-core/src/event/events.rs @@ -65,11 +65,11 @@ pub enum Event { /// /// In general, a point `p` on the screen should be transformed as follows: /// ``` + /// # use kas_core::cast::{Cast, CastFloat}; /// # use kas_core::geom::{Coord, DVec2}; /// # let (alpha, delta) = (DVec2::ZERO, DVec2::ZERO); - /// # let mut p = Coord::ZERO; - /// // Works for Coord type; for DVec2 type-conversions are unnecessary: - /// p = (alpha.complex_mul(p.into()) + delta).into(); + /// let mut p = Coord::ZERO; // or whatever + /// p = (alpha.complex_mul(p.cast()) + delta).cast_nearest(); /// ``` /// /// When it is known that there is no rotational component, one can use a diff --git a/examples/mandlebrot/mandlebrot.rs b/examples/mandlebrot/mandlebrot.rs index 73fb19f3d..997543b87 100644 --- a/examples/mandlebrot/mandlebrot.rs +++ b/examples/mandlebrot/mandlebrot.rs @@ -78,8 +78,8 @@ impl Default for PushConstants { } impl PushConstants { fn set(&mut self, p: DVec2, q: DVec2, iterations: i32) { - self.p = p.into(); - self.q = q.into(); + self.p = p.cast_approx(); + self.q = q.cast_approx(); self.iterations = iterations; } } @@ -232,8 +232,8 @@ impl CustomWindow for PipeWindow { self.push_constants.set(p.0, p.1, p.3); let rel_width = p.2; - let aa = Vec2::from(rect.pos); - let bb = aa + Vec2::from(rect.size); + let aa = Vec2::conv(rect.pos); + let bb = aa + Vec2::conv(rect.size); let depth = pass.depth(); let ab = Vec3(aa.0, bb.1, depth); @@ -333,10 +333,10 @@ widget! { #[inline] fn set_rect(&mut self, _: &mut SetRectMgr, rect: Rect, _: AlignHints) { self.core.rect = rect; - let size = DVec2::from(rect.size); + let size = DVec2::conv(rect.size); let rel_width = DVec2(size.0 / size.1, 1.0); self.view_alpha = 2.0 / size.1; - self.view_delta = -(DVec2::from(rect.pos) * 2.0 + size) / size.1; + self.view_delta = -(DVec2::conv(rect.pos) * 2.0 + size) / size.1; self.rel_width = rel_width.0 as f32; } From 42708ff7926e35519eea309fdeddd2b307b02f0a Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Tue, 15 Feb 2022 17:32:41 +0000 Subject: [PATCH 4/4] Fix mandlebrot example with double-precision --- examples/mandlebrot/mandlebrot.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/examples/mandlebrot/mandlebrot.rs b/examples/mandlebrot/mandlebrot.rs index 997543b87..a4a6fbdcb 100644 --- a/examples/mandlebrot/mandlebrot.rs +++ b/examples/mandlebrot/mandlebrot.rs @@ -78,8 +78,16 @@ impl Default for PushConstants { } impl PushConstants { fn set(&mut self, p: DVec2, q: DVec2, iterations: i32) { - self.p = p.cast_approx(); - self.q = q.cast_approx(); + #[cfg(feature = "shader64")] + { + self.p = p; + self.q = q; + } + #[cfg(not(feature = "shader64"))] + { + self.p = p.cast_approx(); + self.q = q.cast_approx(); + } self.iterations = iterations; } }