This commit is contained in:
Laurenz Stampfl 2025-03-10 10:29:47 +01:00
parent c14eeae249
commit ea021a29e3
7 changed files with 60 additions and 43 deletions

View File

@ -20,7 +20,10 @@ use typst::syntax::{FileId, Source, Span};
use typst::WorldExt;
use typst_pdf::{PdfOptions, Timestamp, Validator};
use crate::args::{CompileArgs, CompileCommand, DiagnosticFormat, Input, Output, OutputFormat, PdfStandard, PdfVersion, WatchCommand};
use crate::args::{
CompileArgs, CompileCommand, DiagnosticFormat, Input, Output, OutputFormat,
PdfStandard, PdfVersion, WatchCommand,
};
#[cfg(feature = "http-server")]
use crate::server::HtmlServer;
use crate::timings::Timer;
@ -298,14 +301,14 @@ fn export_pdf(document: &PagedDocument, config: &CompileConfig) -> SourceResult<
PdfStandard::A_3u => Validator::A_3u,
PdfStandard::A_4 => Validator::A_4,
PdfStandard::A_4f => Validator::A_4f,
PdfStandard::A_4e => Validator::A_4e
PdfStandard::A_4e => Validator::A_4e,
}
};
Some(validator)
}
};
let pdf_version = config.pdf_version.map(|v| match v {
PdfVersion::V_1_4 => typst_pdf::PdfVersion::Pdf14,
PdfVersion::V_1_5 => typst_pdf::PdfVersion::Pdf15,
@ -313,13 +316,13 @@ fn export_pdf(document: &PagedDocument, config: &CompileConfig) -> SourceResult<
PdfVersion::V_1_7 => typst_pdf::PdfVersion::Pdf17,
PdfVersion::V_2_0 => typst_pdf::PdfVersion::Pdf20,
});
let options = PdfOptions {
ident: Smart::Auto,
timestamp,
page_ranges: config.pages.clone(),
validator,
pdf_version
validator,
pdf_version,
};
let buffer = typst_pdf::pdf(document, &options)?;
config

View File

