[librsvg/rustify-rsvg-convert: 27/78] rsvg-convert: Start to work on sizing the output properly
- From: Sven Neumann <sneumann src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg/rustify-rsvg-convert: 27/78] rsvg-convert: Start to work on sizing the output properly
- Date: Wed, 3 Feb 2021 10:18:30 +0000 (UTC)
commit 20a3df4e97d30f5edfbf8981fa7b50e7eb3705a7
Author: Sven Neumann <sven svenfoo org>
Date: Thu Nov 5 00:28:29 2020 +0100
rsvg-convert: Start to work on sizing the output properly
src/bin/rsvg-convert/cli.rs | 37 ++++++++++++---------
src/bin/rsvg-convert/main.rs | 38 +++++++++++++--------
src/bin/rsvg-convert/size.rs | 29 ++++++++++++++++
src/bin/rsvg-convert/surface.rs | 74 +++++++++++++++++++----------------------
4 files changed, 110 insertions(+), 68 deletions(-)
---
diff --git a/src/bin/rsvg-convert/cli.rs b/src/bin/rsvg-convert/cli.rs
index 5567dd43..a5f21b94 100644
--- a/src/bin/rsvg-convert/cli.rs
+++ b/src/bin/rsvg-convert/cli.rs
@@ -5,6 +5,7 @@ use std::path::{Path, PathBuf};
use librsvg::{Color, Parse};
use crate::input::Input;
+use crate::size::{Dpi, Zoom};
arg_enum! {
#[derive(Clone, Copy, Debug)]
@@ -19,9 +20,9 @@ arg_enum! {
#[derive(Debug)]
pub struct Args {
- pub dpi_x: f64,
- pub dpi_y: f64,
- pub zoom: (f32, f32),
+ pub dpi: Dpi,
+ zoom_x: Option<f64>,
+ zoom_y: Option<f64>,
pub width: Option<u32>,
pub height: Option<u32>,
pub format: Format,
@@ -66,7 +67,6 @@ impl Args {
.long("x-zoom")
.takes_value(true)
.value_name("float")
- .default_value("1.0")
.conflicts_with("zoom")
.help("Horizontal zoom factor"),
)
@@ -76,7 +76,6 @@ impl Args {
.long("y-zoom")
.takes_value(true)
.value_name("float")
- .default_value("1.0")
.conflicts_with("zoom")
.help("Vertical zoom factor"),
)
@@ -86,7 +85,6 @@ impl Args {
.long("zoom")
.takes_value(true)
.value_name("float")
- .default_value("1.0")
.help("Zoom factor"),
)
.arg(
@@ -197,17 +195,17 @@ impl Args {
}
};
+ let zoom = value_t!(matches, "zoom", f64).or_none()?;
+ let zoom_x = value_t!(matches, "zoom_x", f64).or_none()?;
+ let zoom_y = value_t!(matches, "zoom_y", f64).or_none()?;
+
let args = Args {
- dpi_x: value_t!(matches, "res_x", f64)?,
- dpi_y: value_t!(matches, "res_y", f64)?,
- zoom: if matches.is_present("zoom") {
- let zoom = value_t!(matches, "zoom", f32)?;
- (zoom, zoom)
- } else {
- let zoom_x = value_t!(matches, "zoom_x", f32)?;
- let zoom_y = value_t!(matches, "zoom_y", f32)?;
- (zoom_x, zoom_y)
+ dpi: Dpi {
+ x: value_t!(matches, "res_x", f64)?,
+ y: value_t!(matches, "res_y", f64)?,
},
+ zoom_x: zoom.or(zoom_x),
+ zoom_y: zoom.or(zoom_y),
width: value_t!(matches, "size_x", u32).or_none()?,
height: value_t!(matches, "size_y", u32).or_none()?,
format,
@@ -252,6 +250,15 @@ impl Args {
pub fn input(&self) -> Input<'_> {
Input::new(&self.input)
}
+
+ pub fn zoom(&self) -> Zoom {
+ match (self.zoom_x, self.zoom_y) {
+ (None, None) => Zoom { x: 1.0, y: 1.0 },
+ (Some(x), None) => Zoom { x, y: x },
+ (None, Some(y)) => Zoom { x: y, y },
+ (Some(x), Some(y)) => Zoom { x, y },
+ }
+ }
}
trait NotFound {
diff --git a/src/bin/rsvg-convert/main.rs b/src/bin/rsvg-convert/main.rs
index 4ac0c439..c250287d 100644
--- a/src/bin/rsvg-convert/main.rs
+++ b/src/bin/rsvg-convert/main.rs
@@ -4,13 +4,15 @@ extern crate clap;
mod cli;
mod input;
mod output;
+mod size;
mod surface;
use cssparser::Color;
-use librsvg::{CairoRenderer, Loader, RenderingError};
+use librsvg::{CairoRenderer, Loader, RenderingError, SvgHandle};
use crate::cli::Args;
use crate::output::Stream;
+use crate::size::Size;
use crate::surface::Surface;
#[macro_export]
@@ -37,6 +39,13 @@ fn load_stylesheet(args: &Args) -> std::io::Result<Option<String>> {
}
}
+fn get_size(_handle: &SvgHandle, renderer: &CairoRenderer, args: &Args) -> Option<Size> {
+ // TODO
+ renderer
+ .intrinsic_size_in_pixels()
+ .map(|(w, h)| Size::new(w, h).scale(args.zoom()))
+}
+
fn main() {
let args = Args::new().unwrap_or_else(|e| e.exit());
@@ -58,21 +67,21 @@ fn main() {
.unwrap_or_else(|e| exit!("Error applying stylesheet: {}", e));
}
- let renderer = CairoRenderer::new(&handle).with_dpi(args.dpi_x, args.dpi_y);
+ let renderer = CairoRenderer::new(&handle).with_dpi(args.dpi.x, args.dpi.y);
if target.is_none() {
- target = match renderer.intrinsic_size_in_pixels() {
- Some((width, height)) => {
- let output = Stream::new(args.output())
- .unwrap_or_else(|e| exit!("Error opening output: {}", e));
-
- match Surface::new(args.format, width, height, output) {
- Ok(surface) => Some(surface),
- Err(cairo::Status::InvalidSize) => size_limit_exceeded(),
- Err(e) => exit!("Error creating output surface: {}", e),
- }
+ let size = get_size(&handle, &renderer, &args)
+ .unwrap_or_else(|| exit!("Could not get dimensions for file {}", input));
+
+ target = {
+ let output = Stream::new(args.output())
+ .unwrap_or_else(|e| exit!("Error opening output: {}", e));
+
+ match Surface::new(args.format, size, output) {
+ Ok(surface) => Some(surface),
+ Err(cairo::Status::InvalidSize) => size_limit_exceeded(),
+ Err(e) => exit!("Error creating output surface: {}", e),
}
- None => None,
};
}
@@ -88,6 +97,9 @@ fn main() {
);
}
+ let zoom = args.zoom();
+ cr.scale(zoom.x, zoom.y);
+
surface
.render(&renderer, &cr, args.export_id())
.unwrap_or_else(|e| match e {
diff --git a/src/bin/rsvg-convert/size.rs b/src/bin/rsvg-convert/size.rs
new file mode 100644
index 00000000..5b86481d
--- /dev/null
+++ b/src/bin/rsvg-convert/size.rs
@@ -0,0 +1,29 @@
+#[derive(Debug)]
+pub struct Dpi {
+ pub x: f64,
+ pub y: f64,
+}
+
+pub struct Zoom {
+ pub x: f64,
+ pub y: f64,
+}
+
+#[derive(Clone, Debug)]
+pub struct Size {
+ pub w: f64,
+ pub h: f64,
+}
+
+impl Size {
+ pub fn new(w: f64, h: f64) -> Self {
+ Self { w, h }
+ }
+
+ pub fn scale(&self, zoom: Zoom) -> Self {
+ Self {
+ w: self.w * zoom.x,
+ h: self.h * zoom.y,
+ }
+ }
+}
diff --git a/src/bin/rsvg-convert/surface.rs b/src/bin/rsvg-convert/surface.rs
index b94c203a..b577bd75 100644
--- a/src/bin/rsvg-convert/surface.rs
+++ b/src/bin/rsvg-convert/surface.rs
@@ -5,17 +5,18 @@ use librsvg::{CairoRenderer, RenderingError};
use crate::cli::Format;
use crate::output::Stream;
+use crate::size::Size;
-// TODO
+// TODO: use from src/lib/handle.rs
fn checked_i32(x: f64) -> Result<i32, cairo::Status> {
cast::i32(x).map_err(|_| cairo::Status::InvalidSize)
}
pub enum Surface {
Png(cairo::ImageSurface, Stream),
- Pdf(cairo::PdfSurface, (f64, f64)),
- Ps(cairo::PsSurface, (f64, f64)),
- Svg(cairo::SvgSurface, (f64, f64)),
+ Pdf(cairo::PdfSurface, Size),
+ Ps(cairo::PsSurface, Size),
+ Svg(cairo::SvgSurface, Size),
}
impl Deref for Surface {
@@ -32,68 +33,61 @@ impl Deref for Surface {
}
impl Surface {
- pub fn new(
- format: Format,
- width: f64,
- height: f64,
- stream: Stream,
- ) -> Result<Self, cairo::Status> {
+ pub fn new(format: Format, size: Size, stream: Stream) -> Result<Self, cairo::Status> {
match format {
- Format::Png => Self::new_for_png(width, height, stream),
- Format::Pdf => Self::new_for_pdf(width, height, stream),
- Format::Ps => Self::new_for_ps(width, height, stream, false),
- Format::Eps => Self::new_for_ps(width, height, stream, true),
- Format::Svg => Self::new_for_svg(width, height, stream),
+ Format::Png => Self::new_for_png(size, stream),
+ Format::Pdf => Self::new_for_pdf(size, stream),
+ Format::Ps => Self::new_for_ps(size, stream, false),
+ Format::Eps => Self::new_for_ps(size, stream, true),
+ Format::Svg => Self::new_for_svg(size, stream),
}
}
- fn new_for_png(width: f64, height: f64, stream: Stream) -> Result<Self, cairo::Status> {
- let w = checked_i32(width.round())?;
- let h = checked_i32(height.round())?;
+ fn new_for_png(size: Size, stream: Stream) -> Result<Self, cairo::Status> {
+ let w = checked_i32(size.w.round())?;
+ let h = checked_i32(size.h.round())?;
let surface = cairo::ImageSurface::create(cairo::Format::ARgb32, w, h)?;
Ok(Self::Png(surface, stream))
}
- fn new_for_pdf(width: f64, height: f64, stream: Stream) -> Result<Self, cairo::Status> {
- let surface = cairo::PdfSurface::for_stream(width, height, stream)?;
+ fn new_for_pdf(size: Size, stream: Stream) -> Result<Self, cairo::Status> {
+ let surface = cairo::PdfSurface::for_stream(size.w, size.h, stream)?;
if let Some(date) = metadata::creation_date() {
surface.set_metadata(cairo::PdfMetadata::CreateDate, &date)?;
}
- Ok(Self::Pdf(surface, (width, height)))
+ Ok(Self::Pdf(surface, size))
}
- fn new_for_ps(
- width: f64,
- height: f64,
- stream: Stream,
- eps: bool,
- ) -> Result<Self, cairo::Status> {
- let surface = cairo::PsSurface::for_stream(width, height, stream)?;
+ fn new_for_ps(size: Size, stream: Stream, eps: bool) -> Result<Self, cairo::Status> {
+ let surface = cairo::PsSurface::for_stream(size.w, size.h, stream)?;
surface.set_eps(eps);
- Ok(Self::Ps(surface, (width, height)))
+ Ok(Self::Ps(surface, size))
}
- fn new_for_svg(width: f64, height: f64, stream: Stream) -> Result<Self, cairo::Status> {
- let surface = cairo::SvgSurface::for_stream(width, height, stream)?;
- Ok(Self::Svg(surface, (width, height)))
+ fn new_for_svg(size: Size, stream: Stream) -> Result<Self, cairo::Status> {
+ let surface = cairo::SvgSurface::for_stream(size.w, size.h, stream)?;
+ Ok(Self::Svg(surface, size))
}
- fn size(&self) -> (f64, f64) {
+ fn size(&self) -> Size {
match self {
- Self::Png(s, _) => (s.get_width() as f64, s.get_height() as f64),
- Self::Pdf(_, size) => *size,
- Self::Ps(_, size) => *size,
- Self::Svg(_, size) => *size,
+ Self::Png(surface, _) => Size {
+ w: surface.get_width() as f64,
+ h: surface.get_height() as f64,
+ },
+ Self::Pdf(_, size) => size.clone(),
+ Self::Ps(_, size) => size.clone(),
+ Self::Svg(_, size) => size.clone(),
}
}
fn bounds(&self) -> cairo::Rectangle {
- let (width, height) = self.size();
+ let size = self.size();
cairo::Rectangle {
x: 0.0,
y: 0.0,
- width,
- height,
+ width: size.w,
+ height: size.h,
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]