diff options
| author | Laurenz <laurmaedje@gmail.com> | 2022-11-03 11:44:53 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2022-11-03 13:35:39 +0100 |
| commit | 37a7afddfaffd44cb9bc013c9506599267e08983 (patch) | |
| tree | 20e7d62d3c5418baff01a21d0406b91bf3096214 /library/src/layout/spacing.rs | |
| parent | 56342bd972a13ffe21beaf2b87ab7eb1597704b4 (diff) | |
Split crates
Diffstat (limited to 'library/src/layout/spacing.rs')
| -rw-r--r-- | library/src/layout/spacing.rs | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/library/src/layout/spacing.rs b/library/src/layout/spacing.rs new file mode 100644 index 00000000..67fff5db --- /dev/null +++ b/library/src/layout/spacing.rs @@ -0,0 +1,100 @@ +use std::cmp::Ordering; + +use crate::prelude::*; +use crate::text::ParNode; + +/// Horizontal spacing. +#[derive(Debug, Clone, Hash)] +pub struct HNode { + pub amount: Spacing, + pub weak: bool, +} + +#[node] +impl HNode { + fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> { + let amount = args.expect("spacing")?; + let weak = args.named("weak")?.unwrap_or(false); + Ok(Self { amount, weak }.pack()) + } +} + +/// Vertical spacing. +#[derive(Debug, Clone, Hash)] +pub struct VNode { + pub amount: Spacing, + pub weak: bool, + pub generated: bool, +} + +#[node] +impl VNode { + fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> { + let amount = args.expect("spacing")?; + let weak = args.named("weak")?.unwrap_or(false); + Ok(Self { amount, weak, generated: false }.pack()) + } +} + +/// Kinds of spacing. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub enum Spacing { + /// Spacing specified in absolute terms and relative to the parent's size. + Relative(Rel<Length>), + /// Spacing specified as a fraction of the remaining free space in the + /// parent. + Fractional(Fr), +} + +impl Spacing { + /// Whether this is fractional spacing. + pub fn is_fractional(self) -> bool { + matches!(self, Self::Fractional(_)) + } +} + +impl From<Abs> for Spacing { + fn from(abs: Abs) -> Self { + Self::Relative(abs.into()) + } +} + +impl PartialOrd for Spacing { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + match (self, other) { + (Self::Relative(a), Self::Relative(b)) => a.partial_cmp(b), + (Self::Fractional(a), Self::Fractional(b)) => a.partial_cmp(b), + _ => None, + } + } +} + +castable! { + Spacing, + Expected: "relative length or fraction", + Value::Length(v) => Self::Relative(v.into()), + Value::Ratio(v) => Self::Relative(v.into()), + Value::Relative(v) => Self::Relative(v), + Value::Fraction(v) => Self::Fractional(v), +} + +/// Spacing around and between blocks, relative to paragraph spacing. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub struct BlockSpacing(Rel<Length>); + +castable!(BlockSpacing: Rel<Length>); + +impl Resolve for BlockSpacing { + type Output = Abs; + + fn resolve(self, styles: StyleChain) -> Self::Output { + let whole = styles.get(ParNode::SPACING); + self.0.resolve(styles).relative_to(whole) + } +} + +impl From<Ratio> for BlockSpacing { + fn from(ratio: Ratio) -> Self { + Self(ratio.into()) + } +} |
