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 +4 -4
- data/lib/emfsvg/version.rb +1 -1
- data/lib/emfsvg.rb +0 -1
- metadata +1 -16
- data/lib/emfsvg/compat.rb +0 -134
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4334821604725312749ae532acdd4d729ec4bbdde73897e097d9aedf5404b20e
|
|
4
|
+
data.tar.gz: 077c491cd219b2f274036fb613353e0226ea150fa0cf70e0f544ae07f4b88598
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d18d84ed9d2d156aee6e89fc946c4d6c53c00678b7b627c5c995cc7fb72f7bb52780dfeb27ecc14047e5aa3906502e1ca05d2609c6556201685dbacaee9fc3db
|
|
7
|
+
data.tar.gz: afb7470b2d7761102326ee7877cfa41c488966dadfde449abe91cdc332aead381b9f4a8bcef6a5bd582f7423d2336cbd982e1c213e5d210f38f336997ed2d720
|
data/lib/emfsvg/version.rb
CHANGED
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.
|
|
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
|