emfsvg 0.1.2 → 0.1.4

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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +98 -14
  3. data/lib/emfsvg/device_context.rb +9 -6
  4. data/lib/emfsvg/dib_decoder.rb +12 -8
  5. data/lib/emfsvg/drawing_hint.rb +88 -0
  6. data/lib/emfsvg/error.rb +11 -0
  7. data/lib/emfsvg/format_helpers.rb +46 -2
  8. data/lib/emfsvg/glyph_index_mapper.rb +5 -6
  9. data/lib/emfsvg/object_table.rb +7 -15
  10. data/lib/emfsvg/record_access.rb +38 -0
  11. data/lib/emfsvg/renderer.rb +114 -55
  12. data/lib/emfsvg/svg/clip_path_registry.rb +287 -4
  13. data/lib/emfsvg/svg/color.rb +32 -9
  14. data/lib/emfsvg/svg/document.rb +7 -0
  15. data/lib/emfsvg/svg/element.rb +4 -4
  16. data/lib/emfsvg/svg/elements/clip_path.rb +89 -24
  17. data/lib/emfsvg/svg/elements/defs.rb +85 -4
  18. data/lib/emfsvg/svg/elements/group.rb +30 -4
  19. data/lib/emfsvg/svg/elements/path.rb +239 -3
  20. data/lib/emfsvg/svg/elements/rect.rb +5 -2
  21. data/lib/emfsvg/svg/elements/stylable.rb +41 -11
  22. data/lib/emfsvg/svg/elements/text.rb +101 -16
  23. data/lib/emfsvg/svg/elements.rb +1 -1
  24. data/lib/emfsvg/svg/paint.rb +8 -2
  25. data/lib/emfsvg/svg/parser.rb +15 -4
  26. data/lib/emfsvg/svg/path_data/command.rb +1 -1
  27. data/lib/emfsvg/svg/path_data.rb +47 -36
  28. data/lib/emfsvg/svg/stroke.rb +78 -12
  29. data/lib/emfsvg/svg.rb +1 -1
  30. data/lib/emfsvg/svg_builder.rb +38 -9
  31. data/lib/emfsvg/translation/context.rb +262 -10
  32. data/lib/emfsvg/translation/decimal_detector.rb +26 -8
  33. data/lib/emfsvg/translation/emf_renderer.rb +16 -12
  34. data/lib/emfsvg/translation/handler_registry.rb +16 -6
  35. data/lib/emfsvg/translation/handlers/circular_arc.rb +103 -0
  36. data/lib/emfsvg/translation/handlers/defs_handler.rb +33 -4
  37. data/lib/emfsvg/translation/handlers/ellipse_handler.rb +2 -2
  38. data/lib/emfsvg/translation/handlers/elliptical_arc.rb +125 -0
  39. data/lib/emfsvg/translation/handlers/group_handler.rb +7 -0
  40. data/lib/emfsvg/translation/handlers/image_handler.rb +53 -8
  41. data/lib/emfsvg/translation/handlers/line_handler.rb +2 -2
  42. data/lib/emfsvg/translation/handlers/mapped_arc.rb +41 -0
  43. data/lib/emfsvg/translation/handlers/mapped_circular_arc.rb +55 -0
  44. data/lib/emfsvg/translation/handlers/mapped_pie.rb +30 -0
  45. data/lib/emfsvg/translation/handlers/path_flattener.rb +70 -49
  46. data/lib/emfsvg/translation/handlers/path_handler.rb +169 -14
  47. data/lib/emfsvg/translation/handlers/polyline_handler.rb +2 -2
  48. data/lib/emfsvg/translation/handlers/rect_handler.rb +21 -5
  49. data/lib/emfsvg/translation/handlers/shared_gdi.rb +75 -12
  50. data/lib/emfsvg/translation/handlers/text_handler.rb +92 -29
  51. data/lib/emfsvg/translation/handlers.rb +5 -0
  52. data/lib/emfsvg/translation/header_builder.rb +20 -0
  53. data/lib/emfsvg/translation/local_origin.rb +40 -0
  54. data/lib/emfsvg/translation/record_emitter.rb +8 -5
  55. data/lib/emfsvg/translation/scaler/fixed.rb +8 -2
  56. data/lib/emfsvg/translation.rb +1 -0
  57. data/lib/emfsvg/version.rb +1 -1
  58. data/lib/emfsvg/visitors/emr_visitor.rb +197 -129
  59. data/lib/emfsvg.rb +49 -2
  60. metadata +24 -10
