summaryrefslogtreecommitdiff
path: root/src/exec/state.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/exec/state.rs')
-rw-r--r--src/exec/state.rs163
1 files changed, 163 insertions, 0 deletions
diff --git a/src/exec/state.rs b/src/exec/state.rs
new file mode 100644
index 00000000..21fb7fb6
--- /dev/null
+++ b/src/exec/state.rs
@@ -0,0 +1,163 @@
+use std::rc::Rc;
+
+use fontdock::{fallback, FallbackTree, FontStretch, FontStyle, FontVariant, FontWeight};
+
+use crate::geom::{
+ Align, ChildAlign, Dir, LayoutDirs, Length, Linear, Relative, Sides, Size, Spec,
+};
+use crate::layout::Expansion;
+use crate::paper::{Paper, PaperClass, PAPER_A4};
+
+/// The evaluation state.
+#[derive(Debug, Clone, PartialEq)]
+pub struct State {
+ /// The current page settings.
+ pub page: PageSettings,
+ /// The current paragraph settings.
+ pub par: ParSettings,
+ /// The current font settings.
+ pub font: FontSettings,
+ /// The current layouting directions.
+ pub dirs: LayoutDirs,
+ /// The current alignments of an item in its parent.
+ pub align: ChildAlign,
+}
+
+impl Default for State {
+ fn default() -> Self {
+ Self {
+ page: PageSettings::default(),
+ par: ParSettings::default(),
+ font: FontSettings::default(),
+ dirs: LayoutDirs::new(Dir::TTB, Dir::LTR),
+ align: ChildAlign::new(Align::Start, Align::Start),
+ }
+ }
+}
+
+/// Defines page properties.
+#[derive(Debug, Copy, Clone, PartialEq)]
+pub struct PageSettings {
+ /// The class of this page.
+ pub class: PaperClass,
+ /// The width and height of the page.
+ pub size: Size,
+ /// Whether the expand the pages to the `size` or to fit the content.
+ pub expand: Spec<Expansion>,
+ /// The amount of white space in the order [left, top, right, bottom]. If a
+ /// side is set to `None`, the default for the paper class is used.
+ pub margins: Sides<Option<Linear>>,
+}
+
+impl PageSettings {
+ /// The default page style for the given paper.
+ pub fn new(paper: Paper) -> Self {
+ Self {
+ class: paper.class,
+ size: paper.size(),
+ expand: Spec::uniform(Expansion::Fill),
+ margins: Sides::uniform(None),
+ }
+ }
+
+ /// The margins.
+ pub fn margins(&self) -> Sides<Linear> {
+ let default = self.class.default_margins();
+ Sides {
+ left: self.margins.left.unwrap_or(default.left),
+ top: self.margins.top.unwrap_or(default.top),
+ right: self.margins.right.unwrap_or(default.right),
+ bottom: self.margins.bottom.unwrap_or(default.bottom),
+ }
+ }
+}
+
+impl Default for PageSettings {
+ fn default() -> Self {
+ Self::new(PAPER_A4)
+ }
+}
+
+/// Defines paragraph properties.
+#[derive(Debug, Copy, Clone, PartialEq)]
+pub struct ParSettings {
+ /// The spacing between words (dependent on scaled font size).
+ pub word_spacing: Linear,
+ /// The spacing between lines (dependent on scaled font size).
+ pub line_spacing: Linear,
+ /// The spacing between paragraphs (dependent on scaled font size).
+ pub par_spacing: Linear,
+}
+
+impl Default for ParSettings {
+ fn default() -> Self {
+ Self {
+ word_spacing: Relative::new(0.25).into(),
+ line_spacing: Relative::new(0.2).into(),
+ par_spacing: Relative::new(0.5).into(),
+ }
+ }
+}
+
+/// Defines font properties.
+#[derive(Debug, Clone, PartialEq)]
+pub struct FontSettings {
+ /// A tree of font family names and generic class names.
+ pub families: Rc<FallbackTree>,
+ /// The selected font variant.
+ pub variant: FontVariant,
+ /// The font size.
+ pub size: Length,
+ /// The linear to apply on the base font size.
+ pub scale: Linear,
+ /// Whether the strong toggle is active or inactive. This determines
+ /// whether the next `*` adds or removes font weight.
+ pub strong: bool,
+ /// Whether the emphasis toggle is active or inactive. This determines
+ /// whether the next `_` makes italic or non-italic.
+ pub emph: bool,
+}
+
+impl FontSettings {
+ /// Access the `families` mutably.
+ pub fn families_mut(&mut self) -> &mut FallbackTree {
+ Rc::make_mut(&mut self.families)
+ }
+
+ /// The absolute font size.
+ pub fn font_size(&self) -> Length {
+ self.scale.resolve(self.size)
+ }
+}
+
+impl Default for FontSettings {
+ fn default() -> Self {
+ Self {
+ /// The default tree of font fallbacks.
+ families: Rc::new(fallback! {
+ list: ["sans-serif"],
+ classes: {
+ "serif" => ["source serif pro", "noto serif"],
+ "sans-serif" => ["source sans pro", "noto sans"],
+ "monospace" => ["source code pro", "noto sans mono"],
+ },
+ base: [
+ "source sans pro",
+ "noto sans",
+ "segoe ui emoji",
+ "noto emoji",
+ "latin modern math",
+ ],
+ }),
+ variant: FontVariant {
+ style: FontStyle::Normal,
+ weight: FontWeight::REGULAR,
+ stretch: FontStretch::Normal,
+ },
+ size: Length::pt(11.0),
+ scale: Linear::ONE,
+ strong: false,
+ emph: false,
+ }
+ }
+}