summaryrefslogtreecommitdiff
path: root/src/library/layout
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-10-28 16:43:38 +0200
committerLaurenz <laurmaedje@gmail.com>2022-10-28 16:43:38 +0200
commit95e9134a3c7d7a14d8c8928413fdffc665671895 (patch)
tree822b5f6c2d23aba33cfe4d199405e493e37c3d70 /src/library/layout
parent66030ae5d73d85a0463562230b87f8ec7554c746 (diff)
Refactor `geom` module
Diffstat (limited to 'src/library/layout')
-rw-r--r--src/library/layout/align.rs10
-rw-r--r--src/library/layout/columns.rs8
-rw-r--r--src/library/layout/container.rs2
-rw-r--r--src/library/layout/flow.rs18
-rw-r--r--src/library/layout/grid.rs77
-rw-r--r--src/library/layout/pad.rs6
-rw-r--r--src/library/layout/page.rs25
-rw-r--r--src/library/layout/place.rs6
-rw-r--r--src/library/layout/spacing.rs16
-rw-r--r--src/library/layout/stack.rs65
-rw-r--r--src/library/layout/transform.rs8
11 files changed, 137 insertions, 104 deletions
diff --git a/src/library/layout/align.rs b/src/library/layout/align.rs
index 705d555b..95f5c01f 100644
--- a/src/library/layout/align.rs
+++ b/src/library/layout/align.rs
@@ -5,7 +5,7 @@ use crate::library::text::{HorizontalAlign, ParNode};
#[derive(Debug, Hash)]
pub struct AlignNode {
/// How to align the node horizontally and vertically.
- pub aligns: Spec<Option<RawAlign>>,
+ pub aligns: Axes<Option<RawAlign>>,
/// The node to be aligned.
pub child: LayoutNode,
}
@@ -13,11 +13,11 @@ pub struct AlignNode {
#[node]
impl AlignNode {
fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
- let aligns: Spec<Option<RawAlign>> = args.find()?.unwrap_or_default();
+ let aligns: Axes<Option<RawAlign>> = args.find()?.unwrap_or_default();
let body: Content = args.expect("body")?;
Ok(match (body, aligns) {
(Content::Block(node), _) => Content::Block(node.aligned(aligns)),
- (other, Spec { x: Some(x), y: None }) => {
+ (other, Axes { x: Some(x), y: None }) => {
other.styled(ParNode::ALIGN, HorizontalAlign(x))
}
(other, _) => Content::Block(other.pack().aligned(aligns)),
@@ -34,7 +34,7 @@ impl Layout for AlignNode {
) -> SourceResult<Vec<Frame>> {
// The child only needs to expand along an axis if there's no alignment.
let mut pod = regions.clone();
- pod.expand &= self.aligns.map_is_none();
+ pod.expand &= self.aligns.as_ref().map(Option::is_none);
// Align paragraphs inside the child.
let mut passed = StyleMap::new();
@@ -51,7 +51,7 @@ impl Layout for AlignNode {
let aligns = self
.aligns
.map(|align| align.resolve(styles))
- .unwrap_or(Spec::new(Align::Left, Align::Top));
+ .unwrap_or(Axes::new(Align::Left, Align::Top));
frame.resize(target, aligns);
}
diff --git a/src/library/layout/columns.rs b/src/library/layout/columns.rs
index 8ae4394e..3ba3598c 100644
--- a/src/library/layout/columns.rs
+++ b/src/library/layout/columns.rs
@@ -15,7 +15,7 @@ pub struct ColumnsNode {
impl ColumnsNode {
/// The size of the gutter space between each column.
#[property(resolve)]
- pub const GUTTER: Relative<RawLength> = Ratio::new(0.04).into();
+ pub const GUTTER: Rel<Length> = Ratio::new(0.04).into();
fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
Ok(Content::block(Self {
@@ -53,7 +53,7 @@ impl Layout for ColumnsNode {
.skip(1)
.collect(),
last: regions.last,
- expand: Spec::new(true, regions.expand.y),
+ expand: Axes::new(true, regions.expand.y),
};
// Layout the children.
@@ -69,9 +69,9 @@ impl Layout for ColumnsNode {
// Otherwise its the maximum column height for the frame. In that
// case, the frame is first created with zero height and then
// resized.
- let height = if regions.expand.y { region.y } else { Length::zero() };
+ let height = if regions.expand.y { region.y } else { Abs::zero() };
let mut output = Frame::new(Size::new(regions.first.x, height));
- let mut cursor = Length::zero();
+ let mut cursor = Abs::zero();
for _ in 0 .. columns {
let frame = match frames.next() {
diff --git a/src/library/layout/container.rs b/src/library/layout/container.rs
index 23556a2e..9b1f8f56 100644
--- a/src/library/layout/container.rs
+++ b/src/library/layout/container.rs
@@ -9,7 +9,7 @@ impl BoxNode {
let width = args.named("width")?;
let height = args.named("height")?;
let body: LayoutNode = args.eat()?.unwrap_or_default();
- Ok(Content::inline(body.sized(Spec::new(width, height))))
+ Ok(Content::inline(body.sized(Axes::new(width, height))))
}
}
diff --git a/src/library/layout/flow.rs b/src/library/layout/flow.rs
index 7cb52910..1f0a2b4a 100644
--- a/src/library/layout/flow.rs
+++ b/src/library/layout/flow.rs
@@ -81,14 +81,14 @@ pub struct FlowLayouter {
/// The regions to layout children into.
regions: Regions,
/// Whether the flow should expand to fill the region.
- expand: Spec<bool>,
+ expand: Axes<bool>,
/// The full size of `regions.size` that was available before we started
/// subtracting.
full: Size,
/// The size used by the frames for the current region.
used: Size,
/// The sum of fractions in the current region.
- fr: Fraction,
+ fr: Fr,
/// Spacing and layouted nodes.
items: Vec<FlowItem>,
/// Finished frames for previous regions.
@@ -98,11 +98,11 @@ pub struct FlowLayouter {
/// A prepared item in a flow layout.
enum FlowItem {
/// Absolute spacing between other items.
- Absolute(Length),
+ Absolute(Abs),
/// Fractional spacing between other items.
- Fractional(Fraction),
+ Fractional(Fr),
/// A frame for a layouted child node and how to align it.
- Frame(Frame, Spec<Align>),
+ Frame(Frame, Axes<Align>),
/// An absolutely placed frame.
Placed(Frame),
}
@@ -122,7 +122,7 @@ impl FlowLayouter {
expand,
full,
used: Size::zero(),
- fr: Fraction::zero(),
+ fr: Fr::zero(),
items: vec![],
finished: vec![],
}
@@ -169,7 +169,7 @@ impl FlowLayouter {
}
// How to align the node.
- let aligns = Spec::new(
+ let aligns = Axes::new(
// For non-expanding paragraphs it is crucial that we align the
// whole paragraph as it is itself aligned.
styles.get(ParNode::ALIGN),
@@ -215,7 +215,7 @@ impl FlowLayouter {
}
let mut output = Frame::new(size);
- let mut offset = Length::zero();
+ let mut offset = Abs::zero();
let mut ruler = Align::Top;
// Place all frames.
@@ -245,7 +245,7 @@ impl FlowLayouter {
self.regions.next();
self.full = self.regions.first;
self.used = Size::zero();
- self.fr = Fraction::zero();
+ self.fr = Fr::zero();
self.finished.push(output);
}
diff --git a/src/library/layout/grid.rs b/src/library/layout/grid.rs
index 2c246df9..a1098c6d 100644
--- a/src/library/layout/grid.rs
+++ b/src/library/layout/grid.rs
@@ -4,9 +4,9 @@ use crate::library::prelude::*;
#[derive(Debug, Hash)]
pub struct GridNode {
/// Defines sizing for content rows and columns.
- pub tracks: Spec<Vec<TrackSizing>>,
+ pub tracks: Axes<Vec<TrackSizing>>,
/// Defines sizing of gutter rows and columns between content.
- pub gutter: Spec<Vec<TrackSizing>>,
+ pub gutter: Axes<Vec<TrackSizing>>,
/// The nodes to be arranged in a grid.
pub cells: Vec<LayoutNode>,
}
@@ -20,8 +20,8 @@ impl GridNode {
let column_gutter = args.named("column-gutter")?;
let row_gutter = args.named("row-gutter")?;
Ok(Content::block(Self {
- tracks: Spec::new(columns, rows),
- gutter: Spec::new(
+ tracks: Axes::new(columns, rows),
+ gutter: Axes::new(
column_gutter.unwrap_or_else(|| base_gutter.clone()),
row_gutter.unwrap_or(base_gutter),
),
@@ -59,10 +59,10 @@ pub enum TrackSizing {
Auto,
/// A track size specified in absolute terms and relative to the parent's
/// size.
- Relative(Relative<RawLength>),
+ Relative(Rel<Length>),
/// A track size specified as a fraction of the remaining free space in the
/// parent.
- Fractional(Fraction),
+ Fractional(Fr),
}
castable! {
@@ -105,16 +105,16 @@ pub struct GridLayouter<'a> {
/// The inherited styles.
styles: StyleChain<'a>,
/// Resolved column sizes.
- rcols: Vec<Length>,
+ rcols: Vec<Abs>,
/// Rows in the current region.
lrows: Vec<Row>,
/// The full height of the current region.
- full: Length,
+ full: Abs,
/// The used-up size of the current region. The horizontal size is
/// determined once after columns are resolved and not touched again.
used: Size,
/// The sum of fractions in the current region.
- fr: Fraction,
+ fr: Fr,
/// Frames for finished regions.
finished: Vec<Frame>,
}
@@ -125,7 +125,7 @@ enum Row {
/// Finished row frame of auto or relative row.
Frame(Frame),
/// Fractional row with y index.
- Fr(Fraction, usize),
+ Fr(Fr, usize),
}
impl<'a> GridLayouter<'a> {
@@ -134,8 +134,8 @@ impl<'a> GridLayouter<'a> {
/// This prepares grid layout by unifying content and gutter tracks.
pub fn new(
world: Tracked<'a, dyn World>,
- tracks: Spec<&[TrackSizing]>,
- gutter: Spec<&[TrackSizing]>,
+ tracks: Axes<&[TrackSizing]>,
+ gutter: Axes<&[TrackSizing]>,
cells: &'a [LayoutNode],
regions: &Regions,
styles: StyleChain<'a>,
@@ -156,7 +156,7 @@ impl<'a> GridLayouter<'a> {
};
let auto = TrackSizing::Auto;
- let zero = TrackSizing::Relative(Relative::zero());
+ let zero = TrackSizing::Relative(Rel::zero());
let get_or = |tracks: &[_], idx, default| {
tracks.get(idx).or(tracks.last()).copied().unwrap_or(default)
};
@@ -178,13 +178,13 @@ impl<'a> GridLayouter<'a> {
rows.pop();
let full = regions.first.y;
- let rcols = vec![Length::zero(); cols.len()];
+ let rcols = vec![Abs::zero(); cols.len()];
let lrows = vec![];
// We use the regions for auto row measurement. Since at that moment,
// columns are already sized, we can enable horizontal expansion.
let mut regions = regions.clone();
- regions.expand = Spec::new(true, false);
+ regions.expand = Axes::new(true, false);
Self {
world,
@@ -197,7 +197,7 @@ impl<'a> GridLayouter<'a> {
lrows,
full,
used: Size::zero(),
- fr: Fraction::zero(),
+ fr: Fr::zero(),
finished: vec![],
}
}
@@ -230,10 +230,10 @@ impl<'a> GridLayouter<'a> {
/// Determine all column sizes.
fn measure_columns(&mut self) -> SourceResult<()> {
// Sum of sizes of resolved relative tracks.
- let mut rel = Length::zero();
+ let mut rel = Abs::zero();
// Sum of fractions of all fractional tracks.
- let mut fr = Fraction::zero();
+ let mut fr = Fr::zero();
// Resolve the size of all relative columns and compute the sum of all
// fractional tracks.
@@ -252,14 +252,14 @@ impl<'a> GridLayouter<'a> {
// Size that is not used by fixed-size columns.
let available = self.regions.first.x - rel;
- if available >= Length::zero() {
+ if available >= Abs::zero() {
// Determine size of auto columns.
let (auto, count) = self.measure_auto_columns(available)?;
// If there is remaining space, distribute it to fractional columns,
// otherwise shrink auto columns.
let remaining = available - auto;
- if remaining >= Length::zero() {
+ if remaining >= Abs::zero() {
if !fr.is_zero() {
self.grow_fractional_columns(remaining, fr);
}
@@ -275,11 +275,8 @@ impl<'a> GridLayouter<'a> {
}
/// Measure the size that is available to auto columns.
- fn measure_auto_columns(
- &mut self,
- available: Length,
- ) -> SourceResult<(Length, usize)> {
- let mut auto = Length::zero();
+ fn measure_auto_columns(&mut self, available: Abs) -> SourceResult<(Abs, usize)> {
+ let mut auto = Abs::zero();
let mut count = 0;
// Determine size of auto columns by laying out all cells in those
@@ -289,12 +286,12 @@ impl<'a> GridLayouter<'a> {
continue;
}
- let mut resolved = Length::zero();
+ let mut resolved = Abs::zero();
for y in 0 .. self.rows.len() {
if let Some(node) = self.cell(x, y) {
let size = Size::new(available, self.regions.base.y);
let mut pod =
- Regions::one(size, self.regions.base, Spec::splat(false));
+ Regions::one(size, self.regions.base, Axes::splat(false));
// For relative rows, we can already resolve the correct
// base, for auto it's already correct and for fr we could
@@ -318,7 +315,7 @@ impl<'a> GridLayouter<'a> {
}
/// Distribute remaining space to fractional columns.
- fn grow_fractional_columns(&mut self, remaining: Length, fr: Fraction) {
+ fn grow_fractional_columns(&mut self, remaining: Abs, fr: Fr) {
for (&col, rcol) in self.cols.iter().zip(&mut self.rcols) {
if let TrackSizing::Fractional(v) = col {
*rcol = v.share(fr, remaining);
@@ -327,7 +324,7 @@ impl<'a> GridLayouter<'a> {
}
/// Redistribute space to auto columns so that each gets a fair share.
- fn shrink_auto_columns(&mut self, available: Length, count: usize) {
+ fn shrink_auto_columns(&mut self, available: Abs, count: usize) {
// The fair share each auto column may have.
let fair = available / count as f64;
@@ -359,7 +356,7 @@ impl<'a> GridLayouter<'a> {
/// Layout a row with automatic height. Such a row may break across multiple
/// regions.
fn layout_auto_row(&mut self, y: usize) -> SourceResult<()> {
- let mut resolved: Vec<Length> = vec![];
+ let mut resolved: Vec<Abs> = vec![];
// Determine the size for each region of the row.
for (x, &rcol) in self.rcols.iter().enumerate() {
@@ -426,11 +423,7 @@ impl<'a> GridLayouter<'a> {
/// Layout a row with relative height. Such a row cannot break across
/// multiple regions, but it may force a region break.
- fn layout_relative_row(
- &mut self,
- v: Relative<RawLength>,
- y: usize,
- ) -> SourceResult<()> {
+ fn layout_relative_row(&mut self, v: Rel<Length>, y: usize) -> SourceResult<()> {
let resolved = v.resolve(self.styles).relative_to(self.regions.base.y);
let frame = self.layout_single_row(resolved, y)?;
@@ -451,7 +444,7 @@ impl<'a> GridLayouter<'a> {
}
/// Layout a row with fixed height and return its frame.
- fn layout_single_row(&mut self, height: Length, y: usize) -> SourceResult<Frame> {
+ fn layout_single_row(&mut self, height: Abs, y: usize) -> SourceResult<Frame> {
let mut output = Frame::new(Size::new(self.used.x, height));
let mut pos = Point::zero();
@@ -462,11 +455,11 @@ impl<'a> GridLayouter<'a> {
// Set the base to the region's base for auto rows and to the
// size for relative and fractional rows.
- let base = Spec::new(self.cols[x], self.rows[y])
+ let base = Axes::new(self.cols[x], self.rows[y])
.map(|s| s == TrackSizing::Auto)
.select(self.regions.base, size);
- let pod = Regions::one(size, base, Spec::splat(true));
+ let pod = Regions::one(size, base, Axes::splat(true));
let frame = node.layout(self.world, &pod, self.styles)?.remove(0);
match frame.role() {
Some(Role::ListLabel | Role::ListItemBody) => {
@@ -488,7 +481,7 @@ impl<'a> GridLayouter<'a> {
/// Layout a row spanning multiple regions.
fn layout_multi_row(
&mut self,
- heights: &[Length],
+ heights: &[Abs],
y: usize,
) -> SourceResult<Vec<Frame>> {
// Prepare frames.
@@ -499,7 +492,7 @@ impl<'a> GridLayouter<'a> {
// Prepare regions.
let size = Size::new(self.used.x, heights[0]);
- let mut pod = Regions::one(size, self.regions.base, Spec::splat(true));
+ let mut pod = Regions::one(size, self.regions.base, Axes::splat(true));
pod.backlog = heights[1 ..].to_vec();
// Layout the row.
@@ -573,8 +566,8 @@ impl<'a> GridLayouter<'a> {
self.finished.push(output);
self.regions.next();
self.full = self.regions.first.y;
- self.used.y = Length::zero();
- self.fr = Fraction::zero();
+ self.used.y = Abs::zero();
+ self.fr = Fr::zero();
Ok(())
}
diff --git a/src/library/layout/pad.rs b/src/library/layout/pad.rs
index 06c3672f..b0238d40 100644
--- a/src/library/layout/pad.rs
+++ b/src/library/layout/pad.rs
@@ -4,7 +4,7 @@ use crate::library::prelude::*;
#[derive(Debug, Hash)]
pub struct PadNode {
/// The amount of padding.
- pub padding: Sides<Relative<RawLength>>,
+ pub padding: Sides<Rel<Length>>,
/// The child node whose sides to pad.
pub child: LayoutNode,
}
@@ -54,7 +54,7 @@ impl Layout for PadNode {
}
/// Shrink a size by padding relative to the size itself.
-fn shrink(size: Size, padding: Sides<Relative<Length>>) -> Size {
+fn shrink(size: Size, padding: Sides<Rel<Abs>>) -> Size {
size - padding.relative_to(size).sum_by_axis()
}
@@ -77,7 +77,7 @@ fn shrink(size: Size, padding: Sides<Relative<Length>>) -> Size {
/// <=> w - p.rel * w - p.abs = s
/// <=> (1 - p.rel) * w = s + p.abs
/// <=> w = (s + p.abs) / (1 - p.rel)
-fn grow(size: Size, padding: Sides<Relative<Length>>) -> Size {
+fn grow(size: Size, padding: Sides<Rel<Abs>>) -> Size {
size.zip(padding.sum_by_axis())
.map(|(s, p)| (s + p.abs).safe_div(1.0 - p.rel.get()))
}
diff --git a/src/library/layout/page.rs b/src/library/layout/page.rs
index 7d13163d..2e5cf2f9 100644
--- a/src/library/layout/page.rs
+++ b/src/library/layout/page.rs
@@ -11,17 +11,16 @@ pub struct PageNode(pub LayoutNode);
impl PageNode {
/// The unflipped width of the page.
#[property(resolve)]
- pub const WIDTH: Smart<RawLength> = Smart::Custom(Paper::A4.width().into());
+ pub const WIDTH: Smart<Length> = Smart::Custom(Paper::A4.width().into());
/// The unflipped height of the page.
#[property(resolve)]
- pub const HEIGHT: Smart<RawLength> = Smart::Custom(Paper::A4.height().into());
+ pub const HEIGHT: Smart<Length> = Smart::Custom(Paper::A4.height().into());
/// Whether the page is flipped into landscape orientation.
pub const FLIPPED: bool = false;
/// The page's margins.
#[property(fold)]
- pub const MARGINS: Sides<Option<Smart<Relative<RawLength>>>> =
- Sides::splat(Smart::Auto);
+ pub const MARGINS: Sides<Option<Smart<Rel<Length>>>> = Sides::splat(Smart::Auto);
/// How many columns the page has.
pub const COLUMNS: NonZeroUsize = NonZeroUsize::new(1).unwrap();
@@ -63,8 +62,8 @@ impl PageNode {
) -> SourceResult<Vec<Frame>> {
// When one of the lengths is infinite the page fits its content along
// that axis.
- let width = styles.get(Self::WIDTH).unwrap_or(Length::inf());
- let height = styles.get(Self::HEIGHT).unwrap_or(Length::inf());
+ let width = styles.get(Self::WIDTH).unwrap_or(Abs::inf());
+ let height = styles.get(Self::HEIGHT).unwrap_or(Abs::inf());
let mut size = Size::new(width, height);
if styles.get(Self::FLIPPED) {
std::mem::swap(&mut size.x, &mut size.y);
@@ -76,7 +75,7 @@ impl PageNode {
}
// Determine the margins.
- let default = Relative::from(0.1190 * min);
+ let default = Rel::from(0.1190 * min);
let padding = styles.get(Self::MARGINS).map(|side| side.unwrap_or(default));
let mut child = self.0.clone();
@@ -96,7 +95,7 @@ impl PageNode {
}
// Layout the child.
- let regions = Regions::repeat(size, size, size.map(Length::is_finite));
+ let regions = Regions::repeat(size, size, size.map(Abs::is_finite));
let mut frames = child.layout(world, &regions, styles)?;
let header = styles.get(Self::HEADER);
@@ -127,7 +126,7 @@ impl PageNode {
(Role::Background, background, Point::zero(), size),
] {
if let Some(content) = marginal.resolve(world, page)? {
- let pod = Regions::one(area, area, Spec::splat(true));
+ let pod = Regions::one(area, area, Axes::splat(true));
let mut sub = content.layout(world, &pod, styles)?.remove(0);
sub.apply_role(role);
@@ -224,13 +223,13 @@ pub struct Paper {
impl Paper {
/// The width of the paper.
- pub fn width(self) -> Length {
- Length::mm(self.width)
+ pub fn width(self) -> Abs {
+ Abs::mm(self.width)
}
/// The height of the paper.
- pub fn height(self) -> Length {
- Length::mm(self.height)
+ pub fn height(self) -> Abs {
+ Abs::mm(self.height)
}
}
diff --git a/src/library/layout/place.rs b/src/library/layout/place.rs
index 01da62e5..8b68c087 100644
--- a/src/library/layout/place.rs
+++ b/src/library/layout/place.rs
@@ -8,12 +8,12 @@ pub struct PlaceNode(pub LayoutNode);
#[node]
impl PlaceNode {
fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
- let aligns = args.find()?.unwrap_or(Spec::with_x(Some(RawAlign::Start)));
+ let aligns = args.find()?.unwrap_or(Axes::with_x(Some(RawAlign::Start)));
let dx = args.named("dx")?.unwrap_or_default();
let dy = args.named("dy")?.unwrap_or_default();
let body: LayoutNode = args.expect("body")?;
Ok(Content::block(Self(
- body.moved(Spec::new(dx, dy)).aligned(aligns),
+ body.moved(Axes::new(dx, dy)).aligned(aligns),
)))
}
}
@@ -30,7 +30,7 @@ impl Layout for PlaceNode {
// The pod is the base area of the region because for absolute
// placement we don't really care about the already used area.
let pod = {
- let finite = regions.base.map(Length::is_finite);
+ let finite = regions.base.map(Abs::is_finite);
let expand = finite & (regions.expand | out_of_flow);
Regions::one(regions.base, regions.base, expand)
};
diff --git a/src/library/layout/spacing.rs b/src/library/layout/spacing.rs
index 0c5cbb92..28e52d73 100644
--- a/src/library/layout/spacing.rs
+++ b/src/library/layout/spacing.rs
@@ -31,10 +31,10 @@ impl VNode {
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Spacing {
/// Spacing specified in absolute terms and relative to the parent's size.
- Relative(Relative<RawLength>),
+ Relative(Rel<Length>),
/// Spacing specified as a fraction of the remaining free space in the
/// parent.
- Fractional(Fraction),
+ Fractional(Fr),
}
impl Spacing {
@@ -44,9 +44,9 @@ impl Spacing {
}
}
-impl From<Length> for Spacing {
- fn from(length: Length) -> Self {
- Self::Relative(length.into())
+impl From<Abs> for Spacing {
+ fn from(abs: Abs) -> Self {
+ Self::Relative(abs.into())
}
}
@@ -71,12 +71,12 @@ castable! {
/// Spacing around and between block-level nodes, relative to paragraph spacing.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub struct BlockSpacing(Relative<RawLength>);
+pub struct BlockSpacing(Rel<Length>);
-castable!(BlockSpacing: Relative<RawLength>);
+castable!(BlockSpacing: Rel<Length>);
impl Resolve for BlockSpacing {
- type Output = Length;
+ type Output = Abs;
fn resolve(self, styles: StyleChain) -> Self::Output {
let whole = styles.get(ParNode::SPACING);
diff --git a/src/library/layout/stack.rs b/src/library/layout/stack.rs
index b9a26642..b9663dd6 100644
--- a/src/library/layout/stack.rs
+++ b/src/library/layout/stack.rs
@@ -90,19 +90,19 @@ pub struct StackLayouter<'a> {
/// The stacking direction.
dir: Dir,
/// The axis of the stacking direction.
- axis: SpecAxis,
+ axis: Axis,
/// The regions to layout children into.
regions: Regions,
/// The inherited styles.
styles: StyleChain<'a>,
/// Whether the stack itself should expand to fill the region.
- expand: Spec<bool>,
+ expand: Axes<bool>,
/// The full size of the current region that was available at the start.
full: Size,
/// The generic size used by the frames for the current region.
- used: Gen<Length>,
+ used: Gen<Abs>,
/// The sum of fractions in the current region.
- fr: Fraction,
+ fr: Fr,
/// Already layouted items whose exact positions are not yet known due to
/// fractional spacing.
items: Vec<StackItem>,
@@ -113,9 +113,9 @@ pub struct StackLayouter<'a> {
/// A prepared item in a stack layout.
enum StackItem {
/// Absolute spacing between other items.
- Absolute(Length),
+ Absolute(Abs),
/// Fractional spacing between other items.
- Fractional(Fraction),
+ Fractional(Fr),
/// A frame for a layouted child node.
Frame(Frame, Align),
}
@@ -139,7 +139,7 @@ impl<'a> StackLayouter<'a> {
expand,
full,
used: Gen::zero(),
- fr: Fraction::zero(),
+ fr: Fr::zero(),
items: vec![],
finished: vec![],
}
@@ -200,7 +200,12 @@ impl<'a> StackLayouter<'a> {
frame.apply_role(Role::GenericBlock);
// Grow our size, shrink the region and save the frame for later.
- let size = frame.size().to_gen(self.axis);
+ let size = frame.size();
+ let size = match self.axis {
+ Axis::X => Gen::new(size.y, size.x),
+ Axis::Y => Gen::new(size.x, size.y),
+ };
+
self.used.main += size.main;
self.used.cross.set_max(size.cross);
*self.regions.first.get_mut(self.axis) -= size.main;
@@ -218,7 +223,7 @@ impl<'a> StackLayouter<'a> {
pub fn finish_region(&mut self) {
// Determine the size of the stack in this region dependening on whether
// the region expands.
- let used = self.used.to_spec(self.axis);
+ let used = self.used.to_axes(self.axis);
let mut size = self.expand.select(self.full, used);
// Expand fully if there are fr spacings.
@@ -230,7 +235,7 @@ impl<'a> StackLayouter<'a> {
}
let mut output = Frame::new(size);
- let mut cursor = Length::zero();
+ let mut cursor = Abs::zero();
let mut ruler: Align = self.dir.start().into();
// Place all frames.
@@ -255,7 +260,7 @@ impl<'a> StackLayouter<'a> {
self.used.main - child - cursor
};
- let pos = Gen::new(Length::zero(), block).to_point(self.axis);
+ let pos = Gen::new(Abs::zero(), block).to_point(self.axis);
cursor += child;
output.push_frame(pos, frame);
}
@@ -266,7 +271,7 @@ impl<'a> StackLayouter<'a> {
self.regions.next();
self.full = self.regions.first;
self.used = Gen::zero();
- self.fr = Fraction::zero();
+ self.fr = Fr::zero();
self.finished.push(output);
}
@@ -276,3 +281,39 @@ impl<'a> StackLayouter<'a> {
self.finished
}
}
+
+/// A container with a main and cross component.
+#[derive(Default, Copy, Clone, Eq, PartialEq, Hash)]
+pub struct Gen<T> {
+ /// The main component.
+ pub cross: T,
+ /// The cross component.
+ pub main: T,
+}
+
+impl<T> Gen<T> {
+ /// Create a new instance from the two components.
+ pub const fn new(cross: T, main: T) -> Self {
+ Self { cross, main }
+ }
+
+ /// Convert to the specific representation, given the current main axis.
+ pub fn to_axes(self, main: Axis) -> Axes<T> {
+ match main {
+ Axis::X => Axes::new(self.main, self.cross),
+ Axis::Y => Axes::new(self.cross, self.main),
+ }
+ }
+}
+
+impl Gen<Abs> {
+ /// The zero value.
+ pub fn zero() -> Self {
+ Self { cross: Abs::zero(), main: Abs::zero() }
+ }
+
+ /// Convert to a point.
+ pub fn to_point(self, main: Axis) -> Point {
+ self.to_axes(main).to_point()
+ }
+}
diff --git a/src/library/layout/transform.rs b/src/library/layout/transform.rs
index b110f343..ff42744a 100644
--- a/src/library/layout/transform.rs
+++ b/src/library/layout/transform.rs
@@ -5,7 +5,7 @@ use crate::library::prelude::*;
#[derive(Debug, Hash)]
pub struct MoveNode {
/// The offset by which to move the node.
- pub delta: Spec<Relative<RawLength>>,
+ pub delta: Axes<Rel<Length>>,
/// The node whose contents should be moved.
pub child: LayoutNode,
}
@@ -16,7 +16,7 @@ impl MoveNode {
let dx = args.named("dx")?.unwrap_or_default();
let dy = args.named("dy")?.unwrap_or_default();
Ok(Content::inline(Self {
- delta: Spec::new(dx, dy),
+ delta: Axes::new(dx, dy),
child: args.expect("body")?,
}))
}
@@ -60,7 +60,7 @@ pub type ScaleNode = TransformNode<SCALE>;
impl<const T: TransformKind> TransformNode<T> {
/// The origin of the transformation.
#[property(resolve)]
- pub const ORIGIN: Spec<Option<RawAlign>> = Spec::default();
+ pub const ORIGIN: Axes<Option<RawAlign>> = Axes::default();
fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
let transform = match T {
@@ -94,7 +94,7 @@ impl<const T: TransformKind> Layout for TransformNode<T> {
let mut frames = self.child.layout(world, regions, styles)?;
for frame in &mut frames {
- let Spec { x, y } = origin.zip(frame.size()).map(|(o, s)| o.position(s));
+ let Axes { x, y } = origin.zip(frame.size()).map(|(o, s)| o.position(s));
let transform = Transform::translate(x, y)
.pre_concat(self.transform)
.pre_concat(Transform::translate(-x, -y));