data/lib/emfsvg.rb CHANGED
@@ -8,6 +8,7 @@ module Emfsvg
8
8
  autoload :FormatError, "emfsvg/error"
9
9
  autoload :ParseError, "emfsvg/error"
10
10
  autoload :RenderError, "emfsvg/error"
11
+ autoload :ResourceLimitError, "emfsvg/error"
11
12
  autoload :Renderer, "emfsvg/renderer"
12
13
  autoload :DeviceContext, "emfsvg/device_context"
13
14
  autoload :ObjectTable, "emfsvg/object_table"
@@ -24,6 +25,10 @@ module Emfsvg
24
25
  autoload :DibEncoder, "emfsvg/dib_encoder"
25
26
  autoload :Svg, "emfsvg/svg"
26
27
  autoload :Translation, "emfsvg/translation"
28
+ autoload :DrawingHint, "emfsvg/drawing_hint"
29
+ autoload :RecordAccess, "emfsvg/record_access"
30
+
31
+ const_get(:Error)
27
32
 
28
33
  class << self
29
34
  # Render an Emf::Model::Metafile to an SVG string.
@@ -37,16 +42,22 @@ module Emfsvg
37
42
  # (default: false — EMF+ is structured-parsed by emf but
38
43
  # not yet rendered)
39
44
  def to_svg(metafile, **options)
40
- Renderer.call(metafile, Options.new(**options))
45
+ svg = Renderer.call(metafile, Options.new(**options))
46
+ warn_skipped_records(metafile)
47
+ svg
48
+ rescue Emf::Error => e
49
+ reraise_upstream_error(e)
41
50
  end
42
51
 
43
52
  # Parse from bytes then render.
44
53
  def from_bytes(bytes, **options)
45
- to_svg(Emf.parse(bytes), **options)
54
+ check_input_size!(bytes.bytesize)
55
+ to_svg(parse_metafile(bytes), **options)
46
56
  end
47
57
 
48
58
  # Parse from a file path then render.
49
59
  def from_file(path, **options)
60
+ check_input_size!(File.size(path))
50
61
  from_bytes(File.binread(path), **options)
51
62
  end
52
63
 
@@ -65,5 +76,41 @@ module Emfsvg
65
76
  def from_svg_file(path)
66
77
  from_svg(File.read(path))
67
78
  end
79
+
80
+ private
81
+
82
+ def warn_skipped_records(metafile)
83
+ return unless metafile.respond_to?(:diagnostics)
84
+
85
+ skipped = metafile.diagnostics.select { |diagnostic| diagnostic.disposition == :skipped }
86
+ return if skipped.empty?
87
+
88
+ entries = skipped.sort_by(&:record_index).map do |diagnostic|
89
+ "index=#{diagnostic.record_index},type=#{diagnostic.record_type}," \
90
+ "code=#{diagnostic.record_code},offset=#{diagnostic.byte_offset}"
91
+ end
92
+ Kernel.warn("emfsvg: skipped EMF records: #{entries.join(';')}")
93
+ end
94
+
95
+ def reraise_upstream_error(error)
96
+ raise error unless defined?(Emf::ResourceLimitError) && error.is_a?(Emf::ResourceLimitError)
97
+
98
+ raise ResourceLimitError.new(resource: error.resource, limit: error.limit, actual: error.actual), cause: error
99
+ end
100
+
101
+ def check_input_size!(actual)
102
+ limit = Emf::Emr::Parser::MAX_INPUT_BYTES
103
+ return if actual <= limit
104
+
105
+ raise ResourceLimitError.new(resource: :input_bytes, limit: limit, actual: actual)
106
+ end
107
+
108
+ def parse_metafile(bytes)
109
+ Emf.parse(bytes)
110
+ rescue Emf::FormatError, Emf::ParseError => e
111
+ raise ParseError, e.message, cause: e
112
+ rescue Emf::Error => e
113
+ reraise_upstream_error(e)
114
+ end
68
115
  end
69
116
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: emfsvg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-07-26 00:00:00.000000000 Z
11
+ date: 2026-11-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64
@@ -44,14 +44,20 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0.1'
47
+ version: '0.2'
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: 0.2.0
48
51
  type: :runtime
49
52
  prerelease: false
50
53
  version_requirements: !ruby/object:Gem::Requirement
51
54
  requirements:
52
55
  - - "~>"
53
56
  - !ruby/object:Gem::Version
54
- version: '0.1'
57
+ version: '0.2'
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 0.2.0
55
61
  - !ruby/object:Gem::Dependency
