emfsvg 0.1.0 → 0.1.1

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: 8406a813f99a3967f711a2b650958d84f51b0583f16d982f4546fb6cd2460713
4
- data.tar.gz: aec4ceefd1fcb5a45ee36e9887df3c33348d23906a2461b51a7104e87fe02088
3
+ metadata.gz: 4334821604725312749ae532acdd4d729ec4bbdde73897e097d9aedf5404b20e
4
+ data.tar.gz: 077c491cd219b2f274036fb613353e0226ea150fa0cf70e0f544ae07f4b88598
5
5
  SHA512:
6
- metadata.gz: 04d0506ac5adaef03d45450d0b93e0b352950c9c36ba4139c708d167b3cd5f62368258d5788561c5a8112da4cd8fdded08bd2e64d7587e708985bb139493f7ba
7
- data.tar.gz: 4c403342b7abfb81b84eea0d3919b0db0d2307a8857cd0da167c5a1e951ff852813e2acc83f8f1d905b67b9be73c7538fe25701710567611ba98e06ef76c1405
6
+ metadata.gz: d18d84ed9d2d156aee6e89fc946c4d6c53c00678b7b627c5c995cc7fb72f7bb52780dfeb27ecc14047e5aa3906502e1ca05d2609c6556201685dbacaee9fc3db
7
+ data.tar.gz: afb7470b2d7761102326ee7877cfa41c488966dadfde449abe91cdc332aead381b9f4a8bcef6a5bd582f7423d2336cbd982e1c213e5d210f38f336997ed2d720
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Emfsvg
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
data/lib/emfsvg.rb CHANGED
@@ -13,7 +13,6 @@ module Emfsvg
13
13
  autoload :TransformStack, "emfsvg/transform_stack"
14
14
  autoload :SvgBuilder, "emfsvg/svg_builder"
15
15
  autoload :Options, "emfsvg/options"
16
- autoload :Compat, "emfsvg/compat"
17
16
  autoload :DibDecoder, "emfsvg/dib_decoder"
18
17
  autoload :PngEncoder, "emfsvg/png_encoder"
19
18
  autoload :ClipRegion, "emfsvg/clip_region"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: emfsvg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
@@ -79,20 +79,6 @@ dependencies:
79
79
  - - "~>"
80
80
  - !ruby/object:Gem::Version
81
81
  version: '1.6'
82
- - !ruby/object:Gem::Dependency
83
- name: rexml
84
- requirement: !ruby/object:Gem::Requirement
85
- requirements:
86
- - - "~>"
87
- - !ruby/object:Gem::Version
88
- version: '3.3'
89
- type: :runtime
90
- prerelease: false
91
- version_requirements: !ruby/object:Gem::Requirement
92
- requirements:
93
- - - "~>"
94
- - !ruby/object:Gem::Version
95
- version: '3.3'
96
82
  description: Convert Microsoft Enhanced Metafile (EMF) to SVG and back. Consumes the
97
83
  `emf` gem's domain model. Replaces the FFI wrapper around libemf2svg with a pure-Ruby
98
84
  transformer.
@@ -110,7 +96,6 @@ files:
110
96
  - lib/emfsvg/bsd_rand.rb
111
97
  - lib/emfsvg/bsd_rand_sequence.txt
112
98
  - lib/emfsvg/clip_region.rb
113
- - lib/emfsvg/compat.rb
114
99
  - lib/emfsvg/device_context.rb
115
100
  - lib/emfsvg/dib_decoder.rb
116
101
  - lib/emfsvg/error.rb