@ -52,7 +52,7 @@ impl RasterImage {
icc: Smart<Bytes>,
) -> StrResult<RasterImage> {
let mut is_rotated = false;
let (dynamic, icc, dpi) = match format {
RasterFormat::Exchange(format) => {
fn decode<T: ImageDecoder>(
@ -140,7 +140,14 @@ impl RasterImage {
}
};
Ok(Self(Arc::new(Repr { data, format, is_rotated, dynamic: Arc::new(dynamic), icc, dpi })))
Ok(Self(Arc::new(Repr {
data,
format,
is_rotated,
dynamic: Arc::new(dynamic),
icc,
dpi,
})))
}
/// The raw image data.
@ -167,7 +174,7 @@ impl RasterImage {
pub fn is_rotated(&self) -> bool {
self.0.is_rotated
}
/// The image's pixel density in pixels per inch, if known.
///
/// This is guaranteed to be positive.

View File

@ -1,13 +1,13 @@
use std::collections::{BTreeMap, HashMap, HashSet};
use krilla::annotation::Annotation;
use krilla::configure::{Configuration, PdfVersion, ValidationError};
use krilla::destination::{NamedDestination, XyzDestination};
use krilla::error::KrillaError;
use krilla::page::PageLabel;
use krilla::path::PathBuilder;
use krilla::surface::Surface;
use krilla::{Document, PageSettings, SerializeSettings};
use krilla::configure::{Configuration, PdfVersion, ValidationError};
use typst_library::diag::{bail, SourceResult};
use typst_library::foundations::NativeElement;
use typst_library::introspection::Location;
@ -319,8 +319,12 @@ pub(crate) fn handle_group(
/// Finish a krilla document and handle export errors.
fn finish(document: Document, gc: GlobalContext) -> SourceResult<Vec<u8>> {
let validator: krilla::configure::Validator = gc.options.validator.map(|v| v.into()).unwrap_or(krilla::configure::Validator::None);
let validator: krilla::configure::Validator = gc
.options
.validator
.map(|v| v.into())
.unwrap_or(krilla::configure::Validator::None);
match document.finish() {
Ok(r) => Ok(r),
Err(e) => match e {
@ -334,11 +338,9 @@ fn finish(document: Document, gc: GlobalContext) -> SourceResult<Vec<u8>> {
}
KrillaError::ValidationError(ve) => {
// We can only produce 1 error, so just take the first one.
let prefix = format!(
"validated export for {} failed:",
validator.as_str()
);
let prefix =
format!("validated export for {} failed:", validator.as_str());
match &ve[0] {
ValidationError::TooLongString => {
bail!(Span::detached(), "{prefix} a PDF string longer \
@ -434,7 +436,7 @@ fn finish(document: Document, gc: GlobalContext) -> SourceResult<Vec<u8>> {
bail!(Span::detached(), "{prefix} missing document language";
hint: "set the language of the document");
}
// Needs to be set by typst-pdf.
ValidationError::MissingHeadingTitle => {
bail!(Span::detached(), "{prefix} missing heading title";
@ -534,6 +536,6 @@ fn get_configuration(options: &PdfOptions) -> SourceResult<Configuration> {
}
}
};
Ok(config)
}

View File

@ -8,7 +8,9 @@ use krilla::SvgSettings;
use typst_library::diag::{bail, SourceResult};
use typst_library::foundations::Smart;
use typst_library::layout::Size;
use typst_library::visualize::{ExchangeFormat, Image, ImageKind, ImageScaling, RasterFormat, RasterImage};
use typst_library::visualize::{
ExchangeFormat, Image, ImageKind, ImageScaling, RasterFormat, RasterImage,
};
use typst_syntax::Span;
use crate::convert::{FrameContext, GlobalContext};
@ -23,7 +25,7 @@ pub(crate) fn handle_image(
span: Span,
) -> SourceResult<()> {
surface.push_transform(&fc.state().transform().to_krilla());
let interpolate = image.scaling() == Smart::Custom(ImageScaling::Smooth);
match image.kind() {
@ -43,10 +45,7 @@ pub(crate) fn handle_image(
surface.draw_svg(
svg.tree(),
size.to_krilla(),
SvgSettings {
embed_text: true,
..Default::default()
},
SvgSettings { embed_text: true, ..Default::default() },
);
}
}
@ -159,12 +158,16 @@ impl CustomImage for PdfImage {
}
#[comemo::memoize]
fn convert_raster(raster: RasterImage, interpolate: bool) -> Option<krilla::image::Image> {
fn convert_raster(
raster: RasterImage,
interpolate: bool,
) -> Option<krilla::image::Image> {
match raster.format() {
RasterFormat::Exchange(e) => match e {
ExchangeFormat::Jpg => {
if !raster.is_rotated() {
let image_data: Arc<dyn AsRef<[u8]> + Send + Sync> = Arc::new(raster.data().clone());
let image_data: Arc<dyn AsRef<[u8]> + Send + Sync> =
Arc::new(raster.data().clone());
krilla::image::Image::from_jpeg(image_data.into(), interpolate)
} else {
// Can't embed original JPEG data if it had to be rotated.
@ -172,7 +175,9 @@ fn convert_raster(raster: RasterImage, interpolate: bool) -> Option<krilla::imag
}
}
_ => krilla::image::Image::from_custom(PdfImage::new(raster), interpolate),
},
RasterFormat::Pixel(_) => {
krilla::image::Image::from_custom(PdfImage::new(raster), interpolate)
}
RasterFormat::Pixel(_) => krilla::image::Image::from_custom(PdfImage::new(raster), interpolate)
}
}

View File

@ -41,7 +41,7 @@ pub(crate) fn handle_link(
let y2 = max_y.to_f32();
let rect = Rect::from_ltrb(x1, y1, x2, y2).unwrap();
// TODO: Support quad points.
let pos = match dest {

View File

@ -79,18 +79,16 @@ fn convert_font(
if let Some(font) = gc.fonts_forward.get(&typst_font) {
Ok(font.clone())
} else {
let font_data: Arc<dyn AsRef<[u8]> + Send + Sync> = Arc::new(typst_font.data().clone());
let font = match krilla::font::Font::new(
font_data.into(),
typst_font.index(),
true,
) {
None => {
let font_str = display_font(&typst_font);
bail!(Span::detached(), "failed to process font {font_str}");
}
Some(f) => f,
};
let font_data: Arc<dyn AsRef<[u8]> + Send + Sync> =
Arc::new(typst_font.data().clone());
let font =
match krilla::font::Font::new(font_data.into(), typst_font.index(), true) {
None => {
let font_str = display_font(&typst_font);
bail!(Span::detached(), "failed to process font {font_str}");
}
Some(f) => f,
};
gc.fonts_forward.insert(typst_font.clone(), font.clone());
gc.fonts_backward.insert(font.clone(), typst_font.clone());

View File

@ -6,7 +6,9 @@ use krilla::path as kp;
use krilla::path::PathBuilder;
use typst_library::layout::{Abs, Point, Size, Transform};
use typst_library::text::Font;
use typst_library::visualize::{Color, ColorSpace, Curve, CurveItem, FillRule, LineCap, LineJoin};
use typst_library::visualize::{
Color, ColorSpace, Curve, CurveItem, FillRule, LineCap, LineJoin,
};
pub(crate) trait SizeExt {
fn to_krilla(&self) -> kg::Size;