Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions docs/features/conversion.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,22 @@ svg_to_eps = Vectory::Svg.from_path("diagram.svg").to_eps
eps_to_svg = Vectory::Eps.from_path("diagram.eps").to_svg
----

=== Two-Step Conversions (EPS/PS → SVG)
=== Direct Conversions (via postsvg)

EPS and PS files are converted to SVG through a PDF intermediate:

1. **EPS/PS → PDF** (via Ghostscript): Preserves BoundingBox information
2. **PDF → SVG** (via Inkscape): Converts PDF to SVG
EPS and PS files are converted to SVG directly by the postsvg gem (pure Ruby, no Ghostscript or Inkscape):

[source,ruby]
----
# Two-step conversion (automatic)
eps = Vectory::Eps.from_path("diagram.eps")
svg = eps.to_svg # Internally: EPS → PDF → SVG
svg = eps.to_svg # Uses postsvg directly

ps = Vectory::Ps.from_path("diagram.ps")
svg = ps.to_svg # Also postsvg
----

This two-step process ensures accurate dimension preservation from EPS/PS files.
postsvg reads the `%%BoundingBox` DSC comment to size the viewBox. Limitations: text/font rendering, image embedding, gradients/patterns, CMYK, and PS Level 2/3 advanced operators are not yet supported by postsvg upstream — EPS/PS files using those features will silently degrade.

=== Two-Step Conversions (EPS/PS → PDF/PS/EMF)

=== EMF Conversions (via emfsvg)

Expand All @@ -73,11 +74,11 @@ emf = Vectory::Svg.from_path("chart.svg").to_emf
|SVG|EMF|emfsvg gem
|SVG|PDF|Inkscape

|EPS|SVG|Ghostscript + Inkscape (two-step)
|EPS|SVG|postsvg gem
|EPS|PDF|Ghostscript
|EPS|PS|Via PDF intermediate

|PS|SVG|Ghostscript + Inkscape (two-step)
|PS|SVG|postsvg gem
|PS|PDF|Ghostscript
|PS|EPS|Via PDF intermediate

Expand Down
21 changes: 14 additions & 7 deletions docs/features/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -68,23 +68,30 @@ Vectory uses different external tools depending on the source and target formats

=== Direct Conversions (via Inkscape)

* **SVG → EPS/PS/EMF/PDF** (via Inkscape export)
* **EPS/PS/EMF/PDF → SVG** (via Inkscape import)
* **SVG → EPS/PS/PDF** (via Inkscape export)
* **PDF → SVG** (via Inkscape import)

Inkscape handles direct conversions to and from SVG format.

=== Direct Conversions (via emfsvg)

* **EMF → SVG** (via emfsvg gem)
* **SVG ↔ EMF** (via emfsvg gem, both directions)

The emfsvg gem provides native EMF to SVG conversion in pure Ruby, with no external tool dependency.
The emfsvg gem provides bidirectional EMF ↔ SVG conversion in pure Ruby, with no external tool dependency.

=== Direct Conversions (via postsvg)

* **EPS → SVG** (via postsvg gem)
* **PS → SVG** (via postsvg gem)

The postsvg gem converts PS/EPS to SVG in pure Ruby, with no external tool dependency.

=== Two-Step Conversions (via Ghostscript + Inkscape)

* **EPS → PDF → SVG** (Ghostscript for EPS→PDF, Inkscape for PDF→SVG)
* **PS → PDF → SVG** (Ghostscript for PS→PDF, Inkscape for PDF→SVG)
* **EPS → PDF → SVG** (legacy path; replaced by postsvg for `Eps#to_svg`)
* **PS → PDF → SVG** (legacy path; replaced by postsvg for `Ps#to_svg`)

This two-step process preserves BoundingBox information from EPS/PS files.
EPS/PS → PDF and EPS/PS → PS/EMF (via PDF intermediate) still go through Ghostscript.

=== Conversion Tool Matrix

Expand Down
3 changes: 2 additions & 1 deletion docs/getting-started/core-concepts.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,12 @@ Vectory uses a flexible conversion pipeline:
Some conversions are direct:
* **SVG → EPS/PS/PDF**: Via Inkscape
* **SVG ↔ EMF**: Via emfsvg (both directions, pure Ruby)
* **EPS → SVG** and **PS → SVG**: Via postsvg (pure Ruby)

=== Two-Step Conversions

Other conversions use an intermediate PDF format:
* **EPS/PS → PDF → SVG**: Via Ghostscript + Inkscape
* **EPS/PS → PDF → {PS,EMF}**: Via Ghostscript + Inkscape

This two-step conversion ensures:
* BoundingBox preservation from EPS/PS
Expand Down
4 changes: 3 additions & 1 deletion lib/vectory/eps.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# frozen_string_literal: true

require "postsvg"

module Vectory
class Eps < Vector
def self.default_extension
Expand All @@ -24,7 +26,7 @@ def to_ps
end

def to_svg
to_pdf.to_svg
Svg.from_content(Postsvg.convert(content))
end

def to_emf
Expand Down
4 changes: 3 additions & 1 deletion lib/vectory/ps.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# frozen_string_literal: true

require "postsvg"

module Vectory
class Ps < Vector
def self.default_extension
Expand Down Expand Up @@ -28,7 +30,7 @@ def to_emf
end

def to_svg
to_pdf.to_svg
Svg.from_content(Postsvg.convert(content))
end

def to_pdf
Expand Down
30 changes: 0 additions & 30 deletions spec/vectory/eps_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,6 @@
.and_raise(Vectory::ConversionError, "ghostscript failed")
end

it "propagates error from to_pdf to to_svg" do
expect do
eps.to_svg
end.to raise_error(Vectory::ConversionError, /ghostscript failed/)
end

it "propagates error from to_pdf to to_ps" do
expect do
eps.to_ps
Expand All @@ -112,29 +106,5 @@
end.to raise_error(Vectory::ConversionError, /ghostscript failed/)
end
end

context "when Inkscape conversion fails" do
before do
# Allow ps2pdf to succeed
allow(Vectory::GhostscriptWrapper).to receive(:convert)
.and_return("fake pdf content")

# Also make pdf_to_eps fail (used in fallback)
allow(Vectory::GhostscriptWrapper).to receive(:pdf_to_eps)
.and_raise(Vectory::ConversionError, "Ghostscript fallback failed")

# Make Inkscape fail
converter = instance_double(Vectory::InkscapeWrapper)
allow(Vectory::InkscapeWrapper).to receive(:instance).and_return(converter)
allow(converter).to receive(:convert)
.and_raise(Vectory::ConversionError, "Inkscape failed")
end

it "propagates error from Inkscape to to_svg" do
expect do
eps.to_svg
end.to raise_error(Vectory::ConversionError, /Ghostscript fallback failed/)
end
end
end
end
1 change: 1 addition & 0 deletions vectory.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Gem::Specification.new do |spec|
spec.add_dependency "image_size", ">= 3.2.0"
spec.add_dependency "marcel", "~> 1.0"
spec.add_dependency "nokogiri", "~> 1.14"
spec.add_dependency "postsvg", "~> 0.1"
spec.add_dependency "thor", "~> 1.0"
spec.add_dependency "ukiryu", "~> 0.3.0"
end
Loading