Switch `BoxBounds` from a position-and-size representation to an offset-and-extent representation.

This makes the implementation of rectangle union (`Add`/`AddAssign`) far easier as we just compute the min and max of the offset and extent coordinates. It also makes the conversion into and from `swf::Rectangle` easier as it's now effectively a generic version of that datatype.

On the other hand, `width`, `height`, and `size` now have to be calculated, and require `T` to be self-`Sub`. I'm not sure if this is that much of a problem or not.
This commit is contained in:
David Wendt 2020-03-21 22:12:38 -04:00
parent 0a1de3276f
commit e7c34d9745
1 changed files with 62 additions and 50 deletions

View File

@ -1,7 +1,7 @@
//! CSS dimension types //! CSS dimension types
use gc_arena::Collect; use gc_arena::Collect;
use std::cmp::{max, min, Ord}; use std::cmp::{max, min, Ord};
use std::ops::{Add, AddAssign}; use std::ops::{Add, AddAssign, Sub};
use swf::{Rectangle, Twips}; use swf::{Rectangle, Twips};
/// A type which represents the top-left position of a layout box. /// A type which represents the top-left position of a layout box.
@ -137,9 +137,9 @@ where
#[collect(require_static)] #[collect(require_static)]
pub struct BoxBounds<T> { pub struct BoxBounds<T> {
offset_x: T, offset_x: T,
width: T, extent_x: T,
offset_y: T, offset_y: T,
height: T, extent_y: T,
} }
impl<T> Default for BoxBounds<T> impl<T> Default for BoxBounds<T>
@ -149,26 +149,23 @@ where
fn default() -> Self { fn default() -> Self {
Self { Self {
offset_x: Default::default(), offset_x: Default::default(),
width: Default::default(), extent_x: Default::default(),
offset_y: Default::default(), offset_y: Default::default(),
height: Default::default(), extent_y: Default::default(),
} }
} }
} }
impl<T> Into<Rectangle> for BoxBounds<T> impl<T> Into<Rectangle> for BoxBounds<T>
where where
T: Into<Twips> + Add<T, Output = T> + Clone, T: Into<Twips> + Add<T, Output = T>,
{ {
fn into(self) -> Rectangle { fn into(self) -> Rectangle {
let x_max = self.extent_x().into();
let y_max = self.extent_y().into();
Rectangle { Rectangle {
x_min: self.offset_x.into(), x_min: self.offset_x.into(),
x_max, x_max: self.extent_x.into(),
y_min: self.offset_y.into(), y_min: self.offset_y.into(),
y_max, y_max: self.extent_y.into(),
} }
} }
} }
@ -180,22 +177,35 @@ where
fn from(bounds: Rectangle) -> Self { fn from(bounds: Rectangle) -> Self {
Self { Self {
offset_x: T::from(bounds.x_min), offset_x: T::from(bounds.x_min),
width: T::from(bounds.x_max - bounds.x_min), extent_x: T::from(bounds.x_max),
offset_y: T::from(bounds.y_min), offset_y: T::from(bounds.y_min),
height: T::from(bounds.y_max - bounds.y_min), extent_y: T::from(bounds.y_max),
} }
} }
} }
impl<T> BoxBounds<T> { impl<T> BoxBounds<T>
where
T: Add<T, Output = T> + Sub<T, Output = T> + Clone,
{
pub fn from_position_and_size(pos: Position<T>, size: Size<T>) -> Self { pub fn from_position_and_size(pos: Position<T>, size: Size<T>) -> Self {
Self { Self {
offset_x: pos.x, offset_x: pos.x.clone(),
width: size.width, extent_x: pos.x + size.width,
offset_y: pos.y, offset_y: pos.y.clone(),
height: size.height, extent_y: pos.y + size.height,
} }
} }
pub fn into_position_and_size(self) -> (Position<T>, Size<T>) {
let width = self.extent_x - self.offset_x.clone();
let height = self.extent_y - self.offset_y.clone();
(
Position::from((self.offset_x, self.offset_y)),
Size::from((width, height)),
)
}
} }
impl<T> BoxBounds<T> impl<T> BoxBounds<T>
@ -210,48 +220,48 @@ where
self.offset_y.clone() self.offset_y.clone()
} }
pub fn width(&self) -> T { pub fn extent_x(&self) -> T {
self.width.clone() self.extent_x.clone()
} }
pub fn height(&self) -> T { pub fn extent_y(&self) -> T {
self.height.clone() self.extent_y.clone()
} }
pub fn origin(&self) -> Position<T> { pub fn origin(&self) -> Position<T> {
Position::from((self.offset_x(), self.offset_y())) Position::from((self.offset_x(), self.offset_y()))
} }
}
impl<T> BoxBounds<T>
where
T: Sub<T, Output = T> + Clone,
{
pub fn width(&self) -> T {
self.extent_x() - self.offset_x()
}
pub fn height(&self) -> T {
self.extent_y() - self.offset_y()
}
pub fn size(&self) -> Size<T> { pub fn size(&self) -> Size<T> {
Size::from((self.width(), self.height())) Size::from((self.width(), self.height()))
} }
} }
impl<T> BoxBounds<T>
where
T: Add<T, Output = T> + Clone,
{
pub fn extent_x(&self) -> T {
self.offset_x.clone() + self.width.clone()
}
pub fn extent_y(&self) -> T {
self.offset_y.clone() + self.height.clone()
}
}
impl<T> Add for BoxBounds<T> impl<T> Add for BoxBounds<T>
where where
T: Add<T> + Ord, T: Add<T> + Ord + Clone,
{ {
type Output = Self; type Output = Self;
fn add(self, rhs: Self) -> Self::Output { fn add(self, rhs: Self) -> Self::Output {
Self { Self {
offset_x: min(self.offset_x, rhs.offset_x), offset_x: min(self.offset_x, rhs.offset_x),
width: max(self.width, rhs.width), extent_x: max(self.extent_x, rhs.extent_x),
offset_y: min(self.offset_y, rhs.offset_y), offset_y: min(self.offset_y, rhs.offset_y),
height: max(self.height, rhs.height), extent_y: max(self.extent_y, rhs.extent_y),
} }
} }
} }
@ -262,9 +272,9 @@ where
{ {
fn add_assign(&mut self, rhs: Self) { fn add_assign(&mut self, rhs: Self) {
self.offset_x = min(self.offset_x.clone(), rhs.offset_x); self.offset_x = min(self.offset_x.clone(), rhs.offset_x);
self.width = max(self.width.clone(), rhs.width); self.extent_x = max(self.extent_x.clone(), rhs.extent_x);
self.offset_y = min(self.offset_y.clone(), rhs.offset_y); self.offset_y = min(self.offset_y.clone(), rhs.offset_y);
self.height = max(self.height.clone(), rhs.height); self.extent_y = max(self.extent_y.clone(), rhs.extent_y);
} }
} }
@ -276,10 +286,10 @@ where
fn add(self, rhs: Position<T>) -> Self::Output { fn add(self, rhs: Position<T>) -> Self::Output {
Self { Self {
offset_x: self.offset_x + rhs.x, offset_x: self.offset_x + rhs.x.clone(),
width: self.width, extent_x: self.extent_x + rhs.x,
offset_y: self.offset_y + rhs.y, offset_y: self.offset_y + rhs.y.clone(),
height: self.height, extent_y: self.extent_y + rhs.y,
} }
} }
} }
@ -289,8 +299,10 @@ where
T: AddAssign<T> + Clone, T: AddAssign<T> + Clone,
{ {
fn add_assign(&mut self, rhs: Position<T>) { fn add_assign(&mut self, rhs: Position<T>) {
self.offset_x += rhs.x; self.offset_x += rhs.x.clone();
self.offset_y += rhs.y; self.extent_x += rhs.x;
self.offset_y += rhs.y.clone();
self.extent_y += rhs.y;
} }
} }
@ -303,9 +315,9 @@ where
fn add(self, rhs: Size<T>) -> Self::Output { fn add(self, rhs: Size<T>) -> Self::Output {
Self { Self {
offset_x: self.offset_x, offset_x: self.offset_x,
width: self.width + rhs.width, extent_x: self.extent_x + rhs.width,
offset_y: self.offset_y, offset_y: self.offset_y,
height: self.height + rhs.height, extent_y: self.extent_y + rhs.height,
} }
} }
} }
@ -315,7 +327,7 @@ where
T: AddAssign<T> + Clone, T: AddAssign<T> + Clone,
{ {
fn add_assign(&mut self, rhs: Size<T>) { fn add_assign(&mut self, rhs: Size<T>) {
self.width += rhs.width; self.extent_x += rhs.width;
self.height += rhs.height; self.extent_y += rhs.height;
} }
} }