vectory 0.10.2 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 50d97784f6629c9150bb2da21c151ba9f5a971e0c949bcb40c6f1e56a56a9e0c
4
- data.tar.gz: 1494199096329b53ec283fc424df6b49fcb1a0f95271b841e8289ee7d2e7fb49
3
+ metadata.gz: 3a9abbde7cd6a7876ad8a2f8077786e870dcf860b3206bef30f061f997145d31
4
+ data.tar.gz: 05c8f3c7a6ab01aa09e3facc83d145ba17a6a8ea7dde5e2bba02ab1405d49999
5
5
  SHA512:
6
- metadata.gz: 13129736f9ec596505e93e5e2b8904928be9dfb98ee9198259b34bdfecfdcbc2e0ca35e8e99133af06f9e65899434c55873f7bb5c94f42951360d13e6d812fc6
7
- data.tar.gz: 4daa37bcf802de4eaac71466694b229d6fee62e10b11237253f05a4e855da18b7646fcd14d4530ae8961ebf49b6cfcc60887b29761e4096ac65a885224fa9ec9
6
+ metadata.gz: a9651cbe852b2ba5dbdbdb07db31105aa33bf9a41bcc7bd0cb4f621c679ba41f4343f85ae0d4f3722a34cfaab2cb4cb80210e2aa383b71d7df34256b36a781ac
7
+ data.tar.gz: c03d30678dfa73b41dac5b987cd70905fc0edc2dcd5621a7bdfb2d61bf8be11769f1d4135602c93aa7b51b243e05b915d0c7b0e55f5002badc50d45365863e3a
data/README.adoc CHANGED
@@ -21,14 +21,12 @@ ____
21
21
 
22
22
  === Prerequisites
23
23
 
24
- Vectory relies on the following software to be installed:
24
+ Vectory ships as a pure-Ruby gem. Format support is provided by these Ruby gems (installed automatically):
25
25
 
26
- * https://github.com/claricle/emfsvg[emfsvg]
27
- * https://inkscape.org[Inkscape]
28
- * https://www.ghostscript.com/[Ghostscript]
26
+ * https://github.com/claricle/emfsvg[emfsvg] (EMF <-> SVG)
27
+ * https://github.com/claricle/postsvg[postsvg] (PS/EPS <-> SVG)
29
28
 
30
- NOTE: Inkscape 1.3.1+ does not work properly with EPS/PS on Windows. To avoid
31
- this issue, the 1.3.0 version of Inkscape can be used.
29
+ No external binaries are required.
32
30
 
33
31
 
34
32
  === Gem install
data/lib/vectory/cli.rb CHANGED
@@ -9,14 +9,10 @@ module Vectory
9
9
  STATUS_UNSUPPORTED_OUTPUT_FORMAT_ERROR = 3
10
10
  STATUS_CONVERSION_ERROR = 4
11
11
  STATUS_SYSTEM_CALL_ERROR = 5
12
- STATUS_INKSCAPE_NOT_FOUND_ERROR = 6
13
12
  STATUS_SAME_FORMAT_ERROR = 7
14
- STATUS_GHOSTSCRIPT_NOT_FOUND_ERROR = 8
15
13
 
16
14
  MAP_ERROR_TO_STATUS = {
17
15
  Vectory::ConversionError => STATUS_CONVERSION_ERROR,
18
- Vectory::InkscapeNotFoundError => STATUS_INKSCAPE_NOT_FOUND_ERROR,
19
- Vectory::GhostscriptNotFoundError => STATUS_GHOSTSCRIPT_NOT_FOUND_ERROR,
20
16
  Vectory::SystemCallError => STATUS_SYSTEM_CALL_ERROR,
21
17
  }.freeze
22
18
 
@@ -3,14 +3,10 @@
3
3
  module Vectory
4
4
  # Configuration for Vectory
5
5
  #
6
- # Provides centralized configuration for tool paths, timeouts, caching, etc.
6
+ # Provides centralized configuration for timeouts, caching, etc.
7
7
  # Can be loaded from environment variables or a configuration file.
8
8
  #
9
- # @example Set custom Inkscape path
10
- # Vectory::Configuration.instance.inkscape_path = "/path/to/inkscape"
11
- #
12
9
  # @example Load from environment variables
13
- # # Set VECTORY_INKSCAPE_PATH environment variable
14
10
  # Vectory::Configuration.load_from_environment