56
62
  name: fontisan
57
63
  requirement: !ruby/object:Gem::Requirement
@@ -67,33 +73,33 @@ dependencies:
67
73
  - !ruby/object:Gem::Version
68
74
  version: '0'
69
75
  - !ruby/object:Gem::Dependency
70
- name: libpng
76
+ name: leptris
71
77
  requirement: !ruby/object:Gem::Requirement
72
78
  requirements:
73
79
  - - "~>"
74
80
  - !ruby/object:Gem::Version
75
- version: '1.6'
81
+ version: 1.9.399
76
82
  type: :runtime
77
83
  prerelease: false
78
84
  version_requirements: !ruby/object:Gem::Requirement
79
85
  requirements:
80
86
  - - "~>"
81
87
  - !ruby/object:Gem::Version
82
- version: '1.6'
88
+ version: 1.9.399
83
89
  - !ruby/object:Gem::Dependency
84
- name: nokogiri
90
+ name: libpng
85
91
  requirement: !ruby/object:Gem::Requirement
86
92
  requirements:
87
93
  - - "~>"
88
94
  - !ruby/object:Gem::Version
89
- version: '1.16'
95
+ version: '1.6'
90
96
  type: :runtime
91
97
  prerelease: false
92
98
  version_requirements: !ruby/object:Gem::Requirement
93
99
  requirements:
94
100
  - - "~>"
95
101
  - !ruby/object:Gem::Version
96
- version: '1.16'
102
+ version: '1.6'
97
103
  description: Convert Microsoft Enhanced Metafile (EMF) to SVG and back. Consumes the
98
104
  `emf` gem's domain model. Replaces the FFI wrapper around libemf2svg with a pure-Ruby
99
105
  transformer.
@@ -114,6 +120,7 @@ files:
114
120
  - lib/emfsvg/device_context.rb
115
121
  - lib/emfsvg/dib_decoder.rb
116
122
  - lib/emfsvg/dib_encoder.rb
123
+ - lib/emfsvg/drawing_hint.rb
117
124
  - lib/emfsvg/error.rb
118
125
  - lib/emfsvg/format_helpers.rb
119
126
  - lib/emfsvg/glyph_index_mapper.rb
@@ -121,6 +128,7 @@ files:
121
128
  - lib/emfsvg/options.rb
122
129
  - lib/emfsvg/png_decoder.rb
123
130
  - lib/emfsvg/png_encoder.rb
131
+ - lib/emfsvg/record_access.rb
124
132
  - lib/emfsvg/renderer.rb
125
133
  - lib/emfsvg/svg.rb
126
134
  - lib/emfsvg/svg/attribute_parser.rb
@@ -157,12 +165,17 @@ files:
157
165
  - lib/emfsvg/translation/handler_registry.rb
158
166
  - lib/emfsvg/translation/handlers.rb
159
167
  - lib/emfsvg/translation/handlers/circle_handler.rb
168
+ - lib/emfsvg/translation/handlers/circular_arc.rb
160
169
  - lib/emfsvg/translation/handlers/clip_path_handler.rb
161
170
  - lib/emfsvg/translation/handlers/defs_handler.rb
162
171
  - lib/emfsvg/translation/handlers/ellipse_handler.rb
172
+ - lib/emfsvg/translation/handlers/elliptical_arc.rb
163
173
  - lib/emfsvg/translation/handlers/group_handler.rb
164
174
  - lib/emfsvg/translation/handlers/image_handler.rb
165
175
  - lib/emfsvg/translation/handlers/line_handler.rb
176
+ - lib/emfsvg/translation/handlers/mapped_arc.rb
177
+ - lib/emfsvg/translation/handlers/mapped_circular_arc.rb
178
+ - lib/emfsvg/translation/handlers/mapped_pie.rb
166
179
  - lib/emfsvg/translation/handlers/path_flattener.rb
167
180
  - lib/emfsvg/translation/handlers/path_handler.rb
168
181
  - lib/emfsvg/translation/handlers/polygon_handler.rb
@@ -171,6 +184,7 @@ files:
171
184
  - lib/emfsvg/translation/handlers/shared_gdi.rb
172
185
  - lib/emfsvg/translation/handlers/text_handler.rb
173
186
  - lib/emfsvg/translation/header_builder.rb
187
+ - lib/emfsvg/translation/local_origin.rb
174
188
  - lib/emfsvg/translation/record_emitter.rb
175
189
  - lib/emfsvg/translation/scaler.rb
176
190
  - lib/emfsvg/translation/scaler/fixed.rb