mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Update standard library functions 🎁
This commit is contained in:
parent
4d0bdc4ca4
commit
f6cb4d725e
@ -20,6 +20,7 @@ pub mod prelude {
|
|||||||
pub use crate::size::{Size, Size2D, SizeBox};
|
pub use crate::size::{Size, Size2D, SizeBox};
|
||||||
pub use crate::style::{PageStyle, TextStyle};
|
pub use crate::style::{PageStyle, TextStyle};
|
||||||
pub use super::helpers::*;
|
pub use super::helpers::*;
|
||||||
|
pub use Command::*;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Typesetting function types.
|
/// Typesetting function types.
|
||||||
@ -93,6 +94,9 @@ pub enum Command<'a> {
|
|||||||
Add(Layout),
|
Add(Layout),
|
||||||
AddMultiple(MultiLayout),
|
AddMultiple(MultiLayout),
|
||||||
|
|
||||||
|
AddPrimarySpace(Size),
|
||||||
|
AddSecondarySpace(Size),
|
||||||
|
|
||||||
FinishRun,
|
FinishRun,
|
||||||
FinishBox,
|
FinishBox,
|
||||||
FinishLayout,
|
FinishLayout,
|
||||||
|
@ -67,7 +67,7 @@ impl FlexLayouter {
|
|||||||
/// Create a new flex layouter.
|
/// Create a new flex layouter.
|
||||||
pub fn new(ctx: FlexContext) -> FlexLayouter {
|
pub fn new(ctx: FlexContext) -> FlexLayouter {
|
||||||
let stack = StackLayouter::new(StackContext {
|
let stack = StackLayouter::new(StackContext {
|
||||||
spaces: ctx.spaces,
|
spaces: ctx.spaces.clone(),
|
||||||
axes: ctx.axes,
|
axes: ctx.axes,
|
||||||
shrink_to_fit: ctx.shrink_to_fit,
|
shrink_to_fit: ctx.shrink_to_fit,
|
||||||
});
|
});
|
||||||
@ -118,7 +118,7 @@ impl FlexLayouter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Update the axes in use by this flex layouter.
|
/// Update the axes in use by this flex layouter.
|
||||||
pub fn set_axes(&self, axes: LayoutAxes) {
|
pub fn set_axes(&mut self, axes: LayoutAxes) {
|
||||||
self.units.push(FlexUnit::SetAxes(axes));
|
self.units.push(FlexUnit::SetAxes(axes));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,7 +246,7 @@ impl FlexLayouter {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish_aligned_run(&mut self) -> LayoutResult<()> {
|
fn finish_aligned_run(&mut self) {
|
||||||
let anchor = self.ctx.axes.primary.anchor(self.merged_dimensions.x);
|
let anchor = self.ctx.axes.primary.anchor(self.merged_dimensions.x);
|
||||||
let factor = if self.ctx.axes.primary.axis.is_positive() { 1 } else { -1 };
|
let factor = if self.ctx.axes.primary.axis.is_positive() { 1 } else { -1 };
|
||||||
|
|
||||||
@ -259,13 +259,11 @@ impl FlexLayouter {
|
|||||||
|
|
||||||
self.merged_dimensions.y = crate::size::max(self.merged_dimensions.y, self.run.size.y);
|
self.merged_dimensions.y = crate::size::max(self.merged_dimensions.y, self.run.size.y);
|
||||||
self.run.size = Size2D::zero();
|
self.run.size = Size2D::zero();
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This layouter's context.
|
/// This layouter's context.
|
||||||
pub fn ctx(&self) -> FlexContext {
|
pub fn ctx(&self) -> &FlexContext {
|
||||||
self.ctx
|
&self.ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remaining(&self) -> LayoutResult<LayoutSpaces> {
|
pub fn remaining(&self) -> LayoutResult<LayoutSpaces> {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
//! The core layouting engine.
|
//! The core layouting engine.
|
||||||
|
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
|
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
@ -93,7 +93,7 @@ impl StackLayouter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Update the axes in use by this stack layouter.
|
/// Update the axes in use by this stack layouter.
|
||||||
pub fn set_axes(&self, axes: LayoutAxes) {
|
pub fn set_axes(&mut self, axes: LayoutAxes) {
|
||||||
if axes != self.ctx.axes {
|
if axes != self.ctx.axes {
|
||||||
self.finish_boxes();
|
self.finish_boxes();
|
||||||
self.usable = self.remains();
|
self.usable = self.remains();
|
||||||
@ -171,8 +171,8 @@ impl StackLayouter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// This layouter's context.
|
/// This layouter's context.
|
||||||
pub fn ctx(&self) -> StackContext {
|
pub fn ctx(&self) -> &StackContext {
|
||||||
self.ctx
|
&self.ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The (generalized) usable area of the current space.
|
/// The (generalized) usable area of the current space.
|
||||||
|
@ -11,21 +11,21 @@ pub fn layout_tree(tree: &SyntaxTree, ctx: LayoutContext) -> LayoutResult<MultiL
|
|||||||
struct TreeLayouter<'a, 'p> {
|
struct TreeLayouter<'a, 'p> {
|
||||||
ctx: LayoutContext<'a, 'p>,
|
ctx: LayoutContext<'a, 'p>,
|
||||||
flex: FlexLayouter,
|
flex: FlexLayouter,
|
||||||
style: Cow<'a, TextStyle>,
|
style: TextStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'p> TreeLayouter<'a, 'p> {
|
impl<'a, 'p> TreeLayouter<'a, 'p> {
|
||||||
/// Create a new layouter.
|
/// Create a new layouter.
|
||||||
fn new(ctx: LayoutContext<'a, 'p>) -> TreeLayouter<'a, 'p> {
|
fn new(ctx: LayoutContext<'a, 'p>) -> TreeLayouter<'a, 'p> {
|
||||||
TreeLayouter {
|
TreeLayouter {
|
||||||
ctx,
|
|
||||||
flex: FlexLayouter::new(FlexContext {
|
flex: FlexLayouter::new(FlexContext {
|
||||||
flex_spacing: flex_spacing(&ctx.style),
|
flex_spacing: flex_spacing(&ctx.style),
|
||||||
spaces: ctx.spaces,
|
spaces: ctx.spaces.clone(),
|
||||||
axes: ctx.axes,
|
axes: ctx.axes,
|
||||||
shrink_to_fit: ctx.shrink_to_fit,
|
shrink_to_fit: ctx.shrink_to_fit,
|
||||||
}),
|
}),
|
||||||
style: Cow::Borrowed(ctx.style),
|
style: ctx.style.clone(),
|
||||||
|
ctx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,9 +52,9 @@ impl<'a, 'p> TreeLayouter<'a, 'p> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Node::ToggleItalics => self.style.to_mut().toggle_class(FontClass::Italic),
|
Node::ToggleItalics => self.style.toggle_class(FontClass::Italic),
|
||||||
Node::ToggleBold => self.style.to_mut().toggle_class(FontClass::Bold),
|
Node::ToggleBold => self.style.toggle_class(FontClass::Bold),
|
||||||
Node::ToggleMonospace => self.style.to_mut().toggle_class(FontClass::Monospace),
|
Node::ToggleMonospace => self.style.toggle_class(FontClass::Monospace),
|
||||||
|
|
||||||
Node::Func(func) => self.layout_func(func)?,
|
Node::Func(func) => self.layout_func(func)?,
|
||||||
}
|
}
|
||||||
@ -85,13 +85,16 @@ impl<'a, 'p> TreeLayouter<'a, 'p> {
|
|||||||
Command::Add(layout) => self.flex.add(layout),
|
Command::Add(layout) => self.flex.add(layout),
|
||||||
Command::AddMultiple(layouts) => self.flex.add_multiple(layouts),
|
Command::AddMultiple(layouts) => self.flex.add_multiple(layouts),
|
||||||
|
|
||||||
|
Command::AddPrimarySpace(space) => self.flex.add_primary_space(space),
|
||||||
|
Command::AddSecondarySpace(space) => self.flex.add_secondary_space(space)?,
|
||||||
|
|
||||||
Command::FinishRun => self.flex.add_run_break(),
|
Command::FinishRun => self.flex.add_run_break(),
|
||||||
Command::FinishBox => self.flex.finish_box()?,
|
Command::FinishBox => self.flex.finish_box()?,
|
||||||
Command::FinishLayout => self.flex.finish_layout(true)?,
|
Command::FinishLayout => self.flex.finish_layout(true)?,
|
||||||
|
|
||||||
Command::BreakParagraph => self.break_paragraph()?,
|
Command::BreakParagraph => self.break_paragraph()?,
|
||||||
|
|
||||||
Command::SetStyle(style) => *self.style.to_mut() = style,
|
Command::SetStyle(style) => self.style = style,
|
||||||
Command::SetAxes(axes) => {
|
Command::SetAxes(axes) => {
|
||||||
self.flex.set_axes(axes);
|
self.flex.set_axes(axes);
|
||||||
self.ctx.axes = axes;
|
self.ctx.axes = axes;
|
||||||
|
43
src/library/axes.rs
Normal file
43
src/library/axes.rs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
use crate::func::prelude::*;
|
||||||
|
|
||||||
|
/// 📐 `align`: Aligns content in different ways.
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct Align {
|
||||||
|
body: Option<SyntaxTree>,
|
||||||
|
alignment: Alignment,
|
||||||
|
}
|
||||||
|
|
||||||
|
function! {
|
||||||
|
data: Align,
|
||||||
|
|
||||||
|
parse(args, body, ctx) {
|
||||||
|
let body = parse!(optional: body, ctx);
|
||||||
|
let arg = args.get_pos::<ArgIdent>()?;
|
||||||
|
let alignment = match arg.val {
|
||||||
|
"left" | "origin" => Alignment::Origin,
|
||||||
|
"center" => Alignment::Center,
|
||||||
|
"right" | "end" => Alignment::End,
|
||||||
|
s => err!("invalid alignment specifier: {}", s),
|
||||||
|
};
|
||||||
|
args.done()?;
|
||||||
|
|
||||||
|
Ok(Align {
|
||||||
|
body,
|
||||||
|
alignment,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
layout(this, ctx) {
|
||||||
|
let mut new_axes = ctx.axes;
|
||||||
|
new_axes.primary.alignment = this.alignment;
|
||||||
|
|
||||||
|
Ok(match &this.body {
|
||||||
|
Some(body) => commands![
|
||||||
|
SetAxes(new_axes),
|
||||||
|
LayoutTree(body),
|
||||||
|
SetAxes(ctx.axes),
|
||||||
|
],
|
||||||
|
None => commands![Command::SetAxes(new_axes)]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
21
src/library/boxed.rs
Normal file
21
src/library/boxed.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
use crate::func::prelude::*;
|
||||||
|
|
||||||
|
/// `box`: Layouts content into a box.
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct Boxed {
|
||||||
|
body: SyntaxTree,
|
||||||
|
}
|
||||||
|
|
||||||
|
function! {
|
||||||
|
data: Boxed,
|
||||||
|
|
||||||
|
parse(args, body, ctx) {
|
||||||
|
args.done()?;
|
||||||
|
let body = parse!(required: body, ctx);
|
||||||
|
Ok(Boxed { body })
|
||||||
|
}
|
||||||
|
|
||||||
|
layout(this, ctx) {
|
||||||
|
Ok(commands![AddMultiple(layout_tree(&this.body, ctx)?)])
|
||||||
|
}
|
||||||
|
}
|
@ -2,22 +2,23 @@
|
|||||||
|
|
||||||
use crate::func::Scope;
|
use crate::func::Scope;
|
||||||
|
|
||||||
mod structure;
|
pub_use_mod!(boxed);
|
||||||
mod style;
|
pub_use_mod!(axes);
|
||||||
|
pub_use_mod!(spacing);
|
||||||
pub use structure::*;
|
pub_use_mod!(style);
|
||||||
pub use style::*;
|
|
||||||
|
|
||||||
/// Create a scope with all standard functions.
|
/// Create a scope with all standard functions.
|
||||||
pub fn std() -> Scope {
|
pub fn std() -> Scope {
|
||||||
let mut std = Scope::new();
|
let mut std = Scope::new();
|
||||||
|
|
||||||
std.add::<Align>("align");
|
|
||||||
std.add::<Boxed>("box");
|
std.add::<Boxed>("box");
|
||||||
|
|
||||||
std.add::<Linebreak>("line.break");
|
std.add::<Align>("align");
|
||||||
std.add::<Linebreak>("n");
|
|
||||||
std.add::<Pagebreak>("page.break");
|
std.add::<LineBreak>("n");
|
||||||
|
std.add::<LineBreak>("line.break");
|
||||||
|
std.add::<ParagraphBreak>("paragraph.break");
|
||||||
|
std.add::<PageBreak>("page.break");
|
||||||
|
|
||||||
std.add::<HorizontalSpace>("h");
|
std.add::<HorizontalSpace>("h");
|
||||||
std.add::<VerticalSpace>("v");
|
std.add::<VerticalSpace>("v");
|
||||||
|
81
src/library/spacing.rs
Normal file
81
src/library/spacing.rs
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
use crate::func::prelude::*;
|
||||||
|
|
||||||
|
/// `line.break`, `n`: Ends the current line.
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct LineBreak;
|
||||||
|
|
||||||
|
function! {
|
||||||
|
data: LineBreak,
|
||||||
|
parse: plain,
|
||||||
|
layout(_, _) { Ok(commands![FinishRun]) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `paragraph.break`: Ends the current paragraph.
|
||||||
|
///
|
||||||
|
/// This has the same effect as two subsequent newlines.
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct ParagraphBreak;
|
||||||
|
|
||||||
|
function! {
|
||||||
|
data: ParagraphBreak,
|
||||||
|
parse: plain,
|
||||||
|
layout(_, _) { Ok(commands![FinishBox]) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `page.break`: Ends the current page.
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct PageBreak;
|
||||||
|
|
||||||
|
function! {
|
||||||
|
data: PageBreak,
|
||||||
|
parse: plain,
|
||||||
|
layout(_, _) { Ok(commands![FinishLayout]) }
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! space_func {
|
||||||
|
($ident:ident, $doc:expr, $var:ident => $command:expr) => (
|
||||||
|
#[doc = $doc]
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct $ident(Spacing);
|
||||||
|
|
||||||
|
function! {
|
||||||
|
data: $ident,
|
||||||
|
|
||||||
|
parse(args, body, _ctx) {
|
||||||
|
parse!(forbidden: body);
|
||||||
|
|
||||||
|
let arg = args.get_pos::<ArgExpr>()?;
|
||||||
|
let spacing = match arg.val {
|
||||||
|
Expression::Size(s) => Spacing::Absolute(*s),
|
||||||
|
Expression::Num(f) => Spacing::Relative(*f as f32),
|
||||||
|
_ => err!("invalid spacing, expected size or number"),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok($ident(spacing))
|
||||||
|
}
|
||||||
|
|
||||||
|
layout(this, ctx) {
|
||||||
|
let $var = match this.0 {
|
||||||
|
Spacing::Absolute(s) => s,
|
||||||
|
Spacing::Relative(f) => f * ctx.style.font_size,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(commands![$command])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Absolute or font-relative spacing.
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
enum Spacing {
|
||||||
|
Absolute(Size),
|
||||||
|
Relative(f32),
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: h != primary and v != secondary.
|
||||||
|
space_func!(HorizontalSpace, "📖 `h`: Adds horizontal whitespace.",
|
||||||
|
space => AddPrimarySpace(space));
|
||||||
|
|
||||||
|
space_func!(VerticalSpace, "📑 `v`: Adds vertical whitespace.",
|
||||||
|
space => AddSecondarySpace(space));
|
@ -1,172 +0,0 @@
|
|||||||
use crate::func::prelude::*;
|
|
||||||
use Command::*;
|
|
||||||
|
|
||||||
/// ↩ `line.break`, `n`: Ends the current line.
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub struct Linebreak;
|
|
||||||
|
|
||||||
function! {
|
|
||||||
data: Linebreak,
|
|
||||||
parse: plain,
|
|
||||||
layout(_, _) { Ok(commands![BreakFlex]) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ↕ `paragraph.break`: Ends the current paragraph.
|
|
||||||
///
|
|
||||||
/// This has the same effect as two subsequent newlines.
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub struct Parbreak;
|
|
||||||
|
|
||||||
function! {
|
|
||||||
data: Parbreak,
|
|
||||||
parse: plain,
|
|
||||||
layout(_, _) { Ok(commands![FinishFlex]) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 📜 `page.break`: Ends the current page.
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub struct Pagebreak;
|
|
||||||
|
|
||||||
function! {
|
|
||||||
data: Pagebreak,
|
|
||||||
parse: plain,
|
|
||||||
layout(_, _) { Ok(commands![BreakStack]) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 📐 `align`: Aligns content in different ways.
|
|
||||||
///
|
|
||||||
/// **Positional arguments:**
|
|
||||||
/// - `left`, `right` or `center` _(required)_.
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub struct Align {
|
|
||||||
body: Option<SyntaxTree>,
|
|
||||||
alignment: Alignment,
|
|
||||||
}
|
|
||||||
|
|
||||||
function! {
|
|
||||||
data: Align,
|
|
||||||
|
|
||||||
parse(args, body, ctx) {
|
|
||||||
let body = parse!(optional: body, ctx);
|
|
||||||
let arg = args.get_pos::<ArgIdent>()?;
|
|
||||||
let alignment = match arg.val {
|
|
||||||
"left" => Alignment::Left,
|
|
||||||
"right" => Alignment::Right,
|
|
||||||
"center" => Alignment::Center,
|
|
||||||
s => err!("invalid alignment specifier: {}", s),
|
|
||||||
};
|
|
||||||
args.done()?;
|
|
||||||
|
|
||||||
Ok(Align {
|
|
||||||
body,
|
|
||||||
alignment,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
layout(this, ctx) {
|
|
||||||
Ok(commands![match &this.body {
|
|
||||||
Some(body) => {
|
|
||||||
AddMany(layout_tree(body, LayoutContext {
|
|
||||||
alignment: this.alignment,
|
|
||||||
.. ctx
|
|
||||||
})?)
|
|
||||||
}
|
|
||||||
None => SetAlignment(this.alignment)
|
|
||||||
}])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 📦 `box`: Layouts content into a box.
|
|
||||||
///
|
|
||||||
/// **Positional arguments:** None.
|
|
||||||
///
|
|
||||||
/// **Keyword arguments:**
|
|
||||||
/// - flow: either `horizontal` or `vertical` _(optional)_.
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub struct Boxed {
|
|
||||||
body: SyntaxTree,
|
|
||||||
flow: Flow,
|
|
||||||
}
|
|
||||||
|
|
||||||
function! {
|
|
||||||
data: Boxed,
|
|
||||||
|
|
||||||
parse(args, body, ctx) {
|
|
||||||
let body = parse!(required: body, ctx);
|
|
||||||
|
|
||||||
let mut flow = Flow::Vertical;
|
|
||||||
if let Some(ident) = args.get_key_opt::<ArgIdent>("flow")? {
|
|
||||||
flow = match ident.val {
|
|
||||||
"vertical" => Flow::Vertical,
|
|
||||||
"horizontal" => Flow::Horizontal,
|
|
||||||
f => err!("invalid flow specifier: {}", f),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
args.done()?;
|
|
||||||
|
|
||||||
Ok(Boxed {
|
|
||||||
body,
|
|
||||||
flow,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
layout(this, ctx) {
|
|
||||||
Ok(commands![
|
|
||||||
AddMany(layout_tree(&this.body, LayoutContext {
|
|
||||||
flow: this.flow,
|
|
||||||
.. ctx
|
|
||||||
})?)
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! spacefunc {
|
|
||||||
($ident:ident, $doc:expr, $var:ident => $command:expr) => (
|
|
||||||
#[doc = $doc]
|
|
||||||
///
|
|
||||||
/// **Positional arguments:**
|
|
||||||
/// - Spacing as a size or number, which is interpreted as a multiple
|
|
||||||
/// of the font size _(required)_.
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub struct $ident(Spacing);
|
|
||||||
|
|
||||||
function! {
|
|
||||||
data: $ident,
|
|
||||||
|
|
||||||
parse(args, body, _ctx) {
|
|
||||||
parse!(forbidden: body);
|
|
||||||
|
|
||||||
let arg = args.get_pos::<ArgExpr>()?;
|
|
||||||
let spacing = match arg.val {
|
|
||||||
Expression::Size(s) => Spacing::Absolute(*s),
|
|
||||||
Expression::Num(f) => Spacing::Relative(*f as f32),
|
|
||||||
_ => err!("invalid spacing, expected size or number"),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok($ident(spacing))
|
|
||||||
}
|
|
||||||
|
|
||||||
layout(this, ctx) {
|
|
||||||
let $var = match this.0 {
|
|
||||||
Spacing::Absolute(s) => s,
|
|
||||||
Spacing::Relative(f) => f * ctx.style.font_size,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(commands![$command])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Absolute or font-relative spacing.
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
enum Spacing {
|
|
||||||
Absolute(Size),
|
|
||||||
Relative(f32),
|
|
||||||
}
|
|
||||||
|
|
||||||
spacefunc!(HorizontalSpace, "📖 `h`: Adds horizontal whitespace.",
|
|
||||||
space => AddFlex(Layout::empty(space, Size::zero())));
|
|
||||||
|
|
||||||
spacefunc!(VerticalSpace, "📑 `v`: Adds vertical whitespace.",
|
|
||||||
space => Add(Layout::empty(Size::zero(), space)));
|
|
@ -23,17 +23,17 @@ macro_rules! stylefunc {
|
|||||||
|
|
||||||
Ok(match &this.body {
|
Ok(match &this.body {
|
||||||
Some(body) => commands![
|
Some(body) => commands![
|
||||||
Command::SetStyle(new_style),
|
SetStyle(new_style),
|
||||||
Command::LayoutTree(body),
|
LayoutTree(body),
|
||||||
Command::SetStyle(ctx.style.clone()),
|
SetStyle(ctx.style.clone()),
|
||||||
],
|
],
|
||||||
None => commands![Command::SetStyle(new_style)]
|
None => commands![SetStyle(new_style)]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
stylefunc!(Italic, "💡 `italic`: Sets text in _italics_.");
|
stylefunc!(Italic, "`italic`: Sets text in _italics_.");
|
||||||
stylefunc!(Bold, "🧱 `bold`: Sets text in **bold**.");
|
stylefunc!(Bold, "`bold`: Sets text in **bold**.");
|
||||||
stylefunc!(Monospace, "👩💻 `mono`: Sets text in `monospace`.");
|
stylefunc!(Monospace, "`mono`: Sets text in `monospace`.");
|
||||||
|
@ -57,3 +57,10 @@ macro_rules! debug_display {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! pub_use_mod {
|
||||||
|
($name:ident) => {
|
||||||
|
mod $name;
|
||||||
|
pub use $name::*;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -77,7 +77,7 @@ fn test(name: &str, src: &str) {
|
|||||||
|
|
||||||
// Make run warm.
|
// Make run warm.
|
||||||
#[cfg(not(debug_assertions))] let warmup_start = Instant::now();
|
#[cfg(not(debug_assertions))] let warmup_start = Instant::now();
|
||||||
typesetter.typeset(&src).unwrap();
|
#[cfg(not(debug_assertions))] typesetter.typeset(&src).unwrap();
|
||||||
#[cfg(not(debug_assertions))] let warmup_end = Instant::now();
|
#[cfg(not(debug_assertions))] let warmup_end = Instant::now();
|
||||||
|
|
||||||
// Layout into box layout.
|
// Layout into box layout.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user