[librsvg: 1/7] rect: replace IRect with a generic rect
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 1/7] rect: replace IRect with a generic rect
- Date: Tue, 10 Dec 2019 13:55:45 +0000 (UTC)
commit f8fa7f9366bcd97f2cb8dd49c3b06a62f443a02e
Author: Paolo Borelli <pborelli gnome org>
Date: Sun Dec 8 11:28:36 2019 +0100
rect: replace IRect with a generic rect
Move IRect code to a generic Rect<T> in preparation to sharing
it with Rect<f64>. The generic rect is in a local submodule, so
that we can use Rect as an alias for rect::Rect<f64>.
For now I left the scale method in an extension trait since I am
not sure how deal with ceil/floor etc.
rsvg_internals/src/rect.rs | 285 ++++++++++++++++++++++++++-------------------
1 file changed, 162 insertions(+), 123 deletions(-)
---
diff --git a/rsvg_internals/src/rect.rs b/rsvg_internals/src/rect.rs
index 896f2c3a..03ad6a4e 100644
--- a/rsvg_internals/src/rect.rs
+++ b/rsvg_internals/src/rect.rs
@@ -1,8 +1,169 @@
use cairo;
-use core::ops::Range;
use crate::float_eq_cairo::ApproxEqCairo;
+mod rect {
+ use core::ops::{Add, Range, Sub};
+ use num_traits::Zero;
+
+ // Use our own min() and max() that are acceptable for floating point
+
+ fn min<T: PartialOrd>(x: T, y: T) -> T {
+ if x <= y {
+ x
+ } else {
+ y
+ }
+ }
+
+ fn max<T: PartialOrd>(x: T, y: T) -> T {
+ if x >= y {
+ x
+ } else {
+ y
+ }
+ }
+
+ #[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
+ pub struct Rect<T> {
+ pub x0: T,
+ pub y0: T,
+ pub x1: T,
+ pub y1: T,
+ }
+
+ impl<T> Rect<T> {
+ #[inline]
+ pub fn new(x0: T, y0: T, x1: T, y1: T) -> Self {
+ Self { x0, y0, x1, y1 }
+ }
+ }
+
+ impl<T> Rect<T>
+ where
+ T: Copy + PartialOrd + PartialEq + Add<T, Output = T> + Sub<T, Output = T> + Zero,
+ {
+ #[inline]
+ pub fn from_size(w: T, h: T) -> Self {
+ Self {
+ x0: Zero::zero(),
+ y0: Zero::zero(),
+ x1: w,
+ y1: h,
+ }
+ }
+
+ #[inline]
+ pub fn width(&self) -> T {
+ self.x1 - self.x0
+ }
+
+ #[inline]
+ pub fn height(&self) -> T {
+ self.y1 - self.y0
+ }
+
+ #[inline]
+ pub fn size(&self) -> (T, T) {
+ (self.width(), self.height())
+ }
+
+ #[inline]
+ pub fn x_range(&self) -> Range<T> {
+ self.x0..self.x1
+ }
+
+ #[inline]
+ pub fn y_range(&self) -> Range<T> {
+ self.y0..self.y1
+ }
+
+ #[inline]
+ pub fn contains(self, x: T, y: T) -> bool {
+ x >= self.x0 && x < self.x1 && y >= self.y0 && y < self.y1
+ }
+
+ #[inline]
+ pub fn translate(&self, by: (T, T)) -> Self {
+ Self {
+ x0: self.x0 + by.0,
+ y0: self.y0 + by.1,
+ x1: self.x1 + by.0,
+ y1: self.y1 + by.1,
+ }
+ }
+
+ #[inline]
+ pub fn intersection(&self, rect: &Self) -> Option<Self> {
+ let (x0, y0, x1, y1) = (
+ max(self.x0, rect.x0),
+ max(self.y0, rect.y0),
+ min(self.x1, rect.x1),
+ min(self.y1, rect.y1),
+ );
+
+ if x1 > x0 && y1 > y0 {
+ Some(Self { x0, y0, x1, y1 })
+ } else {
+ None
+ }
+ }
+
+ #[inline]
+ pub fn union(&self, rect: &Self) -> Self {
+ Self {
+ x0: min(self.x0, rect.x0),
+ y0: min(self.y0, rect.y0),
+ x1: max(self.x1, rect.x1),
+ y1: max(self.y1, rect.y1),
+ }
+ }
+ }
+
+ impl Rect<i32> {
+ #[inline]
+ pub fn is_empty(&self) -> bool {
+ self.width() == Zero::zero() || self.height() == Zero::zero()
+ }
+
+ #[inline]
+ pub fn scale(self, x: f64, y: f64) -> Self {
+ Self {
+ x0: (f64::from(self.x0) * x).floor() as i32,
+ y0: (f64::from(self.y0) * y).floor() as i32,
+ x1: (f64::from(self.x1) * x).ceil() as i32,
+ y1: (f64::from(self.y1) * y).ceil() as i32,
+ }
+ }
+ }
+}
+
+pub type IRect = rect::Rect<i32>;
+
+impl From<cairo::Rectangle> for IRect {
+ #[inline]
+ fn from(r: cairo::Rectangle) -> Self {
+ Self {
+ x0: r.x.floor() as i32,
+ y0: r.y.floor() as i32,
+ x1: (r.x + r.width).ceil() as i32,
+ y1: (r.y + r.height).ceil() as i32,
+ }
+ }
+}
+
+impl From<IRect> for cairo::Rectangle {
+ #[inline]
+ fn from(r: IRect) -> Self {
+ Self {
+ x: f64::from(r.x0),
+ y: f64::from(r.y0),
+ width: f64::from(r.x1 - r.x0),
+ height: f64::from(r.y1 - r.y0),
+ }
+ }
+}
+
pub trait RectangleExt {
fn new(x: f64, y: f64, width: f64, height: f64) -> cairo::Rectangle;
fn from_size(width: f64, height: f64) -> cairo::Rectangle;
@@ -137,128 +298,6 @@ impl TransformRect for cairo::Matrix {
}
}
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub struct IRect {
- pub x0: i32,
- pub y0: i32,
- pub x1: i32,
- pub y1: i32,
-}
-
-impl IRect {
- #[inline]
- pub fn new(x0: i32, y0: i32, x1: i32, y1: i32) -> IRect {
- IRect { x0, y0, x1, y1 }
- }
-
- #[inline]
- pub fn from_size(w: i32, h: i32) -> IRect {
- IRect {
- x0: 0,
- y0: 0,
- x1: w,
- y1: h,
- }
- }
-
- #[inline]
- pub fn width(&self) -> i32 {
- self.x1 - self.x0
- }
-
- #[inline]
- pub fn height(&self) -> i32 {
- self.y1 - self.y0
- }
-
- #[inline]
- pub fn x_range(&self) -> Range<i32> {
- self.x0..self.x1
- }
-
- #[inline]
- pub fn y_range(&self) -> Range<i32> {
- self.y0..self.y1
- }
-
- /// Returns true if the `IRect` contains the given coordinates.
- #[inline]
- pub fn contains(self, x: i32, y: i32) -> bool {
- x >= self.x0 && x < self.x1 && y >= self.y0 && y < self.y1
- }
-
- /// Returns an `IRect` scaled by the given amounts.
- ///
- /// The returned `IRect` encompasses all, even partially covered, pixels after the scaling.
- #[inline]
- pub fn scale(self, x: f64, y: f64) -> IRect {
- IRect {
- x0: (f64::from(self.x0) * x).floor() as i32,
- y0: (f64::from(self.y0) * y).floor() as i32,
- x1: (f64::from(self.x1) * x).ceil() as i32,
- y1: (f64::from(self.y1) * y).ceil() as i32,
- }
- }
-
- /// Returns an `IRect` translated by the given amounts.
- #[inline]
- pub fn translate(&self, by: (i32, i32)) -> IRect {
- IRect {
- x0: self.x0 + by.0,
- y0: self.y0 + by.1,
- x1: self.x1 + by.0,
- y1: self.y1 + by.1,
- }
- }
-
- #[inline]
- pub fn intersection(&self, rect: &Self) -> Option<IRect> {
- let (x0, y0, x1, y1) = (
- self.x0.max(rect.x0),
- self.y0.max(rect.y0),
- self.x1.min(rect.x1),
- self.y1.min(rect.y1),
- );
-
- if x1 > x0 && y1 > y0 {
- Some(IRect { x0, y0, x1, y1 })
- } else {
- None
- }
- }
-}
-
-impl From<cairo::Rectangle> for IRect {
- #[inline]
- fn from(
- cairo::Rectangle {
- x,
- y,
- width,
- height,
- }: cairo::Rectangle,
- ) -> Self {
- Self {
- x0: x.floor() as i32,
- y0: y.floor() as i32,
- x1: (x + width).ceil() as i32,
- y1: (y + height).ceil() as i32,
- }
- }
-}
-
-impl From<IRect> for cairo::Rectangle {
- #[inline]
- fn from(IRect { x0, y0, x1, y1 }: IRect) -> Self {
- Self {
- x: f64::from(x0),
- y: f64::from(y0),
- width: f64::from(x1 - x0),
- height: f64::from(y1 - y0),
- }
- }
-}
-
#[cfg(test)]
mod tests {
use super::*;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]