data/lib/emfsvg/compat.rb DELETED
@@ -1,134 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Compares emfsvg's output against libemf2svg's reference output for the
4
- # same EMF input. Used by spec/compat_with_libemf2svg_spec.rb.
5
- #
6
- # This is NOT a "must produce identical SVG" test — emfsvg is a clean-room
7
- # rewrite that handles a subset of EMF records. It IS:
8
- # - a structural-equivalence check for the records emfsvg handles
9
- # - a quantification of the gap (compatibility ratio per fixture)
10
- # - a regression guard so the ratio doesn't shrink over time
11
- #
12
- # Usage:
13
- # Emfsvg::Compat::Comparator.call(fixtures_glob, ref_dir, out_dir)
14
- #
15
- # Requires the libemf2svg-conv binary (or our emf2svg_ref wrapper) at
16
- # Emfsvg::Compat::LIBEMF2SVG_REF_PATH. The spec auto-skips if missing.
17
-
18
- require "open3"
19
- require "fileutils"
20
- require "tmpdir"
21
- require "rexml/document"
22
-
23
- module Emfsvg
24
- module Compat
25
- REF_BINARY_DEFAULT = "/Users/mulgogi/src/claricle/libemf2svg/emf2svg_ref"
26
- REF_LIB_DIR_DEFAULT = "/Users/mulgogi/src/claricle/libemf2svg/build"
27
-
28
- module_function
29
-
30
- def ref_binary_available?
31
- path = ENV.fetch("EMF2SVG_REF_PATH", REF_BINARY_DEFAULT)
32
- File.executable?(path)
33
- end
34
-
35
- # Generate a reference SVG using libemf2svg. Returns the SVG bytes,
36
- # or nil if generation failed.
37
- def generate_reference(emf_path, output_path = nil)
38
- binary = ENV.fetch("EMF2SVG_REF_PATH", REF_BINARY_DEFAULT)
39
- lib_dir = ENV.fetch("EMF2SVG_REF_LIB_DIR", REF_LIB_DIR_DEFAULT)
40
- env = { "DYLD_LIBRARY_PATH" => lib_dir }
41
- output_path ||= "#{Dir.mktmpdir}/#{File.basename(emf_path, '.emf')}.svg"
42
- _, _, status = Open3.capture3(env, binary, emf_path, output_path)
43
- return nil unless status.success?
44
-
45
- File.binread(output_path)
46
- ensure
47
- File.delete(output_path) if output_path && !block_given?
48
- end
49
-
50
- # Generate emfsvg output. Requires the emfsvg gem to be loaded.
51
- def generate_emfsvg(emf_path, options = {})
52
- Emfsvg.from_file(emf_path, **options)
53
- end
54
-
55
- # Normalise an SVG document for structural comparison:
56
- # - parse to REXML
57
- # - return the root element
58
- def parse_svg(svg_string)
59
- REXML::Document.new(svg_string).root
60
- rescue REXML::ParseException
61
- nil
62
- end
63
-
64
- # Count drawing elements in an SVG. Returns a hash like
65
- # { "rect" => 3, "path" => 17, "ellipse" => 2 }.
66
- def count_elements(svg_root)
67
- counts = Hash.new(0)
68
- return counts unless svg_root
69
-
70
- REXML::XPath.each(svg_root, "descendant-or-self::*") do |el|
71
- counts[el.name] += 1
72
- end
73
- counts
74
- end
75
-
76
- # Per-fixture comparison result.
77
- Result = Struct.new(:fixture, :ref_bytes, :emfsvg_bytes, :ref_elements,
78
- :emfsvg_elements, keyword_init: true) do
79
- def byte_ratio
80
- ref_bytes.zero? ? 0.0 : (emfsvg_bytes.to_f / ref_bytes * 100).round(1)
81
- end
82
-
83
- def element_overlap
84
- return 0.0 if emfsvg_elements.empty?
85
-
86
- shared = emfsvg_elements.keys & ref_elements.keys
87
- shared.sum { |k| [emfsvg_elements[k], ref_elements[k]].min }.to_f /
88
- emfsvg_elements.values.sum
89
- end
90
-
91
- def to_s
92
- format("%-40s ref=%8d out=%7d (%5.1f%%) elements_overlap=%.1f",
93
- fixture, ref_bytes, emfsvg_bytes, byte_ratio, element_overlap * 100)
94
- end
95
- end
96
-
97
- # Walk a fixtures glob, produce both outputs, return Result array.
98
- def compare_glob(fixtures_glob)
99
- results = []
100
- Dir.glob(fixtures_glob).each do |emf|
101
- ref_svg = generate_reference(emf)
102
- next unless ref_svg
103
-
104
- emfsvg_svg = begin
105
- generate_emfsvg(emf)
106
- rescue StandardError
107
- nil
108
- end
109
- next unless emfsvg_svg
110
-
111
- results << Result.new(
112
- fixture: File.basename(emf),
113
- ref_bytes: ref_svg.bytesize,
114
- emfsvg_bytes: emfsvg_svg.bytesize,
115
- ref_elements: count_elements(parse_svg(ref_svg)),
116
- emfsvg_elements: count_elements(parse_svg(emfsvg_svg))
117
- )
118
- end
119
- results
120
- end
121
-
122
- # Summary across many results.
123
- def summarize(results)
124
- return "no results" if results.empty?
125
-
126
- total_ref = results.sum(&:ref_bytes)
127
- total_out = results.sum(&:emfsvg_bytes)
128
- ratio = total_ref.zero? ? 0 : (total_out.to_f / total_ref * 100).round(1)
129
- avg_overlap = results.sum(&:element_overlap) / results.size
130
- format("fixtures=%d total_ref=%d total_out=%d byte_ratio=%.1f%% avg_element_overlap=%.1f%%",
131
- results.size, total_ref, total_out, ratio, avg_overlap * 100)
132
- end
133
- end
134
- end