Require the PdfEmbedding feature

This commit is contained in:
Laurenz Stampfl 2025-07-20 00:13:25 +02:00
parent 070a375f3e
commit 5ef332caa4
3 changed files with 51 additions and 50 deletions

View File

@ -15,7 +15,7 @@ use std::fmt::{self, Debug, Formatter};
use std::sync::Arc;
use ecow::{eco_format, EcoString};
use typst_library::World;
use typst_library::{Feature, World};
use typst_syntax::{Span, Spanned};
use typst_utils::LazyHash;
@ -271,32 +271,42 @@ impl Packed<ImageElem> {
.within(loaded)?,
),
ImageFormat::Vector(VectorFormat::Pdf) => {
let document =
PdfDocument::new(loaded.data.clone(), engine.world.clone())
.within(loaded)?;
let page_num = self.page.get(styles);
if engine.world.library().features.is_enabled(Feature::PdfEmbedding) {
let document =
PdfDocument::new(loaded.data.clone(), engine.world.clone())
.within(loaded)?;
let page_num = self.page.get(styles);
if page_num == 0 {
if page_num == 0 {
bail!(
span,
"{page_num} is not a valid page number";
hint: "page numbers for PDF start at 1"
)
};
// The user provides the page number start from 1, further down the pipeline,
// page numbers are 0-based.
let page_idx = page_num - 1;
let num_pages = document.len();
let Some(pdf_image) = PdfImage::new(document, page_idx) else {
bail!(
span,
"page {page_num} doesn't exist";
hint: "the document only has {num_pages} pages"
);
};
ImageKind::Pdf(pdf_image)
} else {
bail!(
span,
"{page_num} is not a valid page number";
hint: "page numbers start at 1"
)
};
let page_idx = page_num - 1;
let num_pages = document.len();
// The user provides the page number staring from 1, further down the pipeline they page
// numbers are 0-based.
let Some(pdf_image) = PdfImage::new(document, page_idx) else {
bail!(
span,
"page {page_num} doesn't exist";
hint: "the document only has {num_pages} pages"
)
};
ImageKind::Pdf(pdf_image)
"embedding PDFs is currently an experimental, opt-in feature";
hint: "enable the corresponding feature to try it out";
hint: "convert your PDF to SVG instead"
);
}
}
};

View File

