From 46846a337e8084acd46c70bccc2fca2659e9fb9a Mon Sep 17 00:00:00 2001 From: Laurenz Date: Wed, 8 Nov 2023 14:32:42 +0100 Subject: [PATCH] Extract `typst-pdf` crate --- Cargo.lock | 35 ++-- Cargo.toml | 5 + crates/typst-cli/Cargo.toml | 1 + crates/typst-cli/src/compile.rs | 2 +- crates/typst-library/src/meta/numbering.rs | 2 +- crates/typst-pdf/Cargo.toml | 34 ++++ .../src/export/pdf => typst-pdf/src}/color.rs | 6 +- .../src/export/pdf => typst-pdf/src}/extg.rs | 0 .../src/export/pdf => typst-pdf/src}/font.rs | 8 +- .../export/pdf => typst-pdf/src}/gradient.rs | 11 +- .../pdf => typst-pdf/src}/icc/sGrey-v4.icc | Bin .../pdf => typst-pdf/src}/icc/sRGB-v4.icc | Bin .../src/export/pdf => typst-pdf/src}/image.rs | 6 +- .../pdf/mod.rs => typst-pdf/src/lib.rs} | 78 ++------- .../export/pdf => typst-pdf/src}/outline.rs | 7 +- .../src/export/pdf => typst-pdf/src}/page.rs | 157 +++++++++--------- .../pdf => typst-pdf/src}/postscript/hsl.ps | 0 .../pdf => typst-pdf/src}/postscript/hsv.ps | 0 .../pdf => typst-pdf/src}/postscript/oklab.ps | 0 crates/typst/Cargo.toml | 13 +- crates/typst/src/doc.rs | 40 ++++- crates/typst/src/eval/library.rs | 7 +- crates/typst/src/eval/mod.rs | 2 +- crates/typst/src/eval/ops.rs | 1 + crates/typst/src/eval/value.rs | 2 +- crates/typst/src/export/mod.rs | 5 - crates/typst/src/geom/align.rs | 1 + crates/typst/src/geom/em.rs | 1 + crates/typst/src/lib.rs | 1 - crates/typst/src/model/realize.rs | 1 + crates/typst/src/model/selector.rs | 4 +- tests/Cargo.toml | 1 + tests/src/tests.rs | 2 +- 33 files changed, 235 insertions(+), 198 deletions(-) create mode 100644 crates/typst-pdf/Cargo.toml rename crates/{typst/src/export/pdf => typst-pdf/src}/color.rs (99%) rename crates/{typst/src/export/pdf => typst-pdf/src}/extg.rs (100%) rename crates/{typst/src/export/pdf => typst-pdf/src}/font.rs (98%) rename crates/{typst/src/export/pdf => typst-pdf/src}/gradient.rs (99%) rename crates/{typst/src/export/pdf => typst-pdf/src}/icc/sGrey-v4.icc (100%) rename crates/{typst/src/export/pdf => typst-pdf/src}/icc/sRGB-v4.icc (100%) rename crates/{typst/src/export/pdf => typst-pdf/src}/image.rs (97%) rename crates/{typst/src/export/pdf/mod.rs => typst-pdf/src/lib.rs} (84%) rename crates/{typst/src/export/pdf => typst-pdf/src}/outline.rs (98%) rename crates/{typst/src/export/pdf => typst-pdf/src}/page.rs (88%) rename crates/{typst/src/export/pdf => typst-pdf/src}/postscript/hsl.ps (100%) rename crates/{typst/src/export/pdf => typst-pdf/src}/postscript/hsv.ps (100%) rename crates/{typst/src/export/pdf => typst-pdf/src}/postscript/oklab.ps (100%) delete mode 100644 crates/typst/src/export/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 50bb43472..299e3a582 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2892,22 +2892,17 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" name = "typst" version = "0.9.0" dependencies = [ - "base64", "bitflags 2.4.1", - "bytemuck", "comemo", "ecow", - "flate2", "fontdb", "image", "indexmap 2.0.2", "kurbo", "lasso", "log", - "miniz_oxide", "once_cell", "palette", - "pdf-writer", "regex", "roxmltree", "rustybuzz", @@ -2915,22 +2910,16 @@ dependencies = [ "siphasher", "smallvec", "stacker", - "subsetter", - "svg2pdf", "time", "toml", "tracing", "ttf-parser", "typst-macros", "typst-syntax", - "unicode-ident", "unicode-math-class", - "unicode-properties", "unicode-segmentation", - "unscanny", "usvg", "wasmi", - "xmp-writer", ] [[package]] @@ -2971,6 +2960,7 @@ dependencies = [ "tracing-subscriber", "typst", "typst-library", + "typst-pdf", "typst-render", "typst-svg", "ureq", @@ -3062,6 +3052,28 @@ dependencies = [ "syn 2.0.38", ] +[[package]] +name = "typst-pdf" +version = "0.9.0" +dependencies = [ + "base64", + "bytemuck", + "comemo", + "ecow", + "image", + "miniz_oxide", + "once_cell", + "pdf-writer", + "subsetter", + "svg2pdf", + "tracing", + "ttf-parser", + "typst", + "unicode-properties", + "unscanny", + "xmp-writer", +] + [[package]] name = "typst-render" version = "0.9.0" @@ -3124,6 +3136,7 @@ dependencies = [ "ttf-parser", "typst", "typst-library", + "typst-pdf", "typst-render", "typst-svg", "unscanny", diff --git a/Cargo.toml b/Cargo.toml index 089874945..b4eaf9939 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,8 +17,12 @@ keywords = ["typst"] [workspace.dependencies] typst = { path = "crates/typst" } +typst-cli = { path = "crates/typst-cli" } +typst-docs = { path = "crates/typst-docs" } +typst-ide = { path = "crates/typst-ide" } typst-library = { path = "crates/typst-library" } typst-macros = { path = "crates/typst-macros" } +typst-pdf = { path = "crates/typst-pdf" } typst-render = { path = "crates/typst-render" } typst-svg = { path = "crates/typst-svg" } typst-syntax = { path = "crates/typst-syntax" } @@ -86,6 +90,7 @@ serde_json = "1" serde_yaml = "0.9" siphasher = "0.3" smallvec = { version = "1.11.1", features = ["union", "const_generics", "const_new"] } +stacker = "0.1.15" subsetter = "0.1.1" svg2pdf = "0.9" syn = { version = "2", features = ["full", "extra-traits"] } diff --git a/crates/typst-cli/Cargo.toml b/crates/typst-cli/Cargo.toml index 6e270bd8b..d797555e2 100644 --- a/crates/typst-cli/Cargo.toml +++ b/crates/typst-cli/Cargo.toml @@ -22,6 +22,7 @@ doc = false [dependencies] typst = { workspace = true } typst-library = { workspace = true } +typst-pdf = { workspace = true } typst-render = { workspace = true } typst-svg = { workspace = true } chrono = { workspace = true } diff --git a/crates/typst-cli/src/compile.rs b/crates/typst-cli/src/compile.rs index 9eec36cb4..48d6401c6 100644 --- a/crates/typst-cli/src/compile.rs +++ b/crates/typst-cli/src/compile.rs @@ -153,7 +153,7 @@ fn export_pdf( world: &SystemWorld, ) -> StrResult<()> { let ident = world.input().to_string_lossy(); - let buffer = typst::export::pdf(document, Some(&ident), now()); + let buffer = typst_pdf::pdf(document, Some(&ident), now()); let output = command.output(); fs::write(output, buffer) .map_err(|err| eco_format!("failed to write PDF file ({err})"))?; diff --git a/crates/typst-library/src/meta/numbering.rs b/crates/typst-library/src/meta/numbering.rs index 7843757c1..72906ff61 100644 --- a/crates/typst-library/src/meta/numbering.rs +++ b/crates/typst-library/src/meta/numbering.rs @@ -2,7 +2,7 @@ use std::str::FromStr; use chinese_number::{ChineseCase, ChineseCountMethod, ChineseVariant, NumberToChinese}; use ecow::EcoVec; -use typst::export::{PdfPageLabel, PdfPageLabelStyle}; +use typst::doc::{PdfPageLabel, PdfPageLabelStyle}; use crate::prelude::*; use crate::text::Case; diff --git a/crates/typst-pdf/Cargo.toml b/crates/typst-pdf/Cargo.toml new file mode 100644 index 000000000..74e38a697 --- /dev/null +++ b/crates/typst-pdf/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "typst-pdf" +description = "PDF exporter for Typst." +version.workspace = true +rust-version.workspace = true +authors.workspace = true +edition.workspace = true +homepage.workspace = true +repository.workspace = true +license.workspace = true +categories.workspace = true +keywords.workspace = true + +[lib] +doctest = false +bench = false + +[dependencies] +typst = { workspace = true } +base64 = { workspace = true } +bytemuck = { workspace = true } +comemo = { workspace = true } +ecow = { workspace = true} +image = { workspace = true } +miniz_oxide = { workspace = true } +once_cell = { workspace = true } +pdf-writer = { workspace = true } +subsetter = { workspace = true } +svg2pdf = { workspace = true } +tracing = { workspace = true } +ttf-parser = { workspace = true } +unicode-properties = { workspace = true } +unscanny = { workspace = true } +xmp-writer = { workspace = true } diff --git a/crates/typst/src/export/pdf/color.rs b/crates/typst-pdf/src/color.rs similarity index 99% rename from crates/typst/src/export/pdf/color.rs rename to crates/typst-pdf/src/color.rs index d5b6f3f1d..80d277edc 100644 --- a/crates/typst/src/export/pdf/color.rs +++ b/crates/typst-pdf/src/color.rs @@ -1,10 +1,10 @@ use once_cell::sync::Lazy; use pdf_writer::types::DeviceNSubtype; use pdf_writer::{writers, Chunk, Dict, Filter, Name, Ref}; +use typst::geom::{Color, ColorSpace, Paint}; -use super::page::{PageContext, Transforms}; -use crate::export::pdf::deflate; -use crate::geom::{Color, ColorSpace, Paint}; +use crate::deflate; +use crate::page::{PageContext, Transforms}; // The names of the color spaces. pub const SRGB: Name<'static> = Name(b"srgb"); diff --git a/crates/typst/src/export/pdf/extg.rs b/crates/typst-pdf/src/extg.rs similarity index 100% rename from crates/typst/src/export/pdf/extg.rs rename to crates/typst-pdf/src/extg.rs diff --git a/crates/typst/src/export/pdf/font.rs b/crates/typst-pdf/src/font.rs similarity index 98% rename from crates/typst/src/export/pdf/font.rs rename to crates/typst-pdf/src/font.rs index d99927042..ccf2f4032 100644 --- a/crates/typst/src/export/pdf/font.rs +++ b/crates/typst-pdf/src/font.rs @@ -5,11 +5,11 @@ use ecow::{eco_format, EcoString}; use pdf_writer::types::{CidFontType, FontFlags, SystemInfo, UnicodeCmap}; use pdf_writer::{Filter, Finish, Name, Rect, Str}; use ttf_parser::{name_id, GlyphId, Tag}; +use typst::font::Font; +use typst::util::SliceExt; use unicode_properties::{GeneralCategory, UnicodeGeneralCategory}; -use super::{deflate, EmExt, PdfContext}; -use crate::font::Font; -use crate::util::SliceExt; +use crate::{deflate, EmExt, PdfContext}; const CFF: Tag = Tag::from_bytes(b"CFF "); const CFF2: Tag = Tag::from_bytes(b"CFF2"); @@ -187,7 +187,7 @@ fn subset_font(font: &Font, glyphs: &[u16]) -> Arc> { fn subset_tag(glyphs: &BTreeMap) -> EcoString { const LEN: usize = 6; const BASE: u128 = 26; - let mut hash = crate::util::hash128(&glyphs); + let mut hash = typst::util::hash128(&glyphs); let mut letter = [b'A'; LEN]; for l in letter.iter_mut() { *l = b'A' + (hash % BASE) as u8; diff --git a/crates/typst/src/export/pdf/gradient.rs b/crates/typst-pdf/src/gradient.rs similarity index 99% rename from crates/typst/src/export/pdf/gradient.rs rename to crates/typst-pdf/src/gradient.rs index 6ecf85882..e5cae30e0 100644 --- a/crates/typst/src/export/pdf/gradient.rs +++ b/crates/typst-pdf/src/gradient.rs @@ -6,16 +6,15 @@ use pdf_writer::types::FunctionShadingType; use pdf_writer::writers::StreamShadingType; use pdf_writer::{types::ColorSpaceOperand, Name}; use pdf_writer::{Filter, Finish, Ref}; - -use super::color::{ColorSpaceExt, PaintEncode, QuantizedColor}; -use super::page::{PageContext, Transforms}; -use super::{AbsExt, PdfContext}; -use crate::export::pdf::deflate; -use crate::geom::{ +use typst::geom::{ Abs, Angle, Color, ColorSpace, ConicGradient, Gradient, Numeric, Point, Quadrant, Ratio, Relative, Transform, WeightedColor, }; +use crate::color::{ColorSpaceExt, PaintEncode, QuantizedColor}; +use crate::page::{PageContext, Transforms}; +use crate::{deflate, AbsExt, PdfContext}; + /// A unique-transform-aspect-ratio combination that will be encoded into the /// PDF. #[derive(Debug, Clone, Eq, PartialEq, Hash)] diff --git a/crates/typst/src/export/pdf/icc/sGrey-v4.icc b/crates/typst-pdf/src/icc/sGrey-v4.icc similarity index 100% rename from crates/typst/src/export/pdf/icc/sGrey-v4.icc rename to crates/typst-pdf/src/icc/sGrey-v4.icc diff --git a/crates/typst/src/export/pdf/icc/sRGB-v4.icc b/crates/typst-pdf/src/icc/sRGB-v4.icc similarity index 100% rename from crates/typst/src/export/pdf/icc/sRGB-v4.icc rename to crates/typst-pdf/src/icc/sRGB-v4.icc diff --git a/crates/typst/src/export/pdf/image.rs b/crates/typst-pdf/src/image.rs similarity index 97% rename from crates/typst/src/export/pdf/image.rs rename to crates/typst-pdf/src/image.rs index 7264c8c56..8d526efd0 100644 --- a/crates/typst/src/export/pdf/image.rs +++ b/crates/typst-pdf/src/image.rs @@ -4,10 +4,10 @@ use std::sync::Arc; use image::{DynamicImage, GenericImageView, Rgba}; use pdf_writer::{Chunk, Filter, Finish, Ref}; +use typst::geom::ColorSpace; +use typst::image::{ImageKind, RasterFormat, RasterImage, SvgImage}; -use super::{deflate, PdfContext}; -use crate::geom::ColorSpace; -use crate::image::{ImageKind, RasterFormat, RasterImage, SvgImage}; +use crate::{deflate, PdfContext}; /// Embed all used images into the PDF. #[tracing::instrument(skip_all)] diff --git a/crates/typst/src/export/pdf/mod.rs b/crates/typst-pdf/src/lib.rs similarity index 84% rename from crates/typst/src/export/pdf/mod.rs rename to crates/typst-pdf/src/lib.rs index 51ed6d926..92c844954 100644 --- a/crates/typst/src/export/pdf/mod.rs +++ b/crates/typst-pdf/src/lib.rs @@ -8,31 +8,26 @@ mod image; mod outline; mod page; -pub use self::color::{ColorEncode, ColorSpaces}; -pub use self::page::{PdfPageLabel, PdfPageLabelStyle}; - use std::cmp::Eq; use std::collections::{BTreeMap, HashMap}; use std::hash::Hash; -use std::num::NonZeroUsize; use base64::Engine; use ecow::{eco_format, EcoString}; use pdf_writer::types::Direction; -use pdf_writer::writers::PageLabel; use pdf_writer::{Finish, Name, Pdf, Ref, TextStr}; +use typst::doc::{Document, Lang}; +use typst::eval::Datetime; +use typst::font::Font; +use typst::geom::{Abs, Dir, Em}; +use typst::image::Image; +use typst::model::Introspector; use xmp_writer::{DateTime, LangId, RenditionClass, Timezone, XmpWriter}; -use self::gradient::PdfGradient; -use self::page::Page; -use crate::doc::{Document, Lang}; -use crate::eval::Datetime; -use crate::font::Font; -use crate::geom::{Abs, Dir, Em}; -use crate::image::Image; -use crate::model::Introspector; - -use extg::ExtGState; +use crate::color::ColorSpaces; +use crate::extg::ExtGState; +use crate::gradient::PdfGradient; +use crate::page::Page; /// Export a document into a PDF file. /// @@ -161,7 +156,7 @@ fn write_catalog(ctx: &mut PdfContext, ident: Option<&str>, timestamp: Option, timestamp: Option Vec<(NonZeroUsize, Ref)> { - let mut result = vec![]; - let mut prev: Option<&PdfPageLabel> = None; - - for (i, page) in ctx.pages.iter().enumerate() { - let nr = NonZeroUsize::new(1 + i).unwrap(); - let Some(label) = &page.label else { continue }; - - // Don't create a label if neither style nor prefix are specified. - if label.prefix.is_none() && label.style.is_none() { - continue; - } - - if let Some(pre) = prev { - if label.prefix == pre.prefix - && label.style == pre.style - && label.offset == pre.offset.map(|n| n.saturating_add(1)) - { - prev = Some(label); - continue; - } - } - - let id = ctx.alloc.bump(); - let mut entry = ctx.pdf.indirect(id).start::(); - - // Only add what is actually provided. Don't add empty prefix string if - // it wasn't given for example. - if let Some(prefix) = &label.prefix { - entry.prefix(TextStr(prefix)); - } - - if let Some(style) = label.style { - entry.style(style.into()); - } - - if let Some(offset) = label.offset { - entry.offset(offset.get() as i32); - } - - result.push((nr, id)); - prev = Some(label); - } - - result -} - /// Compress data with the DEFLATE algorithm. #[tracing::instrument(skip_all)] fn deflate(data: &[u8]) -> Vec { @@ -315,7 +261,7 @@ fn deflate(data: &[u8]) -> Vec { /// Create a base64-encoded hash of the value. fn hash_base64(value: &T) -> String { base64::engine::general_purpose::STANDARD - .encode(crate::util::hash128(value).to_be_bytes()) + .encode(typst::util::hash128(value).to_be_bytes()) } /// Converts a datetime to a pdf-writer date. diff --git a/crates/typst/src/export/pdf/outline.rs b/crates/typst-pdf/src/outline.rs similarity index 98% rename from crates/typst/src/export/pdf/outline.rs rename to crates/typst-pdf/src/outline.rs index f6f9f09d8..e51d85c3f 100644 --- a/crates/typst/src/export/pdf/outline.rs +++ b/crates/typst-pdf/src/outline.rs @@ -1,10 +1,11 @@ use std::num::NonZeroUsize; use pdf_writer::{Finish, Ref, TextStr}; +use typst::eval::item; +use typst::geom::{Abs, Smart}; +use typst::model::Content; -use super::{AbsExt, PdfContext}; -use crate::geom::{Abs, Smart}; -use crate::model::Content; +use crate::{AbsExt, PdfContext}; /// Construct the outline for the document. #[tracing::instrument(skip_all)] diff --git a/crates/typst/src/export/pdf/page.rs b/crates/typst-pdf/src/page.rs similarity index 88% rename from crates/typst/src/export/pdf/page.rs rename to crates/typst-pdf/src/page.rs index 5e6cd2a2c..4de472f0b 100644 --- a/crates/typst/src/export/pdf/page.rs +++ b/crates/typst-pdf/src/page.rs @@ -1,24 +1,27 @@ use std::num::NonZeroUsize; use std::sync::Arc; -use ecow::{eco_format, EcoString}; +use ecow::eco_format; use pdf_writer::types::{ ActionType, AnnotationType, ColorSpaceOperand, LineCapStyle, LineJoinStyle, NumberingStyle, }; -use pdf_writer::{Content, Filter, Finish, Name, Rect, Ref, Str}; - -use super::color::PaintEncode; -use super::extg::ExtGState; -use super::{deflate, AbsExt, EmExt, PdfContext}; -use crate::doc::{Destination, Frame, FrameItem, GroupItem, Meta, TextItem}; -use crate::eval::Repr; -use crate::font::Font; -use crate::geom::{ +use pdf_writer::writers::PageLabel; +use pdf_writer::{Content, Filter, Finish, Name, Rect, Ref, Str, TextStr}; +use typst::doc::{ + Destination, Frame, FrameItem, GroupItem, Meta, PdfPageLabel, PdfPageLabelStyle, + TextItem, +}; +use typst::font::Font; +use typst::geom::{ self, Abs, Em, FixedStroke, Geometry, LineCap, LineJoin, Numeric, Paint, Point, Ratio, Shape, Size, Transform, }; -use crate::image::Image; +use typst::image::Image; + +use crate::color::PaintEncode; +use crate::extg::ExtGState; +use crate::{deflate, AbsExt, EmExt, PdfContext}; /// Construct page objects. #[tracing::instrument(skip_all)] @@ -189,6 +192,55 @@ fn write_page(ctx: &mut PdfContext, i: usize) { ctx.pdf.stream(content_id, &data).filter(Filter::FlateDecode); } +/// Write the page labels. +#[tracing::instrument(skip_all)] +pub fn write_page_labels(ctx: &mut PdfContext) -> Vec<(NonZeroUsize, Ref)> { + let mut result = vec![]; + let mut prev: Option<&PdfPageLabel> = None; + + for (i, page) in ctx.pages.iter().enumerate() { + let nr = NonZeroUsize::new(1 + i).unwrap(); + let Some(label) = &page.label else { continue }; + + // Don't create a label if neither style nor prefix are specified. + if label.prefix.is_none() && label.style.is_none() { + continue; + } + + if let Some(pre) = prev { + if label.prefix == pre.prefix + && label.style == pre.style + && label.offset == pre.offset.map(|n| n.saturating_add(1)) + { + prev = Some(label); + continue; + } + } + + let id = ctx.alloc.bump(); + let mut entry = ctx.pdf.indirect(id).start::(); + + // Only add what is actually provided. Don't add empty prefix string if + // it wasn't given for example. + if let Some(prefix) = &label.prefix { + entry.prefix(TextStr(prefix)); + } + + if let Some(style) = label.style { + entry.style(to_pdf_numbering_style(style)); + } + + if let Some(offset) = label.offset { + entry.offset(offset.get() as i32); + } + + result.push((nr, id)); + prev = Some(label); + } + + result +} + /// Memoized version of [`deflate`] specialized for a page's content stream. #[comemo::memoize] fn deflate_content(content: &[u8]) -> Arc> { @@ -401,10 +453,10 @@ impl PageContext<'_, '_> { self.content.set_line_width(thickness.to_f32()); if self.state.stroke.as_ref().map(|s| &s.line_cap) != Some(line_cap) { - self.content.set_line_cap(line_cap.into()); + self.content.set_line_cap(to_pdf_line_cap(*line_cap)); } if self.state.stroke.as_ref().map(|s| &s.line_join) != Some(line_join) { - self.content.set_line_join(line_join.into()); + self.content.set_line_join(to_pdf_line_join(*line_join)); } if self.state.stroke.as_ref().map(|s| &s.dash_pattern) != Some(dash_pattern) { if let Some(pattern) = dash_pattern { @@ -680,73 +732,28 @@ fn write_link(ctx: &mut PageContext, pos: Point, dest: &Destination, size: Size) ctx.links.push((dest.clone(), rect)); } -impl From<&LineCap> for LineCapStyle { - fn from(line_cap: &LineCap) -> Self { - match line_cap { - LineCap::Butt => LineCapStyle::ButtCap, - LineCap::Round => LineCapStyle::RoundCap, - LineCap::Square => LineCapStyle::ProjectingSquareCap, - } +fn to_pdf_line_cap(cap: LineCap) -> LineCapStyle { + match cap { + LineCap::Butt => LineCapStyle::ButtCap, + LineCap::Round => LineCapStyle::RoundCap, + LineCap::Square => LineCapStyle::ProjectingSquareCap, } } -impl From<&LineJoin> for LineJoinStyle { - fn from(line_join: &LineJoin) -> Self { - match line_join { - LineJoin::Miter => LineJoinStyle::MiterJoin, - LineJoin::Round => LineJoinStyle::RoundJoin, - LineJoin::Bevel => LineJoinStyle::BevelJoin, - } +fn to_pdf_line_join(join: LineJoin) -> LineJoinStyle { + match join { + LineJoin::Miter => LineJoinStyle::MiterJoin, + LineJoin::Round => LineJoinStyle::RoundJoin, + LineJoin::Bevel => LineJoinStyle::BevelJoin, } } -/// Specification for a PDF page label. -#[derive(Debug, Clone, PartialEq, Hash, Default)] -pub struct PdfPageLabel { - /// Can be any string or none. Will always be prepended to the numbering style. - pub prefix: Option, - /// Based on the numbering pattern. - /// - /// If `None` or numbering is a function, the field will be empty. - pub style: Option, - /// Offset for the page label start. - /// - /// Describes where to start counting from when setting a style. - /// (Has to be greater or equal than 1) - pub offset: Option, -} - -impl Repr for PdfPageLabel { - fn repr(&self) -> EcoString { - eco_format!("{self:?}") - } -} - -/// A PDF page label number style. -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub enum PdfPageLabelStyle { - /// Decimal arabic numerals (1, 2, 3). - Arabic, - /// Lowercase roman numerals (i, ii, iii). - LowerRoman, - /// Uppercase roman numerals (I, II, III). - UpperRoman, - /// Lowercase letters (`a` to `z` for the first 26 pages, - /// `aa` to `zz` and so on for the next). - LowerAlpha, - /// Uppercase letters (`A` to `Z` for the first 26 pages, - /// `AA` to `ZZ` and so on for the next). - UpperAlpha, -} - -impl From for NumberingStyle { - fn from(value: PdfPageLabelStyle) -> Self { - match value { - PdfPageLabelStyle::Arabic => Self::Arabic, - PdfPageLabelStyle::LowerRoman => Self::LowerRoman, - PdfPageLabelStyle::UpperRoman => Self::UpperRoman, - PdfPageLabelStyle::LowerAlpha => Self::LowerAlpha, - PdfPageLabelStyle::UpperAlpha => Self::UpperAlpha, - } +fn to_pdf_numbering_style(style: PdfPageLabelStyle) -> NumberingStyle { + match style { + PdfPageLabelStyle::Arabic => NumberingStyle::Arabic, + PdfPageLabelStyle::LowerRoman => NumberingStyle::LowerRoman, + PdfPageLabelStyle::UpperRoman => NumberingStyle::UpperRoman, + PdfPageLabelStyle::LowerAlpha => NumberingStyle::LowerAlpha, + PdfPageLabelStyle::UpperAlpha => NumberingStyle::UpperAlpha, } } diff --git a/crates/typst/src/export/pdf/postscript/hsl.ps b/crates/typst-pdf/src/postscript/hsl.ps similarity index 100% rename from crates/typst/src/export/pdf/postscript/hsl.ps rename to crates/typst-pdf/src/postscript/hsl.ps diff --git a/crates/typst/src/export/pdf/postscript/hsv.ps b/crates/typst-pdf/src/postscript/hsv.ps similarity index 100% rename from crates/typst/src/export/pdf/postscript/hsv.ps rename to crates/typst-pdf/src/postscript/hsv.ps diff --git a/crates/typst/src/export/pdf/postscript/oklab.ps b/crates/typst-pdf/src/postscript/oklab.ps similarity index 100% rename from crates/typst/src/export/pdf/postscript/oklab.ps rename to crates/typst-pdf/src/postscript/oklab.ps diff --git a/crates/typst/Cargo.toml b/crates/typst/Cargo.toml index 4a0955096..1edd99466 100644 --- a/crates/typst/Cargo.toml +++ b/crates/typst/Cargo.toml @@ -18,42 +18,31 @@ bench = false [dependencies] typst-macros = { workspace = true } typst-syntax = { workspace = true } -base64 = { workspace = true } bitflags = { workspace = true } -bytemuck = { workspace = true } comemo = { workspace = true } ecow = { workspace = true} -flate2 = { workspace = true } fontdb = { workspace = true } image = { workspace = true } indexmap = { workspace = true } kurbo = { workspace = true } lasso = { workspace = true } log = { workspace = true } -miniz_oxide = { workspace = true } once_cell = { workspace = true } palette = { workspace = true } -pdf-writer = { workspace = true } regex = { workspace = true } roxmltree = { workspace = true } rustybuzz = { workspace = true } serde = { workspace = true } siphasher = { workspace = true } smallvec = { workspace = true } -subsetter = { workspace = true } -svg2pdf = { workspace = true } time = { workspace = true } toml = { workspace = true } tracing = { workspace = true } ttf-parser = { workspace = true } -unicode-ident = { workspace = true } unicode-math-class = { workspace = true } -unicode-properties = { workspace = true } unicode-segmentation = { workspace = true } -unscanny = { workspace = true } usvg = { workspace = true } wasmi = { workspace = true } -xmp-writer = { workspace = true } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] -stacker = "0.1.15" +stacker = { workspace = true } diff --git a/crates/typst/src/doc.rs b/crates/typst/src/doc.rs index 742c6245a..48f201dc9 100644 --- a/crates/typst/src/doc.rs +++ b/crates/typst/src/doc.rs @@ -9,7 +9,6 @@ use std::sync::Arc; use ecow::{eco_format, EcoString}; use crate::eval::{cast, dict, ty, Datetime, Dict, Repr, Value}; -use crate::export::PdfPageLabel; use crate::font::Font; use crate::geom::{ self, styled_rect, Abs, Axes, Color, Corners, Dir, Em, FixedAlign, FixedStroke, @@ -835,6 +834,45 @@ impl From for Dict { } } +/// Specification for a PDF page label. +#[derive(Debug, Clone, PartialEq, Hash, Default)] +pub struct PdfPageLabel { + /// Can be any string or none. Will always be prepended to the numbering style. + pub prefix: Option, + /// Based on the numbering pattern. + /// + /// If `None` or numbering is a function, the field will be empty. + pub style: Option, + /// Offset for the page label start. + /// + /// Describes where to start counting from when setting a style. + /// (Has to be greater or equal than 1) + pub offset: Option, +} + +impl Repr for PdfPageLabel { + fn repr(&self) -> EcoString { + eco_format!("{self:?}") + } +} + +/// A PDF page label number style. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub enum PdfPageLabelStyle { + /// Decimal arabic numerals (1, 2, 3). + Arabic, + /// Lowercase roman numerals (i, ii, iii). + LowerRoman, + /// Uppercase roman numerals (I, II, III). + UpperRoman, + /// Lowercase letters (`a` to `z` for the first 26 pages, + /// `aa` to `zz` and so on for the next). + LowerAlpha, + /// Uppercase letters (`A` to `Z` for the first 26 pages, + /// `AA` to `ZZ` and so on for the next). + UpperAlpha, +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/typst/src/eval/library.rs b/crates/typst/src/eval/library.rs index c712adaee..cd3d09d3d 100644 --- a/crates/typst/src/eval/library.rs +++ b/crates/typst/src/eval/library.rs @@ -167,8 +167,13 @@ pub fn set_lang_items(items: LangItems) { } /// Access a lang item. -macro_rules! item { +#[macro_export] +#[doc(hidden)] +macro_rules! __item { ($name:ident) => { $crate::eval::LANG_ITEMS.get().unwrap().$name }; } + +#[doc(inline)] +pub use crate::__item as item; diff --git a/crates/typst/src/eval/mod.rs b/crates/typst/src/eval/mod.rs index 8ac2c40bc..26de43998 100644 --- a/crates/typst/src/eval/mod.rs +++ b/crates/typst/src/eval/mod.rs @@ -55,7 +55,7 @@ pub use self::fields::fields_on; pub use self::func::{ func, CapturesVisitor, Func, NativeFunc, NativeFuncData, ParamInfo, }; -pub use self::library::{set_lang_items, LangItems, Library}; +pub use self::library::{item, set_lang_items, LangItems, Library}; pub use self::methods::mutable_methods_on; pub use self::module::Module; pub use self::none::NoneValue; diff --git a/crates/typst/src/eval/ops.rs b/crates/typst/src/eval/ops.rs index 093eaa5f3..e0c3b984d 100644 --- a/crates/typst/src/eval/ops.rs +++ b/crates/typst/src/eval/ops.rs @@ -6,6 +6,7 @@ use ecow::eco_format; use super::{format_str, IntoValue, Regex, Repr, Value}; use crate::diag::{bail, StrResult}; +use crate::eval::item; use crate::geom::{Align, Length, Numeric, Rel, Smart, Stroke}; use Value::*; diff --git a/crates/typst/src/eval/value.rs b/crates/typst/src/eval/value.rs index b87c85924..1d866418c 100644 --- a/crates/typst/src/eval/value.rs +++ b/crates/typst/src/eval/value.rs @@ -17,7 +17,7 @@ use super::{ Version, }; use crate::diag::StrResult; -use crate::eval::Datetime; +use crate::eval::{item, Datetime}; use crate::geom::{Abs, Angle, Color, Em, Fr, Gradient, Length, Ratio, Rel}; use crate::model::{Label, Styles}; use crate::syntax::{ast, Span}; diff --git a/crates/typst/src/export/mod.rs b/crates/typst/src/export/mod.rs deleted file mode 100644 index bdcc9c406..000000000 --- a/crates/typst/src/export/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -//! Exporting into external formats. - -mod pdf; - -pub use self::pdf::{pdf, PdfPageLabel, PdfPageLabelStyle}; diff --git a/crates/typst/src/geom/align.rs b/crates/typst/src/geom/align.rs index 59e608b11..a1c0735a5 100644 --- a/crates/typst/src/geom/align.rs +++ b/crates/typst/src/geom/align.rs @@ -1,4 +1,5 @@ use super::*; +use crate::eval::item; /// Where to [align]($align) something along an axis. /// diff --git a/crates/typst/src/geom/em.rs b/crates/typst/src/geom/em.rs index 9cb0c55a4..e6bbee719 100644 --- a/crates/typst/src/geom/em.rs +++ b/crates/typst/src/geom/em.rs @@ -1,4 +1,5 @@ use super::*; +use crate::eval::item; /// A length that is relative to the font size. /// diff --git a/crates/typst/src/lib.rs b/crates/typst/src/lib.rs index 7303eca80..1e55385cc 100644 --- a/crates/typst/src/lib.rs +++ b/crates/typst/src/lib.rs @@ -43,7 +43,6 @@ pub mod util; pub mod eval; pub mod diag; pub mod doc; -pub mod export; pub mod font; pub mod geom; pub mod image; diff --git a/crates/typst/src/model/realize.rs b/crates/typst/src/model/realize.rs index 7e926b0f7..02f19e910 100644 --- a/crates/typst/src/model/realize.rs +++ b/crates/typst/src/model/realize.rs @@ -7,6 +7,7 @@ use super::{ }; use crate::diag::SourceResult; use crate::doc::Meta; +use crate::eval::item; use crate::util::hash128; /// Whether the target is affected by show rules in the given style chain. diff --git a/crates/typst/src/model/selector.rs b/crates/typst/src/model/selector.rs index 6d117acdf..89c518bcb 100644 --- a/crates/typst/src/model/selector.rs +++ b/crates/typst/src/model/selector.rs @@ -8,8 +8,8 @@ use smallvec::SmallVec; use super::{Content, Element, Label, Locatable, Location}; use crate::diag::{bail, StrResult}; use crate::eval::{ - cast, func, scope, ty, CastInfo, Dict, FromValue, Func, Reflect, Regex, Repr, Str, - Symbol, Type, Value, + cast, func, item, scope, ty, CastInfo, Dict, FromValue, Func, Reflect, Regex, Repr, + Str, Symbol, Type, Value, }; use crate::util::pretty_array_like; diff --git a/tests/Cargo.toml b/tests/Cargo.toml index cce7c6af9..ca8c1c0c7 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -9,6 +9,7 @@ publish = false [dev-dependencies] typst = { workspace = true } typst-library = { workspace = true } +typst-pdf = { workspace = true } typst-render = { workspace = true } typst-svg = { workspace = true } clap = { workspace = true } diff --git a/tests/src/tests.rs b/tests/src/tests.rs index 3cf8aa1c8..0271839c5 100644 --- a/tests/src/tests.rs +++ b/tests/src/tests.rs @@ -420,7 +420,7 @@ fn test( let document = Document { pages: frames, ..Default::default() }; if compare_ever { if let Some(pdf_path) = pdf_path { - let pdf_data = typst::export::pdf( + let pdf_data = typst_pdf::pdf( &document, Some(&format!("typst-test: {}", name.display())), world.today(Some(0)),