From e29f55bb294cc298daad97accf6d8a76976b409c Mon Sep 17 00:00:00 2001 From: Laurenz Date: Mon, 19 Sep 2022 17:44:40 +0200 Subject: Remove font store --- src/export/pdf/font.rs | 7 +++---- src/export/pdf/mod.rs | 19 ++++++++----------- src/export/pdf/page.rs | 30 ++++++++++++++---------------- src/export/render.rs | 39 ++++++++++++++------------------------- 4 files changed, 39 insertions(+), 56 deletions(-) (limited to 'src/export') diff --git a/src/export/pdf/font.rs b/src/export/pdf/font.rs index b3481c43..446d36bc 100644 --- a/src/export/pdf/font.rs +++ b/src/export/pdf/font.rs @@ -9,7 +9,7 @@ use crate::util::SliceExt; /// Embed all used fonts into the PDF. pub fn write_fonts(ctx: &mut PdfContext) { - for &font_id in ctx.font_map.items() { + for font in ctx.font_map.items() { let type0_ref = ctx.alloc.bump(); let cid_ref = ctx.alloc.bump(); let descriptor_ref = ctx.alloc.bump(); @@ -17,8 +17,7 @@ pub fn write_fonts(ctx: &mut PdfContext) { let data_ref = ctx.alloc.bump(); ctx.font_refs.push(type0_ref); - let glyphs = &ctx.glyph_sets[&font_id]; - let font = ctx.fonts.get(font_id); + let glyphs = &ctx.glyph_sets[font]; let metrics = font.metrics(); let ttf = font.ttf(); @@ -161,7 +160,7 @@ pub fn write_fonts(ctx: &mut PdfContext) { .filter(Filter::FlateDecode); // Subset and write the font's bytes. - let data = font.buffer(); + let data = font.data(); let subsetted = { let glyphs: Vec<_> = glyphs.iter().copied().collect(); let profile = subsetter::Profile::pdf(&glyphs); diff --git a/src/export/pdf/mod.rs b/src/export/pdf/mod.rs index 7468f7d7..a87f5c6b 100644 --- a/src/export/pdf/mod.rs +++ b/src/export/pdf/mod.rs @@ -14,12 +14,11 @@ use pdf_writer::{Finish, Name, PdfWriter, Ref, TextStr}; use self::outline::{Heading, HeadingNode}; use self::page::Page; -use crate::font::{FontId, FontStore}; +use crate::font::Font; use crate::frame::Frame; use crate::geom::{Dir, Em, Length}; use crate::image::Image; use crate::library::text::Lang; -use crate::Context; /// Export a collection of frames into a PDF file. /// @@ -28,8 +27,8 @@ use crate::Context; /// included in the PDF. /// /// Returns the raw bytes making up the PDF file. -pub fn pdf(ctx: &Context, frames: &[Frame]) -> Vec { - let mut ctx = PdfContext::new(ctx); +pub fn pdf(frames: &[Frame]) -> Vec { + let mut ctx = PdfContext::new(); page::construct_pages(&mut ctx, frames); font::write_fonts(&mut ctx); image::write_images(&mut ctx); @@ -43,9 +42,8 @@ const SRGB: Name<'static> = Name(b"srgb"); const D65_GRAY: Name<'static> = Name(b"d65gray"); /// Context for exporting a whole PDF document. -pub struct PdfContext<'a> { +pub struct PdfContext { writer: PdfWriter, - fonts: &'a FontStore, pages: Vec, page_heights: Vec, alloc: Ref, @@ -53,20 +51,19 @@ pub struct PdfContext<'a> { font_refs: Vec, image_refs: Vec, page_refs: Vec, - font_map: Remapper, + font_map: Remapper, image_map: Remapper, - glyph_sets: HashMap>, + glyph_sets: HashMap>, languages: HashMap, heading_tree: Vec, } -impl<'a> PdfContext<'a> { - fn new(ctx: &'a Context) -> Self { +impl PdfContext { + fn new() -> Self { let mut alloc = Ref::new(1); let page_tree_ref = alloc.bump(); Self { writer: PdfWriter::new(), - fonts: &ctx.fonts, pages: vec![], page_heights: vec![], alloc, diff --git a/src/export/pdf/page.rs b/src/export/pdf/page.rs index 6df7531b..708eafad 100644 --- a/src/export/pdf/page.rs +++ b/src/export/pdf/page.rs @@ -5,7 +5,7 @@ use pdf_writer::{Content, Filter, Finish, Name, Rect, Ref, Str}; use super::{ deflate, EmExt, Heading, HeadingNode, LengthExt, PdfContext, RefExt, D65_GRAY, SRGB, }; -use crate::font::FontId; +use crate::font::Font; use crate::frame::{Destination, Element, Frame, Group, Role, Text}; use crate::geom::{ self, Color, Em, Geometry, Length, Numeric, Paint, Point, Ratio, Shape, Size, Stroke, @@ -154,8 +154,8 @@ pub struct Page { } /// An exporter for the contents of a single PDF page. -struct PageContext<'a, 'b> { - parent: &'a mut PdfContext<'b>, +struct PageContext<'a> { + parent: &'a mut PdfContext, page_ref: Ref, content: Content, state: State, @@ -169,14 +169,14 @@ struct PageContext<'a, 'b> { #[derive(Debug, Default, Clone)] struct State { transform: Transform, - font: Option<(FontId, Length)>, + font: Option<(Font, Length)>, fill: Option, fill_space: Option>, stroke: Option, stroke_space: Option>, } -impl<'a, 'b> PageContext<'a, 'b> { +impl<'a> PageContext<'a> { fn save_state(&mut self) { self.saves.push(self.state.clone()); self.content.save_state(); @@ -200,12 +200,12 @@ impl<'a, 'b> PageContext<'a, 'b> { ]); } - fn set_font(&mut self, font_id: FontId, size: Length) { - if self.state.font != Some((font_id, size)) { - self.parent.font_map.insert(font_id); - let name = format_eco!("F{}", self.parent.font_map.map(font_id)); + fn set_font(&mut self, font: &Font, size: Length) { + if self.state.font.as_ref().map(|(f, s)| (f, *s)) != Some((font, size)) { + self.parent.font_map.insert(font.clone()); + let name = format_eco!("F{}", self.parent.font_map.map(font.clone())); self.content.set_font(Name(name.as_bytes()), size.to_f32()); - self.state.font = Some((font_id, size)); + self.state.font = Some((font.clone(), size)); } } @@ -328,17 +328,15 @@ fn write_text(ctx: &mut PageContext, x: f32, y: f32, text: &Text) { *ctx.parent.languages.entry(text.lang).or_insert(0) += text.glyphs.len(); ctx.parent .glyph_sets - .entry(text.font_id) + .entry(text.font.clone()) .or_default() .extend(text.glyphs.iter().map(|g| g.id)); - let font = ctx.parent.fonts.get(text.font_id); - ctx.set_fill(text.fill); - ctx.set_font(text.font_id, text.size); + ctx.set_font(&text.font, text.size); ctx.content.begin_text(); - // Position the text. + // Positiosn the text. ctx.content.set_text_matrix([1.0, 0.0, 0.0, -1.0, x, y]); let mut positioned = ctx.content.show_positioned(); @@ -363,7 +361,7 @@ fn write_text(ctx: &mut PageContext, x: f32, y: f32, text: &Text) { encoded.push((glyph.id >> 8) as u8); encoded.push((glyph.id & 0xff) as u8); - if let Some(advance) = font.advance(glyph.id) { + if let Some(advance) = text.font.advance(glyph.id) { adjustment += glyph.x_advance - advance; } diff --git a/src/export/render.rs b/src/export/render.rs index 688cf979..bf735ded 100644 --- a/src/export/render.rs +++ b/src/export/render.rs @@ -13,7 +13,6 @@ use crate::geom::{ self, Geometry, Length, Paint, PathElement, Shape, Size, Stroke, Transform, }; use crate::image::{DecodedImage, Image}; -use crate::Context; /// Export a frame into a rendered image. /// @@ -22,7 +21,7 @@ use crate::Context; /// /// In addition to the frame, you need to pass in the context used during /// compilation so that fonts and images can be rendered. -pub fn render(ctx: &Context, frame: &Frame, pixel_per_pt: f32) -> sk::Pixmap { +pub fn render(frame: &Frame, pixel_per_pt: f32) -> sk::Pixmap { let size = frame.size(); let pxw = (pixel_per_pt * size.x.to_f32()).round().max(1.0) as u32; let pxh = (pixel_per_pt * size.y.to_f32()).round().max(1.0) as u32; @@ -31,7 +30,7 @@ pub fn render(ctx: &Context, frame: &Frame, pixel_per_pt: f32) -> sk::Pixmap { canvas.fill(sk::Color::WHITE); let ts = sk::Transform::from_scale(pixel_per_pt, pixel_per_pt); - render_frame(&mut canvas, ts, None, ctx, frame); + render_frame(&mut canvas, ts, None, frame); canvas } @@ -41,7 +40,6 @@ fn render_frame( canvas: &mut sk::Pixmap, ts: sk::Transform, mask: Option<&sk::ClipMask>, - ctx: &Context, frame: &Frame, ) { for (pos, element) in frame.elements() { @@ -51,10 +49,10 @@ fn render_frame( match element { Element::Group(group) => { - render_group(canvas, ts, mask, ctx, group); + render_group(canvas, ts, mask, group); } Element::Text(text) => { - render_text(canvas, ts, mask, ctx, text); + render_text(canvas, ts, mask, text); } Element::Shape(shape) => { render_shape(canvas, ts, mask, shape); @@ -72,7 +70,6 @@ fn render_group( canvas: &mut sk::Pixmap, ts: sk::Transform, mask: Option<&sk::ClipMask>, - ctx: &Context, group: &Group, ) { let ts = ts.pre_concat(group.transform.into()); @@ -107,7 +104,7 @@ fn render_group( } } - render_frame(canvas, ts, mask, ctx, &group.frame); + render_frame(canvas, ts, mask, &group.frame); } /// Render a text run into the canvas. @@ -115,7 +112,6 @@ fn render_text( canvas: &mut sk::Pixmap, ts: sk::Transform, mask: Option<&sk::ClipMask>, - ctx: &Context, text: &Text, ) { let mut x = 0.0; @@ -124,9 +120,9 @@ fn render_text( let offset = x + glyph.x_offset.at(text.size).to_f32(); let ts = ts.pre_translate(offset, 0.0); - render_svg_glyph(canvas, ts, mask, ctx, text, id) - .or_else(|| render_bitmap_glyph(canvas, ts, mask, ctx, text, id)) - .or_else(|| render_outline_glyph(canvas, ts, mask, ctx, text, id)); + render_svg_glyph(canvas, ts, mask, text, id) + .or_else(|| render_bitmap_glyph(canvas, ts, mask, text, id)) + .or_else(|| render_outline_glyph(canvas, ts, mask, text, id)); x += glyph.x_advance.at(text.size).to_f32(); } @@ -137,12 +133,10 @@ fn render_svg_glyph( canvas: &mut sk::Pixmap, ts: sk::Transform, _: Option<&sk::ClipMask>, - ctx: &Context, text: &Text, id: GlyphId, ) -> Option<()> { - let font = ctx.fonts.get(text.font_id); - let mut data = font.ttf().glyph_svg_image(id)?; + let mut data = text.font.ttf().glyph_svg_image(id)?; // Decompress SVGZ. let mut decoded = vec![]; @@ -164,7 +158,7 @@ fn render_svg_glyph( // If there's no viewbox defined, use the em square for our scale // transformation ... - let upem = font.units_per_em() as f32; + let upem = text.font.units_per_em() as f32; let (mut width, mut height) = (upem, upem); // ... but if there's a viewbox or width, use that. @@ -188,14 +182,12 @@ fn render_bitmap_glyph( canvas: &mut sk::Pixmap, ts: sk::Transform, mask: Option<&sk::ClipMask>, - ctx: &Context, text: &Text, id: GlyphId, ) -> Option<()> { let size = text.size.to_f32(); let ppem = size * ts.sy; - let font = ctx.fonts.get(text.font_id); - let raster = font.ttf().glyph_raster_image(id, ppem as u16)?; + let raster = text.font.ttf().glyph_raster_image(id, ppem as u16)?; let ext = match raster.format { ttf_parser::RasterImageFormat::PNG => "png", }; @@ -217,7 +209,6 @@ fn render_outline_glyph( canvas: &mut sk::Pixmap, ts: sk::Transform, mask: Option<&sk::ClipMask>, - ctx: &Context, text: &Text, id: GlyphId, ) -> Option<()> { @@ -227,10 +218,9 @@ fn render_outline_glyph( // rasterization can't be used due to very large text size or weird // scale/skewing transforms. if ppem > 100.0 || ts.kx != 0.0 || ts.ky != 0.0 || ts.sx != ts.sy { - let font = ctx.fonts.get(text.font_id); let path = { let mut builder = WrappedPathBuilder(sk::PathBuilder::new()); - font.ttf().outline_glyph(id, &mut builder)?; + text.font.ttf().outline_glyph(id, &mut builder)?; builder.0.finish()? }; @@ -239,7 +229,7 @@ fn render_outline_glyph( // Flip vertically because font design coordinate // system is Y-up. - let scale = text.size.to_f32() / font.units_per_em() as f32; + let scale = text.size.to_f32() / text.font.units_per_em() as f32; let ts = ts.pre_scale(scale, -scale); canvas.fill_path(&path, &paint, rule, ts, mask)?; return Some(()); @@ -248,9 +238,8 @@ fn render_outline_glyph( // Rasterize the glyph with `pixglyph`. // Try to retrieve a prepared glyph or prepare it from scratch if it // doesn't exist, yet. - let glyph = pixglyph::Glyph::load(ctx.fonts.get(text.font_id).ttf(), id)?; + let glyph = pixglyph::Glyph::load(text.font.ttf(), id)?; let bitmap = glyph.rasterize(ts.tx, ts.ty, ppem); - let cw = canvas.width() as i32; let ch = canvas.height() as i32; let mw = bitmap.width as i32; -- cgit v1.2.3