diff --git a/crates/render/src/renderer.rs b/crates/render/src/renderer.rs index a5bfcbf26..205d4d73c 100644 --- a/crates/render/src/renderer.rs +++ b/crates/render/src/renderer.rs @@ -105,8 +105,11 @@ impl Renderer { } } - /// Render `doc` into a `width`×`height` image using `view` (document → pixel transform). + /// Render `doc` into a `width`×`height` image using `view` (document → pixel transform). Type + /// set in one of the document's composite fonts draws in the document's definition, also when + /// no session has registered it (a document that is not in front, or read from a file). pub fn render(&mut self, doc: &Document, width: u32, height: u32, view: Affine, opts: &RenderOptions) -> Rendered { + let _lent = vectorcraft_text::FontDb::global().lend_composite_fonts(&doc.composite_fonts); let _frame = vectorcraft_text::KeptLayoutsFrame::begin(); self.render_as(doc, width, height, view, opts, false, 1) } @@ -340,6 +343,7 @@ impl Renderer { pub fn render_region_inks(&mut self, doc: &Document, region: Rect, scale: f64, opts: &RenderOptions) -> Vec { let (w, h) = region_pixels(region, scale); let view = Affine::scale(scale) * Affine::translate((-region.x0, -region.y0)); + let _lent = vectorcraft_text::FontDb::global().lend_composite_fonts(&doc.composite_fonts); let _frame = vectorcraft_text::KeptLayoutsFrame::begin(); self.render_as(doc, w, h, view, opts, true, 1).pixels } @@ -356,6 +360,7 @@ impl Renderer { /// [`Self::render_node`] with `opts` (e.g. [`RenderOptions::mark_undecoded_images`]). pub fn render_node_with(&mut self, doc: &Document, n: &Arc, w: u16, h: u16, view: Affine, opts: &RenderOptions) -> Option { + let _lent = vectorcraft_text::FontDb::global().lend_composite_fonts(&doc.composite_fonts); self.check_plugins(doc); self.check_symbols(doc); let inv = view.inverse(); @@ -395,6 +400,7 @@ impl Renderer { background: Option<[u8; 4]>, opts: &RenderOptions, ) -> Option { + let _lent = vectorcraft_text::FontDb::global().lend_composite_fonts(&doc.composite_fonts); self.check_plugins(doc); self.check_symbols(doc); let b = brush_fx::cull_bounds(&doc.symbol_boxes(), n)?; diff --git a/crates/render/src/tests/fontchange.rs b/crates/render/src/tests/fontchange.rs index 82c5c77ff..4ead4a5c1 100644 --- a/crates/render/src/tests/fontchange.rs +++ b/crates/render/src/tests/fontchange.rs @@ -138,6 +138,50 @@ fn composite_font_parts_are_not_highlighted_as_substituted_glyphs() { assert!(g.substituted_glyphs.elements().is_empty() && g.substituted_fonts.elements().is_empty()); } +/// Type in one of a document's composite fonts draws in the document's definition when nothing has +/// registered it: in a render, an ink render, a thumbnail and a placed document's art, as type set +/// in the part's font draws. +/// The font database is left without it afterwards. +#[test] +fn a_documents_own_composite_font_draws_without_being_registered() { + use vectorcraft_doc::{CompositeFont, CompositePart, CompositeParts}; + let _adding = adding_fonts(); + const NAME: &str = "CF Unregistered"; + let db = vectorcraft_text::FontDb::global(); + let typed = |family: &str| { + let mut d = Document::new(300.0, 150.0); + let style = CharStyle { size: 60.0, font_family: family.into(), ..Default::default() }; + let n = Node::new(d.alloc_id(), NodeKind::Text(Box::new(TextObject::point(Point::new(10.0, 100.0), "Hamburg", style)))); + let l = d.layers[0].id; + let id = d.insert(Some(l), 0, n).unwrap(); + (d, id) + }; + let (mut composite, id) = typed(NAME); + let mut parts = CompositeParts::all(CompositePart::new("Source Sans 3", "Regular")); + parts.roman = CompositePart::new("JetBrains Mono", "Regular"); + composite.composite_fonts.push(CompositeFont { name: NAME.into(), parts }); + let (plain, plain_id) = typed("JetBrains Mono"); + assert!(db.composite_font(NAME).is_none()); + let opts = RenderOptions { background: Some([255, 255, 255, 255]), ..Default::default() }; + let view = Affine::IDENTITY; + assert_eq!( + Renderer::new().render(&composite, 300, 150, view, &opts).pixels, + Renderer::new().render(&plain, 300, 150, view, &opts).pixels, + "rendered" + ); + let region = Rect::new(0.0, 0.0, 300.0, 150.0); + assert_eq!( + Renderer::new().render_region_inks(&composite, region, 1.0, &opts), + Renderer::new().render_region_inks(&plain, region, 1.0, &opts), + "rendered as ink amounts" + ); + let thumbnail = |d: &Document, id| Renderer::new().render_thumbnail(d, id, 64).map(|r| r.pixels); + assert_eq!(thumbnail(&composite, id), thumbnail(&plain, plain_id), "thumbnail"); + let placed = |d: &Document| crate::placed_document::render_inside(&mut Renderer::new(), d, &d.layers[0], 300, 150, view).map(|r| r.pixels); + assert_eq!(placed(&composite), placed(&plain), "a placed document's art"); + assert!(db.composite_font(NAME).is_none(), "given back after each render"); +} + /// Type at 80% opacity, in Multiply and with a drop shadow redraws in a font that becomes /// available: the glyph geometry kept for it is laid out again. #[test]