Skip to content

Commit b850bbd

Browse files
laurmaedjereknih
andcommitted
Bump edition and usvg
Co-Authored-By: Martin <[email protected]>
1 parent a156cda commit b850bbd

4 files changed

Lines changed: 56 additions & 83 deletions

File tree

Cargo.toml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "svg2pdf"
33
version = "0.1.0"
44
authors = ["Martin Haug <[email protected]>"]
5-
edition = "2018"
5+
edition = "2021"
66
description = "Convert SVG files to PDFs."
77
repository = "https://github.com/typst/svg2pdf"
88
readme = "README.md"
@@ -11,14 +11,12 @@ categories = ["encoding", "graphics", "multimedia"]
1111
keywords = ["svg", "pdf", "vector-graphics", "conversion"]
1212

1313
[features]
14-
default = ["png", "jpeg", "text", "system-fonts"]
14+
default = ["png", "jpeg", "text"]
1515
png = ["image/png"]
1616
jpeg = ["image/jpeg"]
17-
text = ["usvg/text"]
18-
system-fonts = ["usvg/system-fonts", "usvg/memmap-fonts"]
1917

2018
[dependencies]
21-
image = { version = "0.23", default-features = false, optional = true }
2219
miniz_oxide = "0.4"
2320
pdf-writer = "0.4.1"
24-
usvg = { version = "0.19", default-features = false }
21+
usvg = { version = "0.20", default-features = false }
22+
image = { version = "0.23", default-features = false, optional = true }

