add PS export as well. also rename svg2pdf into convert and add PS export to it
This commit is contained in:
parent
0e08bc6696
commit
1ca35d8426
|
@ -13,7 +13,7 @@ members = [
|
||||||
"examples/canvas_moire",
|
"examples/canvas_moire",
|
||||||
"examples/canvas_text",
|
"examples/canvas_text",
|
||||||
"examples/lottie_basic",
|
"examples/lottie_basic",
|
||||||
"examples/svg2pdf",
|
"examples/convert",
|
||||||
"examples/swf_basic",
|
"examples/swf_basic",
|
||||||
"geometry",
|
"geometry",
|
||||||
"gl",
|
"gl",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[package]
|
[package]
|
||||||
name = "svg2pdf"
|
name = "convert"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Sebastian Köln <sebk@rynx.org>"]
|
authors = ["Sebastian Köln <sebk@rynx.org>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
|
@ -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(())
|
||||||
|
}
|
|
@ -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(())
|
|
||||||
}
|
|
|
@ -199,6 +199,76 @@ impl Scene {
|
||||||
Ok(())
|
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 {
|
pub fn paths<'a>(&'a self) -> PathIter {
|
||||||
PathIter {
|
PathIter {
|
||||||
scene: self,
|
scene: self,
|
||||||
|
|
Loading…
Reference in New Issue