15
11
  class Configuration
16
12
  # Default timeout for external tool execution (seconds)
@@ -22,8 +18,8 @@ module Vectory
22
18
  # Default temporary directory
23
19
  DEFAULT_TEMP_DIR = nil # Use system default
24
20
 
25
- attr_accessor :inkscape_path, :ghostscript_path, :timeout, :cache_ttl,
26
- :cache_enabled, :temp_dir, :verbose_logging
21
+ attr_accessor :timeout, :cache_ttl, :cache_enabled, :temp_dir,
22
+ :verbose_logging
27
23
 
28
24
  # Get the singleton instance
29
25
  #
@@ -46,15 +42,11 @@ module Vectory
46
42
  @cache_enabled = true
47
43
  @temp_dir = DEFAULT_TEMP_DIR
48
44
  @verbose_logging = false
49
- @inkscape_path = nil
50
- @ghostscript_path = nil
51
45
  end
52
46
 
53
47
  # Load configuration from environment variables
54
48
  #
55
49
  # Supported environment variables:
56
- # - VECTORY_INKSCAPE_PATH: Path to Inkscape executable
57
- # - VECTORY_GHOSTSCRIPT_PATH: Path to Ghostscript executable
58
50
  # - VECTORY_TIMEOUT: Timeout for external tools (default: 120)
59
51
  # - VECTORY_CACHE_TTL: Cache TTL in seconds (default: 300)
60
52
  # - VECTORY_CACHE_ENABLED: Enable/disable caching (default: true)
@@ -65,8 +57,6 @@ module Vectory
65
57
  def self.load_from_environment
66
58
  config = instance
67
59
 
68
- config.inkscape_path = ENV["VECTORY_INKSCAPE_PATH"] if ENV["VECTORY_INKSCAPE_PATH"]
69
- config.ghostscript_path = ENV["VECTORY_GHOSTSCRIPT_PATH"] if ENV["VECTORY_GHOSTSCRIPT_PATH"]
70
60
  config.timeout = ENV["VECTORY_TIMEOUT"]&.to_i || config.timeout
71
61
  config.cache_ttl = ENV["VECTORY_CACHE_TTL"]&.to_i || config.cache_ttl
72
62
  config.cache_enabled = ENV["VECTORY_CACHE_ENABLED"] != "false"
@@ -86,8 +76,6 @@ module Vectory
86
76
  config_data = YAML.load_file(path)
87
77
 
88
78
  config = instance
89
- config.inkscape_path = config_data["inkscape_path"] if config_data["inkscape_path"]
90
- config.ghostscript_path = config_data["ghostscript_path"] if config_data["ghostscript_path"]
91
79
  config.timeout = config_data["timeout"] || config.timeout
92
80
  config.cache_ttl = config_data["cache_ttl"] || config.cache_ttl
