Skip to main content

LayoutEngine

Struct LayoutEngine 

Source
pub struct LayoutEngine<'a> { /* private fields */ }
Expand description

Deterministic measure → propose → query → resolve → commit engine.

Implementations§

Source§

impl<'a> LayoutEngine<'a>

Source

pub fn new( limits: &'a ResourceLimits, fonts: &'a FontManager, options: LayoutOptions, ) -> Result<Self>

Creates an engine over explicit limits and fonts.

Examples found in repository?
examples/basic.rs (line 25)
18fn main() -> Result<(), Box<dyn std::error::Error>> {
19    let limits = ResourceLimits::default();
20    let compiler = Compiler::builder().limits(limits.clone()).build()?;
21    let template = compiler.compile_template_yaml(include_bytes!("basic.yml"))?;
22    let data: DataValue = serde_json::from_slice(include_bytes!("basic-data.json"))?;
23    let document = compiler.bind(&template, &data, &[])?;
24    let fonts = example_fonts()?;
25    let scene = LayoutEngine::new(&limits, &fonts, LayoutOptions::default())?.resolve(&document)?;
26    let (output, outcome) = export_bytes(
27        &scene,
28        &ExportRequest {
29            format: ExportFormat::Svg,
30            ..ExportRequest::default()
31        },
32        &ExportContext {
33            limits: &limits,
34            fonts: &fonts,
35            assets: None,
36        },
37    )?;
38    let output_path = output_path("basic.svg")?;
39    std::fs::write(&output_path, output)?;
40    println!(
41        "pages={} svg_bytes={} output={}",
42        scene.pages.len(),
43        outcome.bytes_written,
44        output_path.display()
45    );
46    Ok(())
47}
More examples
Hide additional examples
examples/intermediate.rs (line 48)
23fn main() -> Result<(), Box<dyn std::error::Error>> {
24    let limits = ResourceLimits::default();
25    let compiler = Compiler::builder().limits(limits.clone()).build()?;
26    let template = compiler.compile_template_yaml(include_bytes!("intermediate.yml"))?;
27    let data: DataValue = serde_json::from_slice(include_bytes!("intermediate-data.json"))?;
28    let mut document = compiler.bind(&template, &data, &[])?;
29    let mut log = OperationLog::new_bounded(8, 8 * 1024 * 1024)?;
30    let patch = Patch {
31        sequence: 1,
32        operations: vec![PatchOperation::Move {
33            id: ElementId::new("review-marker")?,
34            x: "185mm".parse()?,
35            y: "112mm".parse()?,
36        }],
37    };
38    log.apply(&mut document, &patch, limits.max_patch_operations)?;
39    let fonts = example_fonts()?;
40    let fingerprint = DocumentFingerprint::compute_with_patches(
41        &template,
42        &data,
43        std::slice::from_ref(&patch),
44        None,
45        &fonts,
46        &limits,
47    )?;
48    let engine = LayoutEngine::new(&limits, &fonts, LayoutOptions::default())?;
49    let mut cache = SceneCache::with_byte_capacity(8, 64 * 1024 * 1024)?;
50    let scene = engine.resolve_cached(&document, fingerprint, &mut cache)?;
51    let cached = engine.resolve_cached(&document, fingerprint, &mut cache)?;
52    if !Arc::ptr_eq(&scene, &cached) || scene.pages.len() != 2 {
53        return Err(std::io::Error::other("expected one cached two-page scene").into());
54    }
55
56    let pdf_request = ExportRequest {
57        format: ExportFormat::Pdf,
58        pdf_mode: PdfMode::Editable,
59        ..ExportRequest::default()
60    };
61    let context = ExportContext {
62        limits: &limits,
63        fonts: &fonts,
64        assets: None,
65    };
66    let report = preflight(
67        &scene,
68        &pdf_request,
69        &context,
70        &PreflightOptions {
71            strict: true,
72            ..PreflightOptions::default()
73        },
74        &OperationControl::default(),
75    )?;
76    report.enforce(true)?;
77    let (pdf, pdf_outcome) = export_bytes(&scene, &pdf_request, &context)?;
78    let (html, html_outcome) = export_bytes(
79        &scene,
80        &ExportRequest {
81            format: ExportFormat::Html,
82            html_mode: HtmlMode::Fixed,
83            ..ExportRequest::default()
84        },
85        &context,
86    )?;
87    let (page_one_svg, page_one_outcome) = export_svg_page(&scene, 0, &context)?;
88    let (page_two_svg, page_two_outcome) = export_svg_page(&scene, 1, &context)?;
89
90    let pdf_path = output_path("intermediate.pdf")?;
91    let html_path = output_path("intermediate.html")?;
92    let page_one_path = output_path("intermediate-page-1.svg")?;
93    let page_two_path = output_path("intermediate-page-2.svg")?;
94    let report_path = output_path("intermediate-preflight.json")?;
95    std::fs::write(&pdf_path, pdf)?;
96    std::fs::write(&html_path, html)?;
97    std::fs::write(&page_one_path, page_one_svg)?;
98    std::fs::write(&page_two_path, page_two_svg)?;
99    std::fs::write(&report_path, serde_json::to_vec_pretty(&report)?)?;
100    let inspector = SceneInspector::new(&scene);
101    println!(
102        "pages={} roles={:?}/{:?} undo={} pdf_bytes={} html_bytes={} svg_bytes={}/{}\npdf={}\nhtml={}\npage_1={}\npage_2={}\npreflight={}",
103        scene.pages.len(),
104        inspector.inspect_page(0)?.role,
105        inspector.inspect_page(1)?.role,
106        log.undo_len(),
107        pdf_outcome.bytes_written,
108        html_outcome.bytes_written,
109        page_one_outcome.bytes_written,
110        page_two_outcome.bytes_written,
111        pdf_path.display(),
112        html_path.display(),
113        page_one_path.display(),
114        page_two_path.display(),
115        report_path.display()
116    );
117    Ok(())
118}
Source

