summaryrefslogtreecommitdiff
path: root/src/layout
diff options
context:
space:
mode:
Diffstat (limited to 'src/layout')
-rw-r--r--src/layout/elements.rs15
-rw-r--r--src/layout/line.rs30
-rw-r--r--src/layout/mod.rs16
-rw-r--r--src/layout/shaping.rs11
-rw-r--r--src/layout/stack.rs55
-rw-r--r--src/layout/tree.rs17
6 files changed, 68 insertions, 76 deletions
diff --git a/src/layout/elements.rs b/src/layout/elements.rs
index dd148a24..b5f83bfe 100644
--- a/src/layout/elements.rs
+++ b/src/layout/elements.rs
@@ -5,11 +5,11 @@ use std::fmt::{self, Debug, Formatter};
use fontdock::FaceId;
use ttf_parser::GlyphId;
-use crate::geom::Size;
+use crate::geom::Point;
/// A collection of absolutely positioned layout elements.
#[derive(Debug, Default, Clone, PartialEq)]
-pub struct LayoutElements(pub Vec<(Size, LayoutElement)>);
+pub struct LayoutElements(pub Vec<(Point, LayoutElement)>);
impl LayoutElements {
/// Create an new empty collection.
@@ -18,16 +18,15 @@ impl LayoutElements {
}
/// Add an element at a position.
- pub fn push(&mut self, pos: Size, element: LayoutElement) {
+ pub fn push(&mut self, pos: Point, element: LayoutElement) {
self.0.push((pos, element));
}
- /// Add all elements of another collection, offsetting each by the given
- /// `offset`. This can be used to place a sublayout at a position in another
- /// layout.
- pub fn extend_offset(&mut self, offset: Size, more: Self) {
+ /// Add all elements of another collection, placing them relative to the
+ /// given position.
+ pub fn push_elements(&mut self, pos: Point, more: Self) {
for (subpos, element) in more.0 {
- self.0.push((subpos + offset, element));
+ self.0.push((pos + subpos.to_vec2(), element));
}
}
}
diff --git a/src/layout/line.rs b/src/layout/line.rs
index d8e97df3..86531f30 100644
--- a/src/layout/line.rs
+++ b/src/layout/line.rs
@@ -95,14 +95,14 @@ impl LineLayouter {
let usable = self.stack.usable().primary(sys);
rest_run.usable = Some(match layout.align.primary {
GenAlign::Start => unreachable!("start > x"),
- GenAlign::Center => usable - 2.0 * self.run.size.x,
- GenAlign::End => usable - self.run.size.x,
+ GenAlign::Center => usable - 2.0 * self.run.size.width,
+ GenAlign::End => usable - self.run.size.width,
});
- rest_run.size.y = self.run.size.y;
+ rest_run.size.height = self.run.size.height;
self.finish_line();
- self.stack.add_spacing(-rest_run.size.y, SpacingKind::Hard);
+ self.stack.add_spacing(-rest_run.size.height, SpacingKind::Hard);
self.run = rest_run;
}
@@ -126,10 +126,10 @@ impl LineLayouter {
}
self.run.align = Some(layout.align);
- self.run.layouts.push((self.run.size.x, layout));
+ self.run.layouts.push((self.run.size.width, layout));
- self.run.size.x += size.x;
- self.run.size.y = self.run.size.y.max(size.y);
+ self.run.size.width += size.width;
+ self.run.size.height = self.run.size.height.max(size.height);
self.run.last_spacing = LastSpacing::None;
}
@@ -152,10 +152,10 @@ impl LineLayouter {
// If there was another run already, override the stack's size.
if let Some(primary) = self.run.usable {
- usable.x = primary;
+ usable.width = primary;
}
- usable.x -= self.run.size.x;
+ usable.width -= self.run.size.width;
usable
}
@@ -163,8 +163,8 @@ impl LineLayouter {
pub fn add_primary_spacing(&mut self, mut spacing: f64, kind: SpacingKind) {
match kind {
SpacingKind::Hard => {
- spacing = spacing.min(self.usable().x);
- self.run.size.x += spacing;
+ spacing = spacing.min(self.usable().width);
+ self.run.size.width += spacing;
self.run.last_spacing = LastSpacing::Hard;
}
@@ -215,7 +215,7 @@ impl LineLayouter {
/// it will fit into this layouter's underlying stack.
pub fn remaining(&self) -> LayoutSpaces {
let mut spaces = self.stack.remaining();
- *spaces[0].size.secondary_mut(self.ctx.sys) -= self.run.size.y;
+ *spaces[0].size.secondary_mut(self.ctx.sys) -= self.run.size.height;
spaces
}
@@ -246,11 +246,11 @@ impl LineLayouter {
for (offset, layout) in layouts {
let x = match self.ctx.sys.primary.is_positive() {
true => offset,
- false => self.run.size.x - offset - layout.size.primary(self.ctx.sys),
+ false => self.run.size.width - offset - layout.size.primary(self.ctx.sys),
};
- let pos = Size::with_x(x);
- elements.extend_offset(pos, layout.elements);
+ let pos = Point::new(x, 0.0);
+ elements.push_elements(pos, layout.elements);
}
self.stack.add(BoxLayout {
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index fcaab372..11c03b0b 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -10,9 +10,10 @@ mod tree;
pub use primitive::*;
pub use tree::layout_tree as layout;
+use crate::geom::{Insets, Point, Rect, RectExt, Sides, Size, SizeExt};
+
use crate::eval::Scope;
use crate::font::SharedFontLoader;
-use crate::geom::{Margins, Size};
use crate::style::{LayoutStyle, PageStyle, TextStyle};
use crate::syntax::SynTree;
@@ -67,22 +68,21 @@ pub struct LayoutSpace {
/// The maximum size of the rectangle to layout into.
pub size: Size,
/// Padding that should be respected on each side.
- pub padding: Margins,
+ pub insets: Insets,
/// Whether to expand the size of the resulting layout to the full size of
/// this space or to shrink it to fit the content.
pub expansion: LayoutExpansion,
}
impl LayoutSpace {
- /// The offset from the origin to the start of content, i.e.
- /// `(padding.left, padding.top)`.
- pub fn start(&self) -> Size {
- Size::new(self.padding.left, self.padding.top)
+ /// The position of the padded start in the space.
+ pub fn start(&self) -> Point {
+ Point::new(-self.insets.x0, -self.insets.y0)
}
/// The actually usable area (size minus padding).
pub fn usable(&self) -> Size {
- self.size.unpadded(self.padding)
+ self.size + self.insets.size()
}
/// The inner layout space with size reduced by the padding, zero padding of
@@ -90,7 +90,7 @@ impl LayoutSpace {
pub fn inner(&self) -> Self {
Self {
size: self.usable(),
- padding: Margins::ZERO,
+ insets: Insets::ZERO,
expansion: LayoutExpansion::new(false, false),
}
}
diff --git a/src/layout/shaping.rs b/src/layout/shaping.rs
index 0f42d4bb..4de30a9e 100644
--- a/src/layout/shaping.rs
+++ b/src/layout/shaping.rs
@@ -11,7 +11,6 @@ use super::elements::{LayoutElement, Shaped};
use super::BoxLayout as Layout;
use super::*;
use crate::font::FontLoader;
-use crate::geom::Size;
use crate::style::TextStyle;
/// Shape text into a box.
@@ -74,7 +73,7 @@ impl<'a> Shaper<'a> {
// Flush the last buffered parts of the word.
if !self.shaped.text.is_empty() {
- let pos = Size::new(self.offset, 0.0);
+ let pos = Point::new(self.offset, 0.0);
self.layout.elements.push(pos, LayoutElement::Text(self.shaped));
}
@@ -97,9 +96,9 @@ impl<'a> Shaper<'a> {
Shaped::new(FaceId::MAX, self.opts.style.font_size()),
);
- let pos = Size::new(self.offset, 0.0);
+ let pos = Point::new(self.offset, 0.0);
self.layout.elements.push(pos, LayoutElement::Text(shaped));
- self.offset = self.layout.size.x;
+ self.offset = self.layout.size.width;
}
self.shaped.face = index;
@@ -107,9 +106,9 @@ impl<'a> Shaper<'a> {
self.shaped.text.push(c);
self.shaped.glyphs.push(glyph);
- self.shaped.offsets.push(self.layout.size.x - self.offset);
+ self.shaped.offsets.push(self.layout.size.width - self.offset);
- self.layout.size.x += char_width;
+ self.layout.size.width += char_width;
}
async fn select_font(&mut self, c: char) -> Option<(FaceId, GlyphId, f64)> {
diff --git a/src/layout/stack.rs b/src/layout/stack.rs
index 3e63f5e5..a68fbac0 100644
--- a/src/layout/stack.rs
+++ b/src/layout/stack.rs
@@ -20,7 +20,6 @@
//! sentence in the second box.
use super::*;
-use crate::geom::Value4;
/// Performs the stack layouting.
pub struct StackLayouter {
@@ -64,7 +63,7 @@ struct Space {
/// Dictate which alignments for new boxes are still allowed and which
/// require a new space to be started. For example, after an `End`-aligned
/// item, no `Start`-aligned one can follow.
- rulers: Value4<GenAlign>,
+ rulers: Sides<GenAlign>,
/// The spacing state. This influences how new spacing is handled, e.g. hard
/// spacing may override soft spacing.
last_spacing: LastSpacing,
@@ -127,7 +126,7 @@ impl StackLayouter {
SpacingKind::Hard => {
// Reduce the spacing such that it definitely fits.
spacing = spacing.min(self.space.usable.secondary(self.ctx.sys));
- let size = Size::with_y(spacing);
+ let size = Size::new(0.0, spacing);
self.update_metrics(size);
self.space.layouts.push((self.ctx.sys, BoxLayout {
@@ -161,15 +160,15 @@ impl StackLayouter {
let mut size = self.space.size.generalized(sys);
let mut extra = self.space.extra.generalized(sys);
- size.x += (added.x - extra.x).max(0.0);
- size.y += (added.y - extra.y).max(0.0);
+ size.width += (added.width - extra.width).max(0.0);
+ size.height += (added.height - extra.height).max(0.0);
- extra.x = extra.x.max(added.x);
- extra.y = (extra.y - added.y).max(0.0);
+ extra.width = extra.width.max(added.width);
+ extra.height = (extra.height - added.height).max(0.0);
self.space.size = size.specialized(sys);
self.space.extra = extra.specialized(sys);
- *self.space.usable.secondary_mut(sys) -= added.y;
+ *self.space.usable.secondary_mut(sys) -= added.height;
}
/// Returns true if a space break is necessary.
@@ -239,7 +238,7 @@ impl StackLayouter {
let mut spaces = vec![LayoutSpace {
size,
- padding: Margins::ZERO,
+ insets: Insets::ZERO,
expansion: LayoutExpansion::new(false, false),
}];
@@ -253,7 +252,7 @@ impl StackLayouter {
/// The remaining usable size.
pub fn usable(&self) -> Size {
self.space.usable
- - Size::with_y(self.space.last_spacing.soft_or_zero())
+ - Size::new(0.0, self.space.last_spacing.soft_or_zero())
.specialized(self.ctx.sys)
}
@@ -286,13 +285,13 @@ impl StackLayouter {
let usable = space.usable();
if space.expansion.horizontal {
- self.space.size.x = usable.x;
+ self.space.size.width = usable.width;
}
if space.expansion.vertical {
- self.space.size.y = usable.y;
+ self.space.size.height = usable.height;
}
- let size = self.space.size.padded(space.padding);
+ let size = self.space.size - space.insets.size();
// ------------------------------------------------------------------ //
// Step 2: Forward pass. Create a bounding box for each layout in which
@@ -302,11 +301,11 @@ impl StackLayouter {
let start = space.start();
let mut bounds = vec![];
- let mut bound = Margins {
- left: start.x,
- top: start.y,
- right: start.x + self.space.size.x,
- bottom: start.y + self.space.size.y,
+ let mut bound = Rect {
+ x0: start.x,
+ y0: start.y,
+ x1: start.x + self.space.size.width,
+ y1: start.y + self.space.size.height,
};
for (sys, layout) in &self.space.layouts {
@@ -340,8 +339,8 @@ impl StackLayouter {
// is thus stored in `extent.y`. The primary extent is reset for
// this new axis-aligned run.
if rotation != sys.secondary.axis() {
- extent.y = extent.x;
- extent.x = 0.0;
+ extent.height = extent.width;
+ extent.width = 0.0;
rotation = sys.secondary.axis();
}
@@ -349,12 +348,12 @@ impl StackLayouter {
// accumulated secondary extent of all layouts we have seen so far,
// which are the layouts after this one since we iterate reversed.
*bound.get_mut(sys.secondary, GenAlign::End) -=
- sys.secondary.factor() * extent.y;
+ sys.secondary.factor() * extent.height;
// Then, we add this layout's secondary extent to the accumulator.
let size = layout.size.generalized(*sys);
- extent.x = extent.x.max(size.x);
- extent.y += size.y;
+ extent.width = extent.width.max(size.width);
+ extent.height += size.height;
}
// ------------------------------------------------------------------ //
@@ -370,13 +369,11 @@ impl StackLayouter {
// The space in which this layout is aligned is given by the
// distances between the borders of its bounding box.
- let usable = Size::new(bound.right - bound.left, bound.bottom - bound.top)
- .generalized(sys);
-
+ let usable = bound.size().generalized(sys);
let local = usable.anchor(align, sys) - size.anchor(align, sys);
- let pos = Size::new(bound.left, bound.top) + local.specialized(sys);
+ let pos = bound.origin() + local.to_size().specialized(sys).to_vec2();
- elements.extend_offset(pos, layout.elements);
+ elements.push_elements(pos, layout.elements);
}
self.layouts.push(BoxLayout { size, align: self.ctx.align, elements });
@@ -406,7 +403,7 @@ impl Space {
size: Size::ZERO,
usable,
extra: Size::ZERO,
- rulers: Value4::with_all(GenAlign::Start),
+ rulers: Sides::uniform(GenAlign::Start),
last_spacing: LastSpacing::Hard,
}
}
diff --git a/src/layout/tree.rs b/src/layout/tree.rs
index b43ef089..58774215 100644
--- a/src/layout/tree.rs
+++ b/src/layout/tree.rs
@@ -202,16 +202,13 @@ impl<'a> TreeLayouter<'a> {
// The line layouter has no idea of page styles and thus we
// need to recompute the layouting space resulting of the
// new page style and update it within the layouter.
- let margins = style.margins();
- self.ctx.base = style.size.unpadded(margins);
- self.layouter.set_spaces(
- vec![LayoutSpace {
- size: style.size,
- padding: margins,
- expansion: LayoutExpansion::new(true, true),
- }],
- true,
- );
+ let space = LayoutSpace {
+ size: style.size,
+ insets: style.insets(),
+ expansion: LayoutExpansion::new(true, true),
+ };
+ self.ctx.base = space.usable();
+ self.layouter.set_spaces(vec![space], true);
} else {
error!(
@self.feedback, span,