/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use geom::point::Point2D; use geom::rect::Rect; use std::default::Default; use std::num::{NumCast, One, Zero}; use std::fmt; // An Au is an "App Unit" and represents 1/60th of a CSS pixel. It was // originally proposed in 2002 as a standard unit of measure in Gecko. // See https://bugzilla.mozilla.org/show_bug.cgi?id=177805 for more info. #[deriving(Clone, Eq, Ord, Zero)] pub struct Au(pub i32); impl Default for Au { #[inline] fn default() -> Au { Au(0) } } impl fmt::Show for Au { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let Au(n) = *self; write!(f.buf, "Au({})", n) }} impl Add for Au { #[inline] fn add(&self, other: &Au) -> Au { let Au(s) = *self; let Au(o) = *other; Au(s + o) } } impl Sub for Au { #[inline] fn sub(&self, other: &Au) -> Au { let Au(s) = *self; let Au(o) = *other; Au(s - o) } } impl Mul for Au { #[inline] fn mul(&self, other: &Au) -> Au { let Au(s) = *self; let Au(o) = *other; Au(s * o) } } impl Div for Au { #[inline] fn div(&self, other: &Au) -> Au { let Au(s) = *self; let Au(o) = *other; Au(s / o) } } impl Rem for Au { #[inline] fn rem(&self, other: &Au) -> Au { let Au(s) = *self; let Au(o) = *other; Au(s % o) } } impl Neg for Au { #[inline] fn neg(&self) -> Au { let Au(s) = *self; Au(-s) } } impl One for Au { #[inline] fn one() -> Au { Au(1) } } impl Num for Au {} #[inline] pub fn min(x: Au, y: Au) -> Au { if x < y { x } else { y } } #[inline] pub fn max(x: Au, y: Au) -> Au { if x > y { x } else { y } } impl NumCast for Au { #[inline] fn from(n: T) -> Option { Some(Au(n.to_i32().unwrap())) } } impl ToPrimitive for Au { #[inline] fn to_i64(&self) -> Option { let Au(s) = *self; Some(s as i64) } #[inline] fn to_u64(&self) -> Option { let Au(s) = *self; Some(s as u64) } #[inline] fn to_f32(&self) -> Option { let Au(s) = *self; s.to_f32() } #[inline] fn to_f64(&self) -> Option { let Au(s) = *self; s.to_f64() } } impl Au { /// FIXME(pcwalton): Workaround for lack of cross crate inlining of newtype structs! #[inline] pub fn new(value: i32) -> Au { Au(value) } #[inline] pub fn scale_by(self, factor: f64) -> Au { let Au(s) = self; Au(((s as f64) * factor) as i32) } #[inline] pub fn from_px(px: int) -> Au { NumCast::from(px * 60).unwrap() } #[inline] pub fn to_nearest_px(&self) -> int { let Au(s) = *self; ((s as f64) / 60f64).round() as int } #[inline] pub fn to_snapped(&self) -> Au { let Au(s) = *self; let res = s % 60i32; return if res >= 30i32 { return Au(s - res + 60i32) } else { return Au(s - res) }; } #[inline] pub fn from_pt(pt: f64) -> Au { from_px(pt_to_px(pt) as int) } #[inline] pub fn from_frac_px(px: f64) -> Au { Au((px * 60f64) as i32) } #[inline] pub fn min(x: Au, y: Au) -> Au { let Au(xi) = x; let Au(yi) = y; if xi < yi { x } else { y } } #[inline] pub fn max(x: Au, y: Au) -> Au { let Au(xi) = x; let Au(yi) = y; if xi > yi { x } else { y } } } // assumes 72 points per inch, and 96 px per inch pub fn pt_to_px(pt: f64) -> f64 { pt / 72f64 * 96f64 } // assumes 72 points per inch, and 96 px per inch pub fn px_to_pt(px: f64) -> f64 { px / 96f64 * 72f64 } pub fn from_frac_px(px: f64) -> Au { Au((px * 60f64) as i32) } pub fn from_px(px: int) -> Au { NumCast::from(px * 60).unwrap() } pub fn to_px(au: Au) -> int { let Au(a) = au; (a / 60) as int } pub fn to_frac_px(au: Au) -> f64 { let Au(a) = au; (a as f64) / 60f64 } // assumes 72 points per inch, and 96 px per inch pub fn from_pt(pt: f64) -> Au { from_px((pt / 72f64 * 96f64) as int) } // assumes 72 points per inch, and 96 px per inch pub fn to_pt(au: Au) -> f64 { let Au(a) = au; (a as f64) / 60f64 * 72f64 / 96f64 } /// Returns true if the rect contains the given point. Points on the top or left sides of the rect /// are considered inside the rectangle, while points on the right or bottom sides of the rect are /// not considered inside the rectangle. pub fn rect_contains_point>(rect: Rect, point: Point2D) -> bool { point.x >= rect.origin.x && point.x < rect.origin.x + rect.size.width && point.y >= rect.origin.y && point.y < rect.origin.y + rect.size.height }