src/defer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ pub fn write_gradients(
164164
shading.shading_type(pending.shading_type);
165165
shading.color_space().srgb();
166166
shading.function(func);
167-
shading.coords(IntoIterator::into_iter(pending.coords).take(
167+
shading.coords(pending.coords.into_iter().take(
168168
if pending.shading_type == ShadingType::Axial {
169169
4
170170
} else {

src/lib.rs

Lines changed: 39 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use std::collections::HashMap;
4040
use pdf_writer::types::ProcSet;
4141
use pdf_writer::writers::{ColorSpace, ExponentialFunction, FormXObject, Resources};
4242
use pdf_writer::{Content, Finish, Name, PdfWriter, Rect, Ref, TextStr, Writer};
43-
use usvg::{NodeExt, NodeKind, Stop, Tree};
43+
use usvg::{NodeExt, NodeKind, Opacity, Stop, Tree};
4444

4545
mod defer;
4646
mod render;
@@ -234,6 +234,11 @@ impl<'a> Context<'a> {
234234

235235
/// Convert an SVG source string to a standalone PDF buffer.
236236
///
237+
/// Does not load any fonts and consequently cannot convert `text` elements. To
238+
/// convert text, you should convert your source string to a usvg [`Tree`]
239+
/// manually (providing a [font database](usvg::Options::fontdb)) and then use
240+
/// [`convert_tree`].
241+
///
237242
/// Returns an error if the SVG string is malformed.
238243
pub fn convert_str(src: &str, options: Options) -> Result<Vec<u8>, usvg::Error> {
239244
let mut usvg_opts = usvg::Options::default();
@@ -545,31 +550,24 @@ fn apply_mask(
545550

546551
/// A color helper function that stores colors with values between 0.0 and 1.0.
547552
#[derive(Debug, Clone, Copy)]
548-
struct RgbaColor {
553+
struct RgbColor {
549554
/// Red.
550555
r: f32,
551556
/// Green.
552557
g: f32,
553558
/// Blue.
554559
b: f32,
555-
/// Alpha.
556-
a: f32,
557560
}
558561

559-
impl RgbaColor {
562+
impl RgbColor {
560563
/// Create a new color.
561-
fn new(r: f32, g: f32, b: f32, a: f32) -> RgbaColor {
562-
RgbaColor { r, g, b, a }
564+
fn new(r: f32, g: f32, b: f32) -> RgbColor {
565+
RgbColor { r, g, b }
563566
}
564567

565568
/// Create a new color from u8 color components between 0.0 and 255.0.
566-
fn from_u8(r: u8, g: u8, b: u8, a: u8) -> RgbaColor {
567-
RgbaColor::new(
568-
r as f32 / 255.0,
569-
g as f32 / 255.0,
570-
b as f32 / 255.0,
571-
a as f32 / 255.0,
572-
)
569+
fn from_u8(r: u8, g: u8, b: u8) -> RgbColor {
570+
RgbColor::new(r as f32 / 255.0, g as f32 / 255.0, b as f32 / 255.0)
573571
}
574572

575573
/// Create a RGB array for use in PDF.
@@ -578,9 +576,9 @@ impl RgbaColor {
578576
}
579577
}
580578

581-
impl From<usvg::Color> for RgbaColor {
579+
impl From<usvg::Color> for RgbColor {
582580
fn from(color: usvg::Color) -> Self {
583-
Self::from_u8(color.red, color.green, color.blue, color.alpha)
581+
Self::from_u8(color.red, color.green, color.blue)
584582
}
585583
}
586584

@@ -595,22 +593,9 @@ fn register_functions(
595593
let func_ref = ctx.alloc_ref();
596594
stops_to_function(writer, func_ref, stops, false);
597595

598-
let alpha_ref = if stops
599-
.iter()
600-
.any(|stop| stop.opacity.value() < 1.0 || stop.color.alpha < 255)
601-
{
602-
let stops = stops
603-
.iter()
604-
.cloned()
605-
.map(|mut stop| {
606-
stop.color.alpha = (stop.color.alpha as f64 * stop.opacity.value()) as u8;
607-
stop
608-
})
609-
.collect::<Vec<_>>();
610-
596+
let alpha_ref = if stops.iter().any(|stop| stop.opacity.value() < 1.0) {
611597
let alpha_ref = ctx.alloc_ref();
612598
stops_to_function(writer, alpha_ref, &stops, true);
613-
614599
Some(alpha_ref)
615600
} else {
616601
None
@@ -626,32 +611,34 @@ fn stops_to_function(
626611
stops: &[Stop],
627612
alpha: bool,
628613
) -> bool {
629-
let range =
630-
IntoIterator::into_iter([0.0f32, 1.0f32])
631-
.cycle()
632-
.take(if alpha { 2 } else { 6 });
633-
634-
let set_colors =
635-
|exp: &mut ExponentialFunction, a_color: RgbaColor, b_color: RgbaColor| {
636-
if alpha {
637-
exp.c0([a_color.a]);
638-
exp.c1([b_color.a]);
639-
} else {
640-
exp.c0(a_color.to_array());
641-
exp.c1(b_color.to_array());
642-
}
614+
let range = [0.0f32, 1.0f32].into_iter().cycle().take(if alpha { 2 } else { 6 });
615+
616+
let set_alphas =
617+
|exp: &mut ExponentialFunction, a_alpha: Opacity, b_alpha: Opacity| {
618+
exp.c0([a_alpha.value() as f32]);
619+
exp.c1([b_alpha.value() as f32]);
620+
};
621+
622+
let set_rgbs =
623+
|exp: &mut ExponentialFunction, a_color: RgbColor, b_color: RgbColor| {
624+
exp.c0(a_color.to_array());
625+
exp.c1(b_color.to_array());
643626
};
644627

645628
if stops.is_empty() {
646629
return false;
647630
} else if stops.len() == 1 {
648631
let mut exp = writer.exponential_function(id);
649632
let stop = stops[0];
650-
let color = RgbaColor::from(stop.color);
633+
let color = RgbColor::from(stop.color);
651634

652635
exp.domain([0.0, 1.0]);
653636
exp.range(range);
654-
set_colors(&mut exp, color, color);
637+
if alpha {
638+
set_alphas(&mut exp, stop.opacity, stop.opacity)
639+
} else {
640+
set_rgbs(&mut exp, color, color);
641+
}
655642

656643
exp.n(1.0);
657644
return true;
@@ -678,12 +665,16 @@ fn stops_to_function(
678665

679666
for window in stops.windows(2) {
680667
let (a, b) = (window[0], window[1]);
681-
let (a_color, b_color) = (RgbaColor::from(a.color), RgbaColor::from(b.color));
668+
let (a_color, b_color) = (RgbColor::from(a.color), RgbColor::from(b.color));
682669
bounds.push(b.offset.value() as f32);
683670
let mut exp = ExponentialFunction::start(func_array.push());
684671
exp.domain([0.0, 1.0]);
685672
exp.range(range.clone());
686-
set_colors(&mut exp, a_color, b_color);
673+
if alpha {
674+
set_alphas(&mut exp, a.opacity, b.opacity);
675+
} else {
676+
set_rgbs(&mut exp, a_color, b_color);
677+
}
687678

688679
exp.n(1.0);
689680

src/render.rs

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use {
2121

2222
use super::{
2323
apply_clip_path, apply_mask, content_stream, form_xobject, Context, Options,
24-
RgbaColor, SRGB,
24+
RgbColor, SRGB,
2525
};
2626
use crate::convert_tree_into;
2727
use crate::defer::{PendingGS, PendingGradient};
@@ -165,22 +165,8 @@ fn render_path_partial(
165165
content.set_fill_color_space(ColorSpaceOperand::Named(SRGB));
166166
content.set_stroke_color_space(ColorSpaceOperand::Named(SRGB));
167167

168-
// Combine alpha and opacity values.
169-
let stroke_opacity = path.stroke.as_ref().map(|s| {
170-
let mut res = s.opacity.value() as f32;
171-
if let Paint::Color(c) = s.paint {
172-
res *= c.alpha as f32 / 255.0;
173-
}
174-
res
175-
});
176-
177-
let fill_opacity = path.fill.as_ref().map(|f| {
178-
let mut res = f.opacity.value() as f32;
179-
if let Paint::Color(c) = f.paint {
180-
res *= c.alpha as f32 / 255.0;
181-
}
182-
res
183-
});
168+
let stroke_opacity = path.stroke.as_ref().map(|s| s.opacity.value() as f32);
169+
let fill_opacity = path.fill.as_ref().map(|f| f.opacity.value() as f32);
184170

185171
// Write a graphics state for stroke and fill opacity.
186172
if stroke_opacity.unwrap_or(1.0) != 1.0 || fill_opacity.unwrap_or(1.0) != 1.0 {
@@ -219,7 +205,7 @@ fn render_path_partial(
219205

220206
match &stroke.paint {
221207
Paint::Color(c) => {
222-
content.set_stroke_color(RgbaColor::from(*c).to_array());
208+
content.set_stroke_color(RgbColor::from(*c).to_array());
223209
}
224210
Paint::Link(id) => {
225211
let item = ctx.tree.defs_by_id(id).unwrap();
@@ -250,7 +236,7 @@ fn render_path_partial(
250236
if fill {
251237
match path.fill.as_ref().map(|fill| &fill.paint) {
252238
Some(Paint::Color(c)) => {
253-
content.set_fill_color(RgbaColor::from(*c).to_array());
239+
content.set_fill_color(RgbColor::from(*c).to_array());
254240
}
255241
Some(Paint::Link(id)) => {
256242
let item = ctx.tree.defs_by_id(id).unwrap();
@@ -375,15 +361,13 @@ fn prep_shading(
375361
shading.shading_type(gradient.shading_type);
376362
shading.color_space().srgb_gray();
377363
shading.function(alpha_func);
378-
shading.coords(
379-
IntoIterator::into_iter(gradient.transformed_coords(&ctx.c, bbox)).take(
380-
if gradient.shading_type == ShadingType::Axial {
381-
4
382-
} else {
383-
6
384-
},
385-
),
386-
);
364+
shading.coords(gradient.transformed_coords(&ctx.c, bbox).into_iter().take(
365+
if gradient.shading_type == ShadingType::Axial {
366+
4
367+
} else {
368+
6
369+
},
370+
));
387371
shading.extend([true, true]);
388372
shading.finish();
389373

0 commit comments

Comments
 (0)