Add support for converting text in SVGs to paths (#5390)

This commit is contained in:
Laurenz Stampfl 2024-12-08 18:06:25 +01:00 committed by GitHub
parent 468a60103d
commit 67ef6066f4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 35 additions and 4 deletions

View File

@ -55,6 +55,7 @@ pub fn layout_image(
elem.alt(styles),
engine.world,
&families(styles).collect::<Vec<_>>(),
elem.flatten_text(styles),
)
.at(span)?;

View File

@ -94,6 +94,12 @@ pub struct ImageElem {
/// ```
#[default(ImageFit::Cover)]
pub fit: ImageFit,
/// Whether text in SVG images should be converted into paths before
/// embedding. This will result in the text becoming unselectable in
/// the output.
#[default(false)]
pub flatten_text: bool,
}
#[scope]
@ -246,13 +252,14 @@ impl Image {
alt: Option<EcoString>,
world: Tracked<dyn World + '_>,
families: &[&str],
flatten_text: bool,
) -> StrResult<Image> {
let kind = match format {
ImageFormat::Raster(format) => {
ImageKind::Raster(RasterImage::new(data, format)?)
}
ImageFormat::Vector(VectorFormat::Svg) => {
ImageKind::Svg(SvgImage::with_fonts(data, world, families)?)
ImageKind::Svg(SvgImage::with_fonts(data, world, flatten_text, families)?)
}
};

View File

@ -22,6 +22,7 @@ pub struct SvgImage(Arc<Repr>);
struct Repr {
data: Bytes,
size: Axes<f64>,
flatten_text: bool,
font_hash: u128,
tree: usvg::Tree,
}
@ -32,7 +33,13 @@ impl SvgImage {
pub fn new(data: Bytes) -> StrResult<SvgImage> {
let tree =
usvg::Tree::from_data(&data, &base_options()).map_err(format_usvg_error)?;
Ok(Self(Arc::new(Repr { data, size: tree_size(&tree), font_hash: 0, tree })))
Ok(Self(Arc::new(Repr {
data,
size: tree_size(&tree),
font_hash: 0,
flatten_text: false,
tree,
})))
}
/// Decode an SVG image with access to fonts.
@ -40,6 +47,7 @@ impl SvgImage {
pub fn with_fonts(
data: Bytes,
world: Tracked<dyn World + '_>,
flatten_text: bool,
families: &[&str],
) -> StrResult<SvgImage> {
let book = world.book();
@ -60,7 +68,13 @@ impl SvgImage {
)
.map_err(format_usvg_error)?;
let font_hash = resolver.into_inner().unwrap().finish();
Ok(Self(Arc::new(Repr { data, size: tree_size(&tree), font_hash, tree })))
Ok(Self(Arc::new(Repr {
data,
size: tree_size(&tree),
font_hash,
flatten_text,
tree,
})))
}
/// The raw image data.
@ -73,6 +87,11 @@ impl SvgImage {
self.0.size.x
}
/// Whether the SVG's text should be flattened.
pub fn flatten_text(&self) -> bool {
self.0.flatten_text
}
/// The SVG's height in pixels.
pub fn height(&self) -> f64 {
self.0.size.y

View File

@ -208,7 +208,11 @@ fn encode_svg(
) -> Result<(Chunk, Ref), svg2pdf::ConversionError> {
svg2pdf::to_chunk(
svg.tree(),
svg2pdf::ConversionOptions { pdfa, ..Default::default() },
svg2pdf::ConversionOptions {
pdfa,
embed_text: !svg.flatten_text(),
..Default::default()
},
)
}