summaryrefslogtreecommitdiff
path: root/src/layout
diff options
context:
space:
mode:
Diffstat (limited to 'src/layout')
-rw-r--r--src/layout/line.rs33
-rw-r--r--src/layout/mod.rs10
-rw-r--r--src/layout/stack.rs31
-rw-r--r--src/layout/tree.rs42
4 files changed, 57 insertions, 59 deletions
diff --git a/src/layout/line.rs b/src/layout/line.rs
index baef9fb0..19ec053d 100644
--- a/src/layout/line.rs
+++ b/src/layout/line.rs
@@ -23,14 +23,10 @@ pub struct LineLayouter {
/// The context for line layouting.
#[derive(Debug, Clone)]
pub struct LineContext {
- /// The spaces to layout into.
- pub spaces: Vec<LayoutSpace>,
/// The initial layouting system, which can be updated through `set_sys`.
pub sys: LayoutSystem,
- /// The alignment of the _resulting_ layout. This does not effect the line
- /// layouting itself, but rather how the finished layout will be positioned
- /// in a parent layout.
- pub align: LayoutAlign,
+ /// The spaces to layout into.
+ pub spaces: Vec<LayoutSpace>,
/// Whether to spill over into copies of the last space or finish layouting
/// when the last space is used up.
pub repeat: bool,
@@ -45,7 +41,6 @@ impl LineLayouter {
stack: StackLayouter::new(StackContext {
spaces: ctx.spaces.clone(),
sys: ctx.sys,
- align: ctx.align,
repeat: ctx.repeat,
}),
ctx,
@@ -54,26 +49,26 @@ impl LineLayouter {
}
/// Add a layout.
- pub fn add(&mut self, layout: BoxLayout) {
+ pub fn add(&mut self, layout: BoxLayout, align: LayoutAlign) {
let sys = self.ctx.sys;
- if let Some(align) = self.run.align {
- if layout.align.secondary != align.secondary {
+ if let Some(prev) = self.run.align {
+ if align.secondary != prev.secondary {
// TODO: Issue warning for non-fitting alignment in
// non-repeating context.
- let fitting = self.stack.is_fitting_alignment(layout.align);
+ let fitting = self.stack.is_fitting_alignment(align);
if !fitting && self.ctx.repeat {
self.finish_space(true);
} else {
self.finish_line();
}
- } else if layout.align.primary < align.primary {
+ } else if align.primary < prev.primary {
self.finish_line();
- } else if layout.align.primary > align.primary {
+ } else if align.primary > prev.primary {
let mut rest_run = LineRun::new();
let usable = self.stack.usable().primary(sys);
- rest_run.usable = Some(match layout.align.primary {
+ rest_run.usable = Some(match align.primary {
GenAlign::Start => unreachable!("start > x"),
GenAlign::Center => usable - 2.0 * self.run.size.width,
GenAlign::End => usable - self.run.size.width,
@@ -105,7 +100,7 @@ impl LineLayouter {
}
}
- self.run.align = Some(layout.align);
+ self.run.align = Some(align);
self.run.layouts.push((self.run.size.width, layout));
self.run.size.width += size.width;
@@ -211,10 +206,8 @@ impl LineLayouter {
/// Finish the active line and start a new one.
pub fn finish_line(&mut self) {
- let mut layout = BoxLayout::new(
- self.run.size.specialized(self.ctx.sys),
- self.run.align.unwrap_or_default(),
- );
+ let mut layout = BoxLayout::new(self.run.size.specialized(self.ctx.sys));
+ let align = self.run.align.unwrap_or_default();
let layouts = std::mem::take(&mut self.run.layouts);
for (offset, child) in layouts {
@@ -227,7 +220,7 @@ impl LineLayouter {
layout.push_layout(pos, child);
}
- self.stack.add(layout);
+ self.stack.add(layout, align);
self.run = LineRun::new();
self.stack.add_spacing(self.ctx.line_spacing, SpacingKind::LINE);
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index 52f7e0e6..7803c747 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -54,16 +54,14 @@ pub async fn layout(
pub struct BoxLayout {
/// The size of the box.
pub size: Size,
- /// How to align this box in a parent container.
- pub align: LayoutAlign,
/// The elements composing this layout.
pub elements: Vec<(Point, LayoutElement)>,
}
impl BoxLayout {
- /// Create an new empty collection.
- pub fn new(size: Size, align: LayoutAlign) -> Self {
- Self { size, align, elements: vec![] }
+ /// Create a new empty collection.
+ pub fn new(size: Size) -> Self {
+ Self { size, elements: vec![] }
}
/// Add an element at a position.
@@ -161,7 +159,7 @@ pub enum Command {
LayoutSyntaxTree(SynTree),
/// Add a finished layout.
- Add(BoxLayout),
+ Add(BoxLayout, LayoutAlign),
/// Add spacing of the given kind along the primary or secondary axis. The
/// kind defines how the spacing interacts with surrounding spacing.
AddSpacing(f64, SpacingKind, GenAxis),
diff --git a/src/layout/stack.rs b/src/layout/stack.rs
index dadc40b9..04c78da5 100644
--- a/src/layout/stack.rs
+++ b/src/layout/stack.rs
@@ -34,14 +34,10 @@ pub struct StackLayouter {
/// The context for stack layouting.
#[derive(Debug, Clone)]
pub struct StackContext {
- /// The spaces to layout into.
- pub spaces: Vec<LayoutSpace>,
/// The initial layouting system, which can be updated through `set_sys`.
pub sys: LayoutSystem,
- /// The alignment of the _resulting_ layout. This does not effect the line
- /// layouting itself, but rather how the finished layout will be positioned
- /// in a parent layout.
- pub align: LayoutAlign,
+ /// The spaces to layout into.
+ pub spaces: Vec<LayoutSpace>,
/// Whether to spill over into copies of the last space or finish layouting
/// when the last space is used up.
pub repeat: bool,
@@ -59,11 +55,11 @@ impl StackLayouter {
}
/// Add a layout to the stack.
- pub fn add(&mut self, layout: BoxLayout) {
+ pub fn add(&mut self, layout: BoxLayout, align: LayoutAlign) {
// If the alignment cannot be fitted in this space, finish it.
// TODO: Issue warning for non-fitting alignment in non-repeating
// context.
- if !self.update_rulers(layout.align) && self.ctx.repeat {
+ if !self.update_rulers(align) && self.ctx.repeat {
self.finish_space(true);
}
@@ -84,7 +80,7 @@ impl StackLayouter {
// Add the box to the vector and remember that spacings are allowed
// again.
- self.space.layouts.push((self.ctx.sys, layout));
+ self.space.layouts.push((self.ctx.sys, align, layout));
self.space.last_spacing = LastSpacing::None;
}
@@ -100,10 +96,8 @@ impl StackLayouter {
self.update_metrics(size);
self.space.layouts.push((
self.ctx.sys,
- BoxLayout::new(
- size.specialized(self.ctx.sys),
- LayoutAlign::default(),
- ),
+ LayoutAlign::default(),
+ BoxLayout::new(size.specialized(self.ctx.sys)),
));
self.space.last_spacing = LastSpacing::Hard;
@@ -279,7 +273,7 @@ impl StackLayouter {
y1: start.y + self.space.size.height,
};
- for (sys, layout) in &self.space.layouts {
+ for (sys, _, layout) in &self.space.layouts {
// First, we store the bounds calculated so far (which were reduced
// by the predecessors of this layout) as the initial bounding box
// of this layout.
@@ -303,7 +297,7 @@ impl StackLayouter {
let mut rotation = SpecAxis::Vertical;
for (bound, entry) in bounds.iter_mut().zip(&self.space.layouts).rev() {
- let (sys, layout) = entry;
+ let (sys, _, layout) = entry;
// When the axes are rotated, the maximal primary size (`extent.x`)
// dictates how much secondary extent the whole run had. This value
@@ -331,12 +325,11 @@ impl StackLayouter {
// Step 4: Align each layout in its bounding box and collect everything
// into a single finished layout.
- let mut layout = BoxLayout::new(size, self.ctx.align);
+ let mut layout = BoxLayout::new(size);
let layouts = std::mem::take(&mut self.space.layouts);
- for ((sys, child), bound) in layouts.into_iter().zip(bounds) {
+ for ((sys, align, child), bound) in layouts.into_iter().zip(bounds) {
let size = child.size.specialized(sys);
- let align = child.align;
// The space in which this layout is aligned is given by the
// distances between the borders of its bounding box.
@@ -373,7 +366,7 @@ struct Space {
/// Whether to include a layout for this space even if it would be empty.
hard: bool,
/// The so-far accumulated layouts.
- layouts: Vec<(LayoutSystem, BoxLayout)>,
+ layouts: Vec<(LayoutSystem, LayoutAlign, BoxLayout)>,
/// The specialized size of this space.
size: Size,
/// The specialized remaining space.
diff --git a/src/layout/tree.rs b/src/layout/tree.rs
index 4e15fb12..fde7833e 100644
--- a/src/layout/tree.rs
+++ b/src/layout/tree.rs
@@ -1,5 +1,7 @@
//! Layouting of syntax trees.
+use fontdock::FontStyle;
+
use super::*;
use crate::eval::Eval;
use crate::shaping;
@@ -25,7 +27,6 @@ impl<'a> TreeLayouter<'a> {
let layouter = LineLayouter::new(LineContext {
spaces: ctx.constraints.spaces.clone(),
sys: ctx.state.sys,
- align: ctx.state.align,
repeat: ctx.constraints.repeat,
line_spacing: ctx.state.text.line_spacing(),
});
@@ -99,16 +100,31 @@ impl<'a> TreeLayouter<'a> {
}
async fn layout_text(&mut self, text: &str) {
- self.layouter.add(
- shaping::shape(
- text,
- self.ctx.state.sys.primary,
- self.ctx.state.align,
- &self.ctx.state.text,
- &mut self.ctx.loader.borrow_mut(),
- )
- .await,
- );
+ let mut variant = self.ctx.state.text.variant;
+
+ if self.ctx.state.text.strong {
+ variant.weight = variant.weight.thicken(300);
+ }
+
+ if self.ctx.state.text.emph {
+ variant.style = match variant.style {
+ FontStyle::Normal => FontStyle::Italic,
+ FontStyle::Italic => FontStyle::Normal,
+ FontStyle::Oblique => FontStyle::Normal,
+ }
+ }
+
+ let boxed = shaping::shape(
+ text,
+ self.ctx.state.sys.primary,
+ self.ctx.state.text.font_size(),
+ variant,
+ &self.ctx.state.text.fallback,
+ &mut self.ctx.loader.borrow_mut(),
+ )
+ .await;
+
+ self.layouter.add(boxed, self.ctx.state.align);
}
async fn layout_heading(&mut self, heading: &NodeHeading) {
@@ -160,9 +176,7 @@ impl<'a> TreeLayouter<'a> {
};
let val = expr.v.eval(self.ctx).await;
-
let commands = val.span_with(expr.span).into_commands();
-
for command in commands {
self.execute_command(command, expr.span).await;
}
@@ -173,7 +187,7 @@ impl<'a> TreeLayouter<'a> {
match command {
LayoutSyntaxTree(tree) => self.layout_tree(&tree).await,
- Add(layout) => self.layouter.add(layout),
+ Add(layout, align) => self.layouter.add(layout, align),
AddSpacing(space, kind, axis) => match axis {
GenAxis::Primary => self.layouter.add_primary_spacing(space, kind),
GenAxis::Secondary => self.layouter.add_secondary_spacing(space, kind),