pub fn new_controlled( limits: &'a ResourceLimits, fonts: &'a FontManager, options: LayoutOptions, control: OperationControl, ) -> Result<Self>

Creates an engine with cooperative cancellation and progress controls.

Source

pub fn with_assets(self, assets: &'a dyn AssetResolver) -> Self

Supplies the explicit resolver needed to resolve image paint geometry.

Source

pub fn resolve(&self, document: &DocumentIr) -> Result<ResolvedScene>

Resolves all geometry before any exporter is selected.

Examples found in repository?
examples/basic.rs (line 25)
18fn main() -> Result<(), Box<dyn std::error::Error>> {
19    let limits = ResourceLimits::default();
20    let compiler = Compiler::builder().limits(limits.clone()).build()?;
21    let template = compiler.compile_template_yaml(include_bytes!("basic.yml"))?;
22    let data: DataValue = serde_json::from_slice(include_bytes!("basic-data.json"))?;
23    let document = compiler.bind(&template, &data, &[])?;
24    let fonts = example_fonts()?;
25    let scene = LayoutEngine::new(&limits, &fonts, LayoutOptions::default())?.resolve(&document)?;
26    let (output, outcome) = export_bytes(
27        &scene,
28        &ExportRequest {
29            format: ExportFormat::Svg,
30            ..ExportRequest::default()
31        },
32        &ExportContext {
33            limits: &limits,
34            fonts: &fonts,
35            assets: None,
36        },
37    )?;
38    let output_path = output_path("basic.svg")?;
39    std::fs::write(&output_path, output)?;
40    println!(
41        "pages={} svg_bytes={} output={}",
42        scene.pages.len(),
43        outcome.bytes_written,
44        output_path.display()
45    );
46    Ok(())
47}
Source

pub fn resolve_cached( &self, document: &DocumentIr, fingerprint: DocumentFingerprint, cache: &mut SceneCache, ) -> Result<Arc<ResolvedScene>>

Resolves only on a fingerprint miss and returns an immutable shared scene.

The fingerprint must be computed from the same template, data, patches, assets, and fonts used to produce document and this engine.

Examples found in repository?
examples/intermediate.rs (line 50)
23fn main() -> Result<(), Box<dyn std::error::Error>> {
24    let limits = ResourceLimits::default();
25    let compiler = Compiler::builder().limits(limits.clone()).build()?;
26    let template = compiler.compile_template_yaml(include_bytes!("intermediate.yml"))?;
27    let data: DataValue = serde_json::from_slice(include_bytes!("intermediate-data.json"))?;
28    let mut document = compiler.bind(&template, &data, &[])?;
29    let mut log = OperationLog::new_bounded(8, 8 * 1024 * 1024)?;
30    let patch = Patch {
31        sequence: 1,
32        operations: vec![PatchOperation::Move {
33            id: ElementId::new("review-marker")?,
34            x: "185mm".parse()?,
35            y: "112mm".parse()?,
36        }],
37    };
38    log.apply(&mut document, &patch, limits.max_patch_operations)?;
39    let fonts = example_fonts()?;
40    let fingerprint = DocumentFingerprint::compute_with_patches(
41        &template,
42        &data,
43        std::slice::from_ref(&patch),
44        None,
45        &fonts,
46        &limits,
47    )?;
48    let engine = LayoutEngine::new(&limits, &fonts, LayoutOptions::default())?;
49    let mut cache = SceneCache::with_byte_capacity(8, 64 * 1024 * 1024)?;
50    let scene = engine.resolve_cached(&document, fingerprint, &mut cache)?;
51    let cached = engine.resolve_cached(&document, fingerprint, &mut cache)?;
52    if !Arc::ptr_eq(&scene, &cached) || scene.pages.len() != 2 {
53        return Err(std::io::Error::other("expected one cached two-page scene").into());
54    }
55
56    let pdf_request = ExportRequest {
57        format: ExportFormat::Pdf,
58        pdf_mode: PdfMode::Editable,
59        ..ExportRequest::default()
60    };
61    let context = ExportContext {
62        limits: &limits,
63        fonts: &fonts,
64        assets: None,
65    };
66    let report = preflight(
67        &scene,
68        &pdf_request,
69        &context,
70        &PreflightOptions {
71            strict: true,
72            ..PreflightOptions::default()
73        },
74        &OperationControl::default(),
75    )?;
76    report.enforce(true)?;
77    let (pdf, pdf_outcome) = export_bytes(&scene, &pdf_request, &context)?;
78    let (html, html_outcome) = export_bytes(
79        &scene,
80        &ExportRequest {
81            format: ExportFormat::Html,
82            html_mode: HtmlMode::Fixed,
83            ..ExportRequest::default()
84        },
85        &context,
86    )?;
87    let (page_one_svg, page_one_outcome) = export_svg_page(&scene, 0, &context)?;
88    let (page_two_svg, page_two_outcome) = export_svg_page(&scene, 1, &context)?;
89
90    let pdf_path = output_path("intermediate.pdf")?;
91    let html_path = output_path("intermediate.html")?;
92    let page_one_path = output_path("intermediate-page-1.svg")?;
93    let page_two_path = output_path("intermediate-page-2.svg")?;
94    let report_path = output_path("intermediate-preflight.json")?;
95    std::fs::write(&pdf_path, pdf)?;
96    std::fs::write(&html_path, html)?;
97    std::fs::write(&page_one_path, page_one_svg)?;
98    std::fs::write(&page_two_path, page_two_svg)?;
99    std::fs::write(&report_path, serde_json::to_vec_pretty(&report)?)?;
100    let inspector = SceneInspector::new(&scene);
101    println!(
102        "pages={} roles={:?}/{:?} undo={} pdf_bytes={} html_bytes={} svg_bytes={}/{}\npdf={}\nhtml={}\npage_1={}\npage_2={}\npreflight={}",
103        scene.pages.len(),
104        inspector.inspect_page(0)?.role,
105        inspector.inspect_page(1)?.role,
106        log.undo_len(),
107        pdf_outcome.bytes_written,
108        html_outcome.bytes_written,
109        page_one_outcome.bytes_written,
110        page_two_outcome.bytes_written,
111        pdf_path.display(),
112        html_path.display(),
113        page_one_path.display(),
114        page_two_path.display(),
115        report_path.display()
116    );
117    Ok(())
118}

Auto Trait Implementations§

§

impl<'a> !RefUnwindSafe for LayoutEngine<'a>

§

impl<'a> !UnwindSafe for LayoutEngine<'a>

§

impl<'a> Freeze for LayoutEngine<'a>

§

impl<'a> Send for LayoutEngine<'a>

§

impl<'a> Sync for LayoutEngine<'a>

§

impl<'a> Unpin for LayoutEngine<'a>

§

impl<'a> UnsafeUnpin for LayoutEngine<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Finish for T

Source§

fn finish(self)

Does nothing but move self, equivalent to drop.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<U, T> ToOwnedObj<U> for T
where U: FromObjRef<T>,

Source§

fn to_owned_obj(&self, data: FontData<'_>) -> U

Convert this type into T, using the provided data to resolve any offsets.
Source§

impl<U, T> ToOwnedTable<U> for T
where U: FromTableRef<T>,

Source§

fn to_owned_table(&self) -> U

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.