typst_library/
routines.rs

1#![allow(unused)]
2
3use std::hash::{Hash, Hasher};
4use std::num::NonZeroUsize;
5
6use comemo::{Tracked, TrackedMut};
7use typst_syntax::Span;
8use typst_utils::LazyHash;
9
10use crate::diag::SourceResult;
11use crate::engine::{Engine, Route, Sink, Traced};
12use crate::foundations::{
13    Args, Cast, Closure, Content, Context, Func, Packed, Scope, StyleChain, Styles, Value,
14};
15use crate::introspection::{Introspector, Locator, SplitLocator};
16use crate::layout::{
17    Abs, BoxElem, ColumnsElem, Fragment, Frame, GridElem, InlineItem, MoveElem, PadElem,
18    PagedDocument, Region, Regions, Rel, RepeatElem, RotateElem, ScaleElem, Size,
19    SkewElem, StackElem,
20};
21use crate::math::EquationElem;
22use crate::model::{DocumentInfo, EnumElem, ListElem, TableElem};
23use crate::visualize::{
24    CircleElem, CurveElem, EllipseElem, ImageElem, LineElem, PathElem, PolygonElem,
25    RectElem, SquareElem,
26};
27use crate::World;
28
29/// Defines the `Routines` struct.
30macro_rules! routines {
31    ($(
32        $(#[$attr:meta])*
33        fn $name:ident $(<$($time:lifetime),*>)? ($($args:tt)*) -> $ret:ty
34    )*) => {
35        /// Defines implementation of various Typst compiler routines as a table
36        /// of function pointers.
37        ///
38        /// This is essentially dynamic linking and done to allow for crate
39        /// splitting.
40        pub struct Routines {
41            $(
42                $(#[$attr])*
43                pub $name: $(for<$($time),*>)? fn ($($args)*) -> $ret
44            ),*
45        }
46
47        impl Hash for Routines {
48            fn hash<H: Hasher>(&self, _: &mut H) {}
49        }
50    };
51}
52
53routines! {
54    /// Evaluates a string as code and return the resulting value.
55    fn eval_string(
56        routines: &Routines,
57        world: Tracked<dyn World + '_>,
58        string: &str,
59        span: Span,
60        mode: EvalMode,
61        scope: Scope,
62    ) -> SourceResult<Value>
63
64    /// Call the closure in the context with the arguments.
65    fn eval_closure(
66        func: &Func,
67        closure: &LazyHash<Closure>,
68        routines: &Routines,
69        world: Tracked<dyn World + '_>,
70        introspector: Tracked<Introspector>,
71        traced: Tracked<Traced>,
72        sink: TrackedMut<Sink>,
73        route: Tracked<Route>,
74        context: Tracked<Context>,
75        args: Args,
76    ) -> SourceResult<Value>
77
78    /// Realizes content into a flat list of well-known, styled items.
79    fn realize<'a>(
80        kind: RealizationKind,
81        engine: &mut Engine,
82        locator: &mut SplitLocator,
83        arenas: &'a Arenas,
84        content: &'a Content,
85        styles: StyleChain<'a>,
86    ) -> SourceResult<Vec<Pair<'a>>>
87
88    /// Lays out content into multiple regions.
89    fn layout_fragment(
90        engine: &mut Engine,
91        content: &Content,
92        locator: Locator,
93        styles: StyleChain,
94        regions: Regions,
95    ) -> SourceResult<Fragment>
96
97    /// Lays out content into a single region, producing a single frame.
98    fn layout_frame(
99        engine: &mut Engine,
100        content: &Content,
101        locator: Locator,
102        styles: StyleChain,
103        region: Region,
104    ) -> SourceResult<Frame>
105
106    /// Lays out a [`ListElem`].
107    fn layout_list(
108        elem: &Packed<ListElem>,
109        engine: &mut Engine,
110        locator: Locator,
111        styles: StyleChain,
112        regions: Regions,
113    ) -> SourceResult<Fragment>
114
115    /// Lays out an [`EnumElem`].
116    fn layout_enum(
117        elem: &Packed<EnumElem>,
118        engine: &mut Engine,
119        locator: Locator,
120        styles: StyleChain,
121        regions: Regions,
122    ) -> SourceResult<Fragment>
123
124    /// Lays out a [`GridElem`].
125    fn layout_grid(
126        elem: &Packed<GridElem>,
127        engine: &mut Engine,
128        locator: Locator,
129        styles: StyleChain,
130        regions: Regions,
131    ) -> SourceResult<Fragment>
132
133    /// Lays out a [`TableElem`].
134    fn layout_table(
135        elem: &Packed<TableElem>,
136        engine: &mut Engine,
137        locator: Locator,
138        styles: StyleChain,
139        regions: Regions,
140    ) -> SourceResult<Fragment>
141
142    /// Lays out a [`StackElem`].
143    fn layout_stack(
144        elem: &Packed<StackElem>,
145        engine: &mut Engine,
146        locator: Locator,
147        styles: StyleChain,
148        regions: Regions,
149    ) -> SourceResult<Fragment>
150
151    /// Lays out a [`ColumnsElem`].
152    fn layout_columns(
153        elem: &Packed<ColumnsElem>,
154        engine: &mut Engine,
155        locator: Locator,
156        styles: StyleChain,
157        regions: Regions,
158    ) -> SourceResult<Fragment>
159
160    /// Lays out a [`MoveElem`].
161    fn layout_move(
162        elem: &Packed<MoveElem>,
163        engine: &mut Engine,
164        locator: Locator,
165        styles: StyleChain,
166        region: Region,
167    ) -> SourceResult<Frame>
168
169    /// Lays out a [`RotateElem`].
170    fn layout_rotate(
171        elem: &Packed<RotateElem>,
172        engine: &mut Engine,
173        locator: Locator,
174        styles: StyleChain,
175        region: Region,
176    ) -> SourceResult<Frame>
177
178    /// Lays out a [`ScaleElem`].
179    fn layout_scale(
180        elem: &Packed<ScaleElem>,
181        engine: &mut Engine,
182        locator: Locator,
183        styles: StyleChain,
184        region: Region,
185    ) -> SourceResult<Frame>
186
187    /// Lays out a [`SkewElem`].
188    fn layout_skew(
189        elem: &Packed<SkewElem>,
190        engine: &mut Engine,
191        locator: Locator,
192        styles: StyleChain,
193        region: Region,
194    ) -> SourceResult<Frame>
195
196    /// Lays out a [`RepeatElem`].
197    fn layout_repeat(
198        elem: &Packed<RepeatElem>,
199        engine: &mut Engine,
200        locator: Locator,
201        styles: StyleChain,
202        region: Region,
203    ) -> SourceResult<Frame>
204
205    /// Lays out a [`PadElem`].
206    fn layout_pad(
207        elem: &Packed<PadElem>,
208        engine: &mut Engine,
209        locator: Locator,
210        styles: StyleChain,
211        regions: Regions,
212    ) -> SourceResult<Fragment>
213
214    /// Lays out a [`LineElem`].
215    fn layout_line(
216        elem: &Packed<LineElem>,
217        _: &mut Engine,
218        _: Locator,
219        styles: StyleChain,
220        region: Region,
221    ) -> SourceResult<Frame>
222
223    /// Lays out a [`CurveElem`].
224    fn layout_curve(
225        elem: &Packed<CurveElem>,
226        _: &mut Engine,
227        _: Locator,
228        styles: StyleChain,
229        region: Region,
230    ) -> SourceResult<Frame>
231
232    /// Lays out a [`PathElem`].
233    fn layout_path(
234        elem: &Packed<PathElem>,
235        _: &mut Engine,
236        _: Locator,
237        styles: StyleChain,
238        region: Region,
239    ) -> SourceResult<Frame>
240
241    /// Lays out a [`PolygonElem`].
242    fn layout_polygon(
243        elem: &Packed<PolygonElem>,
244        _: &mut Engine,
245        _: Locator,
246        styles: StyleChain,
247        region: Region,
248    ) -> SourceResult<Frame>
249
250    /// Lays out a [`RectElem`].
251    fn layout_rect(
252        elem: &Packed<RectElem>,
253        engine: &mut Engine,
254        locator: Locator,
255        styles: StyleChain,
256        region: Region,
257    ) -> SourceResult<Frame>
258
259    /// Lays out a [`SquareElem`].
260    fn layout_square(
261        elem: &Packed<SquareElem>,
262        engine: &mut Engine,
263        locator: Locator,
264        styles: StyleChain,
265        region: Region,
266    ) -> SourceResult<Frame>
267
268    /// Lays out a [`EllipseElem`].
269    fn layout_ellipse(
270        elem: &Packed<EllipseElem>,
271        engine: &mut Engine,
272        locator: Locator,
273        styles: StyleChain,
274        region: Region,
275    ) -> SourceResult<Frame>
276
277    /// Lays out a [`CircleElem`].
278    fn layout_circle(
279        elem: &Packed<CircleElem>,
280        engine: &mut Engine,
281        locator: Locator,
282        styles: StyleChain,
283        region: Region,
284    ) -> SourceResult<Frame>
285
286    /// Lays out an [`ImageElem`].
287    fn layout_image(
288        elem: &Packed<ImageElem>,
289        engine: &mut Engine,
290        locator: Locator,
291        styles: StyleChain,
292        region: Region,
293    ) -> SourceResult<Frame>
294
295    /// Lays out an [`EquationElem`] in a paragraph.
296    fn layout_equation_inline(
297        elem: &Packed<EquationElem>,
298        engine: &mut Engine,
299        locator: Locator,
300        styles: StyleChain,
301        region: Size,
302    ) -> SourceResult<Vec<InlineItem>>
303
304    /// Lays out an [`EquationElem`] in a flow.
305    fn layout_equation_block(
306        elem: &Packed<EquationElem>,
307        engine: &mut Engine,
308        locator: Locator,
309        styles: StyleChain,
310        regions: Regions,
311    ) -> SourceResult<Fragment>
312}
313
314/// In which mode to evaluate a string.
315#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Cast)]
316pub enum EvalMode {
317    /// Evaluate as code, as after a hash.
318    Code,
319    /// Evaluate as markup, like in a Typst file.
320    Markup,
321    /// Evaluate as math, as in an equation.
322    Math,
323}
324
325/// Defines what kind of realization we are performing.
326pub enum RealizationKind<'a> {
327    /// This the root realization for layout. Requires a mutable reference
328    /// to document metadata that will be filled from `set document` rules.
329    LayoutDocument(&'a mut DocumentInfo),
330    /// A nested realization in a container (e.g. a `block`). Requires a mutable
331    /// reference to an enum that will be set to `FragmentKind::Inline` if the
332    /// fragment's content was fully inline.
333    LayoutFragment(&'a mut FragmentKind),
334    /// A nested realization in a paragraph (i.e. a `par`)
335    LayoutPar,
336    /// This the root realization for HTML. Requires a mutable reference
337    /// to document metadata that will be filled from `set document` rules.
338    HtmlDocument(&'a mut DocumentInfo),
339    /// A nested realization in a container (e.g. a `block`). Requires a mutable
340    /// reference to an enum that will be set to `FragmentKind::Inline` if the
341    /// fragment's content was fully inline.
342    HtmlFragment(&'a mut FragmentKind),
343    /// A realization within math.
344    Math,
345}
346
347impl RealizationKind<'_> {
348    /// It this a realization for HTML export?
349    pub fn is_html(&self) -> bool {
350        matches!(self, Self::HtmlDocument(_) | Self::HtmlFragment(_))
351    }
352
353    /// It this a realization for a container?
354    pub fn is_fragment(&self) -> bool {
355        matches!(self, Self::LayoutFragment(_) | Self::HtmlFragment(_))
356    }
357
358    /// If this is a document-level realization, accesses the document info.
359    pub fn as_document_mut(&mut self) -> Option<&mut DocumentInfo> {
360        match self {
361            Self::LayoutDocument(info) | Self::HtmlDocument(info) => Some(*info),
362            _ => None,
363        }
364    }
365
366    /// If this is a container-level realization, accesses the fragment kind.
367    pub fn as_fragment_mut(&mut self) -> Option<&mut FragmentKind> {
368        match self {
369            Self::LayoutFragment(kind) | Self::HtmlFragment(kind) => Some(*kind),
370            _ => None,
371        }
372    }
373}
374
375/// The kind of fragment output that realization produced.
376#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
377pub enum FragmentKind {
378    /// The fragment's contents were fully inline, and as a result, the output
379    /// elements are too.
380    Inline,
381    /// The fragment contained non-inline content, so inline content was forced
382    /// into paragraphs, and as a result, the output elements are not inline.
383    Block,
384}
385
386/// Temporary storage arenas for lifetime extension during realization.
387///
388/// Must be kept live while the content returned from realization is processed.
389#[derive(Default)]
390pub struct Arenas {
391    /// A typed arena for owned content.
392    pub content: typed_arena::Arena<Content>,
393    /// A typed arena for owned styles.
394    pub styles: typed_arena::Arena<Styles>,
395    /// An untyped arena for everything that is `Copy`.
396    pub bump: bumpalo::Bump,
397}
398
399/// A pair of content and a style chain that applies to it.
400pub type Pair<'a> = (&'a Content, StyleChain<'a>);