emfsvg 0.1.0 → 0.1.2
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/README.adoc +86 -58
- data/exe/emfsvg +21 -2
- data/lib/emfsvg/dib_encoder.rb +67 -0
- data/lib/emfsvg/error.rb +2 -0
- data/lib/emfsvg/png_decoder.rb +23 -0
- data/lib/emfsvg/svg/attribute_parser.rb +31 -0
- data/lib/emfsvg/svg/clip_path_registry.rb +43 -0
- data/lib/emfsvg/svg/color.rb +105 -0
- data/lib/emfsvg/svg/document.rb +70 -0
- data/lib/emfsvg/svg/element.rb +66 -0
- data/lib/emfsvg/svg/elements/circle.rb +38 -0
- data/lib/emfsvg/svg/elements/clip_path.rb +128 -0
- data/lib/emfsvg/svg/elements/defs.rb +24 -0
- data/lib/emfsvg/svg/elements/ellipse.rb +35 -0
- data/lib/emfsvg/svg/elements/group.rb +33 -0
- data/lib/emfsvg/svg/elements/image.rb +65 -0
- data/lib/emfsvg/svg/elements/line.rb +35 -0
- data/lib/emfsvg/svg/elements/path.rb +29 -0
- data/lib/emfsvg/svg/elements/polygon.rb +29 -0
- data/lib/emfsvg/svg/elements/polyline.rb +29 -0
- data/lib/emfsvg/svg/elements/rect.rb +44 -0
- data/lib/emfsvg/svg/elements/stylable.rb +28 -0
- data/lib/emfsvg/svg/elements/text.rb +67 -0
- data/lib/emfsvg/svg/elements.rb +42 -0
- data/lib/emfsvg/svg/paint.rb +36 -0
- data/lib/emfsvg/svg/parser.rb +44 -0
- data/lib/emfsvg/svg/path_data/command.rb +15 -0
- data/lib/emfsvg/svg/path_data.rb +135 -0
- data/lib/emfsvg/svg/stroke.rb +107 -0
- data/lib/emfsvg/svg/transform_parser.rb +123 -0
- data/lib/emfsvg/svg.rb +25 -0
- data/lib/emfsvg/translation/context.rb +99 -0
- data/lib/emfsvg/translation/decimal_detector.rb +112 -0
- data/lib/emfsvg/translation/emf_renderer.rb +146 -0
- data/lib/emfsvg/translation/handler_registry.rb +38 -0
- data/lib/emfsvg/translation/handlers/circle_handler.rb +17 -0
- data/lib/emfsvg/translation/handlers/clip_path_handler.rb +16 -0
- data/lib/emfsvg/translation/handlers/defs_handler.rb +17 -0
- data/lib/emfsvg/translation/handlers/ellipse_handler.rb +28 -0
- data/lib/emfsvg/translation/handlers/group_handler.rb +40 -0
- data/lib/emfsvg/translation/handlers/image_handler.rb +94 -0
- data/lib/emfsvg/translation/handlers/line_handler.rb +30 -0
- data/lib/emfsvg/translation/handlers/path_flattener.rb +139 -0
- data/lib/emfsvg/translation/handlers/path_handler.rb +78 -0
- data/lib/emfsvg/translation/handlers/polygon_handler.rb +17 -0
- data/lib/emfsvg/translation/handlers/polyline_handler.rb +51 -0
- data/lib/emfsvg/translation/handlers/rect_handler.rb +43 -0
- data/lib/emfsvg/translation/handlers/shared_gdi.rb +97 -0
- data/lib/emfsvg/translation/handlers/text_handler.rb +137 -0
- data/lib/emfsvg/translation/handlers.rb +25 -0
- data/lib/emfsvg/translation/header_builder.rb +89 -0
- data/lib/emfsvg/translation/record_emitter.rb +36 -0
- data/lib/emfsvg/translation/scaler/fixed.rb +41 -0
- data/lib/emfsvg/translation/scaler/identity.rb +23 -0
- data/lib/emfsvg/translation/scaler.rb +19 -0
- data/lib/emfsvg/translation.rb +16 -0
- data/lib/emfsvg/version.rb +1 -1
- data/lib/emfsvg.rb +21 -1
- metadata +62 -7
- data/lib/emfsvg/compat.rb +0 -134
metadata
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
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.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
|
+
autorequire:
|
|
8
9
|
bindir: exe
|
|
9
10
|
cert_chain: []
|
|
10
|
-
date:
|
|
11
|
+
date: 2026-07-26 00:00:00.000000000 Z
|
|
11
12
|
dependencies:
|
|
12
13
|
- !ruby/object:Gem::Dependency
|
|
13
14
|
name: base64
|
|
@@ -80,19 +81,19 @@ dependencies:
|
|
|
80
81
|
- !ruby/object:Gem::Version
|
|
81
82
|
version: '1.6'
|
|
82
83
|
- !ruby/object:Gem::Dependency
|
|
83
|
-
name:
|
|
84
|
+
name: nokogiri
|
|
84
85
|
requirement: !ruby/object:Gem::Requirement
|
|
85
86
|
requirements:
|
|
86
87
|
- - "~>"
|
|
87
88
|
- !ruby/object:Gem::Version
|
|
88
|
-
version: '
|
|
89
|
+
version: '1.16'
|
|
89
90
|
type: :runtime
|
|
90
91
|
prerelease: false
|
|
91
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
92
93
|
requirements:
|
|
93
94
|
- - "~>"
|
|
94
95
|
- !ruby/object:Gem::Version
|
|
95
|
-
version: '
|
|
96
|
+
version: '1.16'
|
|
96
97
|
description: Convert Microsoft Enhanced Metafile (EMF) to SVG and back. Consumes the
|
|
97
98
|
`emf` gem's domain model. Replaces the FFI wrapper around libemf2svg with a pure-Ruby
|
|
98
99
|
transformer.
|
|
@@ -110,18 +111,70 @@ files:
|
|
|
110
111
|
- lib/emfsvg/bsd_rand.rb
|
|
111
112
|
- lib/emfsvg/bsd_rand_sequence.txt
|
|
112
113
|
- lib/emfsvg/clip_region.rb
|
|
113
|
-
- lib/emfsvg/compat.rb
|
|
114
114
|
- lib/emfsvg/device_context.rb
|
|
115
115
|
- lib/emfsvg/dib_decoder.rb
|
|
116
|
+
- lib/emfsvg/dib_encoder.rb
|
|
116
117
|
- lib/emfsvg/error.rb
|
|
117
118
|
- lib/emfsvg/format_helpers.rb
|
|
118
119
|
- lib/emfsvg/glyph_index_mapper.rb
|
|
119
120
|
- lib/emfsvg/object_table.rb
|
|
120
121
|
- lib/emfsvg/options.rb
|
|
122
|
+
- lib/emfsvg/png_decoder.rb
|
|
121
123
|
- lib/emfsvg/png_encoder.rb
|
|
122
124
|
- lib/emfsvg/renderer.rb
|
|
125
|
+
- lib/emfsvg/svg.rb
|
|
126
|
+
- lib/emfsvg/svg/attribute_parser.rb
|
|
127
|
+
- lib/emfsvg/svg/clip_path_registry.rb
|
|
128
|
+
- lib/emfsvg/svg/color.rb
|
|
129
|
+
- lib/emfsvg/svg/document.rb
|
|
130
|
+
- lib/emfsvg/svg/element.rb
|
|
131
|
+
- lib/emfsvg/svg/elements.rb
|
|
132
|
+
- lib/emfsvg/svg/elements/circle.rb
|
|
133
|
+
- lib/emfsvg/svg/elements/clip_path.rb
|
|
134
|
+
- lib/emfsvg/svg/elements/defs.rb
|
|
135
|
+
- lib/emfsvg/svg/elements/ellipse.rb
|
|
136
|
+
- lib/emfsvg/svg/elements/group.rb
|
|
137
|
+
- lib/emfsvg/svg/elements/image.rb
|
|
138
|
+
- lib/emfsvg/svg/elements/line.rb
|
|
139
|
+
- lib/emfsvg/svg/elements/path.rb
|
|
140
|
+
- lib/emfsvg/svg/elements/polygon.rb
|
|
141
|
+
- lib/emfsvg/svg/elements/polyline.rb
|
|
142
|
+
- lib/emfsvg/svg/elements/rect.rb
|
|
143
|
+
- lib/emfsvg/svg/elements/stylable.rb
|
|
144
|
+
- lib/emfsvg/svg/elements/text.rb
|
|
145
|
+
- lib/emfsvg/svg/paint.rb
|
|
146
|
+
- lib/emfsvg/svg/parser.rb
|
|
147
|
+
- lib/emfsvg/svg/path_data.rb
|
|
148
|
+
- lib/emfsvg/svg/path_data/command.rb
|
|
149
|
+
- lib/emfsvg/svg/stroke.rb
|
|
150
|
+
- lib/emfsvg/svg/transform_parser.rb
|
|
123
151
|
- lib/emfsvg/svg_builder.rb
|
|
124
152
|
- lib/emfsvg/transform_stack.rb
|
|
153
|
+
- lib/emfsvg/translation.rb
|
|
154
|
+
- lib/emfsvg/translation/context.rb
|
|
155
|
+
- lib/emfsvg/translation/decimal_detector.rb
|
|
156
|
+
- lib/emfsvg/translation/emf_renderer.rb
|
|
157
|
+
- lib/emfsvg/translation/handler_registry.rb
|
|
158
|
+
- lib/emfsvg/translation/handlers.rb
|
|
159
|
+
- lib/emfsvg/translation/handlers/circle_handler.rb
|
|
160
|
+
- lib/emfsvg/translation/handlers/clip_path_handler.rb
|
|
161
|
+
- lib/emfsvg/translation/handlers/defs_handler.rb
|
|
162
|
+
- lib/emfsvg/translation/handlers/ellipse_handler.rb
|
|
163
|
+
- lib/emfsvg/translation/handlers/group_handler.rb
|
|
164
|
+
- lib/emfsvg/translation/handlers/image_handler.rb
|
|
165
|
+
- lib/emfsvg/translation/handlers/line_handler.rb
|
|
166
|
+
- lib/emfsvg/translation/handlers/path_flattener.rb
|
|
167
|
+
- lib/emfsvg/translation/handlers/path_handler.rb
|
|
168
|
+
- lib/emfsvg/translation/handlers/polygon_handler.rb
|
|
169
|
+
- lib/emfsvg/translation/handlers/polyline_handler.rb
|
|
170
|
+
- lib/emfsvg/translation/handlers/rect_handler.rb
|
|
171
|
+
- lib/emfsvg/translation/handlers/shared_gdi.rb
|
|
172
|
+
- lib/emfsvg/translation/handlers/text_handler.rb
|
|
173
|
+
- lib/emfsvg/translation/header_builder.rb
|
|
174
|
+
- lib/emfsvg/translation/record_emitter.rb
|
|
175
|
+
- lib/emfsvg/translation/scaler.rb
|
|
176
|
+
- lib/emfsvg/translation/scaler/fixed.rb
|
|
177
|
+
- lib/emfsvg/translation/scaler/identity.rb
|
|
125
178
|
- lib/emfsvg/version.rb
|
|
126
179
|
- lib/emfsvg/visitors.rb
|
|
127
180
|
- lib/emfsvg/visitors/emr_visitor.rb
|
|
@@ -133,6 +186,7 @@ metadata:
|
|
|
133
186
|
source_code_uri: https://github.com/claricle/emfsvg
|
|
134
187
|
changelog_uri: https://github.com/claricle/emfsvg/blob/main/CHANGELOG.adoc
|
|
135
188
|
rubygems_mfa_required: 'true'
|
|
189
|
+
post_install_message:
|
|
136
190
|
rdoc_options: []
|
|
137
191
|
require_paths:
|
|
138
192
|
- lib
|
|
@@ -147,7 +201,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
147
201
|
- !ruby/object:Gem::Version
|
|
148
202
|
version: '0'
|
|
149
203
|
requirements: []
|
|
150
|
-
rubygems_version:
|
|
204
|
+
rubygems_version: 3.5.22
|
|
205
|
+
signing_key:
|
|
151
206
|
specification_version: 4
|
|
152
207
|
summary: EMF <-> SVG transformer (Ruby).
|
|
153
208
|
test_files: []
|
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
|