mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
Refactor size module ♻
This commit is contained in:
parent
e7277fec23
commit
3c0496bb61
@ -1,5 +1,4 @@
|
|||||||
use smallvec::smallvec;
|
use smallvec::smallvec;
|
||||||
use crate::size::max;
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
/// The stack layouter stack boxes onto each other along the secondary layouting
|
/// The stack layouter stack boxes onto each other along the secondary layouting
|
||||||
@ -183,10 +182,11 @@ impl StackLayouter {
|
|||||||
let mut size = self.space.size.generalized(axes);
|
let mut size = self.space.size.generalized(axes);
|
||||||
let mut extra = self.space.extra.generalized(axes);
|
let mut extra = self.space.extra.generalized(axes);
|
||||||
|
|
||||||
size.x += max(dimensions.x - extra.x, Size::ZERO);
|
size.x += (dimensions.x - extra.x).max(Size::ZERO);
|
||||||
size.y += max(dimensions.y - extra.y, Size::ZERO);
|
size.y += (dimensions.y - extra.y).max(Size::ZERO);
|
||||||
extra.x = max(extra.x, dimensions.x);
|
|
||||||
extra.y = max(extra.y - dimensions.y, Size::ZERO);
|
extra.x.max_eq(dimensions.x);
|
||||||
|
extra.y = (extra.y - dimensions.y).max(Size::ZERO);
|
||||||
|
|
||||||
self.space.size = size.specialized(axes);
|
self.space.size = size.specialized(axes);
|
||||||
self.space.extra = extra.specialized(axes);
|
self.space.extra = extra.specialized(axes);
|
||||||
@ -304,7 +304,7 @@ impl StackLayouter {
|
|||||||
// layout uses up space from the origin to the end. Thus, it reduces
|
// layout uses up space from the origin to the end. Thus, it reduces
|
||||||
// the usable space for following layouts at it's origin by its
|
// the usable space for following layouts at it's origin by its
|
||||||
// extent along the secondary axis.
|
// extent along the secondary axis.
|
||||||
*bound.secondary_origin_mut(*axes)
|
*bound.get_mut(*axes, GenericAxisKind::Secondary, Alignment::Origin)
|
||||||
+= axes.secondary.factor() * layout.dimensions.secondary(*axes);
|
+= axes.secondary.factor() * layout.dimensions.secondary(*axes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,7 +334,8 @@ impl StackLayouter {
|
|||||||
// We reduce the bounding box of this layout at it's end by the
|
// We reduce the bounding box of this layout at it's end by the
|
||||||
// accumulated secondary extent of all layouts we have seen so far,
|
// accumulated secondary extent of all layouts we have seen so far,
|
||||||
// which are the layouts after this one since we iterate reversed.
|
// which are the layouts after this one since we iterate reversed.
|
||||||
*bound.secondary_end_mut(*axes) -= axes.secondary.factor() * extent.y;
|
*bound.get_mut(*axes, GenericAxisKind::Secondary, Alignment::End)
|
||||||
|
-= axes.secondary.factor() * extent.y;
|
||||||
|
|
||||||
// Then, we add this layout's secondary extent to the accumulator.
|
// Then, we add this layout's secondary extent to the accumulator.
|
||||||
let size = layout.dimensions.generalized(*axes);
|
let size = layout.dimensions.generalized(*axes);
|
||||||
|
720
src/size.rs
720
src/size.rs
@ -6,15 +6,95 @@ use std::iter::Sum;
|
|||||||
use std::ops::*;
|
use std::ops::*;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::layout::{LayoutAxes, LayoutAlignment, Axis, Alignment};
|
use crate::layout::{LayoutAxes, LayoutAlignment, Axis, GenericAxisKind, Alignment};
|
||||||
|
|
||||||
/// A general space type.
|
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
/// A general spacing type.
|
||||||
|
#[derive(Copy, Clone, PartialEq, PartialOrd)]
|
||||||
pub struct Size {
|
pub struct Size {
|
||||||
/// The size in typographic points (1/72 inches).
|
/// The size in typographic points (1/72 inches).
|
||||||
points: f32,
|
points: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Size {
|
||||||
|
/// The zeroed size.
|
||||||
|
pub const ZERO: Size = Size { points: 0.0 };
|
||||||
|
|
||||||
|
/// Create a size from an amount of points.
|
||||||
|
pub fn pt(points: f32) -> Size { Size { points } }
|
||||||
|
|
||||||
|
/// Create a size from an amount of millimeters.
|
||||||
|
pub fn mm(mm: f32) -> Size { Size { points: 2.83465 * mm } }
|
||||||
|
|
||||||
|
/// Create a size from an amount of centimeters.
|
||||||
|
pub fn cm(cm: f32) -> Size { Size { points: 28.3465 * cm } }
|
||||||
|
|
||||||
|
/// Create a size from an amount of inches.
|
||||||
|
pub fn inches(inches: f32) -> Size { Size { points: 72.0 * inches } }
|
||||||
|
|
||||||
|
/// Convert this size into points.
|
||||||
|
pub fn to_pt(self) -> f32 { self.points }
|
||||||
|
|
||||||
|
/// Convert this size into millimeters.
|
||||||
|
pub fn to_mm(self) -> f32 { self.points * 0.352778 }
|
||||||
|
|
||||||
|
/// Convert this size into centimeters.
|
||||||
|
pub fn to_cm(self) -> f32 { self.points * 0.0352778 }
|
||||||
|
|
||||||
|
/// Convert this size into inches.
|
||||||
|
pub fn to_inches(self) -> f32 { self.points * 0.0138889 }
|
||||||
|
|
||||||
|
/// The maximum of this and the other size.
|
||||||
|
pub fn max(self, other: Size) -> Size {
|
||||||
|
if self > other { self } else { other }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The minimum of this and the other size.
|
||||||
|
pub fn min(self, other: Size) -> Size {
|
||||||
|
if self <= other { self } else { other }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set this size to the maximum of itself and the other size.
|
||||||
|
pub fn max_eq(&mut self, other: Size) { *self = self.max(other); }
|
||||||
|
|
||||||
|
/// Set this size to the minimum of itself and the other size.
|
||||||
|
pub fn min_eq(&mut self, other: Size) { *self = self.min(other); }
|
||||||
|
|
||||||
|
/// The anchor position along the given axis for an item with the given
|
||||||
|
/// alignment in a container with this size.
|
||||||
|
pub fn anchor(self, alignment: Alignment, axis: Axis) -> Size {
|
||||||
|
use Alignment::*;
|
||||||
|
match (axis.is_positive(), alignment) {
|
||||||
|
(true, Origin) | (false, End) => Size::ZERO,
|
||||||
|
(_, Center) => self / 2,
|
||||||
|
(true, End) | (false, Origin) => self,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Size {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{}cm", self.to_cm())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_display!(Size);
|
||||||
|
|
||||||
|
impl Neg for Size {
|
||||||
|
type Output = Size;
|
||||||
|
|
||||||
|
fn neg(self) -> Size {
|
||||||
|
Size { points: -self.points }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sum for Size {
|
||||||
|
fn sum<I>(iter: I) -> Size
|
||||||
|
where I: Iterator<Item = Size> {
|
||||||
|
iter.fold(Size::ZERO, Add::add)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A position or extent in 2-dimensional space.
|
/// A position or extent in 2-dimensional space.
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
pub struct Size2D {
|
pub struct Size2D {
|
||||||
@ -24,6 +104,115 @@ pub struct Size2D {
|
|||||||
pub y: Size,
|
pub y: Size,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Size2D {
|
||||||
|
/// The zeroed 2D-size.
|
||||||
|
pub const ZERO: Size2D = Size2D { x: Size::ZERO, y: Size::ZERO };
|
||||||
|
|
||||||
|
/// Create a new 2D-size from two sizes.
|
||||||
|
pub fn new(x: Size, y: Size) -> Size2D { Size2D { x, y } }
|
||||||
|
|
||||||
|
/// Create a new 2D-size with `x` set to a value and `y` zero.
|
||||||
|
pub fn with_x(x: Size) -> Size2D { Size2D { x, y: Size::ZERO } }
|
||||||
|
|
||||||
|
/// Create a new 2D-size with `y` set to a value and `x` zero.
|
||||||
|
pub fn with_y(y: Size) -> Size2D { Size2D { x: Size::ZERO, y } }
|
||||||
|
|
||||||
|
/// Create a 2D-size with `x` and `y` set to the same value `s`.
|
||||||
|
pub fn with_all(s: Size) -> Size2D { Size2D { x: s, y: s } }
|
||||||
|
|
||||||
|
/// Access the primary size of this specialized 2D-size.
|
||||||
|
pub fn primary(self, axes: LayoutAxes) -> Size {
|
||||||
|
if axes.primary.is_horizontal() { self.x } else { self.y }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Access the primary size of this specialized 2D-size mutably.
|
||||||
|
pub fn primary_mut(&mut self, axes: LayoutAxes) -> &mut Size {
|
||||||
|
if axes.primary.is_horizontal() { &mut self.x } else { &mut self.y }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Access the secondary size of this specialized 2D-size.
|
||||||
|
pub fn secondary(self, axes: LayoutAxes) -> Size {
|
||||||
|
if axes.primary.is_horizontal() { self.y } else { self.x }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Access the secondary size of this specialized 2D-size mutably.
|
||||||
|
pub fn secondary_mut(&mut self, axes: LayoutAxes) -> &mut Size {
|
||||||
|
if axes.primary.is_horizontal() { &mut self.y } else { &mut self.x }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the generalized version of a `Size2D` dependent on the layouting
|
||||||
|
/// axes, that is:
|
||||||
|
/// - `x` describes the primary axis instead of the horizontal one.
|
||||||
|
/// - `y` describes the secondary axis instead of the vertical one.
|
||||||
|
pub fn generalized(self, axes: LayoutAxes) -> Size2D {
|
||||||
|
match axes.primary.is_horizontal() {
|
||||||
|
true => self,
|
||||||
|
false => Size2D { x: self.y, y: self.x },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the specialized version of this generalized Size2D (inverse to
|
||||||
|
/// `generalized`).
|
||||||
|
pub fn specialized(self, axes: LayoutAxes) -> Size2D {
|
||||||
|
// In fact, generalized is its own inverse. For reasons of clarity
|
||||||
|
// at the call site, we still have this second function.
|
||||||
|
self.generalized(axes)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether the given 2D-size fits into this one, that is, both coordinate
|
||||||
|
/// values are smaller or equal.
|
||||||
|
pub fn fits(self, other: Size2D) -> bool {
|
||||||
|
self.x >= other.x && self.y >= other.y
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a 2D-size padded by the paddings of the given box.
|
||||||
|
pub fn padded(self, padding: SizeBox) -> Size2D {
|
||||||
|
Size2D {
|
||||||
|
x: self.x + padding.left + padding.right,
|
||||||
|
y: self.y + padding.top + padding.bottom,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a 2D-size reduced by the paddings of the given box.
|
||||||
|
pub fn unpadded(self, padding: SizeBox) -> Size2D {
|
||||||
|
Size2D {
|
||||||
|
x: self.x - padding.left - padding.right,
|
||||||
|
y: self.y - padding.top - padding.bottom,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The anchor position along the given axis for an item with the given
|
||||||
|
/// alignment in a container with this size.
|
||||||
|
///
|
||||||
|
/// This assumes the size to be generalized such that `x` corresponds to the
|
||||||
|
/// primary axis.
|
||||||
|
pub fn anchor(self, alignment: LayoutAlignment, axes: LayoutAxes) -> Size2D {
|
||||||
|
Size2D {
|
||||||
|
x: self.x.anchor(alignment.primary, axes.primary),
|
||||||
|
y: self.y.anchor(alignment.secondary, axes.secondary),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Size2D {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
write!(f, "[{}, {}]", self.x, self.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_display!(Size2D);
|
||||||
|
|
||||||
|
impl Neg for Size2D {
|
||||||
|
type Output = Size2D;
|
||||||
|
|
||||||
|
fn neg(self) -> Size2D {
|
||||||
|
Size2D {
|
||||||
|
x: -self.x,
|
||||||
|
y: -self.y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A size in four directions.
|
/// A size in four directions.
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
pub struct SizeBox {
|
pub struct SizeBox {
|
||||||
@ -37,201 +226,6 @@ pub struct SizeBox {
|
|||||||
pub bottom: Size,
|
pub bottom: Size,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Either an absolute size or a factor of some metric.
|
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
|
||||||
pub enum ScaleSize {
|
|
||||||
Absolute(Size),
|
|
||||||
Scaled(f32),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A scale size that is scaled by the font size.
|
|
||||||
pub type FSize = ScaleSize;
|
|
||||||
|
|
||||||
/// A scale size that is scaled by the size of the padded parent container.
|
|
||||||
pub type PSize = ScaleSize;
|
|
||||||
|
|
||||||
impl Size {
|
|
||||||
/// The zeroed size.
|
|
||||||
pub const ZERO: Size = Size { points: 0.0 };
|
|
||||||
|
|
||||||
/// Create a zeroed size.
|
|
||||||
pub fn zero() -> Size { Size::ZERO }
|
|
||||||
|
|
||||||
/// Create a size from an amount of points.
|
|
||||||
pub fn pt(points: f32) -> Size { Size { points } }
|
|
||||||
|
|
||||||
/// Create a size from an amount of millimeters.
|
|
||||||
pub fn mm(mm: f32) -> Size { Size { points: 2.83465 * mm } }
|
|
||||||
|
|
||||||
/// Create a size from an amount of centimeters.
|
|
||||||
pub fn cm(cm: f32) -> Size { Size { points: 28.3465 * cm } }
|
|
||||||
|
|
||||||
/// Create a size from an amount of inches.
|
|
||||||
pub fn inches(inches: f32) -> Size { Size { points: 72.0 * inches } }
|
|
||||||
|
|
||||||
/// Convert this size into points.
|
|
||||||
pub fn to_pt(&self) -> f32 { self.points }
|
|
||||||
|
|
||||||
/// Convert this size into millimeters.
|
|
||||||
pub fn to_mm(&self) -> f32 { self.points * 0.352778 }
|
|
||||||
|
|
||||||
/// Convert this size into centimeters.
|
|
||||||
pub fn to_cm(&self) -> f32 { self.points * 0.0352778 }
|
|
||||||
|
|
||||||
/// Convert this size into inches.
|
|
||||||
pub fn to_inches(&self) -> f32 { self.points * 0.0138889 }
|
|
||||||
|
|
||||||
/// Set this size to the maximum of itself and the other size.
|
|
||||||
pub fn max_eq(&mut self, other: Size) {
|
|
||||||
*self = max(*self, other);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set this size to the minimum of itself and the other size.
|
|
||||||
pub fn min_eq(&mut self, other: Size) {
|
|
||||||
*self = min(*self, other);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The anchor position along the given axis for an item with the given
|
|
||||||
/// alignment in a container with this size.
|
|
||||||
pub fn anchor(&self, alignment: Alignment, axis: Axis) -> Size {
|
|
||||||
use Alignment::*;
|
|
||||||
match (axis.is_positive(), alignment) {
|
|
||||||
(true, Origin) | (false, End) => Size::ZERO,
|
|
||||||
(_, Center) => *self / 2,
|
|
||||||
(true, End) | (false, Origin) => *self,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Size2D {
|
|
||||||
/// The zeroed 2D-size.
|
|
||||||
pub const ZERO: Size2D = Size2D { x: Size::ZERO, y: Size::ZERO };
|
|
||||||
|
|
||||||
/// Create a new 2D-size from two sizes.
|
|
||||||
pub fn new(x: Size, y: Size) -> Size2D {
|
|
||||||
Size2D { x, y }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a 2D-size with both sizes set to zero.
|
|
||||||
pub fn zero() -> Size2D {
|
|
||||||
Size2D::ZERO
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a 2D-size with `x` and `y` set to the same value `s`.
|
|
||||||
pub fn with_all(s: Size) -> Size2D {
|
|
||||||
Size2D { x: s, y: s }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a new 2D-size with `x` set to a value and `y` zero.
|
|
||||||
pub fn with_x(x: Size) -> Size2D {
|
|
||||||
Size2D { x, y: Size::ZERO }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a new 2D-size with `y` set to a value and `x` zero.
|
|
||||||
pub fn with_y(y: Size) -> Size2D {
|
|
||||||
Size2D { x: Size::ZERO, y }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Access the primary size of this 2D-size.
|
|
||||||
pub fn primary(&self, axes: LayoutAxes) -> Size {
|
|
||||||
match axes.primary.is_horizontal() {
|
|
||||||
true => self.x,
|
|
||||||
false => self.y,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Access the secondary size of this 2D-size.
|
|
||||||
pub fn secondary(&self, axes: LayoutAxes) -> Size {
|
|
||||||
match axes.primary.is_horizontal() {
|
|
||||||
true => self.y,
|
|
||||||
false => self.x,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Access the primary size of this 2D-size.
|
|
||||||
pub fn primary_mut(&mut self, axes: LayoutAxes) -> &mut Size {
|
|
||||||
match axes.primary.is_horizontal() {
|
|
||||||
true => &mut self.x,
|
|
||||||
false => &mut self.y,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Access the secondary size of this 2D-size.
|
|
||||||
pub fn secondary_mut(&mut self, axes: LayoutAxes) -> &mut Size {
|
|
||||||
match axes.primary.is_horizontal() {
|
|
||||||
true => &mut self.y,
|
|
||||||
false => &mut self.x,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the generalized version of a `Size2D` dependent on
|
|
||||||
/// the layouting axes, that is:
|
|
||||||
/// - The x coordinate describes the primary axis instead of the horizontal one.
|
|
||||||
/// - The y coordinate describes the secondary axis instead of the vertical one.
|
|
||||||
pub fn generalized(&self, axes: LayoutAxes) -> Size2D {
|
|
||||||
match axes.primary.is_horizontal() {
|
|
||||||
true => *self,
|
|
||||||
false => Size2D { x: self.y, y: self.x },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the specialized version of this generalized Size2D.
|
|
||||||
/// (Inverse to `generalized`).
|
|
||||||
pub fn specialized(&self, axes: LayoutAxes) -> Size2D {
|
|
||||||
// In fact, generalized is its own inverse. For reasons of clarity
|
|
||||||
// at the call site, we still have this second function.
|
|
||||||
self.generalized(axes)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a 2D-size padded by the paddings of the given box.
|
|
||||||
pub fn padded(&self, padding: SizeBox) -> Size2D {
|
|
||||||
Size2D {
|
|
||||||
x: self.x + padding.left + padding.right,
|
|
||||||
y: self.y + padding.top + padding.bottom,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a 2D-size reduced by the paddings of the given box.
|
|
||||||
pub fn unpadded(&self, padding: SizeBox) -> Size2D {
|
|
||||||
Size2D {
|
|
||||||
x: self.x - padding.left - padding.right,
|
|
||||||
y: self.y - padding.top - padding.bottom,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether the given 2D-size fits into this one, that is,
|
|
||||||
/// both coordinate values are smaller or equal.
|
|
||||||
pub fn fits(&self, other: Size2D) -> bool {
|
|
||||||
self.x >= other.x && self.y >= other.y
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set this size to the maximum of itself and the other size
|
|
||||||
/// (for both dimensions).
|
|
||||||
pub fn max_eq(&mut self, other: Size2D) {
|
|
||||||
self.x.max_eq(other.x);
|
|
||||||
self.y.max_eq(other.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set this size to the minimum of itself and the other size
|
|
||||||
/// (for both dimensions).
|
|
||||||
pub fn min_eq(&mut self, other: Size2D) {
|
|
||||||
self.x.min_eq(other.x);
|
|
||||||
self.y.min_eq(other.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The anchor position along the given axis for an item with the given
|
|
||||||
/// alignment in a container with this size.
|
|
||||||
///
|
|
||||||
/// This assumes the size to be generalized such that `x` corresponds to the
|
|
||||||
/// primary axis.
|
|
||||||
pub fn anchor(&self, alignment: LayoutAlignment, axes: LayoutAxes) -> Size2D {
|
|
||||||
Size2D {
|
|
||||||
x: self.x.anchor(alignment.primary, axes.primary),
|
|
||||||
y: self.y.anchor(alignment.secondary, axes.secondary),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SizeBox {
|
impl SizeBox {
|
||||||
/// The zeroed size box.
|
/// The zeroed size box.
|
||||||
pub const ZERO: SizeBox = SizeBox {
|
pub const ZERO: SizeBox = SizeBox {
|
||||||
@ -243,17 +237,7 @@ impl SizeBox {
|
|||||||
|
|
||||||
/// Create a new box from four sizes.
|
/// Create a new box from four sizes.
|
||||||
pub fn new(left: Size, top: Size, right: Size, bottom: Size) -> SizeBox {
|
pub fn new(left: Size, top: Size, right: Size, bottom: Size) -> SizeBox {
|
||||||
SizeBox {
|
SizeBox { left, top, right, bottom }
|
||||||
left,
|
|
||||||
top,
|
|
||||||
right,
|
|
||||||
bottom,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a box with all values set to zero.
|
|
||||||
pub fn zero() -> SizeBox {
|
|
||||||
SizeBox::ZERO
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a box with all four fields set to the same value `s`.
|
/// Create a box with all four fields set to the same value `s`.
|
||||||
@ -261,9 +245,20 @@ impl SizeBox {
|
|||||||
SizeBox { left: value, top: value, right: value, bottom: value }
|
SizeBox { left: value, top: value, right: value, bottom: value }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access the origin direction on the secondary axis of this box.
|
/// Get a mutable reference to the value for the specified axis and
|
||||||
pub fn secondary_origin_mut(&mut self, axes: LayoutAxes) -> &mut Size {
|
/// alignment. Center alignment will be treated the same as origin
|
||||||
match axes.secondary {
|
/// alignment.
|
||||||
|
pub fn get_mut(&mut self,
|
||||||
|
axes: LayoutAxes,
|
||||||
|
axis: GenericAxisKind,
|
||||||
|
alignment: Alignment,
|
||||||
|
) -> &mut Size {
|
||||||
|
let mut normalized = axes.generic(axis);
|
||||||
|
if alignment == Alignment::End {
|
||||||
|
normalized = normalized.inv();
|
||||||
|
}
|
||||||
|
|
||||||
|
match normalized {
|
||||||
Axis::LeftToRight => &mut self.left,
|
Axis::LeftToRight => &mut self.left,
|
||||||
Axis::RightToLeft => &mut self.right,
|
Axis::RightToLeft => &mut self.right,
|
||||||
Axis::TopToBottom => &mut self.top,
|
Axis::TopToBottom => &mut self.top,
|
||||||
@ -271,16 +266,6 @@ impl SizeBox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access the end direction on the secondary axis of this box.
|
|
||||||
pub fn secondary_end_mut(&mut self, axes: LayoutAxes) -> &mut Size {
|
|
||||||
match axes.secondary {
|
|
||||||
Axis::LeftToRight => &mut self.right,
|
|
||||||
Axis::RightToLeft => &mut self.left,
|
|
||||||
Axis::TopToBottom => &mut self.bottom,
|
|
||||||
Axis::BottomToTop => &mut self.top,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the `left` and `right` values.
|
/// Set the `left` and `right` values.
|
||||||
pub fn set_all(&mut self, value: Size) {
|
pub fn set_all(&mut self, value: Size) {
|
||||||
*self = SizeBox::with_all(value);
|
*self = SizeBox::with_all(value);
|
||||||
@ -299,6 +284,28 @@ impl SizeBox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for SizeBox {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
write!(f, "[left: {}, top: {}, right: {}, bottom: {}]",
|
||||||
|
self.left, self.top, self.right, self.bottom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_display!(SizeBox);
|
||||||
|
|
||||||
|
/// Either an absolute size or a factor of some metric.
|
||||||
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
|
pub enum ScaleSize {
|
||||||
|
Absolute(Size),
|
||||||
|
Scaled(f32),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A scale size that is scaled by the font size.
|
||||||
|
pub type FSize = ScaleSize;
|
||||||
|
|
||||||
|
/// A scale size that is scaled by the size of the padded parent container.
|
||||||
|
pub type PSize = ScaleSize;
|
||||||
|
|
||||||
impl ScaleSize {
|
impl ScaleSize {
|
||||||
/// Use the absolute value or scale the entity.
|
/// Use the absolute value or scale the entity.
|
||||||
pub fn concretize(&self, entity: Size) -> Size {
|
pub fn concretize(&self, entity: Size) -> Size {
|
||||||
@ -309,25 +316,16 @@ impl ScaleSize {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The maximum of two sizes.
|
impl Display for ScaleSize {
|
||||||
pub fn max(a: Size, b: Size) -> Size {
|
|
||||||
if a >= b { a } else { b }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The minimum of two sizes.
|
|
||||||
pub fn min(a: Size, b: Size) -> Size {
|
|
||||||
if a <= b { a } else { b }
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
impl Display for Size {
|
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
write!(f, "{}cm", self.to_cm())
|
match self {
|
||||||
|
ScaleSize::Absolute(size) => write!(f, "{}", size),
|
||||||
|
ScaleSize::Scaled(scale) => write!(f, "x{}", scale),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_display!(Size);
|
debug_display!(ScaleSize);
|
||||||
|
|
||||||
/// An error which can be returned when parsing a size.
|
/// An error which can be returned when parsing a size.
|
||||||
pub struct ParseSizeError;
|
pub struct ParseSizeError;
|
||||||
@ -359,193 +357,75 @@ impl FromStr for Size {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialOrd for Size {
|
macro_rules! implement_traits {
|
||||||
fn partial_cmp(&self, other: &Size) -> Option<Ordering> {
|
($ty:ident, $t:ident, $o:ident
|
||||||
self.points.partial_cmp(&other.points)
|
reflexive {$(
|
||||||
|
($tr:ident($tf:ident), $at:ident($af:ident), [$($f:ident),*])
|
||||||
|
)*}
|
||||||
|
numbers { $(($w:ident: $($rest:tt)*))* }
|
||||||
|
) => {
|
||||||
|
$(impl $tr for $ty {
|
||||||
|
type Output = $ty;
|
||||||
|
fn $tf($t, $o: $ty) -> $ty {
|
||||||
|
$ty { $($f: $tr::$tf($t.$f, $o.$f),)* }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl $at for $ty {
|
||||||
|
fn $af(&mut $t, $o: $ty) { $($at::$af(&mut $t.$f, $o.$f);)* }
|
||||||
|
})*
|
||||||
|
|
||||||
|
$(implement_traits!(@$w i32, $ty $t $o $($rest)*);)*
|
||||||
|
$(implement_traits!(@$w f32, $ty $t $o $($rest)*);)*
|
||||||
|
};
|
||||||
|
|
||||||
|
(@front $num:ty, $ty:ident $t:ident $o:ident
|
||||||
|
$tr:ident($tf:ident),
|
||||||
|
[$($f:ident),*]
|
||||||
|
) => {
|
||||||
|
impl $tr<$ty> for $num {
|
||||||
|
type Output = $ty;
|
||||||
|
fn $tf($t, $o: $ty) -> $ty {
|
||||||
|
$ty { $($f: $tr::$tf($t as f32, $o.$f),)* }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
(@back $num:ty, $ty:ident $t:ident $o:ident
|
||||||
|
$tr:ident($tf:ident), $at:ident($af:ident),
|
||||||
|
[$($f:ident),*]
|
||||||
|
) => {
|
||||||
|
impl $tr<$num> for $ty {
|
||||||
|
type Output = $ty;
|
||||||
|
fn $tf($t, $o: $num) -> $ty {
|
||||||
|
$ty { $($f: $tr::$tf($t.$f, $o as f32),)* }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl $at<$num> for $ty {
|
||||||
|
fn $af(&mut $t, $o: $num) { $($at::$af(&mut $t.$f, $o as f32);)* }
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Neg for Size {
|
macro_rules! implement_size {
|
||||||
type Output = Size;
|
($ty:ident($t:ident, $o:ident) [$($f:ident),*]) => {
|
||||||
|
implement_traits! {
|
||||||
|
$ty, $t, $o
|
||||||
|
|
||||||
fn neg(self) -> Size {
|
reflexive {
|
||||||
Size { points: -self.points }
|
(Add(add), AddAssign(add_assign), [$($f),*])
|
||||||
|
(Sub(sub), SubAssign(sub_assign), [$($f),*])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
numbers {
|
||||||
|
(front: Mul(mul), [$($f),*])
|
||||||
|
(back: Mul(mul), MulAssign(mul_assign), [$($f),*])
|
||||||
|
(back: Div(div), DivAssign(div_assign), [$($f),*])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sum for Size {
|
implement_size! { Size(self, other) [points] }
|
||||||
fn sum<I>(iter: I) -> Size
|
implement_size! { Size2D(self, other) [x, y] }
|
||||||
where I: Iterator<Item = Size> {
|
|
||||||
iter.fold(Size::ZERO, Add::add)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_reflexive {
|
|
||||||
($trait:ident, $func:ident, $assign_trait:ident, $assign_func:ident) => (
|
|
||||||
impl $trait for Size {
|
|
||||||
type Output = Size;
|
|
||||||
|
|
||||||
fn $func(self, other: Size) -> Size {
|
|
||||||
Size { points: $trait::$func(self.points, other.points) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $assign_trait for Size {
|
|
||||||
fn $assign_func(&mut self, other: Size) {
|
|
||||||
$assign_trait::$assign_func(&mut self.points, other.points);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_num_back {
|
|
||||||
($trait:ident, $func:ident, $assign_trait:ident, $assign_func:ident, $ty:ty) => (
|
|
||||||
impl $trait<$ty> for Size {
|
|
||||||
type Output = Size;
|
|
||||||
|
|
||||||
fn $func(self, other: $ty) -> Size {
|
|
||||||
Size { points: $trait::$func(self.points, other as f32) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $assign_trait<$ty> for Size {
|
|
||||||
fn $assign_func(&mut self, other: $ty) {
|
|
||||||
$assign_trait::$assign_func(&mut self.points, other as f32);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_num_both {
|
|
||||||
($trait:ident, $func:ident, $assign_trait:ident, $assign_func:ident, $ty:ty) => (
|
|
||||||
impl_num_back!($trait, $func, $assign_trait, $assign_func, $ty);
|
|
||||||
|
|
||||||
impl $trait<Size> for $ty {
|
|
||||||
type Output = Size;
|
|
||||||
|
|
||||||
fn $func(self, other: Size) -> Size {
|
|
||||||
Size { points: $trait::$func(self as f32, other.points) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_reflexive!(Add, add, AddAssign, add_assign);
|
|
||||||
impl_reflexive!(Sub, sub, SubAssign, sub_assign);
|
|
||||||
impl_num_both!(Mul, mul, MulAssign, mul_assign, f32);
|
|
||||||
impl_num_both!(Mul, mul, MulAssign, mul_assign, i32);
|
|
||||||
impl_num_back!(Div, div, DivAssign, div_assign, f32);
|
|
||||||
impl_num_back!(Div, div, DivAssign, div_assign, i32);
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
impl Display for Size2D {
|
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
||||||
write!(f, "[{}, {}]", self.x, self.y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug_display!(Size2D);
|
|
||||||
|
|
||||||
impl Neg for Size2D {
|
|
||||||
type Output = Size2D;
|
|
||||||
|
|
||||||
fn neg(self) -> Size2D {
|
|
||||||
Size2D {
|
|
||||||
x: -self.x,
|
|
||||||
y: -self.y,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_reflexive2d {
|
|
||||||
($trait:ident, $func:ident, $assign_trait:ident, $assign_func:ident) => (
|
|
||||||
impl $trait for Size2D {
|
|
||||||
type Output = Size2D;
|
|
||||||
|
|
||||||
fn $func(self, other: Size2D) -> Size2D {
|
|
||||||
Size2D {
|
|
||||||
x: $trait::$func(self.x, other.x),
|
|
||||||
y: $trait::$func(self.y, other.y),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $assign_trait for Size2D {
|
|
||||||
fn $assign_func(&mut self, other: Size2D) {
|
|
||||||
$assign_trait::$assign_func(&mut self.x, other.x);
|
|
||||||
$assign_trait::$assign_func(&mut self.y, other.y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_num_back2d {
|
|
||||||
($trait:ident, $func:ident, $assign_trait:ident, $assign_func:ident, $ty:ty) => (
|
|
||||||
impl $trait<$ty> for Size2D {
|
|
||||||
type Output = Size2D;
|
|
||||||
|
|
||||||
fn $func(self, other: $ty) -> Size2D {
|
|
||||||
Size2D {
|
|
||||||
x: $trait::$func(self.x, other as f32),
|
|
||||||
y: $trait::$func(self.y, other as f32),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $assign_trait<$ty> for Size2D {
|
|
||||||
fn $assign_func(&mut self, other: $ty) {
|
|
||||||
$assign_trait::$assign_func(&mut self.x, other as f32);
|
|
||||||
$assign_trait::$assign_func(&mut self.y, other as f32);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_num_both2d {
|
|
||||||
($trait:ident, $func:ident, $assign_trait:ident, $assign_func:ident, $ty:ty) => (
|
|
||||||
impl_num_back2d!($trait, $func, $assign_trait, $assign_func, $ty);
|
|
||||||
|
|
||||||
impl $trait<Size2D> for $ty {
|
|
||||||
type Output = Size2D;
|
|
||||||
|
|
||||||
fn $func(self, other: Size2D) -> Size2D {
|
|
||||||
Size2D {
|
|
||||||
x: $trait::$func(self as f32, other.x),
|
|
||||||
y: $trait::$func(self as f32, other.y),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_reflexive2d!(Add, add, AddAssign, add_assign);
|
|
||||||
impl_reflexive2d!(Sub, sub, SubAssign, sub_assign);
|
|
||||||
impl_num_both2d!(Mul, mul, MulAssign, mul_assign, f32);
|
|
||||||
impl_num_both2d!(Mul, mul, MulAssign, mul_assign, i32);
|
|
||||||
impl_num_back2d!(Div, div, DivAssign, div_assign, f32);
|
|
||||||
impl_num_back2d!(Div, div, DivAssign, div_assign, i32);
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
impl Display for SizeBox {
|
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
||||||
write!(f, "[left: {}, top: {}, right: {}, bottom: {}]",
|
|
||||||
self.left, self.top, self.right, self.bottom)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug_display!(SizeBox);
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
impl Display for ScaleSize {
|
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
ScaleSize::Absolute(size) => write!(f, "{}", size),
|
|
||||||
ScaleSize::Scaled(scale) => write!(f, "x{}", scale),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug_display!(ScaleSize);
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user