Vectory is a Ruby gem that performs pairwise vector image conversions for common vector image formats (EPS, PS, EMF, SVG).
Vectory shall give you a glorious vectory over EPS files.
Vectory relies on the following software to be installed:
|
Note
|
Inkscape 1.3.1+ does not work properly with EPS/PS on Windows. To avoid this issue, the 1.3.0 version of Inkscape can be used. |
$ vectory [-o {output-file-name}] -f {format} {input-file-name}Where,
format-
the desired output format (one of:
svg,eps,ps,emf) input-file-name-
file path to the input file
output-file-name-
file path to the desired output file (with the file extension) (default: writes to a current directory by the input filename with an extension changed to a desired format)
Some examples:
Take EMF as a path to a file and return SVG as a string:
path = "path/to/file.emf"
Vectory::Emf.from_path(path).to_svg.contentTake EPS as a string and return EMF as a path to a file:
# NOTE: content is shortened for readability
content = "%!PS-Adobe-3.0 EPSF-3.0\n ... %%Trailer"
Vectory::Eps.from_content(content).to_emf.write.pathTake SVG as a datauri and return EMF as a datauri:
# NOTE: datauri is shortened for readability
uri = "data:image/svg+xml;charset=utf-8;base64,PHN2ZyB4bWxucz0iaHR0 ... GRkYiLz48L3N2Zz4="
Vectory::Datauri.new(uri).to_vector.to_emf.to_uri.contentThere are several vector classes which support conversion between each other:
Vectory::Eps
Vectory::Ps
Vectory::Emf
Vectory::SvgEach of them can be instantiated in several ways:
Vectory::Eps.from_path("images/img.eps")
Vectory::Eps.from_content("%!PS-Adobe-3.0...")
Vectory::Eps.from_datauri("data:image/svg+xml;base64,PHN2 ... 2Zz4=")
Vectory::Eps.from_node(Nokogiri::XML(
"<image mimetype="application/postscript" alt="3">
%!PS-Adobe-3.0 EPSF-3.0 ...
</image>"
).child)Converting to other formats:
Vectory::Eps.from_content(content).to_ps
Vectory::Eps.from_content(content).to_emf
Vectory::Eps.from_content(content).to_svgSeveral ways of getting content of an object:
Vectory::Eps.from_content(content).to_svg.content
Vectory::Eps.from_content(content).to_svg.to_uri.content # as datauri
Vectory::Eps.from_content(content).to_svg.write.pathAlso there is the Vectory::Datauri class which represents vectory images in
the datauri format.
Convert an SVG datauri to a plain SVG:
# NOTE: datauri is shortened for readability
uri = "data:image/svg+xml;charset=utf-8;base64,PHN2ZyB4bWxucz0iaHR0 ... GRkYiLz48L3N2Zz4="
Vectory::Datauri.new(uri).to_vector.contentConvert an EPS file to its datauri representation:
eps = Vectory::Eps.from_path("img.eps")
Vectory::Datauri.from_vector(eps).contentThere is also a simplified API for this case:
Vectory::Eps.from_path("img.eps").to_uri.contentVectory can integrate SVG files into XML or HTML, respecting internal id and link references. It supports ID disambiguation for multi-document and multi-svgmap scenarios.
When processing multiple documents or multiple svgmaps within a document, SVG IDs must be unique to avoid conflicts. Vectory applies two types of suffixes:
- ID suffix (Cross-document uniqueness)
-
An optional suffix derived from document or container identity (e.g.,
_ISO_17301-1_2016). This provides uniqueness across documents or collections. - Index suffix (Multi-svgmap uniqueness)
-
Automatically applied based on the svgmap’s position in the document (0, 1, 2, …). Formatted as a 9-digit zero-padded number (e.g.,
_000000000,_000000001). This provides uniqueness when a document contains multiple svgmaps.
Original ID: fig1
With ID suffix only: fig1_ISO_17301-1_2016
With both suffixes: fig1_ISO_17301-1_2016_000000000mapping = Vectory::SvgMapping.new(doc, "", id_suffix: "_ISO_17301-1_2016")
xml_string = mapping.call.to_xmlThe input XML must support the svgmap tag with link mapping.
<svgmap id="_4072bdcb-5895-4821-b636-5795b96787cb">
<figure><image src="action_schemaexpg1.svg"/></figure>
<target href="mn://action_schema">
<xref target="ref1">Computer</xref>
</target>
<target href="http://www.example.com">
<link target="http://www.example.com">Phone</link>
</target>
</svgmap><?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<style type="text/css">
#Layer_1 { fill:none }
svg[id = 'Layer_1'] { fill:none }
.st0{fill:none;stroke:#000000;stroke-miterlimit:10;}
</style>
<a xlink:href="mn://action_schema" xlink:dummy="Layer_1">
<rect x="123.28" y="273.93" class="st0" width="88.05" height="41.84"/>
</a>
<a xlink:href="mn://basic_attribute_schema" >
<rect x="324.69" y="450.52" class="st0" width="132.62" height="40.75"/>
</a>
<a xlink:href="mn://support_resource_schema" >
<rect x="324.69" y="528.36" class="st0" width="148.16" height="40.75"/>
</a>
</svg><figure>
<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1'
id='Layer_1_000000001' x='0px' y='0px' viewBox='0 0 595.28 841.89'>
<style> #Layer_1_000000001 { fill:none }</style>
<a xlink:href='#ref1' xlink:dummy='Layer_1_000000001'>
<rect x='123.28' y='273.93' class='st0' width='88.05' height='41.84'/>
</a>
<a xlink:href='mn://basic_attribute_schema'>
<rect x='324.69' y='450.52' class='st0' width='132.62' height='40.75'/>
</a>
<a xlink:href='mn://support_resource_schema'>
<rect x='324.69' y='528.36' class='st0' width='148.16' height='40.75'/>
</a>
</svg>
</figure>SVG can also be provided inline within the svgmap:
<svgmap id="_60dadf08-48d4-4164-845c-b4e293e00abd">
<figure>
<svg xmlns='http://www.w3.org/2000/svg' id='Layer_1'>
<a href="mn://action_schema">
<rect x="123.28" y="273.93" class="st0"/>
</a>
</svg>
</figure>
<target href="mn://action_schema">
<xref target="ref1">Computer</xref>
</target>
</svgmap>An image object contains information where it is written. It can be obtained
with the #path API:
vector = Vectory::Eps.from_path("img.eps")
vector.pathBefore the first write it raises the NotWrittenToDiskError error:
vector.path # => raise NotWrittenToDiskErrorAfter writing it returns a path of the image on a disk:
vector.write
vector.path # => "/tmp/xxx/yyy"By default it writes to a temporary directory but it can be changed by providing an argument with a desired path:
vector.write("images/img.eps")
vector.path # => "images/img.eps"Since an image can be initially read from a disk, it also keeps an initial path. To avoid accidental overwrite, this path is used only for read-only purposes.
vector.initial_path # => "storage/images/img.eps"Some test fixtures are generated by external tools (Ghostscript, Inkscape, cairo). When these tools are updated, the reference files may need to be regenerated.
To regenerate all test fixtures:
bundle exec rake regenerate_fixturesThis will update the following files:
-
spec/examples/ps2eps/ref.eps- PS to EPS conversion reference -
spec/examples/ps2svg/ref.svg- PS to SVG conversion reference -
spec/examples/svg/doc2-ref.xml- SVG mapping reference
|
Note
|
After regenerating fixtures, review the changes to ensure they are expected before committing. |
Bug reports and pull requests are welcome on GitHub at: