add PS export as well. also rename svg2pdf into convert and add PS export to it

This commit is contained in:
Sebastian Köln 2019-06-24 22:41:34 +03:00
parent 0e08bc6696
commit 1ca35d8426
5 changed files with 98 additions and 22 deletions

View File

@ -13,7 +13,7 @@ members = [
"examples/canvas_moire",
"examples/canvas_text",
"examples/lottie_basic",
"examples/svg2pdf",
"examples/convert",
"examples/swf_basic",
"geometry",
"gl",

View File

@ -1,5 +1,5 @@
[package]
name = "svg2pdf"
name = "convert"
version = "0.1.0"
authors = ["Sebastian Köln <sebk@rynx.org>"]
edition = "2018"

View File

@ -0,0 +1,26 @@
use std::fs::File;
use std::io::{Read, BufWriter};
use std::error::Error;
use std::path::PathBuf;
use pathfinder_svg::BuiltSVG;
use pathfinder_pdf::make_pdf;
use usvg::{Tree, Options};
fn main() -> Result<(), Box<dyn Error>> {
let mut args = std::env::args_os().skip(1);
let input = PathBuf::from(args.next().expect("no input given"));
let output = PathBuf::from(args.next().expect("no output given"));
let mut data = Vec::new();
File::open(input)?.read_to_end(&mut data)?;
let svg = BuiltSVG::from_tree(Tree::from_data(&data, &Options::default()).unwrap());
let scene = &svg.scene;
let mut writer = BufWriter::new(File::create(&output)?);
match output.extension().and_then(|s| s.to_str()) {
Some("pdf") => make_pdf(&mut writer, scene),
Some("ps") => scene.write_ps(&mut writer)?,
_ => return Err("output filename must have .ps or .pdf extension".into())
}
Ok(())
}

View File

@ -1,20 +0,0 @@
use std::fs::File;
use std::io::{Read, BufWriter};
use std::error::Error;
use pathfinder_svg::BuiltSVG;
use pathfinder_pdf::make_pdf;
use usvg::{Tree, Options};
fn main() -> Result<(), Box<dyn Error>> {
let mut args = std::env::args().skip(1);
let input = args.next().expect("no input given");
let output = args.next().expect("no output given");
let mut data = Vec::new();
File::open(input)?.read_to_end(&mut data)?;
let svg = BuiltSVG::from_tree(Tree::from_data(&data, &Options::default()).unwrap());
make_pdf(BufWriter::new(File::create(output)?), &svg.scene);
Ok(())
}

View File

@ -199,6 +199,76 @@ impl Scene {
Ok(())
}
pub fn write_ps<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Write,
{
use std::fmt;
use pathfinder_content::segment::SegmentKind;
struct P(Vector2F);
impl fmt::Display for P {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} {}", self.0.x(), self.0.y())
}
}
writeln!(writer, "%!PS-Adobe-3.0 EPSF-3.0")?;
writeln!(writer, "%%BoundingBox: {:.0} {:.0}",
P(self.view_box.origin()),
P(self.view_box.size()),
)?;
writeln!(writer, "%%HiResBoundingBox: {} {}",
P(self.view_box.origin()),
P(self.view_box.size()),
)?;
writeln!(writer, "0 {} translate", self.view_box.size().y())?;
writeln!(writer, "1 -1 scale")?;
for path_object in &self.paths {
writeln!(writer, "newpath")?;
let color = self.paints[path_object.paint.0 as usize].color.to_f32();
for contour in path_object.outline.contours() {
for (segment_index, segment) in contour.iter().enumerate() {
if segment_index == 0 {
writeln!(writer, "{} moveto", P(segment.baseline.from()))?;
}
match segment.kind {
SegmentKind::None => {}
SegmentKind::Line => {
writeln!(writer, "{} lineto", P(segment.baseline.to()))?;
}
SegmentKind::Quadratic => {
let current = segment.baseline.from();
let c = segment.ctrl.from();
let p = segment.baseline.to();
let c1 = Vector2F::splat(2. / 3.) * c + Vector2F::splat(1. / 3.) * current;
let c2 = Vector2F::splat(2. / 3.) * c + Vector2F::splat(1. / 3.) * p;
writeln!(writer, "{} {} {} curveto", P(c1), P(c2), P(p))?;
}
SegmentKind::Cubic => {
writeln!(writer, "{} {} {} curveto",
P(segment.ctrl.from()),
P(segment.ctrl.to()),
P(segment.baseline.to())
)?;
}
}
}
if contour.is_closed() {
writeln!(writer, "closepath")?;
}
}
writeln!(writer, "{} {} {} setrgbcolor", color.r(), color.g(), color.b())?;
writeln!(writer, "fill")?;
}
writeln!(writer, "showpage")?;
Ok(())
}
pub fn paths<'a>(&'a self) -> PathIter {
PathIter {
scene: self,