93
81
  config.cache_enabled = config_data.fetch("cache_enabled",
@@ -104,8 +92,6 @@ module Vectory
104
92
  # @return [Hash] the configuration as a hash
105
93
  def to_h
106
94
  {
107
- inkscape_path: @inkscape_path,
108
- ghostscript_path: @ghostscript_path,
109
95
  timeout: @timeout,
110
96
  cache_ttl: @cache_ttl,
111
97
  cache_enabled: @cache_enabled,
@@ -114,20 +100,6 @@ module Vectory
114
100
  }
115
101
  end
116
102
 
117
- # Get the Inkscape path (custom or auto-detected)
118
- #
119
- # @return [String, nil] the configured Inkscape path or nil if not set
120
- def effective_inkscape_path
121
- @inkscape_path
122
- end
123
-
124
- # Get the Ghostscript path (custom or auto-detected)
125
- #
126
- # @return [String, nil] the configured Ghostscript path or nil if not set
127
- def effective_ghostscript_path
128
- @ghostscript_path
129
- end
130
-
131
103
  # Check if caching is enabled
132
104
  #
133
105
  # @return [Boolean] true if caching is enabled
data/lib/vectory/emf.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "emf"
3
4
  require "emfsvg"
4
5
 
5
6
  module Vectory
@@ -32,21 +33,33 @@ module Vectory
32
33
  end
33
34
 
34
35
  def to_eps
35
- InkscapeWrapper.convert(
36
- content: content,
37
- input_format: :emf,
38
- output_format: :eps,
39
- output_class: Eps,
40
- )
36
+ to_svg.to_eps
41
37
  end
42
38
 
43
39
  def to_ps
44
- InkscapeWrapper.convert(
45
- content: content,
46
- input_format: :emf,
47
- output_format: :ps,
48
- output_class: Ps,
49
- )
40
+ to_svg.to_ps
41
+ end
42
+
43
+ def height
44
+ bounds = parse_header_bounds
45
+ return super unless bounds
46
+
47
+ bounds.bottom - bounds.top
48
+ end
49
+
50
+ def width
51
+ bounds = parse_header_bounds
52
+ return super unless bounds
53
+
54
+ bounds.right - bounds.left
55
+ end
56
+
57
+ private
58
+
59
+ def parse_header_bounds
60
+ ::Emf.parse(content).header.bounds
61
+ rescue StandardError
62
+ nil
50
63
  end
51
64
  end
52
65
  end
data/lib/vectory/eps.rb CHANGED
@@ -22,7 +22,7 @@ module Vectory
22
22
  end
23
23
 
24
24
  def to_ps
25
- to_pdf.to_ps
25
+ to_svg.to_ps
26
26
  end
27
27
 
28
28
  def to_svg
@@ -30,19 +30,7 @@ module Vectory
30
30
  end
31
31
 
32
32
  def to_emf
33
- to_pdf.to_emf
34
- end
35
-
36
- def to_pdf
37
- pdf_content = GhostscriptWrapper.convert(content, eps_crop: true)
38
- pdf = Pdf.new(pdf_content)
39
- # Pass original BoundingBox dimensions to preserve them in conversions
40
- bbox = parse_bounding_box
41
- if bbox
42
- pdf.original_width = bbox[:urx] - bbox[:llx]
43
- pdf.original_height = bbox[:ury] - bbox[:lly]
44
- end
45
- pdf
33
+ to_svg.to_emf
46
34
  end
47
35
 
48
36
  def height
@@ -3,20 +3,6 @@
3
3
  module Vectory
4
4
  class ConversionError < Error; end
5
5
 
6
- class InkscapeNotFoundError < Error
7
- def initialize(msg = nil)
8
- super(msg || "Inkscape not found in PATH. Please install Inkscape.")
9
- end
10
- end
11
-
12
- class GhostscriptNotFoundError < Error
13
- def initialize(msg = nil)
14
- super(msg || "Ghostscript not found in PATH. Please install Ghostscript.")
15
- end
16
- end
17
-
18
- class InkscapeQueryError < Error; end
19
-
20
6
  class InvalidFormatError < Error
21
7
  def initialize(format, supported_formats)
22
8
  super("Invalid format '#{format}'. Supported formats: #{supported_formats.join(', ')}")
data/lib/vectory/ps.rb CHANGED
@@ -22,29 +22,17 @@ module Vectory
22
22
  end
23
23
 
24
24
  def to_eps
25
- to_pdf.to_eps
25
+ to_svg.to_eps
26
26
  end
27
27
 
28
28
  def to_emf
29
- to_pdf.to_emf
29
+ to_svg.to_emf
30
30
  end
31
31
 
32
32
  def to_svg
33
33
  Svg.from_content(Postsvg.convert(content))
34
34
  end
35
35
 
36
- def to_pdf
37
- pdf_content = GhostscriptWrapper.convert(content, eps_crop: false)
38
- pdf = Pdf.new(pdf_content)
39
- # Pass original BoundingBox dimensions to preserve them in conversions
40
- bbox = parse_bounding_box
41
- if bbox
42
- pdf.original_width = bbox[:urx] - bbox[:llx]
43
- pdf.original_height = bbox[:ury] - bbox[:lly]
44
- end
45
- pdf
46
- end
47
-
48
36
  def height
49
37
  bbox = parse_bounding_box
50
38
  return super unless bbox
data/lib/vectory/svg.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "nokogiri"
4
+ require "postsvg"
4
5
 
5
6
  module Vectory
6
7
  class Svg < Vector
@@ -36,53 +37,43 @@ module Vectory
36
37
  end
37
38
 
38
39
  def to_eps
39
- InkscapeWrapper.convert(
40
- content: content,
41
- input_format: :svg,
42
- output_format: :eps,
43
- output_class: Eps,
44
- )
40
+ Eps.from_content(Postsvg.to_eps(content))
45
41
  end
46
42
 
47
43
  def to_ps
48
- InkscapeWrapper.convert(
49
- content: content,
50
- input_format: :svg,
51
- output_format: :ps,
52
- output_class: Ps,
53
- )
44
+ Ps.from_content(Postsvg.to_ps(content))
54
45
  end
55
46
 
56
47
  def height
57
- # Try to read height from SVG attributes first
58
- doc = Nokogiri::XML(content)
59
- svg_element = doc.at_xpath("//svg:svg",
60
- "svg" => SVG_NS) || doc.at_xpath("//svg")
61
-
62
- if svg_element && svg_element["height"]
63
- svg_element["height"].to_f.round
64
- else
65
- # Fall back to Inkscape query if no height attribute
66
- super
67
- end
48
+ dim_from_attr("height") || dim_from_viewbox(3) || super
68
49
  end
69
50
 
70
51
  def width
71
- # Try to read width from SVG attributes first
72
- doc = Nokogiri::XML(content)
73
- svg_element = doc.at_xpath("//svg:svg",
74
- "svg" => SVG_NS) || doc.at_xpath("//svg")
75
-
76
- if svg_element && svg_element["width"]
77
- svg_element["width"].to_f.round
78
- else
79
- # Fall back to Inkscape query if no width attribute
80
- super
81
- end
52
+ dim_from_attr("width") || dim_from_viewbox(2) || super
82
53
  end
83
54
 
84
55
  private
85
56
 
57
+ def svg_root
58
+ doc = Nokogiri::XML(content)
59
+ doc.at_xpath("//svg:svg", "svg" => SVG_NS) || doc.at_xpath("//svg")
60
+ end
61
+
62
+ def dim_from_attr(name)
63
+ value = svg_root&.[](name)
64
+ value&.to_f&.round
65
+ end
66
+
67
+ def dim_from_viewbox(index)
68
+ vb = svg_root&.[]("viewBox")
69
+ return nil unless vb
70
+
71
+ parts = vb.split
72
+ return nil unless parts.length == 4
73
+
74
+ parts[index].to_f.round
75
+ end
76
+
86
77
  def content=(content)
87
78
  # non-root node inserts the xml tag which breaks markup when placed in
88
79
  # another xml document
@@ -46,11 +46,15 @@ module Vectory
46
46
  end
47
47
 
48
48
  def height
49
- InkscapeWrapper.instance.height(content, self.class.default_extension)
49
+ raise Vectory::NotImplementedError,
50
+ "#height should be implemented in a subclass when no intrinsic " \
51
+ "dimension source is available."
50
52
  end
51
53
 
52
54
  def width
53
- InkscapeWrapper.instance.width(content, self.class.default_extension)
55
+ raise Vectory::NotImplementedError,
56
+ "#width should be implemented in a subclass when no intrinsic " \
57
+ "dimension source is available."
54
58
  end
55
59
 
56
60
  def to_uri
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Vectory
4
- VERSION = "0.10.2"
4
+ VERSION = "0.12.0"
5
5
  end
data/lib/vectory.rb CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  # External dependencies
4
4
  require "logger"
5
- require "ukiryu"
6
5
 
7
6
  # Define base error class and additional error classes
8
7
  # (used in class bodies like cli.rb, so can't be autoloaded)
@@ -25,14 +24,6 @@ require_relative "vectory/version"
25
24
  module Vectory
26
25
  # Core utilities
27
26
  autoload :Utils, "vectory/utils"
28
- autoload :Platform, "vectory/platform"
29
-
30
- # Wrappers
31
- autoload :GhostscriptWrapper, "vectory/ghostscript_wrapper"
32
- autoload :InkscapeWrapper, "vectory/inkscape_wrapper"
33
-
34
- # Conversion system
35
- autoload :Conversion, "vectory/conversion"
36
27
 
37
28
  # Format classes
38
29
  autoload :Configuration, "vectory/configuration"
@@ -40,7 +31,6 @@ module Vectory
40
31
  autoload :ImageResize, "vectory/image_resize"
41
32
  autoload :Datauri, "vectory/datauri"
42
33
  autoload :Vector, "vectory/vector"
43
- autoload :Pdf, "vectory/pdf"
44
34
  autoload :Eps, "vectory/eps"
45
35
  autoload :Ps, "vectory/ps"
46
36
  autoload :Emf, "vectory/emf"
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # One-shot fixture regeneration script.
5
+ # Run from the vectory root: `bundle exec ruby scripts/regenerate_fixtures.rb`
6
+
7
+ require_relative "../lib/vectory"
8
+
9
+ Pairs = [
10
+ ["spec/examples/emf2eps/img.emf", :to_eps, "spec/examples/emf2eps/ref.eps"],
11
+ ["spec/examples/emf2ps/img.emf", :to_ps, "spec/examples/emf2ps/ref.ps"],
12
+ ["spec/examples/eps2emf/img.eps", :to_emf, "spec/examples/eps2emf/ref.emf"],
13
+ ["spec/examples/eps2ps/img.eps", :to_ps, "spec/examples/eps2ps/ref.ps"],
14
+ ["spec/examples/eps2svg/img.eps", :to_svg, "spec/examples/eps2svg/ref.svg"],
15
+ ["spec/examples/ps2emf/img.ps", :to_emf, "spec/examples/ps2emf/ref.emf"],
16
+ ["spec/examples/ps2eps/img.ps", :to_eps, "spec/examples/ps2eps/ref.eps"],
17
+ ["spec/examples/ps2svg/img.ps", :to_svg, "spec/examples/ps2svg/ref.svg"],
18
+ ["spec/examples/svg2emf/img.svg", :to_emf, "spec/examples/svg2emf/ref.emf"],
19
+ ["spec/examples/svg2eps/img.svg", :to_eps, "spec/examples/svg2eps/ref.eps"],
20
+ ["spec/examples/svg2ps/img.svg", :to_ps, "spec/examples/svg2ps/ref.ps"],
21
+ ].freeze
22
+
23
+ Pairs.each do |input, method, output|
24
+ ext = File.extname(input).delete(".")
25
+ klass_name = { "emf" => "Emf", "eps" => "Eps", "ps" => "Ps",
26
+ "svg" => "Svg" }.fetch(ext)
27
+ klass = Vectory.const_get(klass_name)
28
+ result = klass.from_path(input).public_send(method)
29
+ File.binwrite(output, result.content)
30
+ puts "[OK] #{input} -> #{output} (#{result.content.bytesize} bytes)"
31
+ rescue => e
32
+ puts "[FAIL] #{input} -> #{output}: #{e.class}: #{e.message}"
33
+ end
data/vectory.gemspec CHANGED
@@ -31,7 +31,6 @@ Gem::Specification.new do |spec|
31
31
  spec.add_dependency "image_size", ">= 3.2.0"
32
32
  spec.add_dependency "marcel", "~> 1.0"
33
33
  spec.add_dependency "nokogiri", "~> 1.14"
34
- spec.add_dependency "postsvg", "~> 0.1"
34
+ spec.add_dependency "postsvg", "~> 0.3"
35
35
  spec.add_dependency "thor", "~> 1.0"
36
- spec.add_dependency "ukiryu", "~> 0.3.0"
37
36
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vectory
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.2
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
@@ -92,14 +92,14 @@ dependencies:
92
92
  requirements:
93
93
  - - "~>"
94
94
  - !ruby/object:Gem::Version
95
- version: '0.1'
95
+ version: '0.3'
96
96
  type: :runtime
97
97
  prerelease: false
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - "~>"
101
101
  - !ruby/object:Gem::Version
102
- version: '0.1'
102
+ version: '0.3'
103
103
  - !ruby/object:Gem::Dependency
104
104
  name: thor
105
105
  requirement: !ruby/object:Gem::Requirement
@@ -114,20 +114,6 @@ dependencies:
114
114
  - - "~>"
115
115
  - !ruby/object:Gem::Version
116
116
  version: '1.0'
117
- - !ruby/object:Gem::Dependency
118
- name: ukiryu
119
- requirement: !ruby/object:Gem::Requirement
120
- requirements:
121
- - - "~>"
122
- - !ruby/object:Gem::Version
123
- version: 0.3.0
124
- type: :runtime
125
- prerelease: false
126
- version_requirements: !ruby/object:Gem::Requirement
127
- requirements:
128
- - - "~>"
129
- - !ruby/object:Gem::Version
130
- version: 0.3.0
131
117
  description: |
132
118
  Vectory performs pairwise vector image conversions for common
133
119
  vector image formats, such as SVG, EMF, EPS and PS.
@@ -172,21 +158,13 @@ files:
172
158
  - lib/vectory.rb
173
159
  - lib/vectory/cli.rb
174
160
  - lib/vectory/configuration.rb
175
- - lib/vectory/conversion.rb
176
- - lib/vectory/conversion/ghostscript_strategy.rb
177
- - lib/vectory/conversion/inkscape_strategy.rb
178
- - lib/vectory/conversion/strategy.rb
179
161
  - lib/vectory/datauri.rb
180
162
  - lib/vectory/emf.rb
181
163
  - lib/vectory/eps.rb
182
164
  - lib/vectory/errors.rb
183
165
  - lib/vectory/file_magic.rb
184
- - lib/vectory/ghostscript_wrapper.rb
185
166
  - lib/vectory/image.rb
186
167
  - lib/vectory/image_resize.rb
187
- - lib/vectory/inkscape_wrapper.rb
188
- - lib/vectory/pdf.rb
189
- - lib/vectory/platform.rb
190
168
  - lib/vectory/ps.rb
191
169
  - lib/vectory/svg.rb
192
170
  - lib/vectory/svg_document.rb
@@ -194,6 +172,7 @@ files:
194
172
  - lib/vectory/utils.rb
195
173
  - lib/vectory/vector.rb
196
174
  - lib/vectory/version.rb
175
+ - scripts/regenerate_fixtures.rb
197
176
  - tmp/.keep
198
177
  - vectory.gemspec
199
178
  homepage: https://github.com/metanorma/vectory
@@ -1,74 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Vectory
4
- module Conversion
5
- # Ghostscript-based conversion strategy
6
- #
7
- # Handles PS/EPS → PDF conversions using Ghostscript.
8
- # Ghostscript is used for its accurate BoundingBox preservation.
9
- #
10
- # @see https://www.ghostscript.com/
11
- class GhostscriptStrategy < Strategy
12
- # Ghostscript supports PS/EPS → PDF conversions
13
- SUPPORTED_CONVERSIONS = [
14
- %i[ps pdf],
15
- %i[eps pdf],
16
- ].freeze
17
-
18
- # Convert PS/EPS content to PDF using Ghostscript
19
- #
20
- # @param content [String] the PS/EPS content to convert
21
- # @param input_format [Symbol] the input format (:ps or :eps)
22
- # @param output_format [Symbol] the output format (must be :pdf)
23
- # @param options [Hash] additional options
24
- # @option options [Boolean] :eps_crop use EPSCrop for better BoundingBox handling
25
- # @return [String] the PDF content
26
- # @raise [Vectory::GhostscriptNotFoundError] if Ghostscript is not available
27
- # @raise [Vectory::ConversionError] if conversion fails
28
- def convert(content, input_format:, output_format:, **options)
29
- unless output_format == :pdf
30
- raise ArgumentError,
31
- "Ghostscript only supports PDF output, got: #{output_format}"
32
- end
33
-
34
- unless %i[ps eps].include?(input_format)
35
- raise ArgumentError,
36
- "Ghostscript only supports PS/EPS input, got: #{input_format}"
37
- end
38
-
39
- GhostscriptWrapper.convert(content,
40
- eps_crop: options[:eps_crop] || false)
41
- end
42
-
43
- # Check if this conversion is supported
44
- #
45
- # @param input_format [Symbol] the input format
46
- # @param output_format [Symbol] the output format
47
- # @return [Boolean] true if Ghostscript supports this conversion
48
- def supports?(input_format, output_format)
49
- SUPPORTED_CONVERSIONS.include?([input_format, output_format])
50
- end
51
-
52
- # Get supported conversions
53
- #
54
- # @return [Array<Array<Symbol>>] array of [input, output] format pairs
55
- def supported_conversions
56
- SUPPORTED_CONVERSIONS
57
- end
58
-
59
- # Check if Ghostscript is available
60
- #
61
- # @return [Boolean] true if Ghostscript can be found
62
- def available?
63
- GhostscriptWrapper.available?
64
- end
65
-
66
- # Get the tool name
67
- #
68
- # @return [String] "ghostscript"
69
- def tool_name
70
- "ghostscript"
71
- end
72
- end
73
- end
74
- end