Rename areas to regions

This commit is contained in:
Laurenz 2021-05-21 12:55:36 +02:00
parent 1cb6328d20
commit 6472c1e425
9 changed files with 83 additions and 78 deletions

View File

@ -19,8 +19,8 @@ pub enum BackgroundShape {
}
impl Layout for BackgroundNode {
fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Frame> {
let mut frames = self.child.layout(ctx, areas);
fn layout(&self, ctx: &mut LayoutContext, regions: &Regions) -> Vec<Frame> {
let mut frames = self.child.layout(ctx, regions);
for frame in &mut frames {
let (point, shape) = match self.shape {

View File

@ -12,16 +12,16 @@ pub struct FixedNode {
}
impl Layout for FixedNode {
fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Frame> {
let Areas { current, base, .. } = areas;
fn layout(&self, ctx: &mut LayoutContext, regions: &Regions) -> Vec<Frame> {
let Regions { current, base, .. } = regions;
let size = Size::new(
self.width.map_or(current.width, |w| w.resolve(base.width)),
self.height.map_or(current.height, |h| h.resolve(base.height)),
);
let fixed = Spec::new(self.width.is_some(), self.height.is_some());
let areas = Areas::once(size, fixed);
self.child.layout(ctx, &areas)
let regions = Regions::one(size, fixed);
self.child.layout(ctx, &regions)
}
}

View File

@ -58,8 +58,8 @@ impl PageRun {
// that axis.
let Size { width, height } = self.size;
let fixed = Spec::new(width.is_finite(), height.is_finite());
let areas = Areas::repeat(self.size, fixed);
self.child.layout(ctx, &areas)
let regions = Regions::repeat(self.size, fixed);
self.child.layout(ctx, &regions)
}
}
@ -77,8 +77,8 @@ impl AnyNode {
}
impl Layout for AnyNode {
fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Frame> {
self.0.layout(ctx, areas)
fn layout(&self, ctx: &mut LayoutContext, regions: &Regions) -> Vec<Frame> {
self.0.layout(ctx, regions)
}
}
@ -129,8 +129,8 @@ where
/// Layout a node.
pub trait Layout {
/// Layout the node into the given areas.
fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Frame>;
/// Layout the node into the given regions.
fn layout(&self, ctx: &mut LayoutContext, regions: &Regions) -> Vec<Frame>;
}
/// The context for layouting.
@ -139,21 +139,21 @@ pub struct LayoutContext<'a> {
pub env: &'a mut Env,
}
/// A sequence of areas to layout into.
/// A sequence of regions to layout into.
#[derive(Debug, Clone, PartialEq)]
pub struct Areas {
/// The remaining size of the current area.
pub struct Regions {
/// The remaining size of the current region.
pub current: Size,
/// The base size for relative sizing.
pub base: Size,
/// A stack of followup areas.
/// A stack of followup regions.
///
/// Note that this is a stack and not a queue! The size of the next area is
/// Note that this is a stack and not a queue! The size of the next region is
/// `backlog.last()`.
pub backlog: Vec<Size>,
/// The final area that is repeated once the backlog is drained.
/// The final region that is repeated once the backlog is drained.
pub last: Option<Size>,
/// Whether layouting into these areas should produce frames of the exact
/// Whether layouting into these regions should produce frames of the exact
/// size of `current` instead of shrinking to fit the content.
///
/// This property is only handled by nodes that have the ability to control
@ -161,9 +161,9 @@ pub struct Areas {
pub fixed: Spec<bool>,
}
impl Areas {
/// Create a new area sequence of length one.
pub fn once(size: Size, fixed: Spec<bool>) -> Self {
impl Regions {
/// Create a new region sequence with exactly one region.
pub fn one(size: Size, fixed: Spec<bool>) -> Self {
Self {
current: size,
base: size,
@ -173,7 +173,7 @@ impl Areas {
}
}
/// Create a new sequence of same-size areas that repeats indefinitely.
/// Create a new sequence of same-size regions that repeats indefinitely.
pub fn repeat(size: Size, fixed: Spec<bool>) -> Self {
Self {
current: size,
@ -184,7 +184,7 @@ impl Areas {
}
}
/// Map the size of all areas.
/// Map the size of all regions.
pub fn map<F>(&self, mut f: F) -> Self
where
F: FnMut(Size) -> Size,
@ -198,7 +198,7 @@ impl Areas {
}
}
/// Whether `current` is a fully sized (untouched) copy of the last area.
/// Whether `current` is a fully sized (untouched) copy of the last region.
///
/// If this is true, calling `next()` will have no effect.
pub fn in_full_last(&self) -> bool {
@ -208,7 +208,7 @@ impl Areas {
})
}
/// Advance to the next area if there is any.
/// Advance to the next region if there is any.
pub fn next(&mut self) {
if let Some(size) = self.backlog.pop().or(self.last) {
self.current = size;

View File

@ -10,10 +10,10 @@ pub struct PadNode {
}
impl Layout for PadNode {
fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Frame> {
let areas = areas.map(|size| size - self.padding.resolve(size).size());
fn layout(&self, ctx: &mut LayoutContext, regions: &Regions) -> Vec<Frame> {
let regions = regions.map(|size| size - self.padding.resolve(size).size());
let mut frames = self.child.layout(ctx, &areas);
let mut frames = self.child.layout(ctx, &regions);
for frame in &mut frames {
let padded = solve(self.padding, frame.size);
let padding = self.padding.resolve(padded);

View File

@ -32,7 +32,7 @@ pub enum ParChild {
}
impl Layout for ParNode {
fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Frame> {
fn layout(&self, ctx: &mut LayoutContext, regions: &Regions) -> Vec<Frame> {
// Collect all text into one string used for BiDi analysis.
let text = self.collect_text();
@ -41,10 +41,10 @@ impl Layout for ParNode {
// Build a representation of the paragraph on which we can do
// linebreaking without layouting each and every line from scratch.
let layout = ParLayout::new(ctx, areas, self, bidi);
let layout = ParLayout::new(ctx, regions, self, bidi);
// Find suitable linebreaks.
layout.build(ctx, areas.clone(), self)
layout.build(ctx, regions.clone(), self)
}
}
@ -116,7 +116,7 @@ impl<'a> ParLayout<'a> {
/// Build a paragraph layout for the given node.
fn new(
ctx: &mut LayoutContext,
areas: &Areas,
regions: &Regions,
par: &'a ParNode,
bidi: BidiInfo<'a>,
) -> Self {
@ -141,7 +141,7 @@ impl<'a> ParLayout<'a> {
}
}
ParChild::Any(ref node, align) => {
let mut frames = node.layout(ctx, areas).into_iter();
let mut frames = node.layout(ctx, regions).into_iter();
let frame = frames.next().unwrap();
assert!(frames.next().is_none());
items.push(ParItem::Frame(frame, align));
@ -154,11 +154,16 @@ impl<'a> ParLayout<'a> {
}
/// Find first-fit line breaks and build the paragraph.
fn build(self, ctx: &mut LayoutContext, areas: Areas, par: &ParNode) -> Vec<Frame> {
let mut stack = LineStack::new(par.line_spacing, areas);
fn build(
self,
ctx: &mut LayoutContext,
regions: Regions,
par: &ParNode,
) -> Vec<Frame> {
let mut stack = LineStack::new(par.line_spacing, regions);
// The current line attempt.
// Invariant: Always fits into `stack.areas.current`.
// Invariant: Always fits into `stack.regions.current`.
let mut last = None;
// The start of the line in `last`.
@ -173,7 +178,7 @@ impl<'a> ParLayout<'a> {
// If the line doesn't fit anymore, we push the last fitting attempt
// into the stack and rebuild the line from its end. The resulting
// line cannot be broken up further.
if !stack.areas.current.fits(line.size) {
if !stack.regions.current.fits(line.size) {
if let Some((last_line, last_end)) = last.take() {
stack.push(last_line);
start = last_end;
@ -181,17 +186,17 @@ impl<'a> ParLayout<'a> {
}
}
// If the line does not fit vertically, we start a new area.
while !stack.areas.current.height.fits(line.size.height)
&& !stack.areas.in_full_last()
// If the line does not fit vertically, we start a new region.
while !stack.regions.current.height.fits(line.size.height)
&& !stack.regions.in_full_last()
{
stack.finish_area();
stack.finish_region();
}
// If the line does not fit horizontally or we have a mandatory
// line break (i.e. due to "\n"), we push the line into the
// stack.
if mandatory || !stack.areas.current.width.fits(line.size.width) {
if mandatory || !stack.regions.current.width.fits(line.size.width) {
stack.push(line);
start = end;
last = None;
@ -266,20 +271,20 @@ impl ParItem<'_> {
}
}
/// A simple layouter that stacks lines into areas.
/// A simple layouter that stacks lines into regions.
struct LineStack<'a> {
line_spacing: Length,
areas: Areas,
regions: Regions,
finished: Vec<Frame>,
lines: Vec<LineLayout<'a>>,
size: Size,
}
impl<'a> LineStack<'a> {
fn new(line_spacing: Length, areas: Areas) -> Self {
fn new(line_spacing: Length, regions: Regions) -> Self {
Self {
line_spacing,
areas,
regions,
finished: vec![],
lines: vec![],
size: Size::ZERO,
@ -293,13 +298,13 @@ impl<'a> LineStack<'a> {
self.size.height += self.line_spacing;
}
self.areas.current.height -= line.size.height + self.line_spacing;
self.regions.current.height -= line.size.height + self.line_spacing;
self.lines.push(line);
}
fn finish_area(&mut self) {
if self.areas.fixed.horizontal {
self.size.width = self.areas.current.width;
fn finish_region(&mut self) {
if self.regions.fixed.horizontal {
self.size.width = self.regions.current.width;
}
let mut output = Frame::new(self.size, self.size.height);
@ -320,12 +325,12 @@ impl<'a> LineStack<'a> {
}
self.finished.push(output);
self.areas.next();
self.regions.next();
self.size = Size::ZERO;
}
fn finish(mut self) -> Vec<Frame> {
self.finish_area();
self.finish_region();
self.finished
}
}

View File

@ -26,19 +26,19 @@ pub enum StackChild {
}
impl Layout for StackNode {
fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Frame> {
let mut layouter = StackLayouter::new(self.dirs, self.aspect, areas.clone());
fn layout(&self, ctx: &mut LayoutContext, regions: &Regions) -> Vec<Frame> {
let mut layouter = StackLayouter::new(self.dirs, self.aspect, regions.clone());
for child in &self.children {
match *child {
StackChild::Spacing(amount) => layouter.push_spacing(amount),
StackChild::Any(ref node, aligns) => {
let mut frames = node.layout(ctx, &layouter.areas).into_iter();
let mut frames = node.layout(ctx, &layouter.regions).into_iter();
if let Some(frame) = frames.next() {
layouter.push_frame(frame, aligns);
}
for frame in frames {
layouter.finish_area();
layouter.finish_region();
layouter.push_frame(frame, aligns);
}
}
@ -58,7 +58,7 @@ struct StackLayouter {
dirs: Gen<Dir>,
aspect: Option<f64>,
main: SpecAxis,
areas: Areas,
regions: Regions,
finished: Vec<Frame>,
frames: Vec<(Length, Frame, Gen<Align>)>,
full: Size,
@ -67,9 +67,9 @@ struct StackLayouter {
}
impl StackLayouter {
fn new(dirs: Gen<Dir>, aspect: Option<f64>, mut areas: Areas) -> Self {
fn new(dirs: Gen<Dir>, aspect: Option<f64>, mut regions: Regions) -> Self {
if let Some(aspect) = aspect {
areas.apply_aspect_ratio(aspect);
regions.apply_aspect_ratio(aspect);
}
Self {
@ -78,15 +78,15 @@ impl StackLayouter {
main: dirs.main.axis(),
finished: vec![],
frames: vec![],
full: areas.current,
full: regions.current,
size: Gen::ZERO,
ruler: Align::Start,
areas,
regions,
}
}
fn push_spacing(&mut self, amount: Length) {
let remaining = self.areas.current.get_mut(self.main);
let remaining = self.regions.current.get_mut(self.main);
let capped = amount.min(*remaining);
*remaining -= capped;
self.size.main += capped;
@ -94,11 +94,11 @@ impl StackLayouter {
fn push_frame(&mut self, frame: Frame, aligns: Gen<Align>) {
if self.ruler > aligns.main {
self.finish_area();
self.finish_region();
}
while !self.areas.current.fits(frame.size) && !self.areas.in_full_last() {
self.finish_area();
while !self.regions.current.fits(frame.size) && !self.regions.in_full_last() {
self.finish_region();
}
let offset = self.size.main;
@ -106,12 +106,12 @@ impl StackLayouter {
self.size.main += size.main;
self.size.cross.set_max(size.cross);
self.ruler = aligns.main;
*self.areas.current.get_mut(self.main) -= size.main;
*self.regions.current.get_mut(self.main) -= size.main;
self.frames.push((offset, frame, aligns));
}
fn finish_area(&mut self) {
let fixed = self.areas.fixed;
fn finish_region(&mut self) {
let fixed = self.regions.fixed;
let used = self.size.switch(self.main).to_size();
let mut size = Size::new(
@ -165,16 +165,16 @@ impl StackLayouter {
self.size = Gen::ZERO;
self.ruler = Align::Start;
self.areas.next();
self.regions.next();
if let Some(aspect) = self.aspect {
self.areas.apply_aspect_ratio(aspect);
self.regions.apply_aspect_ratio(aspect);
}
self.finished.push(output);
}
fn finish(mut self) -> Vec<Frame> {
self.finish_area();
self.finish_region();
self.finished
}
}

View File

@ -2,7 +2,7 @@ use ::image::GenericImageView;
use super::*;
use crate::env::ImageId;
use crate::layout::{AnyNode, Areas, Element, Frame, Layout, LayoutContext};
use crate::layout::{AnyNode, Element, Frame, Layout, LayoutContext, Regions};
/// `image`: An image.
///
@ -45,8 +45,8 @@ struct ImageNode {
}
impl Layout for ImageNode {
fn layout(&self, _: &mut LayoutContext, areas: &Areas) -> Vec<Frame> {
let Areas { current, base, .. } = areas;
fn layout(&self, _: &mut LayoutContext, regions: &Regions) -> Vec<Frame> {
let Regions { current, base, .. } = regions;
let width = self.width.map(|w| w.resolve(base.width));
let height = self.height.map(|w| w.resolve(base.height));
@ -66,7 +66,7 @@ impl Layout for ImageNode {
// TODO: Fix issue with line spacing.
Size::new(current.height * pixel_ratio, current.height)
} else {
// Totally unbounded area, we have to make up something.
// Totally unbounded region, we have to make up something.
Size::new(Length::pt(pixel_width), Length::pt(pixel_height))
}
}

View File

@ -14,7 +14,7 @@ use crate::layout::PadNode;
/// - Bottom padding: `bottom`, of type `linear` relative to parent height.
///
/// # Return value
/// A template that sets the body into a padded area.
/// A template that pads its region and sets the body into it.
pub fn pad(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
let all = args.eat(ctx);
let left = args.eat_named(ctx, "left");

View File

@ -131,7 +131,7 @@ fn ellipse_impl(
body: TemplateValue,
) -> Value {
Value::template(name, move |ctx| {
// This padding ratio ensures that the rectangular padded area fits
// This padding ratio ensures that the rectangular padded region fits
// perfectly into the ellipse.
const PAD: f64 = 0.5 - SQRT_2 / 4.0;