[librsvg/rustify-rsvg-convert: 42/78] rsvg-convert: simplify output handling and use Gio
- From: Sven Neumann <sneumann src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg/rustify-rsvg-convert: 42/78] rsvg-convert: simplify output handling and use Gio
- Date: Wed, 3 Feb 2021 10:18:30 +0000 (UTC)
commit b0b5b21d5070b85a035d3644dab2a6739cd64061
Author: Paolo Borelli <pborelli gnome org>
Date: Sat Jan 9 15:02:20 2021 +0100
rsvg-convert: simplify output handling and use Gio
Simplify output handling in a way similar to what was done for
info and use GOutpuStream for simmetry and because it has a
into_write() method that we can feed to cairo.
src/bin/rsvg-convert/cli.rs | 15 +++++++-------
src/bin/rsvg-convert/main.rs | 30 ++++++++++++++++++++-------
src/bin/rsvg-convert/output.rs | 45 +++++++++--------------------------------
src/bin/rsvg-convert/surface.rs | 37 ++++++++++++++++-----------------
4 files changed, 57 insertions(+), 70 deletions(-)
---
diff --git a/src/bin/rsvg-convert/cli.rs b/src/bin/rsvg-convert/cli.rs
index 69d5aac3..784e99c3 100644
--- a/src/bin/rsvg-convert/cli.rs
+++ b/src/bin/rsvg-convert/cli.rs
@@ -1,10 +1,11 @@
// command-line interface for rsvg-convert
-use std::path::{Path, PathBuf};
+use std::path::PathBuf;
use librsvg::{Color, Parse};
use crate::input::Input;
+use crate::output::Output;
use crate::size::{Dpi, Scale};
arg_enum! {
@@ -31,7 +32,7 @@ pub struct Args {
pub stylesheet: Option<PathBuf>,
pub unlimited: bool,
pub keep_image_data: bool,
- output: Option<PathBuf>,
+ pub output: Output,
pub input: Vec<Input>,
}
@@ -223,7 +224,11 @@ impl Args {
stylesheet: matches.value_of_os("stylesheet").map(PathBuf::from),
unlimited: matches.is_present("unlimited"),
keep_image_data,
- output: matches.value_of_os("output").map(PathBuf::from),
+ output: matches
+ .value_of_os("output")
+ .map(PathBuf::from)
+ .map(Output::Path)
+ .unwrap_or(Output::Stdout),
input: match matches.values_of_os("FILE") {
Some(values) => values.map(PathBuf::from).map(Input::Path).collect(),
None => vec![Input::Stdin],
@@ -248,10 +253,6 @@ impl Args {
pub fn export_id(&self) -> Option<&str> {
self.export_id.as_deref()
}
-
- pub fn output(&self) -> Option<&Path> {
- self.output.as_deref()
- }
}
fn is_valid_resolution(v: String) -> Result<(), String> {
diff --git a/src/bin/rsvg-convert/main.rs b/src/bin/rsvg-convert/main.rs
index 91ad18c0..d611dbca 100644
--- a/src/bin/rsvg-convert/main.rs
+++ b/src/bin/rsvg-convert/main.rs
@@ -9,13 +9,16 @@ mod surface;
use cssparser::Color;
use gio::prelude::*;
-use gio::{Cancellable, FileExt, InputStream, UnixInputStream};
+use gio::{
+ Cancellable, FileCreateFlags, FileExt, InputStream, OutputStream, UnixInputStream,
+ UnixOutputStream,
+};
use librsvg::rsvg_convert_only::LegacySize;
use librsvg::{CairoRenderer, Loader, RenderingError};
use crate::cli::Args;
use crate::input::Input;
-use crate::output::Stream;
+use crate::output::Output;
use crate::size::{ResizeStrategy, Size};
use crate::surface::Surface;
@@ -109,14 +112,27 @@ fn main() {
};
target = {
- let output = Stream::new(args.output())
- .unwrap_or_else(|e| exit!("Error opening output: {}", e));
-
let size = strategy
.apply(Size::new(width, height), args.keep_aspect_ratio)
.unwrap_or_else(|_| exit!("The SVG {} has no dimensions", input));
- match Surface::new(args.format, size, output) {
+ let output_stream = match args.output {
+ Output::Stdout => {
+ let stream = unsafe { UnixOutputStream::new(1) };
+ stream.upcast::<OutputStream>()
+ }
+ Output::Path(ref p) => {
+ let file = gio::File::new_for_path(p);
+ let stream = file
+ .create(FileCreateFlags::NONE, None::<&Cancellable>)
+ .unwrap_or_else(|e| {
+ exit!("Error opening output \"{}\": {}", args.output, e)
+ });
+ stream.upcast::<OutputStream>()
+ }
+ };
+
+ match Surface::new(args.format, size, output_stream) {
Ok(surface) => Some(surface),
Err(cairo::Status::InvalidSize) => size_limit_exceeded(),
Err(e) => exit!("Error creating output surface: {}", e),
@@ -144,7 +160,7 @@ fn main() {
}
}
- if let Some(ref mut surface) = target {
+ if let Some(surface) = target {
surface
.finish()
.unwrap_or_else(|e| exit!("Error saving output: {}", e));
diff --git a/src/bin/rsvg-convert/output.rs b/src/bin/rsvg-convert/output.rs
index e6862ec4..6ed2829d 100644
--- a/src/bin/rsvg-convert/output.rs
+++ b/src/bin/rsvg-convert/output.rs
@@ -1,44 +1,17 @@
// output stream for rsvg-convert
+use std::path::PathBuf;
-use std::fs;
-use std::io;
-
-pub enum Stream {
- File(fs::File),
- Stdout(io::Stdout),
+#[derive(Clone, Debug)]
+pub enum Output {
+ Stdout,
+ Path(PathBuf),
}
-impl Stream {
- pub fn new(path: Option<&std::path::Path>) -> io::Result<Self> {
- match path {
- Some(path) => {
- let file = fs::File::create(path)?;
- Ok(Self::File(file))
- }
- None => Ok(Self::Stdout(io::stdout())),
- }
- }
-}
-
-impl io::Write for Stream {
- fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
- match self {
- Self::File(file) => file.write(buf),
- Self::Stdout(stream) => stream.write(buf),
- }
- }
-
- fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
- match self {
- Self::File(file) => file.write_all(buf),
- Self::Stdout(stream) => stream.write_all(buf),
- }
- }
-
- fn flush(&mut self) -> io::Result<()> {
+impl std::fmt::Display for Output {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
- Self::File(file) => file.flush(),
- Self::Stdout(stream) => stream.flush(),
+ Output::Stdout => "stdout".fmt(f),
+ Output::Path(p) => p.display().fmt(f),
}
}
}
diff --git a/src/bin/rsvg-convert/surface.rs b/src/bin/rsvg-convert/surface.rs
index 361165ee..3c6f7578 100644
--- a/src/bin/rsvg-convert/surface.rs
+++ b/src/bin/rsvg-convert/surface.rs
@@ -1,10 +1,11 @@
use core::ops::Deref;
use std::io;
+use gio::prelude::*;
+use gio::OutputStream;
use librsvg::{CairoRenderer, RenderingError};
use crate::cli::Format;
-use crate::output::Stream;
use crate::size::Size;
// TODO: use from src/lib/handle.rs
@@ -13,7 +14,7 @@ fn checked_i32(x: f64) -> Result<i32, cairo::Status> {
}
pub enum Surface {
- Png(cairo::ImageSurface, Stream),
+ Png(cairo::ImageSurface, OutputStream),
Pdf(cairo::PdfSurface, Size),
Ps(cairo::PsSurface, Size),
Svg(cairo::SvgSurface, Size),
@@ -33,7 +34,7 @@ impl Deref for Surface {
}
impl Surface {
- pub fn new(format: Format, size: Size, stream: Stream) -> Result<Self, cairo::Status> {
+ pub fn new(format: Format, size: Size, stream: OutputStream) -> Result<Self, cairo::Status> {
match format {
Format::Png => Self::new_for_png(size, stream),
Format::Pdf => Self::new_for_pdf(size, stream),
@@ -43,29 +44,29 @@ impl Surface {
}
}
- fn new_for_png(size: Size, stream: Stream) -> Result<Self, cairo::Status> {
+ fn new_for_png(size: Size, stream: OutputStream) -> 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(size: Size, stream: Stream) -> Result<Self, cairo::Status> {
- let surface = cairo::PdfSurface::for_stream(size.w, size.h, stream)?;
+ fn new_for_pdf(size: Size, stream: OutputStream) -> Result<Self, cairo::Status> {
+ let surface = cairo::PdfSurface::for_stream(size.w, size.h, stream.into_write())?;
if let Some(date) = metadata::creation_date() {
surface.set_metadata(cairo::PdfMetadata::CreateDate, &date)?;
}
Ok(Self::Pdf(surface, size))
}
- 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)?;
+ fn new_for_ps(size: Size, stream: OutputStream, eps: bool) -> Result<Self, cairo::Status> {
+ let surface = cairo::PsSurface::for_stream(size.w, size.h, stream.into_write())?;
surface.set_eps(eps);
Ok(Self::Ps(surface, size))
}
- fn new_for_svg(size: Size, stream: Stream) -> Result<Self, cairo::Status> {
- let surface = cairo::SvgSurface::for_stream(size.w, size.h, stream)?;
+ fn new_for_svg(size: Size, stream: OutputStream) -> Result<Self, cairo::Status> {
+ let surface = cairo::SvgSurface::for_stream(size.w, size.h, stream.into_write())?;
Ok(Self::Svg(surface, size))
}
@@ -111,17 +112,13 @@ impl Surface {
Ok(())
}
- fn finish_output_stream(surface: &cairo::Surface) -> Result<(), cairo::IoError> {
- match surface.finish_output_stream() {
- Ok(_) => Ok(()),
- Err(e) => Err(cairo::IoError::Io(io::Error::from(e))),
- }
- }
-
- pub fn finish(&mut self) -> Result<(), cairo::IoError> {
+ pub fn finish(self) -> Result<(), cairo::IoError> {
match self {
- Self::Png(surface, stream) => surface.write_to_png(stream),
- _ => Self::finish_output_stream(self),
+ Self::Png(surface, stream) => surface.write_to_png(&mut stream.into_write()),
+ _ => match self.finish_output_stream() {
+ Ok(_) => Ok(()),
+ Err(e) => Err(cairo::IoError::Io(io::Error::from(e))),
+ },
}
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]