diff --git a/src/func/mod.rs b/src/func/mod.rs index babde1ae3..48e700342 100644 --- a/src/func/mod.rs +++ b/src/func/mod.rs @@ -19,7 +19,7 @@ pub mod prelude { Expression, Ident, ExpressionKind, Spanned, Span }; - pub use crate::size::{Size, Size2D, SizeBox, ScaleSize, FSize, PSize}; + pub use crate::size::{Size, Size2D, SizeBox, ValueBox, ScaleSize, FSize, PSize}; pub use crate::style::{LayoutStyle, PageStyle, TextStyle}; pub use Command::*; } diff --git a/src/layout/tree.rs b/src/layout/tree.rs index 3c6a4274d..7910fdd3e 100644 --- a/src/layout/tree.rs +++ b/src/layout/tree.rs @@ -124,11 +124,13 @@ impl<'a, 'p> TreeLayouter<'a, 'p> { } self.style.page = style; - self.ctx.base = style.dimensions.unpadded(style.margins); + + let margins = style.margins(); + self.ctx.base = style.dimensions.unpadded(margins); self.stack.set_spaces(smallvec![ LayoutSpace { dimensions: style.dimensions, - padding: style.margins, + padding: margins, expansion: LayoutExpansion::new(true, true), } ], true); diff --git a/src/lib.rs b/src/lib.rs index c4e8fbe1e..516e2a9cc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -91,15 +91,16 @@ impl<'p> Typesetter<'p> { /// Layout a syntax tree and return the produced layout. pub fn layout(&self, tree: &SyntaxTree) -> LayoutResult { use crate::layout::prelude::*; + let margins = self.style.page.margins(); Ok(layout( &tree, LayoutContext { loader: &self.loader, style: &self.style, - base: self.style.page.dimensions.unpadded(self.style.page.margins), + base: self.style.page.dimensions.unpadded(margins), spaces: smallvec![LayoutSpace { dimensions: self.style.page.dimensions, - padding: self.style.page.margins, + padding: margins, expansion: LayoutExpansion::new(true, true), }], repeat: true, diff --git a/src/library/boxed.rs b/src/library/boxed.rs index 3e9a4c7a8..ece8b20f9 100644 --- a/src/library/boxed.rs +++ b/src/library/boxed.rs @@ -34,7 +34,7 @@ function! { for &axis in &[Horizontal, Vertical] { if let Some(psize) = map.get(axis) { - let size = psize.concretize(ctx.base.get(axis)); + let size = psize.scaled(ctx.base.get(axis)); *ctx.base.get_mut(axis) = size; *space.dimensions.get_mut(axis) = size; *space.expansion.get_mut(axis) = true; diff --git a/src/library/maps/axis.rs b/src/library/maps/axis.rs index a177a324f..ca306eab1 100644 --- a/src/library/maps/axis.rs +++ b/src/library/maps/axis.rs @@ -46,7 +46,7 @@ impl ExtentMap { let mut map = ConsistentMap::new(); for arg in args.keys() { - let key = match arg.v.key.v.0.as_str() { + let key = match arg.v.key.v.as_str() { "width" | "w" => AxisKey::Specific(Horizontal), "height" | "h" => AxisKey::Specific(Vertical), "primary-size" | "ps" => AxisKey::Generic(Primary), diff --git a/src/library/maps/mod.rs b/src/library/maps/mod.rs index 284c71810..5b027824c 100644 --- a/src/library/maps/mod.rs +++ b/src/library/maps/mod.rs @@ -10,7 +10,7 @@ macro_rules! key { impl $type { /// Parse this key from an identifier. pub fn from_ident(ident: &Spanned) -> ParseResult { - Ok(match ident.v.0.as_str() { + Ok(match ident.v.as_str() { $($patterns)* _ => error!("expected {}", ::NAME), }) diff --git a/src/library/maps/padding.rs b/src/library/maps/padding.rs index 37f2ba4ad..3da469a7f 100644 --- a/src/library/maps/padding.rs +++ b/src/library/maps/padding.rs @@ -39,17 +39,17 @@ key!(PaddingKey, "axis or side", /// A map for storing padding at sides. #[derive(Debug, Clone, PartialEq)] -pub struct PaddingMap(ConsistentMap, Size>); +pub struct PaddingMap(ConsistentMap, Option>); impl PaddingMap { /// Parse a padding map from the function args. pub fn new(args: &mut FuncArgs) -> ParseResult { let mut map = ConsistentMap::new(); - map.add_opt(PaddingKey::All, args.get_pos_opt::()?)?; + map.add_opt(PaddingKey::All, args.get_pos_opt::>()?)?; for arg in args.keys() { let key = PaddingKey::from_ident(&arg.v.key)?; - let size = Size::from_expr(arg.v.value)?; + let size = Option::::from_expr(arg.v.value)?; map.add(key, size)?; } @@ -57,7 +57,8 @@ impl PaddingMap { } /// Apply the specified padding on the size box. - pub fn apply(&self, axes: LayoutAxes, padding: &mut SizeBox) -> LayoutResult<()> { + pub fn apply(&self, axes: LayoutAxes, padding: &mut ValueBox>) + -> LayoutResult<()> { use PaddingKey::*; let map = self.0.dedup(|key, &val| { diff --git a/src/library/mod.rs b/src/library/mod.rs index 1e5e406c8..c5a5a796a 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -3,7 +3,7 @@ use toddle::query::FontClass; use crate::func::prelude::*; -use crate::style::parse_paper_name; +use crate::style::{Paper, PaperClass}; use self::maps::{ExtentMap, PaddingMap, AxisKey}; pub mod maps; @@ -73,31 +73,37 @@ function! { /// `page.size`: Set the size of pages. #[derive(Debug, PartialEq)] pub enum PageSize { - Map(ExtentMap), - Size(Size2D), + Paper(Paper), + Custom(ExtentMap), } parse(args, body) { parse!(forbidden: body); if let Some(name) = args.get_pos_opt::()? { - PageSize::Size(parse_paper_name(name.0.as_str())?) + PageSize::Paper(Paper::from_name(name.as_str())?) } else { - PageSize::Map(ExtentMap::new(&mut args, true)?) + PageSize::Custom(ExtentMap::new(&mut args, true)?) } } layout(self, ctx) { let mut style = ctx.style.page; - let dims = &mut style.dimensions; match self { - PageSize::Map(map) => { - let map = map.dedup(ctx.axes)?; - map.with(Horizontal, |&psize| dims.x = psize.concretize(dims.x)); - map.with(Vertical, |&psize| dims.y = psize.concretize(dims.y)); + PageSize::Paper(paper) => { + style.class = paper.class; + style.dimensions = paper.dimensions; + } + + PageSize::Custom(map) => { + style.class = PaperClass::Custom; + + let map = map.dedup(ctx.axes)?; + let dims = &mut style.dimensions; + map.with(Horizontal, |&psize| dims.x = psize.scaled(dims.x)); + map.with(Vertical, |&psize| dims.y = psize.scaled(dims.y)); } - PageSize::Size(size) => *dims = *size, } vec![SetPageStyle(style)] @@ -156,7 +162,7 @@ function! { layout(self, ctx) { let axis = self.axis.to_generic(ctx.axes); - let spacing = self.spacing.concretize(ctx.style.text.font_size()); + let spacing = self.spacing.scaled(ctx.style.text.font_size()); vec![AddSpacing(spacing, SpacingKind::Hard, axis)] } } diff --git a/src/size.rs b/src/size.rs index 412b657d3..edab21d1a 100644 --- a/src/size.rs +++ b/src/size.rs @@ -226,17 +226,20 @@ impl Neg for Size2D { } } -/// A size in four directions. +/// A size in four dimensions. +pub type SizeBox = ValueBox; + +/// A value in four dimensions. #[derive(Copy, Clone, PartialEq)] -pub struct SizeBox { +pub struct ValueBox { /// The left extent. - pub left: Size, + pub left: T, /// The top extent. - pub top: Size, + pub top: T, /// The right extent. - pub right: Size, + pub right: T, /// The bottom extent. - pub bottom: Size, + pub bottom: T, } impl SizeBox { @@ -247,21 +250,23 @@ impl SizeBox { right: Size::ZERO, bottom: Size::ZERO, }; +} +impl ValueBox { /// Create a new box from four sizes. - pub fn new(left: Size, top: Size, right: Size, bottom: Size) -> SizeBox { - SizeBox { left, top, right, bottom } + pub fn new(left: T, top: T, right: T, bottom: T) -> ValueBox { + ValueBox { left, top, right, bottom } } /// Create a box with all four fields set to the same value `s`. - pub fn with_all(value: Size) -> SizeBox { - SizeBox { left: value, top: value, right: value, bottom: value } + pub fn with_all(value: T) -> ValueBox { + ValueBox { left: value, top: value, right: value, bottom: value } } /// Get a mutable reference to the value for the specified direction and /// alignment. Center alignment will be treated the same as origin /// alignment. - pub fn get_mut(&mut self, mut direction: Direction, alignment: Alignment) -> &mut Size { + pub fn get_mut(&mut self, mut direction: Direction, alignment: Alignment) -> &mut T { if alignment == End { direction = direction.inv(); } @@ -274,32 +279,32 @@ impl SizeBox { } } - /// Set the `left` and `right` values. - pub fn set_all(&mut self, value: Size) { - *self = SizeBox::with_all(value); + /// Set all values to the given value. + pub fn set_all(&mut self, value: T) { + *self = ValueBox::with_all(value); } /// Set the `left` and `right` values. - pub fn set_horizontal(&mut self, value: Size) { + pub fn set_horizontal(&mut self, value: T) { self.left = value; self.right = value; } /// Set the `top` and `bottom` values. - pub fn set_vertical(&mut self, value: Size) { + pub fn set_vertical(&mut self, value: T) { self.top = value; self.bottom = value; } } -impl Display for SizeBox { +impl Display for ValueBox where T: std::fmt::Debug { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "[left: {}, top: {}, right: {}, bottom: {}]", + write!(f, "[left: {:?}, top: {:?}, right: {:?}, bottom: {:?}]", self.left, self.top, self.right, self.bottom) } } -debug_display!(SizeBox); +debug_display!(ValueBox; T where T: std::fmt::Debug + Copy); /// Either an absolute size or a factor of some metric. #[derive(Copy, Clone, PartialEq)] @@ -316,7 +321,7 @@ pub type PSize = ScaleSize; impl ScaleSize { /// Use the absolute value or scale the entity. - pub fn concretize(&self, entity: Size) -> Size { + pub fn scaled(&self, entity: Size) -> Size { match self { ScaleSize::Absolute(s) => *s, ScaleSize::Scaled(s) => *s * entity, diff --git a/src/style.rs b/src/style.rs index 3bd845153..03fb13103 100644 --- a/src/style.rs +++ b/src/style.rs @@ -3,7 +3,7 @@ use toddle::query::FontClass; use FontClass::*; -use crate::size::{Size, Size2D, SizeBox}; +use crate::size::{Size, Size2D, SizeBox, ValueBox, PSize}; use crate::syntax::ParseResult; /// Defines properties of pages and text. @@ -18,8 +18,8 @@ pub struct LayoutStyle { pub struct TextStyle { /// The classes the font has to be part of. pub classes: Vec, - /// The fallback classes from which the font needs to match the - /// leftmost possible one. + /// The fallback classes from which the font needs to match the leftmost + /// possible one. pub fallback: Vec, /// The base font size. pub base_font_size: Size, @@ -43,12 +43,12 @@ impl TextStyle { /// /// If the class was one of _italic_ or _bold_, then: /// - If it was not present before, the _regular_ class will be removed. - /// - If it was present before, the _regular_ class will be added in case the other - /// style class is not present. + /// - If it was present before, the _regular_ class will be added in case + /// the other style class is not present. pub fn toggle_class(&mut self, class: FontClass) { if self.classes.contains(&class) { - // If we retain a Bold or Italic class, we will not add - // the Regular class. + // If we retain a Bold or Italic class, we will not add the Regular + // class. let mut regular = true; self.classes.retain(|x| { if class == *x { @@ -65,8 +65,7 @@ impl TextStyle { self.classes.push(Regular); } } else { - // If we add an Italic or Bold class, we remove - // the Regular class. + // If we add an Italic or Bold class, we remove the Regular class. if class == Italic || class == Bold { self.classes.retain(|x| x != &Regular); } @@ -93,42 +92,93 @@ impl Default for TextStyle { /// Defines the size and margins of a page. #[derive(Debug, Copy, Clone)] pub struct PageStyle { + /// The class of this page. + pub class: PaperClass, /// The width and height of the page. pub dimensions: Size2D, - /// The amount of white space on each side. - pub margins: SizeBox, + /// The amount of white space on each side. If a side is set to `None`, the + /// default for the paper class is used. + pub margins: ValueBox>, +} + +impl PageStyle { + /// The default page style for the given paper. + pub fn new(paper: Paper) -> PageStyle { + PageStyle { + class: paper.class, + dimensions: paper.dimensions, + margins: ValueBox::with_all(None), + } + } + + /// The absolute margins. + pub fn margins(&self) -> SizeBox { + let dims = self.dimensions; + let default = self.class.default_margins(); + + SizeBox { + left: self.margins.left.unwrap_or(default.left).scaled(dims.x), + top: self.margins.top.unwrap_or(default.top).scaled(dims.y), + right: self.margins.right.unwrap_or(default.right).scaled(dims.x), + bottom: self.margins.bottom.unwrap_or(default.bottom).scaled(dims.y), + } + } } impl Default for PageStyle { fn default() -> PageStyle { - PageStyle { - // A4 paper. - dimensions: Size2D { - x: Size::mm(210.0), - y: Size::mm(297.0), - }, + PageStyle::new(PAPER_A4) + } +} - // All the same margins. - margins: SizeBox { - left: Size::cm(2.5), - top: Size::cm(2.5), - right: Size::cm(2.5), - bottom: Size::cm(2.5), - }, +/// Details about a type of paper. +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct Paper { + /// The kind of paper, which defines the default margins. + pub class: PaperClass, + /// The size of the paper. + pub dimensions: Size2D, +} + +impl Paper { + /// The paper with the given name. + pub fn from_name(name: &str) -> ParseResult { + parse_paper(name) + } +} + +/// What kind of page this is defines defaults for margins. +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub enum PaperClass { + Custom, + Base, +} + +impl PaperClass { + /// The default margins for this page class. + pub fn default_margins(self) -> ValueBox { + use PaperClass::*; + match self { + Custom => ValueBox::with_all(PSize::Scaled(0.1)), + Base => ValueBox::with_all(PSize::Scaled(0.1)), } } } macro_rules! papers { - ($(($var:ident: $width:expr, $height: expr, $($patterns:tt)*))*) => { - $(/// The size of the paper that's in the name. - pub const $var: Size2D = Size2D { - x: Size { points: 2.83465 * $width }, - y: Size { points: 2.83465 * $height }, + ($(($var:ident: $class:expr, $width:expr, $height: expr, $($patterns:tt)*))*) => { + use PaperClass::*; + + $(/// The infos for the paper that's in the name. + pub const $var: Paper = Paper { + dimensions: Size2D { + x: Size { points: 2.83465 * $width }, + y: Size { points: 2.83465 * $height }, + }, + class: $class, };)* - /// The size of a page with the given name. - pub fn parse_paper_name(paper: &str) -> ParseResult { + fn parse_paper(paper: &str) -> ParseResult { Ok(match paper.to_lowercase().as_str() { $($($patterns)* => $var,)* _ => error!("unknown paper size: `{}`", paper), @@ -143,184 +193,189 @@ papers! { // ISO 216 // A Series - (PAPER_A0: 841.0, 1189.0, "a0" | "poster") - (PAPER_A1: 594.0, 841.0, "a1") - (PAPER_A2: 420.0, 594.0, "a2") - (PAPER_A3: 297.0, 420.0, "a3") - (PAPER_A4: 210.0, 297.0, "a4") - (PAPER_A5: 148.0, 210.0, "a5") - (PAPER_A6: 105.0, 148.0, "a6") - (PAPER_A7: 74.0, 105.0, "a7" | "iso-7810-id-2" | "id-2" | "visa" | "flyer") - (PAPER_A8: 52.0, 74.0, "a8") - (PAPER_A9: 37.0, 52.0, "a9") - (PAPER_A10: 26.0, 37.0, "a10") - (PAPER_A11: 18.0, 26.0, "a11") + (PAPER_A0: Base, 841.0, 1189.0, "a0" | "poster") + (PAPER_A1: Base, 594.0, 841.0, "a1") + (PAPER_A2: Base, 420.0, 594.0, "a2") + (PAPER_A3: Base, 297.0, 420.0, "a3") + (PAPER_A4: Base, 210.0, 297.0, "a4") + (PAPER_A5: Base, 148.0, 210.0, "a5") + (PAPER_A6: Base, 105.0, 148.0, "a6") + (PAPER_A7: Base, 74.0, 105.0, "a7" | "iso-7810-id-2" | "id-2" | "visa" | "flyer") + (PAPER_A8: Base, 52.0, 74.0, "a8") + (PAPER_A9: Base, 37.0, 52.0, "a9") + (PAPER_A10: Base, 26.0, 37.0, "a10") + (PAPER_A11: Base, 18.0, 26.0, "a11") // B Series - (PAPER_B1: 707.0, 1000.0, "b1" | "flipchart") - (PAPER_B2: 500.0, 707.0, "b2") - (PAPER_B3: 353.0, 500.0, "b3") - (PAPER_B4: 250.0, 353.0, "b4" | "sheet-music") - (PAPER_B5: 176.0, 250.0, "b5" | "book") - (PAPER_B6: 125.0, 176.0, "b6") - (PAPER_B7: 88.0, 125.0, "b7" | "passport" | "iso-7810-id-3" | "id-3") - (PAPER_B8: 62.0, 88.0, "b8") + (PAPER_B1: Base, 707.0, 1000.0, "b1" | "flipchart") + (PAPER_B2: Base, 500.0, 707.0, "b2") + (PAPER_B3: Base, 353.0, 500.0, "b3") + (PAPER_B4: Base, 250.0, 353.0, "b4" | "sheet-music") + (PAPER_B5: Base, 176.0, 250.0, "b5" | "book") + (PAPER_B6: Base, 125.0, 176.0, "b6") + (PAPER_B7: Base, 88.0, 125.0, "b7" | "passport" | "iso-7810-id-3" | "id-3") + (PAPER_B8: Base, 62.0, 88.0, "b8") // C Series - (PAPER_C3: 324.0, 458.0, "c3") - (PAPER_C4: 229.0, 324.0, "c4") - (PAPER_C5: 162.0, 229.0, "c5") - (PAPER_C6: 114.0, 162.0, "c6") - (PAPER_C7: 81.0, 114.0, "c7") - (PAPER_C8: 57.0, 81.0, "c8") + (PAPER_C3: Base, 324.0, 458.0, "c3") + (PAPER_C4: Base, 229.0, 324.0, "c4") + (PAPER_C5: Base, 162.0, 229.0, "c5") + (PAPER_C6: Base, 114.0, 162.0, "c6") + (PAPER_C7: Base, 81.0, 114.0, "c7") + (PAPER_C8: Base, 57.0, 81.0, "c8") // D Series (DIN extension to ISO) - (PAPER_D3: 272.0, 385.0, "din-d3") - (PAPER_D4: 192.0, 272.0, "din-d4") - (PAPER_D5: 136.0, 192.0, "din-d5" | "dvd") - (PAPER_D6: 96.0, 136.0, "din-d6") - (PAPER_D7: 68.0, 96.0, "din-d7") - (PAPER_D8: 48.0, 68.0, "din-d8") + (PAPER_D3: Base, 272.0, 385.0, "din-d3") + (PAPER_D4: Base, 192.0, 272.0, "din-d4") + (PAPER_D5: Base, 136.0, 192.0, "din-d5" | "dvd") + (PAPER_D6: Base, 96.0, 136.0, "din-d6") + (PAPER_D7: Base, 68.0, 96.0, "din-d7") + (PAPER_D8: Base, 48.0, 68.0, "din-d8") // Academically relevant SIS extensions - (PAPER_G5: 169.0, 239.0, "sis-g5") - (PAPER_E5: 115.0, 220.0, "sis-e5") + (PAPER_G5: Base, 169.0, 239.0, "sis-g5") + (PAPER_E5: Base, 115.0, 220.0, "sis-e5") // ---------------------------------------------------------------------- // // Unites States // Customary - (PAPER_FOLIO: 210.0, 330.0, "folio" | "us-folio" | "us-f4") - (PAPER_LETTER: 216.0, 279.0, "letter" | "ansi-a" | "american-quarto" | "carta") - (PAPER_LEGAL: 216.0, 356.0, "legal") - (PAPER_TABLOID: 279.0, 432.0, "tabloid" | "ansi-b") - (PAPER_LEDGER: 432.0, 279.0, "ledger") - (PAPER_JUNIOR_LEGAL: 127.0, 203.0, "junior-legal" | "index-card") - (PAPER_HALF_LETTER: 140.0, 216.0, "half-letter") - (PAPER_GOVERNMENT_LETTER: 203.0, 267.0, "government-letter") - (PAPER_GOVERNMENT_LEGAL: 216.0, 330.0, "government-legal" | "officio") + (PAPER_FOLIO: Base, 210.0, 330.0, "folio" | "us-folio" | "us-f4") + (PAPER_LETTER: Base, 216.0, 279.0, "letter" | "ansi-a" | + "american-quarto" | "carta") + (PAPER_LEGAL: Base, 216.0, 356.0, "legal") + (PAPER_TABLOID: Base, 279.0, 432.0, "tabloid" | "ansi-b") + (PAPER_LEDGER: Base, 432.0, 279.0, "ledger") + (PAPER_JUNIOR_LEGAL: Base, 127.0, 203.0, "junior-legal" | "index-card") + (PAPER_HALF_LETTER: Base, 140.0, 216.0, "half-letter") + (PAPER_GOVERNMENT_LETTER: Base, 203.0, 267.0, "government-letter") + (PAPER_GOVERNMENT_LEGAL: Base, 216.0, 330.0, "government-legal" | "officio") // ANSI Extensions - (PAPER_ANSI_C: 432.0, 559.0, "ansi-c") - (PAPER_ANSI_D: 559.0, 864.0, "ansi-d") - (PAPER_ANSI_E: 864.0, 1118.0, "ansi-e") - (PAPER_ENGINEERING_F: 711.0, 1016.0, "engineering-f" | "engineering" | "navfac" | "aerospace") + (PAPER_ANSI_C: Base, 432.0, 559.0, "ansi-c") + (PAPER_ANSI_D: Base, 559.0, 864.0, "ansi-d") + (PAPER_ANSI_E: Base, 864.0, 1118.0, "ansi-e") + (PAPER_ENGINEERING_F: Base, 711.0, 1016.0, "engineering-f" | "engineering" | + "navfac" | "aerospace") // Architectural Paper - (PAPER_ARCH_A: 229.0, 305.0, "arch-a" | "arch-1") - (PAPER_ARCH_B: 305.0, 457.0, "arch-b" | "arch-2" | "extra-tabloide") - (PAPER_ARCH_C: 457.0, 610.0, "arch-c" | "arch-3") - (PAPER_ARCH_D: 610.0, 914.0, "arch-d" | "arch-4") - (PAPER_ARCH_E1: 762.0, 1067.0, "arch-e1" | "arch-5") - (PAPER_ARCH_E: 914.0, 1219.0, "arch-e" | "arch-6") + (PAPER_ARCH_A: Base, 229.0, 305.0, "arch-a" | "arch-1") + (PAPER_ARCH_B: Base, 305.0, 457.0, "arch-b" | "arch-2" | "extra-tabloide") + (PAPER_ARCH_C: Base, 457.0, 610.0, "arch-c" | "arch-3") + (PAPER_ARCH_D: Base, 610.0, 914.0, "arch-d" | "arch-4") + (PAPER_ARCH_E1: Base, 762.0, 1067.0, "arch-e1" | "arch-5") + (PAPER_ARCH_E: Base, 914.0, 1219.0, "arch-e" | "arch-6") // ---------------------------------------------------------------------- // // Japan // JIS B Series - (PAPER_JIS_B0: 1030.0, 1456.0, "jis-b0" | "jb0") - (PAPER_JIS_B1: 728.0, 1030.0, "jis-b1" | "jb1") - (PAPER_JIS_B2: 515.0, 728.0, "jis-b2" | "jb2") - (PAPER_JIS_B3: 364.0, 515.0, "jis-b3" | "jb3") - (PAPER_JIS_B4: 257.0, 364.0, "jis-b4" | "jb4") - (PAPER_JIS_B5: 182.0, 257.0, "jis-b5" | "jb5") - (PAPER_JIS_B6: 128.0, 182.0, "jis-b6" | "jb6") - (PAPER_JIS_B7: 91.0, 128.0, "jis-b7" | "jb7") - (PAPER_JIS_B8: 64.0, 91.0, "jis-b8" | "jb8") - (PAPER_JIS_B9: 45.0, 64.0, "jis-b9" | "jb9") - (PAPER_JIS_B10: 32.0, 45.0, "jis-b10" | "jb10") - (PAPER_JIS_B11: 22.0, 32.0, "jis-b11" | "jb11") + (PAPER_JIS_B0: Base, 1030.0, 1456.0, "jis-b0" | "jb0") + (PAPER_JIS_B1: Base, 728.0, 1030.0, "jis-b1" | "jb1") + (PAPER_JIS_B2: Base, 515.0, 728.0, "jis-b2" | "jb2") + (PAPER_JIS_B3: Base, 364.0, 515.0, "jis-b3" | "jb3") + (PAPER_JIS_B4: Base, 257.0, 364.0, "jis-b4" | "jb4") + (PAPER_JIS_B5: Base, 182.0, 257.0, "jis-b5" | "jb5") + (PAPER_JIS_B6: Base, 128.0, 182.0, "jis-b6" | "jb6") + (PAPER_JIS_B7: Base, 91.0, 128.0, "jis-b7" | "jb7") + (PAPER_JIS_B8: Base, 64.0, 91.0, "jis-b8" | "jb8") + (PAPER_JIS_B9: Base, 45.0, 64.0, "jis-b9" | "jb9") + (PAPER_JIS_B10: Base, 32.0, 45.0, "jis-b10" | "jb10") + (PAPER_JIS_B11: Base, 22.0, 32.0, "jis-b11" | "jb11") // Traditional - (PAPER_SHIROKU_BAN_4: 264.0, 379.0, "shiroku-ban-4") - (PAPER_SHIROKU_BAN_5: 189.0, 262.0, "shiroku-ban-5") - (PAPER_SHIROKU_BAN_6: 127.0, 188.0, "shiroku-ban-6") - (PAPER_KIKU_4: 227.0, 306.0, "kiku-4") - (PAPER_KIKU_5: 151.0, 227.0, "kiku-5") + (PAPER_SHIROKU_BAN_4: Base, 264.0, 379.0, "shiroku-ban-4") + (PAPER_SHIROKU_BAN_5: Base, 189.0, 262.0, "shiroku-ban-5") + (PAPER_SHIROKU_BAN_6: Base, 127.0, 188.0, "shiroku-ban-6") + (PAPER_KIKU_4: Base, 227.0, 306.0, "kiku-4") + (PAPER_KIKU_5: Base, 151.0, 227.0, "kiku-5") // ---------------------------------------------------------------------- // // China // Chinese D Series - (PAPER_SAC_D0: 764.0, 1064.0, "sac-d0" | "cn-d0") - (PAPER_SAC_D1: 532.0, 760.0, "sac-d1" | "cn-d1") - (PAPER_SAC_D2: 380.0, 528.0, "sac-d2" | "cn-d2") - (PAPER_SAC_D3: 264.0, 376.0, "sac-d3" | "cn-d3") - (PAPER_SAC_D4: 188.0, 260.0, "sac-d4" | "cn-d4") - (PAPER_SAC_D5: 130.0, 184.0, "sac-d5" | "cn-d5") - (PAPER_SAC_D6: 92.0, 126.0, "sac-d6" | "cn-d6") + (PAPER_SAC_D0: Base, 764.0, 1064.0, "sac-d0" | "cn-d0") + (PAPER_SAC_D1: Base, 532.0, 760.0, "sac-d1" | "cn-d1") + (PAPER_SAC_D2: Base, 380.0, 528.0, "sac-d2" | "cn-d2") + (PAPER_SAC_D3: Base, 264.0, 376.0, "sac-d3" | "cn-d3") + (PAPER_SAC_D4: Base, 188.0, 260.0, "sac-d4" | "cn-d4") + (PAPER_SAC_D5: Base, 130.0, 184.0, "sac-d5" | "cn-d5") + (PAPER_SAC_D6: Base, 92.0, 126.0, "sac-d6" | "cn-d6") // ---------------------------------------------------------------------- // // United Kingdom Imperial (Assortment) - (PAPER_MONARCH: 184.0, 267.0, "monarch") - (PAPER_QUARTO: 229.0, 279.0, "quarto" | "us-quarto") - (PAPER_UK_QUARTO: 203.0, 254.0, "uk-quarto" | "imperial-quarto") - (PAPER_UK_FOOLSCAP: 343.0, 432.0, "foolscap" | "us-foolscap") - (PAPER_FOOLSCAP: 203.0, 330.0, "imperial-foolscap" | "uk-foolscap") - (PAPER_POTT: 318.0, 381.0, "pott") - (PAPER_CROWN: 318.0, 508.0, "crown") - (PAPER_PINCHED_POST: 375.0, 470.0, "pinched-post") - (PAPER_POST: 394.0, 489.0, "post") - (PAPER_LARGE_POST: 419.0, 533.0, "large-post") - (PAPER_DEMY: 445.0, 572.0, "demy") - (PAPER_ROYAL: 508.0, 635.0, "royal") - (PAPER_DOUBLE_CROWN: 508.0, 762.0, "double-crown" | "theatre") - (PAPER_ELEPHANT: 584.0, 711.0, "elephant") - (PAPER_DOUBLE_ROYAL: 635.0, 1016.0, "double-royal" | "rail") - (PAPER_QUAD_CROWN: 762.0, 1016.0, "quad-crown" | "cinema") + (PAPER_MONARCH: Base, 184.0, 267.0, "monarch") + (PAPER_QUARTO: Base, 229.0, 279.0, "quarto" | "us-quarto") + (PAPER_UK_QUARTO: Base, 203.0, 254.0, "uk-quarto" | "imperial-quarto") + (PAPER_UK_FOOLSCAP: Base, 343.0, 432.0, "foolscap" | "us-foolscap") + (PAPER_FOOLSCAP: Base, 203.0, 330.0, "imperial-foolscap" | "uk-foolscap") + (PAPER_POTT: Base, 318.0, 381.0, "pott") + (PAPER_CROWN: Base, 318.0, 508.0, "crown") + (PAPER_PINCHED_POST: Base, 375.0, 470.0, "pinched-post") + (PAPER_POST: Base, 394.0, 489.0, "post") + (PAPER_LARGE_POST: Base, 419.0, 533.0, "large-post") + (PAPER_DEMY: Base, 445.0, 572.0, "demy") + (PAPER_ROYAL: Base, 508.0, 635.0, "royal") + (PAPER_DOUBLE_CROWN: Base, 508.0, 762.0, "double-crown" | "theatre") + (PAPER_ELEPHANT: Base, 584.0, 711.0, "elephant") + (PAPER_DOUBLE_ROYAL: Base, 635.0, 1016.0, "double-royal" | "rail") + (PAPER_QUAD_CROWN: Base, 762.0, 1016.0, "quad-crown" | "cinema") // ---------------------------------------------------------------------- // // French Traditional (AFNOR) - (PAPER_CLOCHE: 300.0, 400.0, "cloche") - (PAPER_POT: 310.0, 400.0, "pot" | "ecolier" | "écolier") - (PAPER_TELLIERE: 340.0, 440.0, "telliere" | "tellière") - (PAPER_COURONNE_ECRITURE: 360.0, 460.0, "couronne-ecriture" | "couronne" | "couronne-écriture") - (PAPER_COURONNE_EDITION: 370.0, 470.0, "couronne-edition" | "couronne-édition") - (PAPER_ROBERTO: 390.0, 500.0, "roberto") - (PAPER_ECU: 400.0, 520.0, "ecu" | "écu") - (PAPER_COQUILLE: 440.0, 560.0, "coquille") - (PAPER_CARRE: 450.0, 560.0, "carre" | "carré") - (PAPER_CAVALIER: 460.0, 620.0, "cavalier") - (PAPER_DEMI_RAISIN: 325.0, 500.0, "demi-raisin") - (PAPER_RAISIN: 500.0, 650.0, "raisin" | "dessin") - (PAPER_DOUBLE_RAISIN: 650.0, 1000.0, "double-raisin") - (PAPER_JESUS: 560.0, 760.0, "jesus" | "jésus") - (PAPER_SOLEIL: 600.0, 800.0, "soleil") - (PAPER_COLOMBIER_AFFICHE: 600.0, 800.0, "colombier-affiche" | "affiche") - (PAPER_COLOMBIER_COMMERCIAL: 630.0, 900.0, "colombier-commercial") - (PAPER_PETIT_AIGLE: 700.0, 940.0, "petit-aigle") - (PAPER_GRAND_AIGLE: 750.0, 1060.0, "grand-aigle" | "napoleon") - (PAPER_GRAND_MONDE: 900.0, 1260.0, "grand-monde") - (PAPER_UNIVERS: 1000.0, 1300.0, "univers" | "universe") + (PAPER_CLOCHE: Base, 300.0, 400.0, "cloche") + (PAPER_POT: Base, 310.0, 400.0, "pot" | "ecolier" | "écolier") + (PAPER_TELLIERE: Base, 340.0, 440.0, "telliere" | "tellière") + (PAPER_COURONNE_ECRITURE: Base, 360.0, 460.0, "couronne-ecriture" | + "couronne" | "couronne-écriture") + (PAPER_COURONNE_EDITION: Base, 370.0, 470.0, "couronne-edition" | + "couronne-édition") + (PAPER_ROBERTO: Base, 390.0, 500.0, "roberto") + (PAPER_ECU: Base, 400.0, 520.0, "ecu" | "écu") + (PAPER_COQUILLE: Base, 440.0, 560.0, "coquille") + (PAPER_CARRE: Base, 450.0, 560.0, "carre" | "carré") + (PAPER_CAVALIER: Base, 460.0, 620.0, "cavalier") + (PAPER_DEMI_RAISIN: Base, 325.0, 500.0, "demi-raisin") + (PAPER_RAISIN: Base, 500.0, 650.0, "raisin" | "dessin") + (PAPER_DOUBLE_RAISIN: Base, 650.0, 1000.0, "double-raisin") + (PAPER_JESUS: Base, 560.0, 760.0, "jesus" | "jésus") + (PAPER_SOLEIL: Base, 600.0, 800.0, "soleil") + (PAPER_COLOMBIER_AFFICHE: Base, 600.0, 800.0, "colombier-affiche" | "affiche") + (PAPER_COLOMBIER_COMMERCIAL: Base, 630.0, 900.0, "colombier-commercial") + (PAPER_PETIT_AIGLE: Base, 700.0, 940.0, "petit-aigle") + (PAPER_GRAND_AIGLE: Base, 750.0, 1060.0, "grand-aigle" | "napoleon") + (PAPER_GRAND_MONDE: Base, 900.0, 1260.0, "grand-monde") + (PAPER_UNIVERS: Base, 1000.0, 1300.0, "univers" | "universe") // ---------------------------------------------------------------------- // // Newspaper - (PAPER_COMPACT: 280.0, 430.0, "compact") - (PAPER_BERLINER: 315.0, 470.0, "berliner" | "midi") - (PAPER_RHENISH: 350.0, 520.0, "rhenish") - (PAPER_BROADSHEET: 381.0, 578.0, "broadsheet" | "newspaper") - (PAPER_NEW_YORK_TIMES: 305.0, 559.0, "new-york-times" | "times") + (PAPER_COMPACT: Base, 280.0, 430.0, "compact") + (PAPER_BERLINER: Base, 315.0, 470.0, "berliner" | "midi") + (PAPER_RHENISH: Base, 350.0, 520.0, "rhenish") + (PAPER_BROADSHEET: Base, 381.0, 578.0, "broadsheet" | "newspaper") + (PAPER_NEW_YORK_TIMES: Base, 305.0, 559.0, "new-york-times" | "times") // ---------------------------------------------------------------------- // // Books - (PAPER_FOLIO_BOOK: 304.8, 482.6, "book-folio") - (PAPER_QUARTO_BOOK: 241.3, 304.8, "book-quarto") - (PAPER_OCTAVO_BOOK: 152.4, 228.6, "book-octavo") - (PAPER_16_MO_BOOK: 101.6, 171.45, "book-16mo") - (PAPER_32_MO_BOOK: 88.9, 139.7, "book-32mo") + (PAPER_FOLIO_BOOK: Base, 304.8, 482.6, "book-folio") + (PAPER_QUARTO_BOOK: Base, 241.3, 304.8, "book-quarto") + (PAPER_OCTAVO_BOOK: Base, 152.4, 228.6, "book-octavo") + (PAPER_16_MO_BOOK: Base, 101.6, 171.45, "book-16mo") + (PAPER_32_MO_BOOK: Base, 88.9, 139.7, "book-32mo") // ---------------------------------------------------------------------- // // Various - (PAPER_ID_1: 85.6, 53.98, "id-card" | "id-1" | "iso-7810-id-1" | "eu-business-card" | "business-card") - (PAPER_US_BUSINESS_CARD: 88.9, 50.8, "us-business-card") - (PAPER_JP_BUSINESS_CARD: 91.0, 55.0, "jp-business-card") - (PAPER_CN_BUSINESS_CARD: 90.0, 54.0, "cn-business-card") - (PAPER_A4_16_9: 297.0, 148.5, "presentation-4-3") - (PAPER_A4_4_3: 280.0, 210.0, "presentation-16-9" | "presentation") - (PAPER_POSTCARD: 101.6, 152.4, "postcard") + (PAPER_ID_1: Base, 85.6, 53.98, "id-card" | "id-1" | "iso-7810-id-1" | + "eu-business-card" | "business-card") + (PAPER_US_BUSINESS_CARD: Base, 88.9, 50.8, "us-business-card") + (PAPER_JP_BUSINESS_CARD: Base, 91.0, 55.0, "jp-business-card") + (PAPER_CN_BUSINESS_CARD: Base, 90.0, 54.0, "cn-business-card") + (PAPER_A4_16_9: Base, 297.0, 148.5, "presentation-4-3") + (PAPER_A4_4_3: Base, 280.0, 210.0, "presentation-16-9" | "presentation") + (PAPER_POSTCARD: Base, 101.6, 152.4, "postcard") } diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs index 57488121d..bf395c2bf 100644 --- a/src/syntax/mod.rs +++ b/src/syntax/mod.rs @@ -235,13 +235,17 @@ debug_display!(Expression); pub struct Ident(pub String); impl Ident { - fn new(string: String) -> ParseResult { + pub fn new(string: String) -> ParseResult { if is_identifier(&string) { Ok(Ident(string)) } else { error!("invalid identifier: `{}`", string); } } + + pub fn as_str(&self) -> &str { + self.0.as_str() + } } impl Display for Ident { @@ -317,3 +321,18 @@ impl ExpressionKind for Spanned where T: ExpressionKind { .map(|v| Spanned::new(v, span)) } } + +impl ExpressionKind for Option where T: ExpressionKind { + const NAME: &'static str = T::NAME; + + fn from_expr(expr: Spanned) -> ParseResult> { + if let Expression::Ident(ident) = &expr.v { + match ident.as_str() { + "default" | "none" => return Ok(None), + _ => {}, + } + } + + T::from_expr(expr).map(|v| Some(v)) + } +} diff --git a/tests/layout.rs b/tests/layout.rs index cca0dee0d..8a72e84bb 100644 --- a/tests/layout.rs +++ b/tests/layout.rs @@ -8,7 +8,7 @@ use std::process::Command; use typstc::Typesetter; use typstc::layout::{MultiLayout, Serialize}; -use typstc::size::{Size, Size2D, SizeBox}; +use typstc::size::{Size, Size2D}; use typstc::style::PageStyle; use typstc::toddle::query::FileSystemFontProvider; use typstc::export::pdf::PdfExporter; @@ -62,7 +62,7 @@ fn test(name: &str, src: &str) -> Result<()> { let mut typesetter = Typesetter::new(); typesetter.set_page_style(PageStyle { dimensions: Size2D::with_all(Size::pt(250.0)), - margins: SizeBox::with_all(Size::pt(10.0)), + .. PageStyle::default() }); let provider = FileSystemFontProvider::from_listing("fonts/fonts.toml")?;