From 3ff40ed8774de320fd1e8402ca8d12c25ba4cc15 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl <47084093+LaurenzV@users.noreply.github.com> Date: Thu, 5 Dec 2024 23:48:31 +0100 Subject: [PATCH] Port PageLabel conversion --- crates/typst-pdf/src/paint.rs | 58 +++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/crates/typst-pdf/src/paint.rs b/crates/typst-pdf/src/paint.rs index 90c3cdf01..ae5d53a4c 100644 --- a/crates/typst-pdf/src/paint.rs +++ b/crates/typst-pdf/src/paint.rs @@ -1,7 +1,10 @@ //! Convert paint types from typst to krilla. +use std::num::NonZeroUsize; use krilla::geom::NormalizedF32; +use krilla::page::{NumberingStyle, PageLabel}; use typst_library::layout::Abs; +use typst_library::model::Numbering; use typst_library::visualize::{ColorSpace, DashPattern, FillRule, FixedStroke, Paint}; use crate::AbsExt; @@ -54,4 +57,59 @@ fn paint(paint: &Paint) -> (krilla::paint::Paint, u8) { Paint::Gradient(_) => (krilla::color::rgb::Color::black().into(), 255), Paint::Pattern(_) => (krilla::color::rgb::Color::black().into(), 255), } +} + +pub(crate) trait PageLabelExt { + fn generate(numbering: &Numbering, number: usize) -> Option; + fn arabic(number: usize) -> PageLabel; +} + +impl PageLabelExt for PageLabel { + /// Create a new `PageLabel` from a `Numbering` applied to a page + /// number. + fn generate(numbering: &Numbering, number: usize) -> Option { + { + let Numbering::Pattern(pat) = numbering else { + return None; + }; + + let (prefix, kind) = pat.pieces.first()?; + + // If there is a suffix, we cannot use the common style optimisation, + // since PDF does not provide a suffix field. + let style = if pat.suffix.is_empty() { + use typst_library::model::NumberingKind as Kind; + use krilla::page::NumberingStyle as Style; + match kind { + Kind::Arabic => Some(Style::Arabic), + Kind::LowerRoman => Some(Style::LowerRoman), + Kind::UpperRoman => Some(Style::UpperRoman), + Kind::LowerLatin if number <= 26 => Some(Style::LowerAlpha), + Kind::LowerLatin if number <= 26 => Some(Style::UpperAlpha), + _ => None, + } + } else { + None + }; + + // Prefix and offset depend on the style: If it is supported by the PDF + // spec, we use the given prefix and an offset. Otherwise, everything + // goes into prefix. + let prefix = if style.is_none() { + Some(pat.apply(&[number])) + } else { + (!prefix.is_empty()).then(|| prefix.clone()) + }; + + let offset = style.and(NonZeroUsize::new(number)); + Some(PageLabel::new(style, prefix.map(|s| s.to_string()), offset)) + } + } + + /// Creates an arabic page label with the specified page number. + /// For example, this will display page label `11` when given the page + /// number 11. + fn arabic(number: usize) -> PageLabel { + PageLabel::new(Some(NumberingStyle::Arabic), None, NonZeroUsize::new(number)) + } } \ No newline at end of file