diff options
| author | Laurenz <laurmaedje@gmail.com> | 2021-03-19 17:57:31 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2021-03-19 17:57:31 +0100 |
| commit | 264a7dedd42e27cd9e604037640cf0594b2ec46b (patch) | |
| tree | d26feea399d54bb86bd44878f40293983bf5251d /src/layout | |
| parent | ca3df70e2a5069832d7d2135967674c34a155442 (diff) | |
Scheduled maintenance 🔨
- New naming scheme
- TextNode instead of NodeText
- CallExpr instead of ExprCall
- ...
- Less glob imports
- Removes Value::Args variant
- Removes prelude
- Renames Layouted to Fragment
- Moves font into env
- Moves shaping into layout
- Moves frame into separate module
Diffstat (limited to 'src/layout')
| -rw-r--r-- | src/layout/background.rs | 12 | ||||
| -rw-r--r-- | src/layout/fixed.rs | 11 | ||||
| -rw-r--r-- | src/layout/frame.rs | 82 | ||||
| -rw-r--r-- | src/layout/mod.rs | 106 | ||||
| -rw-r--r-- | src/layout/node.rs | 24 | ||||
| -rw-r--r-- | src/layout/pad.rs | 11 | ||||
| -rw-r--r-- | src/layout/par.rs | 20 | ||||
| -rw-r--r-- | src/layout/shaping.rs | 198 | ||||
| -rw-r--r-- | src/layout/spacing.rs | 16 | ||||
| -rw-r--r-- | src/layout/stack.rs | 20 | ||||
| -rw-r--r-- | src/layout/text.rs | 17 |
11 files changed, 359 insertions, 158 deletions
diff --git a/src/layout/background.rs b/src/layout/background.rs index b331ba3c..bb155073 100644 --- a/src/layout/background.rs +++ b/src/layout/background.rs @@ -1,16 +1,16 @@ use super::*; -/// A node that places a rectangular filled background behind another node. +/// A node that places a rectangular filled background behind its child. #[derive(Debug, Clone, PartialEq)] -pub struct NodeBackground { +pub struct BackgroundNode { /// The background fill. pub fill: Fill, /// The child node to be filled. pub child: Node, } -impl Layout for NodeBackground { - fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted { +impl Layout for BackgroundNode { + fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Fragment { let mut layouted = self.child.layout(ctx, areas); for frame in layouted.frames_mut() { @@ -25,8 +25,8 @@ impl Layout for NodeBackground { } } -impl From<NodeBackground> for NodeAny { - fn from(background: NodeBackground) -> Self { +impl From<BackgroundNode> for AnyNode { + fn from(background: BackgroundNode) -> Self { Self::new(background) } } diff --git a/src/layout/fixed.rs b/src/layout/fixed.rs index a9554a07..e3365668 100644 --- a/src/layout/fixed.rs +++ b/src/layout/fixed.rs @@ -1,9 +1,8 @@ use super::*; -use crate::geom::Linear; /// A node that can fix its child's width and height. #[derive(Debug, Clone, PartialEq)] -pub struct NodeFixed { +pub struct FixedNode { /// The fixed width, if any. pub width: Option<Linear>, /// The fixed height, if any. @@ -12,8 +11,8 @@ pub struct NodeFixed { pub child: Node, } -impl Layout for NodeFixed { - fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted { +impl Layout for FixedNode { + fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Fragment { let Areas { current, full, .. } = areas; let size = Size::new( self.width.map(|w| w.resolve(full.width)).unwrap_or(current.width), @@ -31,8 +30,8 @@ impl Layout for NodeFixed { } } -impl From<NodeFixed> for NodeAny { - fn from(fixed: NodeFixed) -> Self { +impl From<FixedNode> for AnyNode { + fn from(fixed: FixedNode) -> Self { Self::new(fixed) } } diff --git a/src/layout/frame.rs b/src/layout/frame.rs new file mode 100644 index 00000000..c85d7539 --- /dev/null +++ b/src/layout/frame.rs @@ -0,0 +1,82 @@ +use super::Shaped; +use crate::color::Color; +use crate::env::ResourceId; +use crate::geom::{Point, Size}; + +/// A finished layout with elements at fixed positions. +#[derive(Debug, Clone, PartialEq)] +pub struct Frame { + /// The size of the frame. + pub size: Size, + /// The elements composing this layout. + pub elements: Vec<(Point, Element)>, +} + +impl Frame { + /// Create a new, empty frame. + pub fn new(size: Size) -> Self { + Self { size, elements: vec![] } + } + + /// Add an element at a position. + pub fn push(&mut self, pos: Point, element: Element) { + self.elements.push((pos, element)); + } + + /// Add all elements of another frame, placing them relative to the given + /// position. + pub fn push_frame(&mut self, pos: Point, subframe: Self) { + for (subpos, element) in subframe.elements { + self.push(pos + subpos, element); + } + } +} + +/// The building block frames are composed of. +#[derive(Debug, Clone, PartialEq)] +pub enum Element { + /// Shaped text. + Text(Shaped), + /// A geometric shape. + Geometry(Geometry), + /// A raster image. + Image(Image), +} + +/// A shape with some kind of fill. +#[derive(Debug, Clone, PartialEq)] +pub struct Geometry { + /// The shape to draw. + pub shape: Shape, + /// How the shape looks on the inside. + // + // TODO: This could be made into a Vec<Fill> or something such that + // the user can compose multiple fills with alpha values less + // than one to achieve cool effects. + pub fill: Fill, +} + +/// Some shape. +#[derive(Debug, Clone, PartialEq)] +pub enum Shape { + /// A rectangle. + Rect(Size), +} + +/// The kind of graphic fill to be applied to a [`Shape`]. +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum Fill { + /// The fill is a color. + Color(Color), + /// The fill is an image. + Image(Image), +} + +/// An image element. +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct Image { + /// The image resource. + pub res: ResourceId, + /// The size of the image in the document. + pub size: Size, +} diff --git a/src/layout/mod.rs b/src/layout/mod.rs index b5cfb1b0..ae4ab89d 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -2,27 +2,29 @@ mod background; mod fixed; +mod frame; mod node; mod pad; mod par; +mod shaping; mod spacing; mod stack; mod text; -use crate::color::Color; -use crate::env::{Env, ResourceId}; -use crate::geom::*; -use crate::shaping::Shaped; - pub use background::*; pub use fixed::*; +pub use frame::*; pub use node::*; pub use pad::*; pub use par::*; +pub use shaping::*; pub use spacing::*; pub use stack::*; pub use text::*; +use crate::env::Env; +use crate::geom::*; + /// Layout a tree into a collection of frames. pub fn layout(env: &mut Env, tree: &Tree) -> Vec<Frame> { tree.layout(&mut LayoutContext { env }) @@ -32,7 +34,7 @@ pub fn layout(env: &mut Env, tree: &Tree) -> Vec<Frame> { #[derive(Debug, Clone, PartialEq)] pub struct Tree { /// Runs of pages with the same properties. - pub runs: Vec<NodePages>, + pub runs: Vec<PageRun>, } impl Tree { @@ -44,15 +46,15 @@ impl Tree { /// A run of pages that all have the same properties. #[derive(Debug, Clone, PartialEq)] -pub struct NodePages { +pub struct PageRun { /// The size of each page. pub size: Size, /// The layout node that produces the actual pages (typically a - /// [`NodeStack`]). + /// [`StackNode`]). pub child: Node, } -impl NodePages { +impl PageRun { /// Layout the page run. pub fn layout(&self, ctx: &mut LayoutContext) -> Vec<Frame> { let areas = Areas::repeat(self.size, Spec::uniform(Expand::Fill)); @@ -64,7 +66,7 @@ impl NodePages { /// Layout a node. pub trait Layout { /// Layout the node into the given areas. - fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted; + fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Fragment; } /// The context for layouting. @@ -74,7 +76,7 @@ pub struct LayoutContext<'a> { pub env: &'a mut Env, } -/// A collection of areas to layout into. +/// A sequence of areas to layout into. #[derive(Debug, Clone, PartialEq)] pub struct Areas { /// The remaining size of the current area. @@ -155,7 +157,7 @@ impl Expand { /// The result of layouting a node. #[derive(Debug, Clone, PartialEq)] -pub enum Layouted { +pub enum Fragment { /// Spacing that should be added to the parent. Spacing(Length), /// A layout that should be added to and aligned in the parent. @@ -164,7 +166,7 @@ pub enum Layouted { Frames(Vec<Frame>, LayoutAligns), } -impl Layouted { +impl Fragment { /// Return a reference to all frames contained in this variant (zero, one or /// arbitrarily many). pub fn frames(&self) -> &[Frame] { @@ -193,81 +195,3 @@ impl Layouted { } } } - -/// A finished layout with elements at fixed positions. -#[derive(Debug, Clone, PartialEq)] -pub struct Frame { - /// The size of the frame. - pub size: Size, - /// The elements composing this layout. - pub elements: Vec<(Point, Element)>, -} - -impl Frame { - /// Create a new, empty frame. - pub fn new(size: Size) -> Self { - Self { size, elements: vec![] } - } - - /// Add an element at a position. - pub fn push(&mut self, pos: Point, element: Element) { - self.elements.push((pos, element)); - } - - /// Add all elements of another frame, placing them relative to the given - /// position. - pub fn push_frame(&mut self, pos: Point, subframe: Self) { - for (subpos, element) in subframe.elements { - self.push(pos + subpos, element); - } - } -} - -/// The building block frames are composed of. -#[derive(Debug, Clone, PartialEq)] -pub enum Element { - /// Shaped text. - Text(Shaped), - /// An image. - Image(Image), - /// Some shape that could hold another frame. - Geometry(Geometry), -} - -/// A shape with some kind of fill. -#[derive(Debug, Clone, PartialEq)] -pub struct Geometry { - /// The shape to draw. - pub shape: Shape, - /// How the shape looks on the inside. - // - // TODO: This could be made into a Vec<Fill> or something such that - // the user can compose multiple fills with alpha values less - // than one to achieve cool effects. - pub fill: Fill, -} - -/// Some shape. -#[derive(Debug, Clone, PartialEq)] -pub enum Shape { - /// A rectangle. - Rect(Size), -} - -/// The kind of graphic fill to be applied to a [`Shape`]. -#[derive(Debug, Copy, Clone, PartialEq)] -pub enum Fill { - /// The fill is a color. - Color(Color), - /// The fill is an image. - Image(Image), -} - -/// An image element. -#[derive(Debug, Copy, Clone, PartialEq)] -pub struct Image { - /// The image resource. - pub res: ResourceId, - /// The size of the image in the document. - pub size: Size, -} diff --git a/src/layout/node.rs b/src/layout/node.rs index fa7fe010..443a96ae 100644 --- a/src/layout/node.rs +++ b/src/layout/node.rs @@ -7,15 +7,15 @@ use super::*; #[derive(Clone, PartialEq)] pub enum Node { /// A text node. - Text(NodeText), + Text(TextNode), /// A spacing node. - Spacing(NodeSpacing), + Spacing(SpacingNode), /// A dynamic node that can implement custom layouting behaviour. - Any(NodeAny), + Any(AnyNode), } impl Layout for Node { - fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted { + fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Fragment { match self { Self::Spacing(spacing) => spacing.layout(ctx, areas), Self::Text(text) => text.layout(ctx, areas), @@ -35,9 +35,9 @@ impl Debug for Node { } /// A wrapper around a dynamic layouting node. -pub struct NodeAny(Box<dyn Bounds>); +pub struct AnyNode(Box<dyn Bounds>); -impl NodeAny { +impl AnyNode { /// Create a new instance from any node that satisifies the required bounds. pub fn new<T>(any: T) -> Self where @@ -47,25 +47,25 @@ impl NodeAny { } } -impl Layout for NodeAny { - fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted { +impl Layout for AnyNode { + fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Fragment { self.0.layout(ctx, areas) } } -impl Clone for NodeAny { +impl Clone for AnyNode { fn clone(&self) -> Self { Self(self.0.dyn_clone()) } } -impl PartialEq for NodeAny { +impl PartialEq for AnyNode { fn eq(&self, other: &Self) -> bool { self.0.dyn_eq(other.0.as_ref()) } } -impl Debug for NodeAny { +impl Debug for AnyNode { fn fmt(&self, f: &mut Formatter) -> fmt::Result { self.0.fmt(f) } @@ -73,7 +73,7 @@ impl Debug for NodeAny { impl<T> From<T> for Node where - T: Into<NodeAny>, + T: Into<AnyNode>, { fn from(t: T) -> Self { Self::Any(t.into()) diff --git a/src/layout/pad.rs b/src/layout/pad.rs index 88ef8828..33ce217d 100644 --- a/src/layout/pad.rs +++ b/src/layout/pad.rs @@ -1,17 +1,16 @@ use super::*; -use crate::geom::Linear; /// A node that adds padding to its child. #[derive(Debug, Clone, PartialEq)] -pub struct NodePad { +pub struct PadNode { /// The amount of padding. pub padding: Sides<Linear>, /// The child node whose sides to pad. pub child: Node, } -impl Layout for NodePad { - fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted { +impl Layout for PadNode { + fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Fragment { let areas = shrink(areas, self.padding); let mut layouted = self.child.layout(ctx, &areas); @@ -23,8 +22,8 @@ impl Layout for NodePad { } } -impl From<NodePad> for NodeAny { - fn from(pad: NodePad) -> Self { +impl From<PadNode> for AnyNode { + fn from(pad: PadNode) -> Self { Self::new(pad) } } diff --git a/src/layout/par.rs b/src/layout/par.rs index 8e8f5aac..e9fda015 100644 --- a/src/layout/par.rs +++ b/src/layout/par.rs @@ -2,7 +2,7 @@ use super::*; /// A node that arranges its children into a paragraph. #[derive(Debug, Clone, PartialEq)] -pub struct NodePar { +pub struct ParNode { /// The `main` and `cross` directions of this paragraph. /// /// The children are placed in lines along the `cross` direction. The lines @@ -16,28 +16,28 @@ pub struct NodePar { pub children: Vec<Node>, } -impl Layout for NodePar { - fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted { +impl Layout for ParNode { + fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Fragment { let mut layouter = ParLayouter::new(self, areas.clone()); for child in &self.children { match child.layout(ctx, &layouter.areas) { - Layouted::Spacing(spacing) => layouter.push_spacing(spacing), - Layouted::Frame(frame, aligns) => { + Fragment::Spacing(spacing) => layouter.push_spacing(spacing), + Fragment::Frame(frame, aligns) => { layouter.push_frame(frame, aligns.cross) } - Layouted::Frames(frames, aligns) => { + Fragment::Frames(frames, aligns) => { for frame in frames { layouter.push_frame(frame, aligns.cross); } } } } - Layouted::Frames(layouter.finish(), self.aligns) + Fragment::Frames(layouter.finish(), self.aligns) } } -impl From<NodePar> for NodeAny { - fn from(par: NodePar) -> Self { +impl From<ParNode> for AnyNode { + fn from(par: ParNode) -> Self { Self::new(par) } } @@ -57,7 +57,7 @@ struct ParLayouter { } impl ParLayouter { - fn new(par: &NodePar, areas: Areas) -> Self { + fn new(par: &ParNode, areas: Areas) -> Self { Self { main: par.dirs.main.axis(), cross: par.dirs.cross.axis(), diff --git a/src/layout/shaping.rs b/src/layout/shaping.rs new file mode 100644 index 00000000..141fa10e --- /dev/null +++ b/src/layout/shaping.rs @@ -0,0 +1,198 @@ +//! Super-basic text shaping. +//! +//! This is really only suited for simple Latin text. It picks the most suitable +//! font for each individual character. When the direction is right-to-left, the +//! word is spelled backwards. Vertical shaping is not supported. + +use std::fmt::{self, Debug, Display, Formatter}; + +use fontdock::{FaceId, FaceQuery, FallbackTree, FontVariant}; +use ttf_parser::{Face, GlyphId}; + +use crate::env::FontLoader; +use crate::geom::{Dir, Length, Point, Size}; +use crate::layout::{Element, Frame}; + +/// A shaped run of text. +#[derive(Clone, PartialEq)] +pub struct Shaped { + /// The shaped text. + pub text: String, + /// The font face the text was shaped with. + pub face: FaceId, + /// The shaped glyphs. + pub glyphs: Vec<GlyphId>, + /// The horizontal offsets of the glyphs. This is indexed parallel to + /// `glyphs`. Vertical offsets are not yet supported. + pub offsets: Vec<Length>, + /// The font size. + pub font_size: Length, +} + +impl Shaped { + /// Create a new shape run with empty `text`, `glyphs` and `offsets`. + pub fn new(face: FaceId, font_size: Length) -> Self { + Self { + text: String::new(), + face, + glyphs: vec![], + offsets: vec![], + font_size, + } + } + + /// Encode the glyph ids into a big-endian byte buffer. + pub fn encode_glyphs_be(&self) -> Vec<u8> { + let mut bytes = Vec::with_capacity(2 * self.glyphs.len()); + for &GlyphId(g) in &self.glyphs { + bytes.push((g >> 8) as u8); + bytes.push((g & 0xff) as u8); + } + bytes + } +} + +impl Debug for Shaped { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "Shaped({})", self.text) + } +} + +/// Identifies a vertical metric of a font. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] +pub enum VerticalFontMetric { + /// The distance from the baseline to the typographic ascender. + /// + /// Corresponds to the typographic ascender from the `OS/2` table if present + /// and falls back to the ascender from the `hhea` table otherwise. + Ascender, + /// The approximate height of uppercase letters. + CapHeight, + /// The approximate height of non-ascending lowercase letters. + XHeight, + /// The baseline on which the letters rest. + Baseline, + /// The distance from the baseline to the typographic descender. + /// + /// Corresponds to the typographic descender from the `OS/2` table if + /// present and falls back to the descender from the `hhea` table otherwise. + Descender, +} + +impl Display for VerticalFontMetric { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + f.pad(match self { + Self::Ascender => "ascender", + Self::CapHeight => "cap-height", + Self::XHeight => "x-height", + Self::Baseline => "baseline", + Self::Descender => "descender", + }) + } +} + +/// Shape text into a frame containing [`Shaped`] runs. +pub fn shape( + text: &str, + dir: Dir, + fallback: &FallbackTree, + variant: FontVariant, + font_size: Length, + top_edge: VerticalFontMetric, + bottom_edge: VerticalFontMetric, + loader: &mut FontLoader, +) -> Frame { + let mut frame = Frame::new(Size::new(Length::ZERO, Length::ZERO)); + let mut shaped = Shaped::new(FaceId::MAX, font_size); + let mut width = Length::ZERO; + let mut top = Length::ZERO; + let mut bottom = Length::ZERO; + + // Create an iterator with conditional direction. + let mut forwards = text.chars(); + let mut backwards = text.chars().rev(); + let chars: &mut dyn Iterator<Item = char> = if dir.is_positive() { + &mut forwards + } else { + &mut backwards + }; + + for c in chars { + let query = FaceQuery { fallback: fallback.iter(), variant, c }; + if let Some(id) = loader.query(query) { + let face = loader.face(id).get(); + let (glyph, glyph_width) = match lookup_glyph(face, c) { + Some(v) => v, + None => continue, + }; + + let units_per_em = f64::from(face.units_per_em().unwrap_or(1000)); + let convert = |units| units / units_per_em * font_size; + + // Flush the buffer and reset the metrics if we use a new font face. + if shaped.face != id { + place(&mut frame, shaped, width, top, bottom); + + shaped = Shaped::new(id, font_size); + width = Length::ZERO; + top = convert(f64::from(lookup_metric(face, top_edge))); + bottom = convert(f64::from(lookup_metric(face, bottom_edge))); + } + + shaped.text.push(c); + shaped.glyphs.push(glyph); + shaped.offsets.push(width); + width += convert(f64::from(glyph_width)); + } + } + + place(&mut frame, shaped, width, top, bottom); + + frame +} + +/// Place shaped text into a frame. +fn place(frame: &mut Frame, shaped: Shaped, width: Length, top: Length, bottom: Length) { + if !shaped.text.is_empty() { + frame.push(Point::new(frame.size.width, top), Element::Text(shaped)); + frame.size.width += width; + frame.size.height = frame.size.height.max(top - bottom); + } +} + +/// Look up the glyph for `c` and returns its index alongside its advance width. +fn lookup_glyph(face: &Face, c: char) -> Option<(GlyphId, u16)> { + let glyph = face.glyph_index(c)?; + let width = face.glyph_hor_advance(glyph)?; + Some((glyph, width)) +} + +/// Look up a vertical metric. +fn lookup_metric(face: &Face, metric: VerticalFontMetric) -> i16 { + match metric { + VerticalFontMetric::Ascender => lookup_ascender(face), + VerticalFontMetric::CapHeight => face + .capital_height() + .filter(|&h| h > 0) + .unwrap_or_else(|| lookup_ascender(face)), + VerticalFontMetric::XHeight => face + .x_height() + .filter(|&h| h > 0) + .unwrap_or_else(|| lookup_ascender(face)), + VerticalFontMetric::Baseline => 0, + VerticalFontMetric::Descender => lookup_descender(face), + } +} + +/// The ascender of the face. +fn lookup_ascender(face: &Face) -> i16 { + // We prefer the typographic ascender over the Windows ascender because + // it can be overly large if the font has large glyphs. + face.typographic_ascender().unwrap_or_else(|| face.ascender()) +} + +/// The descender of the face. +fn lookup_descender(face: &Face) -> i16 { + // See `lookup_ascender` for reason. + face.typographic_descender().unwrap_or_else(|| face.descender()) +} diff --git a/src/layout/spacing.rs b/src/layout/spacing.rs index 2bcb7ac1..361b03ee 100644 --- a/src/layout/spacing.rs +++ b/src/layout/spacing.rs @@ -2,9 +2,9 @@ use std::fmt::{self, Debug, Formatter}; use super::*; -/// A spacing node. +/// A node that adds spacing to its parent. #[derive(Copy, Clone, PartialEq)] -pub struct NodeSpacing { +pub struct SpacingNode { /// The amount of spacing to insert. pub amount: Length, /// Defines how spacing interacts with surrounding spacing. @@ -16,20 +16,20 @@ pub struct NodeSpacing { pub softness: u8, } -impl Layout for NodeSpacing { - fn layout(&self, _: &mut LayoutContext, _: &Areas) -> Layouted { - Layouted::Spacing(self.amount) +impl Layout for SpacingNode { + fn layout(&self, _: &mut LayoutContext, _: &Areas) -> Fragment { + Fragment::Spacing(self.amount) } } -impl Debug for NodeSpacing { +impl Debug for SpacingNode { fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "Spacing({}, {})", self.amount, self.softness) } } -impl From<NodeSpacing> for Node { - fn from(spacing: NodeSpacing) -> Self { +impl From<SpacingNode> for Node { + fn from(spacing: SpacingNode) -> Self { Self::Spacing(spacing) } } diff --git a/src/layout/stack.rs b/src/layout/stack.rs index 8748c5c7..32eba676 100644 --- a/src/layout/stack.rs +++ b/src/layout/stack.rs @@ -2,7 +2,7 @@ use super::*; /// A node that stacks its children. #[derive(Debug, Clone, PartialEq)] -pub struct NodeStack { +pub struct StackNode { /// The `main` and `cross` directions of this stack. /// /// The children are stacked along the `main` direction. The `cross` @@ -14,26 +14,26 @@ pub struct NodeStack { pub children: Vec<Node>, } -impl Layout for NodeStack { - fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted { +impl Layout for StackNode { + fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Fragment { let mut layouter = StackLayouter::new(self, areas.clone()); for child in &self.children { match child.layout(ctx, &layouter.areas) { - Layouted::Spacing(spacing) => layouter.push_spacing(spacing), - Layouted::Frame(frame, aligns) => layouter.push_frame(frame, aligns), - Layouted::Frames(frames, aligns) => { + Fragment::Spacing(spacing) => layouter.push_spacing(spacing), + Fragment::Frame(frame, aligns) => layouter.push_frame(frame, aligns), + Fragment::Frames(frames, aligns) => { for frame in frames { layouter.push_frame(frame, aligns); } } } } - Layouted::Frames(layouter.finish(), self.aligns) + Fragment::Frames(layouter.finish(), self.aligns) } } -impl From<NodeStack> for NodeAny { - fn from(stack: NodeStack) -> Self { +impl From<StackNode> for AnyNode { + fn from(stack: StackNode) -> Self { Self::new(stack) } } @@ -49,7 +49,7 @@ struct StackLayouter { } impl StackLayouter { - fn new(stack: &NodeStack, areas: Areas) -> Self { + fn new(stack: &StackNode, areas: Areas) -> Self { Self { main: stack.dirs.main.axis(), dirs: stack.dirs, diff --git a/src/layout/text.rs b/src/layout/text.rs index 7b4eb08e..7faefa0d 100644 --- a/src/layout/text.rs +++ b/src/layout/text.rs @@ -4,11 +4,10 @@ use std::rc::Rc; use fontdock::{FallbackTree, FontVariant}; use super::*; -use crate::shaping::{shape, VerticalFontMetric}; -/// A text node. +/// A consecutive, styled run of text. #[derive(Clone, PartialEq)] -pub struct NodeText { +pub struct TextNode { /// The text. pub text: String, /// The text direction. @@ -27,9 +26,9 @@ pub struct NodeText { pub bottom_edge: VerticalFontMetric, } -impl Layout for NodeText { - fn layout(&self, ctx: &mut LayoutContext, _: &Areas) -> Layouted { - Layouted::Frame( +impl Layout for TextNode { + fn layout(&self, ctx: &mut LayoutContext, _: &Areas) -> Fragment { + Fragment::Frame( shape( &self.text, self.dir, @@ -45,14 +44,14 @@ impl Layout for NodeText { } } -impl Debug for NodeText { +impl Debug for TextNode { fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "Text({})", self.text) } } -impl From<NodeText> for Node { - fn from(text: NodeText) -> Self { +impl From<TextNode> for Node { + fn from(text: TextNode) -> Self { Self::Text(text) } } |