@ -116,9 +116,7 @@ fn build_pdf_texture(pdf: &PdfImage, w: u32, h: u32) -> Option<sk::Pixmap> {
StandardFont::Helvetica => sf.helvetica.normal.clone(),
StandardFont::HelveticaBold => sf.helvetica.bold.clone(),
StandardFont::HelveticaOblique => sf.helvetica.italic.clone(),
StandardFont::HelveticaBoldOblique => {
sf.helvetica.bold_italic.clone()
}
StandardFont::HelveticaBoldOblique => sf.helvetica.bold_italic.clone(),
StandardFont::Courier => sf.courier.normal.clone(),
StandardFont::CourierBold => sf.courier.bold.clone(),
StandardFont::CourierOblique => sf.courier.italic.clone(),
@ -132,8 +130,7 @@ fn build_pdf_texture(pdf: &PdfImage, w: u32, h: u32) -> Option<sk::Pixmap> {
};
bytes.map(|d| {
let font_data: Arc<dyn AsRef<[u8]> + Send + Sync> =
Arc::new(d.clone());
let font_data: Arc<dyn AsRef<[u8]> + Send + Sync> = Arc::new(d.clone());
font_data
})
@ -142,9 +139,7 @@ fn build_pdf_texture(pdf: &PdfImage, w: u32, h: u32) -> Option<sk::Pixmap> {
let interpreter_settings = InterpreterSettings {
font_resolver: Arc::new(move |query| match query {
FontQuery::Standard(s) => select_standard_font(*s),
FontQuery::Fallback(f) => {
select_standard_font(f.pick_standard_font())
}
FontQuery::Fallback(f) => select_standard_font(f.pick_standard_font()),
}),
warning_sink: Arc::new(|_| {}),
};
@ -156,7 +151,7 @@ fn build_pdf_texture(pdf: &PdfImage, w: u32, h: u32) -> Option<sk::Pixmap> {
width: Some(w as u16),
height: Some(h as u16),
};
let hayro_pix = hayro::render(page, &interpreter_settings, &render_settings);
sk::Pixmap::from_vec(hayro_pix.take_u8(), IntSize::from_wh(w, h)?)

View File

@ -1,12 +1,14 @@
use std::borrow::Cow;
use std::sync::Arc;
use base64::Engine;
use ecow::{eco_format, EcoString};
use hayro::{FontData, FontQuery, InterpreterSettings, RenderSettings, StandardFont};
use image::{codecs::png::PngEncoder, ImageEncoder};
use std::borrow::Cow;
use std::sync::Arc;
use typst_library::foundations::Smart;
use typst_library::layout::{Abs, Axes};
use typst_library::visualize::{ExchangeFormat, Image, ImageKind, ImageScaling, PdfImage, RasterFormat};
use typst_library::visualize::{
ExchangeFormat, Image, ImageKind, ImageScaling, PdfImage, RasterFormat,
};
use crate::SVGRenderer;
@ -73,20 +75,19 @@ pub fn convert_image_to_base64_url(image: &Image) -> EcoString {
// doesn't exceed 3000 pixels.
const MIN_WIDTH: f32 = 1000.0;
const MAX_WIDTH: f32 = 3000.0;
let base_width = pdf.width();
let w_scale = (MIN_WIDTH / base_width).max(MAX_WIDTH / base_width);
let base_height = pdf.height();
let h_scale = (MIN_WIDTH / base_height).min(MAX_WIDTH / base_height);
let total_scale = w_scale.min(h_scale);
let width = (base_width * total_scale).ceil() as u32;
let height = (base_height * total_scale).ceil() as u32;
("png", Cow::Owned(pdf_to_png(pdf, width, height)))
},
}
};
let mut url = eco_format!("data:image/{format};base64,");
@ -105,9 +106,7 @@ fn pdf_to_png(pdf: &PdfImage, w: u32, h: u32) -> Vec<u8> {
StandardFont::Helvetica => sf.helvetica.normal.clone(),
StandardFont::HelveticaBold => sf.helvetica.bold.clone(),
StandardFont::HelveticaOblique => sf.helvetica.italic.clone(),
StandardFont::HelveticaBoldOblique => {
sf.helvetica.bold_italic.clone()
}
StandardFont::HelveticaBoldOblique => sf.helvetica.bold_italic.clone(),
StandardFont::Courier => sf.courier.normal.clone(),
StandardFont::CourierBold => sf.courier.bold.clone(),
StandardFont::CourierOblique => sf.courier.italic.clone(),
@ -121,8 +120,7 @@ fn pdf_to_png(pdf: &PdfImage, w: u32, h: u32) -> Vec<u8> {
};
bytes.map(|d| {
let font_data: Arc<dyn AsRef<[u8]> + Send + Sync> =
Arc::new(d.clone());
let font_data: Arc<dyn AsRef<[u8]> + Send + Sync> = Arc::new(d.clone());
font_data
})
@ -131,9 +129,7 @@ fn pdf_to_png(pdf: &PdfImage, w: u32, h: u32) -> Vec<u8> {
let interpreter_settings = InterpreterSettings {
font_resolver: Arc::new(move |query| match query {
FontQuery::Standard(s) => select_standard_font(*s),
FontQuery::Fallback(f) => {
select_standard_font(f.pick_standard_font())
}
FontQuery::Fallback(f) => select_standard_font(f.pick_standard_font()),
}),
warning_sink: Arc::new(|_| {}),
};
@ -149,4 +145,4 @@ fn pdf_to_png(pdf: &PdfImage, w: u32, h: u32) -> Vec<u8> {
let hayro_pix = hayro::render(page, &interpreter_settings, &render_settings);
hayro_pix.take_png()
}
}