diff options
Diffstat (limited to 'src/components/util/logical_geometry.rs')
-rw-r--r-- | src/components/util/logical_geometry.rs | 1023 |
1 files changed, 0 insertions, 1023 deletions
diff --git a/src/components/util/logical_geometry.rs b/src/components/util/logical_geometry.rs deleted file mode 100644 index a16dd6a5c8d..00000000000 --- a/src/components/util/logical_geometry.rs +++ /dev/null @@ -1,1023 +0,0 @@ -/* 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/. */ - -/// Geometry in flow-relative space. - -use geom::{Size2D, Point2D, SideOffsets2D, Rect}; -use std::cmp::{min, max}; -use std::fmt::{Show, Formatter, FormatError}; -use std::num::Zero; - -bitflags!( - #[deriving(Encodable)] - flags WritingMode: u8 { - static FlagRTL = 1 << 0, - static FlagVertical = 1 << 1, - static FlagVerticalLR = 1 << 2, - static FlagSidewaysLeft = 1 << 3 - } -) - -impl WritingMode { - #[inline] - pub fn is_vertical(&self) -> bool { - self.intersects(FlagVertical) - } - - /// Asuming .is_vertical(), does the block direction go left to right? - #[inline] - pub fn is_vertical_lr(&self) -> bool { - self.intersects(FlagVerticalLR) - } - - /// Asuming .is_vertical(), does the inline direction go top to bottom? - #[inline] - pub fn is_inline_tb(&self) -> bool { - !(self.intersects(FlagSidewaysLeft) ^ self.intersects(FlagRTL)) - } - - #[inline] - pub fn is_bidi_ltr(&self) -> bool { - !self.intersects(FlagRTL) - } - - #[inline] - pub fn is_sideways_left(&self) -> bool { - self.intersects(FlagSidewaysLeft) - } -} - -impl Show for WritingMode { - fn fmt(&self, formatter: &mut Formatter) -> Result<(), FormatError> { - if self.is_vertical() { - try!(write!(formatter, "V")); - if self.is_vertical_lr() { - try!(write!(formatter, " LR")); - } else { - try!(write!(formatter, " RL")); - } - if self.intersects(FlagSidewaysLeft) { - try!(write!(formatter, " SidewaysL")); - } - } else { - try!(write!(formatter, "H")); - } - if self.is_bidi_ltr() { - write!(formatter, " LTR") - } else { - write!(formatter, " RTL") - } - } -} - - -/// Wherever logical geometry is used, the writing mode is known based on context: -/// every method takes a `mode` parameter. -/// However, this context is easy to get wrong. -/// In debug builds only, logical geometry objects store their writing mode -/// (in addition to taking it as a parameter to methods) and check it. -/// In non-debug builds, make this storage zero-size and the checks no-ops. -#[cfg(ndebug)] -#[deriving(Encodable, PartialEq, Eq, Clone)] -struct DebugWritingMode; - -#[cfg(not(ndebug))] -#[deriving(Encodable, PartialEq, Eq, Clone)] -struct DebugWritingMode { - mode: WritingMode -} - -#[cfg(ndebug)] -impl DebugWritingMode { - #[inline] - fn check(&self, _other: WritingMode) {} - - #[inline] - fn check_debug(&self, _other: DebugWritingMode) {} - - #[inline] - fn new(_mode: WritingMode) -> DebugWritingMode { - DebugWritingMode - } -} - -#[cfg(not(ndebug))] -impl DebugWritingMode { - #[inline] - fn check(&self, other: WritingMode) { - assert!(self.mode == other) - } - - #[inline] - fn check_debug(&self, other: DebugWritingMode) { - assert!(self.mode == other.mode) - } - - #[inline] - fn new(mode: WritingMode) -> DebugWritingMode { - DebugWritingMode { mode: mode } - } -} - -impl Show for DebugWritingMode { - #[cfg(ndebug)] - fn fmt(&self, formatter: &mut Formatter) -> Result<(), FormatError> { - write!(formatter, "?") - } - - #[cfg(not(ndebug))] - fn fmt(&self, formatter: &mut Formatter) -> Result<(), FormatError> { - self.mode.fmt(formatter) - } -} - - -/// A 2D size in flow-relative dimensions -#[deriving(Encodable, PartialEq, Eq, Clone)] -pub struct LogicalSize<T> { - pub inline: T, // inline-size, a.k.a. logical width, a.k.a. measure - pub block: T, // block-size, a.k.a. logical height, a.k.a. extent - debug_writing_mode: DebugWritingMode, -} - -impl<T: Show> Show for LogicalSize<T> { - fn fmt(&self, formatter: &mut Formatter) -> Result<(), FormatError> { - write!(formatter, "LogicalSize[{}, {}, {}]", - self.debug_writing_mode, self.inline, self.block) - } -} - -// Can not implement the Zero trait: its zero() method does not have the `mode` parameter. -impl<T: Zero> LogicalSize<T> { - #[inline] - pub fn zero(mode: WritingMode) -> LogicalSize<T> { - LogicalSize { - inline: Zero::zero(), - block: Zero::zero(), - debug_writing_mode: DebugWritingMode::new(mode), - } - } - - #[inline] - pub fn is_zero(&self) -> bool { - self.inline.is_zero() && self.block.is_zero() - } -} - -impl<T: Copy> LogicalSize<T> { - #[inline] - pub fn new(mode: WritingMode, inline: T, block: T) -> LogicalSize<T> { - LogicalSize { - inline: inline, - block: block, - debug_writing_mode: DebugWritingMode::new(mode), - } - } - - #[inline] - pub fn from_physical(mode: WritingMode, size: Size2D<T>) -> LogicalSize<T> { - if mode.is_vertical() { - LogicalSize::new(mode, size.height, size.width) - } else { - LogicalSize::new(mode, size.width, size.height) - } - } - - #[inline] - pub fn width(&self, mode: WritingMode) -> T { - self.debug_writing_mode.check(mode); - if mode.is_vertical() { - self.block - } else { - self.inline - } - } - - #[inline] - pub fn set_width(&mut self, mode: WritingMode, width: T) { - self.debug_writing_mode.check(mode); - if mode.is_vertical() { - self.block = width - } else { - self.inline = width - } - } - - #[inline] - pub fn height(&self, mode: WritingMode) -> T { - self.debug_writing_mode.check(mode); - if mode.is_vertical() { - self.inline - } else { - self.block - } - } - - #[inline] - pub fn set_height(&mut self, mode: WritingMode, height: T) { - self.debug_writing_mode.check(mode); - if mode.is_vertical() { - self.inline = height - } else { - self.block = height - } - } - - #[inline] - pub fn to_physical(&self, mode: WritingMode) -> Size2D<T> { - self.debug_writing_mode.check(mode); - if mode.is_vertical() { - Size2D { width: self.block, height: self.inline } - } else { - Size2D { width: self.inline, height: self.block } - } - } - - #[inline] - pub fn convert(&self, mode_from: WritingMode, mode_to: WritingMode) -> LogicalSize<T> { - if mode_from == mode_to { - self.debug_writing_mode.check(mode_from); - *self - } else { - LogicalSize::from_physical(mode_to, self.to_physical(mode_from)) - } - } -} - -impl<T: Add<T, T>> Add<LogicalSize<T>, LogicalSize<T>> for LogicalSize<T> { - #[inline] - fn add(&self, other: &LogicalSize<T>) -> LogicalSize<T> { - self.debug_writing_mode.check_debug(other.debug_writing_mode); - LogicalSize { - debug_writing_mode: self.debug_writing_mode, - inline: self.inline + other.inline, - block: self.block + other.block, - } - } -} - -impl<T: Sub<T, T>> Sub<LogicalSize<T>, LogicalSize<T>> for LogicalSize<T> { - #[inline] - fn sub(&self, other: &LogicalSize<T>) -> LogicalSize<T> { - self.debug_writing_mode.check_debug(other.debug_writing_mode); - LogicalSize { - debug_writing_mode: self.debug_writing_mode, - inline: self.inline - other.inline, - block: self.block - other.block, - } - } -} - - -/// A 2D point in flow-relative dimensions -#[deriving(PartialEq, Encodable, Eq, Clone)] -pub struct LogicalPoint<T> { - pub i: T, /// inline-axis coordinate - pub b: T, /// block-axis coordinate - debug_writing_mode: DebugWritingMode, -} - -impl<T: Show> Show for LogicalPoint<T> { - fn fmt(&self, formatter: &mut Formatter) -> Result<(), FormatError> { - write!(formatter, "LogicalPoint[{}, {}, {}]", - self.debug_writing_mode, self.i, self.b) - } -} - -// Can not implement the Zero trait: its zero() method does not have the `mode` parameter. -impl<T: Zero> LogicalPoint<T> { - #[inline] - pub fn zero(mode: WritingMode) -> LogicalPoint<T> { - LogicalPoint { - i: Zero::zero(), - b: Zero::zero(), - debug_writing_mode: DebugWritingMode::new(mode), - } - } - - #[inline] - pub fn is_zero(&self) -> bool { - self.i.is_zero() && self.b.is_zero() - } -} - -impl<T: Copy> LogicalPoint<T> { - #[inline] - pub fn new(mode: WritingMode, i: T, b: T) -> LogicalPoint<T> { - LogicalPoint { - i: i, - b: b, - debug_writing_mode: DebugWritingMode::new(mode), - } - } -} - -impl<T: Copy + Sub<T, T>> LogicalPoint<T> { - #[inline] - pub fn from_physical(mode: WritingMode, point: Point2D<T>, container_size: Size2D<T>) - -> LogicalPoint<T> { - if mode.is_vertical() { - LogicalPoint { - i: if mode.is_inline_tb() { point.y } else { container_size.height - point.y }, - b: if mode.is_vertical_lr() { point.x } else { container_size.width - point.x }, - debug_writing_mode: DebugWritingMode::new(mode), - } - } else { - LogicalPoint { - i: if mode.is_bidi_ltr() { point.x } else { container_size.width - point.x }, - b: point.y, - debug_writing_mode: DebugWritingMode::new(mode), - } - } - } - - #[inline] - pub fn x(&self, mode: WritingMode, container_size: Size2D<T>) -> T { - self.debug_writing_mode.check(mode); - if mode.is_vertical() { - if mode.is_vertical_lr() { self.b } else { container_size.width - self.b } - } else { - if mode.is_bidi_ltr() { self.i } else { container_size.width - self.i } - } - } - - #[inline] - pub fn set_x(&mut self, mode: WritingMode, x: T, container_size: Size2D<T>) { - self.debug_writing_mode.check(mode); - if mode.is_vertical() { - self.b = if mode.is_vertical_lr() { x } else { container_size.width - x } - } else { - self.i = if mode.is_bidi_ltr() { x } else { container_size.width - x } - } - } - - #[inline] - pub fn y(&self, mode: WritingMode, container_size: Size2D<T>) -> T { - self.debug_writing_mode.check(mode); - if mode.is_vertical() { - if mode.is_inline_tb() { self.i } else { container_size.height - self.i } - } else { - self.b - } - } - - #[inline] - pub fn set_y(&mut self, mode: WritingMode, y: T, container_size: Size2D<T>) { - self.debug_writing_mode.check(mode); - if mode.is_vertical() { - self.i = if mode.is_inline_tb() { y } else { container_size.height - y } - } else { - self.b = y - } - } - - #[inline] - pub fn to_physical(&self, mode: WritingMode, container_size: Size2D<T>) -> Point2D<T> { - self.debug_writing_mode.check(mode); - if mode.is_vertical() { - Point2D { - x: if mode.is_vertical_lr() { self.b } else { container_size.width - self.b }, - y: if mode.is_inline_tb() { self.i } else { container_size.height - self.i } - } - } else { - Point2D { - x: if mode.is_bidi_ltr() { self.i } else { container_size.width - self.i }, - y: self.b - } - } - } - - #[inline] - pub fn convert(&self, mode_from: WritingMode, mode_to: WritingMode, container_size: Size2D<T>) - -> LogicalPoint<T> { - if mode_from == mode_to { - self.debug_writing_mode.check(mode_from); - *self - } else { - LogicalPoint::from_physical( - mode_to, self.to_physical(mode_from, container_size), container_size) - } - } -} - -impl<T: Add<T,T>> LogicalPoint<T> { - /// This doesn’t really makes sense, - /// but happens when dealing with mutliple origins. - #[inline] - pub fn add_point(&self, other: &LogicalPoint<T>) -> LogicalPoint<T> { - self.debug_writing_mode.check_debug(other.debug_writing_mode); - LogicalPoint { - debug_writing_mode: self.debug_writing_mode, - i: self.i + other.i, - b: self.b + other.b, - } - } -} - -impl<T: Add<T,T>> Add<LogicalSize<T>, LogicalPoint<T>> for LogicalPoint<T> { - #[inline] - fn add(&self, other: &LogicalSize<T>) -> LogicalPoint<T> { - self.debug_writing_mode.check_debug(other.debug_writing_mode); - LogicalPoint { - debug_writing_mode: self.debug_writing_mode, - i: self.i + other.inline, - b: self.b + other.block, - } - } -} - -impl<T: Sub<T,T>> Sub<LogicalSize<T>, LogicalPoint<T>> for LogicalPoint<T> { - #[inline] - fn sub(&self, other: &LogicalSize<T>) -> LogicalPoint<T> { - self.debug_writing_mode.check_debug(other.debug_writing_mode); - LogicalPoint { - debug_writing_mode: self.debug_writing_mode, - i: self.i - other.inline, - b: self.b - other.block, - } - } -} - - -/// A "margin" in flow-relative dimensions -/// Represents the four sides of the margins, borders, or padding of a CSS box, -/// or a combination of those. -/// A positive "margin" can be added to a rectangle to obtain a bigger rectangle. -#[deriving(Encodable, PartialEq, Eq, Clone)] -pub struct LogicalMargin<T> { - pub block_start: T, - pub inline_end: T, - pub block_end: T, - pub inline_start: T, - debug_writing_mode: DebugWritingMode, -} - -impl<T: Show> Show for LogicalMargin<T> { - fn fmt(&self, formatter: &mut Formatter) -> Result<(), FormatError> { - write!(formatter, - "LogicalMargin[{}, block_start: {}, inline_end: {}, \ - block_end: {}, inline_start: {}]", - self.debug_writing_mode, self.block_start, - self.inline_end, self.block_end, self.inline_start) - } -} - -impl<T: Zero> LogicalMargin<T> { - #[inline] - pub fn zero(mode: WritingMode) -> LogicalMargin<T> { - LogicalMargin { - block_start: Zero::zero(), - inline_end: Zero::zero(), - block_end: Zero::zero(), - inline_start: Zero::zero(), - debug_writing_mode: DebugWritingMode::new(mode), - } - } - - #[inline] - pub fn is_zero(&self) -> bool { - self.block_start.is_zero() && - self.inline_end.is_zero() && - self.block_end.is_zero() && - self.inline_start.is_zero() - } -} - -impl<T: Copy> LogicalMargin<T> { - #[inline] - pub fn new(mode: WritingMode, block_start: T, inline_end: T, block_end: T, inline_start: T) - -> LogicalMargin<T> { - LogicalMargin { - block_start: block_start, - inline_end: inline_end, - block_end: block_end, - inline_start: inline_start, - debug_writing_mode: DebugWritingMode::new(mode), - } - } - - #[inline] - pub fn new_all_same(mode: WritingMode, value: T) -> LogicalMargin<T> { - LogicalMargin::new(mode, value, value, value, value) - } - - #[inline] - pub fn from_physical(mode: WritingMode, offsets: SideOffsets2D<T>) -> LogicalMargin<T> { - let block_start; - let inline_end; - let block_end; - let inline_start; - if mode.is_vertical() { - if mode.is_vertical_lr() { - block_start = offsets.left; - block_end = offsets.right; - } else { - block_start = offsets.right; - block_end = offsets.left; - } - if mode.is_inline_tb() { - inline_start = offsets.top; - inline_end = offsets.bottom; - } else { - inline_start = offsets.bottom; - inline_end = offsets.top; - } - } else { - block_start = offsets.top; - block_end = offsets.bottom; - if mode.is_bidi_ltr() { - inline_start = offsets.left; - inline_end = offsets.right; - } else { - inline_start = offsets.right; - inline_end = offsets.left; - } - } - LogicalMargin::new(mode, block_start, inline_end, block_end, inline_start) - } - - #[inline] - pub fn top(&self, mode: WritingMode) -> T { - self.debug_writing_mode.check(mode); - if mode.is_vertical() { - if mode.is_inline_tb() { self.inline_start } else { self.inline_end } - } else { - self.block_start - } - } - - #[inline] - pub fn set_top(&mut self, mode: WritingMode, top: T) { - self.debug_writing_mode.check(mode); - if mode.is_vertical() { - if mode.is_inline_tb() { self.inline_start = top } else { self.inline_end = top } - } else { - self.block_start = top - } - } - - #[inline] - pub fn right(&self, mode: WritingMode) -> T { - self.debug_writing_mode.check(mode); - if mode.is_vertical() { - if mode.is_vertical_lr() { self.block_end } else { self.block_start } - } else { - if mode.is_bidi_ltr() { self.inline_end } else { self.inline_start } - } - } - - #[inline] - pub fn set_right(&mut self, mode: WritingMode, right: T) { - self.debug_writing_mode.check(mode); - if mode.is_vertical() { - if mode.is_vertical_lr() { self.block_end = right } else { self.block_start = right } - } else { - if mode.is_bidi_ltr() { self.inline_end = right } else { self.inline_start = right } - } - } - - #[inline] - pub fn bottom(&self, mode: WritingMode) -> T { - self.debug_writing_mode.check(mode); - if mode.is_vertical() { - if mode.is_inline_tb() { self.inline_end } else { self.inline_start } - } else { - self.block_end - } - } - - #[inline] - pub fn set_bottom(&mut self, mode: WritingMode, bottom: T) { - self.debug_writing_mode.check(mode); - if mode.is_vertical() { - if mode.is_inline_tb() { self.inline_end = bottom } else { self.inline_start = bottom } - } else { - self.block_end = bottom - } - } - - #[inline] - pub fn left(&self, mode: WritingMode) -> T { - self.debug_writing_mode.check(mode); - if mode.is_vertical() { - if mode.is_vertical_lr() { self.block_start } else { self.block_end } - } else { - if mode.is_bidi_ltr() { self.inline_start } else { self.inline_end } - } - } - - #[inline] - pub fn set_left(&mut self, mode: WritingMode, left: T) { - self.debug_writing_mode.check(mode); - if mode.is_vertical() { - if mode.is_vertical_lr() { self.block_start = left } else { self.block_end = left } - } else { - if mode.is_bidi_ltr() { self.inline_start = left } else { self.inline_end = left } - } - } - - #[inline] - pub fn to_physical(&self, mode: WritingMode) -> SideOffsets2D<T> { - self.debug_writing_mode.check(mode); - let top; - let right; - let bottom; - let left; - if mode.is_vertical() { - if mode.is_vertical_lr() { - left = self.block_start; - right = self.block_end; - } else { - right = self.block_start; - left = self.block_end; - } - if mode.is_inline_tb() { - top = self.inline_start; - bottom = self.inline_end; - } else { - bottom = self.inline_start; - top = self.inline_end; - } - } else { - top = self.block_start; - bottom = self.block_end; - if mode.is_bidi_ltr() { - left = self.inline_start; - right = self.inline_end; - } else { - right = self.inline_start; - left = self.inline_end; - } - } - SideOffsets2D::new(top, right, bottom, left) - } - - #[inline] - pub fn convert(&self, mode_from: WritingMode, mode_to: WritingMode) -> LogicalMargin<T> { - if mode_from == mode_to { - self.debug_writing_mode.check(mode_from); - *self - } else { - LogicalMargin::from_physical(mode_to, self.to_physical(mode_from)) - } - } -} - -impl<T: Add<T, T>> LogicalMargin<T> { - #[inline] - pub fn inline_start_end(&self) -> T { - self.inline_start + self.inline_end - } - - #[inline] - pub fn block_start_end(&self) -> T { - self.block_start + self.block_end - } - - #[inline] - pub fn top_bottom(&self, mode: WritingMode) -> T { - self.debug_writing_mode.check(mode); - if mode.is_vertical() { - self.inline_start_end() - } else { - self.block_start_end() - } - } - - #[inline] - pub fn left_right(&self, mode: WritingMode) -> T { - self.debug_writing_mode.check(mode); - if mode.is_vertical() { - self.block_start_end() - } else { - self.inline_start_end() - } - } -} - -impl<T: Add<T, T>> Add<LogicalMargin<T>, LogicalMargin<T>> for LogicalMargin<T> { - #[inline] - fn add(&self, other: &LogicalMargin<T>) -> LogicalMargin<T> { - self.debug_writing_mode.check_debug(other.debug_writing_mode); - LogicalMargin { - debug_writing_mode: self.debug_writing_mode, - block_start: self.block_start + other.block_start, - inline_end: self.inline_end + other.inline_end, - block_end: self.block_end + other.block_end, - inline_start: self.inline_start + other.inline_start, - } - } -} - -impl<T: Sub<T, T>> Sub<LogicalMargin<T>, LogicalMargin<T>> for LogicalMargin<T> { - #[inline] - fn sub(&self, other: &LogicalMargin<T>) -> LogicalMargin<T> { - self.debug_writing_mode.check_debug(other.debug_writing_mode); - LogicalMargin { - debug_writing_mode: self.debug_writing_mode, - block_start: self.block_start - other.block_start, - inline_end: self.inline_end - other.inline_end, - block_end: self.block_end - other.block_end, - inline_start: self.inline_start - other.inline_start, - } - } -} - - -/// A rectangle in flow-relative dimensions -#[deriving(Encodable, PartialEq, Eq, Clone)] -pub struct LogicalRect<T> { - pub start: LogicalPoint<T>, - pub size: LogicalSize<T>, - debug_writing_mode: DebugWritingMode, -} - -impl<T: Show> Show for LogicalRect<T> { - fn fmt(&self, formatter: &mut Formatter) -> Result<(), FormatError> { - write!(formatter, - "LogicalRect[{}, inline_start: {}, block_start: {}, \ - inline: {}, block: {}]", - self.debug_writing_mode, self.start.i, self.start.b, - self.size.inline, self.size.block) - } -} - -impl<T: Zero> LogicalRect<T> { - #[inline] - pub fn zero(mode: WritingMode) -> LogicalRect<T> { - LogicalRect { - start: LogicalPoint::zero(mode), - size: LogicalSize::zero(mode), - debug_writing_mode: DebugWritingMode::new(mode), - } - } - - #[inline] - pub fn is_zero(&self) -> bool { - self.start.is_zero() && self.size.is_zero() - } -} - -impl<T: Copy> LogicalRect<T> { - #[inline] - pub fn new(mode: WritingMode, inline_start: T, block_start: T, inline: T, block: T) - -> LogicalRect<T> { - LogicalRect { - start: LogicalPoint::new(mode, inline_start, block_start), - size: LogicalSize::new(mode, inline, block), - debug_writing_mode: DebugWritingMode::new(mode), - } - } - - #[inline] - pub fn from_point_size(mode: WritingMode, start: LogicalPoint<T>, size: LogicalSize<T>) - -> LogicalRect<T> { - start.debug_writing_mode.check(mode); - size.debug_writing_mode.check(mode); - LogicalRect { - start: start, - size: size, - debug_writing_mode: DebugWritingMode::new(mode), - } - } -} - -impl<T: Copy + Add<T, T> + Sub<T, T>> LogicalRect<T> { - #[inline] - pub fn from_physical(mode: WritingMode, rect: Rect<T>, container_size: Size2D<T>) - -> LogicalRect<T> { - let inline_start; - let block_start; - let inline; - let block; - if mode.is_vertical() { - inline = rect.size.height; - block = rect.size.width; - if mode.is_vertical_lr() { - block_start = rect.origin.x; - } else { - block_start = container_size.width - (rect.origin.x + rect.size.width); - } - if mode.is_inline_tb() { - inline_start = rect.origin.y; - } else { - inline_start = container_size.height - (rect.origin.y + rect.size.height); - } - } else { - inline = rect.size.width; - block = rect.size.height; - block_start = rect.origin.y; - if mode.is_bidi_ltr() { - inline_start = rect.origin.x; - } else { - inline_start = container_size.width - (rect.origin.x + rect.size.width); - } - } - LogicalRect { - start: LogicalPoint::new(mode, inline_start, block_start), - size: LogicalSize::new(mode, inline, block), - debug_writing_mode: DebugWritingMode::new(mode), - } - } - - #[inline] - pub fn inline_end(&self) -> T { - self.start.i + self.size.inline - } - - #[inline] - pub fn block_end(&self) -> T { - self.start.b + self.size.block - } - - #[inline] - pub fn to_physical(&self, mode: WritingMode, container_size: Size2D<T>) -> Rect<T> { - self.debug_writing_mode.check(mode); - let x; - let y; - let width; - let height; - if mode.is_vertical() { - width = self.size.block; - height = self.size.inline; - if mode.is_vertical_lr() { - x = self.start.b; - } else { - x = container_size.width - self.block_end(); - } - if mode.is_inline_tb() { - y = self.start.i; - } else { - y = container_size.height - self.inline_end(); - } - } else { - width = self.size.inline; - height = self.size.block; - y = self.start.b; - if mode.is_bidi_ltr() { - x = self.start.i; - } else { - x = container_size.width - self.inline_end(); - } - } - Rect { - origin: Point2D { x: x, y: y }, - size: Size2D { width: width, height: height }, - } - } - - #[inline] - pub fn convert(&self, mode_from: WritingMode, mode_to: WritingMode, container_size: Size2D<T>) - -> LogicalRect<T> { - if mode_from == mode_to { - self.debug_writing_mode.check(mode_from); - *self - } else { - LogicalRect::from_physical( - mode_to, self.to_physical(mode_from, container_size), container_size) - } - } - - pub fn translate(&self, offset: &LogicalPoint<T>) -> LogicalRect<T> { - LogicalRect { - start: self.start + LogicalSize { - inline: offset.i, - block: offset.b, - debug_writing_mode: offset.debug_writing_mode, - }, - size: self.size, - debug_writing_mode: self.debug_writing_mode, - } - } -} - -impl<T: Copy + Ord + Add<T, T> + Sub<T, T>> LogicalRect<T> { - #[inline] - pub fn union(&self, other: &LogicalRect<T>) -> LogicalRect<T> { - self.debug_writing_mode.check_debug(other.debug_writing_mode); - - let inline_start = min(self.start.i, other.start.i); - let block_start = min(self.start.b, other.start.b); - LogicalRect { - start: LogicalPoint { - i: inline_start, - b: block_start, - debug_writing_mode: self.debug_writing_mode, - }, - size: LogicalSize { - inline: max(self.inline_end(), other.inline_end()) - inline_start, - block: max(self.block_end(), other.block_end()) - block_start, - debug_writing_mode: self.debug_writing_mode, - }, - debug_writing_mode: self.debug_writing_mode, - } - } -} - -impl<T: Add<T, T> + Sub<T, T>> Add<LogicalMargin<T>, LogicalRect<T>> for LogicalRect<T> { - #[inline] - fn add(&self, other: &LogicalMargin<T>) -> LogicalRect<T> { - self.debug_writing_mode.check_debug(other.debug_writing_mode); - LogicalRect { - start: LogicalPoint { - // Growing a rectangle on the start side means pushing its - // start point on the negative direction. - i: self.start.i - other.inline_start, - b: self.start.b - other.block_start, - debug_writing_mode: self.debug_writing_mode, - }, - size: LogicalSize { - inline: self.size.inline + other.inline_start_end(), - block: self.size.block + other.block_start_end(), - debug_writing_mode: self.debug_writing_mode, - }, - debug_writing_mode: self.debug_writing_mode, - } - } -} - - -impl<T: Add<T, T> + Sub<T, T>> Sub<LogicalMargin<T>, LogicalRect<T>> for LogicalRect<T> { - #[inline] - fn sub(&self, other: &LogicalMargin<T>) -> LogicalRect<T> { - self.debug_writing_mode.check_debug(other.debug_writing_mode); - LogicalRect { - start: LogicalPoint { - // Shrinking a rectangle on the start side means pushing its - // start point on the positive direction. - i: self.start.i + other.inline_start, - b: self.start.b + other.block_start, - debug_writing_mode: self.debug_writing_mode, - }, - size: LogicalSize { - inline: self.size.inline - other.inline_start_end(), - block: self.size.block - other.block_start_end(), - debug_writing_mode: self.debug_writing_mode, - }, - debug_writing_mode: self.debug_writing_mode, - } - } -} - -#[cfg(test)] -fn modes() -> [WritingMode, ..10] { - [ - WritingMode::empty(), - FlagVertical, - FlagVertical | FlagVerticalLR, - FlagVertical | FlagVerticalLR | FlagSidewaysLeft, - FlagVertical | FlagSidewaysLeft, - FlagRTL, - FlagVertical | FlagRTL, - FlagVertical | FlagVerticalLR | FlagRTL, - FlagVertical | FlagVerticalLR | FlagSidewaysLeft | FlagRTL, - FlagVertical | FlagSidewaysLeft | FlagRTL, - ] -} - -#[test] -fn test_size_round_trip() { - let physical = Size2D(1u32, 2u32); - for &mode in modes().iter() { - let logical = LogicalSize::from_physical(mode, physical); - assert!(logical.to_physical(mode) == physical); - assert!(logical.width(mode) == 1); - assert!(logical.height(mode) == 2); - } -} - -#[test] -fn test_point_round_trip() { - let physical = Point2D(1u32, 2u32); - let container = Size2D(100, 200); - for &mode in modes().iter() { - let logical = LogicalPoint::from_physical(mode, physical, container); - assert!(logical.to_physical(mode, container) == physical); - assert!(logical.x(mode, container) == 1); - assert!(logical.y(mode, container) == 2); - } -} - -#[test] -fn test_margin_round_trip() { - let physical = SideOffsets2D::new(1u32, 2u32, 3u32, 4u32); - for &mode in modes().iter() { - let logical = LogicalMargin::from_physical(mode, physical); - assert!(logical.to_physical(mode) == physical); - assert!(logical.top(mode) == 1); - assert!(logical.right(mode) == 2); - assert!(logical.bottom(mode) == 3); - assert!(logical.left(mode) == 4); - } -} - -#[test] -fn test_rect_round_trip() { - let physical = Rect(Point2D(1u32, 2u32), Size2D(3u32, 4u32)); - let container = Size2D(100, 200); - for &mode in modes().iter() { - let logical = LogicalRect::from_physical(mode, physical, container); - assert!(logical.to_physical(mode, container) == physical); - } -} |