emf 0.1.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.
Files changed (167) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +24 -0
  3. data/README.adoc +136 -0
  4. data/exe/emf +113 -0
  5. data/lib/emf/binary/codec.rb +19 -0
  6. data/lib/emf/binary/types.rb +105 -0
  7. data/lib/emf/binary.rb +10 -0
  8. data/lib/emf/detector.rb +58 -0
  9. data/lib/emf/emf_plus/binary.rb +8 -0
  10. data/lib/emf/emf_plus/parser.rb +13 -0
  11. data/lib/emf/emf_plus/serializer.rb +13 -0
  12. data/lib/emf/emf_plus.rb +9 -0
  13. data/lib/emf/emr/binary/header.rb +41 -0
  14. data/lib/emf/emr/binary/record.rb +17 -0
  15. data/lib/emf/emr/binary/records/abort_path.rb +16 -0
  16. data/lib/emf/emr/binary/records/alpha_blend.rb +17 -0
  17. data/lib/emf/emr/binary/records/angle_arc.rb +19 -0
  18. data/lib/emf/emr/binary/records/arc.rb +19 -0
  19. data/lib/emf/emr/binary/records/arc_to.rb +19 -0
  20. data/lib/emf/emr/binary/records/begin_path.rb +16 -0
  21. data/lib/emf/emr/binary/records/bit_blt.rb +37 -0
  22. data/lib/emf/emr/binary/records/chord.rb +19 -0
  23. data/lib/emf/emr/binary/records/close_figure.rb +16 -0
  24. data/lib/emf/emr/binary/records/color_correct_palette.rb +17 -0
  25. data/lib/emf/emr/binary/records/colormatch_to_target_w.rb +17 -0
  26. data/lib/emf/emr/binary/records/comment.rb +20 -0
  27. data/lib/emf/emr/binary/records/create_brush_indirect.rb +20 -0
  28. data/lib/emf/emr/binary/records/create_colorspace.rb +17 -0
  29. data/lib/emf/emr/binary/records/create_colorspace_w.rb +17 -0
  30. data/lib/emf/emr/binary/records/create_dib_pattern_brush_pt.rb +25 -0
  31. data/lib/emf/emr/binary/records/create_font_indirect_w.rb +18 -0
  32. data/lib/emf/emr/binary/records/create_mono_brush.rb +25 -0
  33. data/lib/emf/emr/binary/records/create_palette.rb +17 -0
  34. data/lib/emf/emr/binary/records/create_pen.rb +20 -0
  35. data/lib/emf/emr/binary/records/delete_colorspace.rb +17 -0
  36. data/lib/emf/emr/binary/records/delete_object.rb +16 -0
  37. data/lib/emf/emr/binary/records/draw_escape.rb +17 -0
  38. data/lib/emf/emr/binary/records/ellipse.rb +18 -0
  39. data/lib/emf/emr/binary/records/end_path.rb +16 -0
  40. data/lib/emf/emr/binary/records/eof.rb +21 -0
  41. data/lib/emf/emr/binary/records/exclude_clip_rect.rb +16 -0
  42. data/lib/emf/emr/binary/records/ext_create_pen.rb +17 -0
  43. data/lib/emf/emr/binary/records/ext_escape.rb +17 -0
  44. data/lib/emf/emr/binary/records/ext_flood_fill.rb +17 -0
  45. data/lib/emf/emr/binary/records/ext_select_clip_rgn.rb +19 -0
  46. data/lib/emf/emr/binary/records/ext_text_out_a.rb +27 -0
  47. data/lib/emf/emr/binary/records/ext_text_out_w.rb +41 -0
  48. data/lib/emf/emr/binary/records/fill_path.rb +16 -0
  49. data/lib/emf/emr/binary/records/fill_rgn.rb +17 -0
  50. data/lib/emf/emr/binary/records/flatten_path.rb +16 -0
  51. data/lib/emf/emr/binary/records/force_ufi_mapping.rb +17 -0
  52. data/lib/emf/emr/binary/records/frame_rgn.rb +17 -0
  53. data/lib/emf/emr/binary/records/gls_bounded_record.rb +17 -0
  54. data/lib/emf/emr/binary/records/gls_record.rb +17 -0
  55. data/lib/emf/emr/binary/records/gradient_fill.rb +19 -0
  56. data/lib/emf/emr/binary/records/intersect_clip_rect.rb +16 -0
  57. data/lib/emf/emr/binary/records/invert_rgn.rb +17 -0
  58. data/lib/emf/emr/binary/records/line_to.rb +16 -0
  59. data/lib/emf/emr/binary/records/mask_blt.rb +17 -0
  60. data/lib/emf/emr/binary/records/modify_world_transform.rb +17 -0
  61. data/lib/emf/emr/binary/records/move_to_ex.rb +16 -0
  62. data/lib/emf/emr/binary/records/named_escape.rb +17 -0
  63. data/lib/emf/emr/binary/records/offset_clip_rgn.rb +16 -0
  64. data/lib/emf/emr/binary/records/paint_rgn.rb +17 -0
  65. data/lib/emf/emr/binary/records/pie.rb +19 -0
  66. data/lib/emf/emr/binary/records/pixel_format.rb +17 -0
  67. data/lib/emf/emr/binary/records/plg_blt.rb +17 -0
  68. data/lib/emf/emr/binary/records/poly_bezier.rb +17 -0
  69. data/lib/emf/emr/binary/records/poly_bezier16.rb +17 -0
  70. data/lib/emf/emr/binary/records/poly_bezier_to.rb +17 -0
  71. data/lib/emf/emr/binary/records/poly_bezier_to16.rb +17 -0
  72. data/lib/emf/emr/binary/records/poly_draw.rb +18 -0
  73. data/lib/emf/emr/binary/records/poly_draw16.rb +18 -0
  74. data/lib/emf/emr/binary/records/poly_polygon.rb +19 -0
  75. data/lib/emf/emr/binary/records/poly_polygon16.rb +19 -0
  76. data/lib/emf/emr/binary/records/poly_polyline.rb +19 -0
  77. data/lib/emf/emr/binary/records/poly_polyline16.rb +19 -0
  78. data/lib/emf/emr/binary/records/poly_textout_a.rb +17 -0
  79. data/lib/emf/emr/binary/records/poly_textout_w.rb +17 -0
  80. data/lib/emf/emr/binary/records/polygon.rb +17 -0
  81. data/lib/emf/emr/binary/records/polygon16.rb +17 -0
  82. data/lib/emf/emr/binary/records/polyline.rb +17 -0
  83. data/lib/emf/emr/binary/records/polyline16.rb +17 -0
  84. data/lib/emf/emr/binary/records/polyline_to.rb +17 -0
  85. data/lib/emf/emr/binary/records/polyline_to16.rb +17 -0
  86. data/lib/emf/emr/binary/records/raw.rb +19 -0
  87. data/lib/emf/emr/binary/records/realize_palette.rb +15 -0
  88. data/lib/emf/emr/binary/records/rectangle.rb +18 -0
  89. data/lib/emf/emr/binary/records/resize_palette.rb +17 -0
  90. data/lib/emf/emr/binary/records/restore_dc.rb +17 -0
  91. data/lib/emf/emr/binary/records/round_rect.rb +19 -0
  92. data/lib/emf/emr/binary/records/save_dc.rb +16 -0
  93. data/lib/emf/emr/binary/records/scale_viewport_ext_ex.rb +19 -0
  94. data/lib/emf/emr/binary/records/scale_window_ext_ex.rb +19 -0
  95. data/lib/emf/emr/binary/records/select_clip_path.rb +20 -0
  96. data/lib/emf/emr/binary/records/select_object.rb +16 -0
  97. data/lib/emf/emr/binary/records/select_palette.rb +16 -0
  98. data/lib/emf/emr/binary/records/set_arc_direction.rb +16 -0
  99. data/lib/emf/emr/binary/records/set_bk_color.rb +16 -0
  100. data/lib/emf/emr/binary/records/set_bk_mode.rb +16 -0
  101. data/lib/emf/emr/binary/records/set_brush_org_ex.rb +16 -0
  102. data/lib/emf/emr/binary/records/set_colorspace.rb +17 -0
  103. data/lib/emf/emr/binary/records/set_dibits_to_device.rb +17 -0
  104. data/lib/emf/emr/binary/records/set_icm_mode.rb +16 -0
  105. data/lib/emf/emr/binary/records/set_icm_profile_a.rb +17 -0
  106. data/lib/emf/emr/binary/records/set_icm_profile_w.rb +17 -0
  107. data/lib/emf/emr/binary/records/set_layout.rb +16 -0
  108. data/lib/emf/emr/binary/records/set_linked_ufis.rb +17 -0
  109. data/lib/emf/emr/binary/records/set_map_mode.rb +16 -0
  110. data/lib/emf/emr/binary/records/set_mapper_flags.rb +16 -0
  111. data/lib/emf/emr/binary/records/set_metargn.rb +16 -0
  112. data/lib/emf/emr/binary/records/set_miter_limit.rb +16 -0
  113. data/lib/emf/emr/binary/records/set_palette_entries.rb +17 -0
  114. data/lib/emf/emr/binary/records/set_pixel_v.rb +18 -0
  115. data/lib/emf/emr/binary/records/set_poly_fill_mode.rb +16 -0
  116. data/lib/emf/emr/binary/records/set_rop2.rb +16 -0
  117. data/lib/emf/emr/binary/records/set_stretch_blt_mode.rb +16 -0
  118. data/lib/emf/emr/binary/records/set_text_align.rb +16 -0
  119. data/lib/emf/emr/binary/records/set_text_color.rb +17 -0
  120. data/lib/emf/emr/binary/records/set_text_justification.rb +17 -0
  121. data/lib/emf/emr/binary/records/set_viewport_ext_ex.rb +16 -0
  122. data/lib/emf/emr/binary/records/set_viewport_org_ex.rb +16 -0
  123. data/lib/emf/emr/binary/records/set_window_ext_ex.rb +16 -0
  124. data/lib/emf/emr/binary/records/set_window_org_ex.rb +16 -0
  125. data/lib/emf/emr/binary/records/set_world_transform.rb +16 -0
  126. data/lib/emf/emr/binary/records/small_text_out.rb +28 -0
  127. data/lib/emf/emr/binary/records/stretch_blt.rb +39 -0
  128. data/lib/emf/emr/binary/records/stretch_dibits.rb +42 -0
  129. data/lib/emf/emr/binary/records/stroke_and_fill_path.rb +16 -0
  130. data/lib/emf/emr/binary/records/stroke_path.rb +16 -0
  131. data/lib/emf/emr/binary/records/transparent_blt.rb +17 -0
  132. data/lib/emf/emr/binary/records/widen_path.rb +16 -0
  133. data/lib/emf/emr/binary/records.rb +258 -0
  134. data/lib/emf/emr/binary/type_codes.rb +132 -0
  135. data/lib/emf/emr/binary/with_bounds.rb +15 -0
  136. data/lib/emf/emr/binary.rb +13 -0
  137. data/lib/emf/emr/parser.rb +185 -0
  138. data/lib/emf/emr/path_association.rb +16 -0
  139. data/lib/emf/emr/serializer.rb +24 -0
  140. data/lib/emf/emr.rb +10 -0
  141. data/lib/emf/error.rb +19 -0
  142. data/lib/emf/model/emr/header.rb +93 -0
  143. data/lib/emf/model/emr/records.rb +48 -0
  144. data/lib/emf/model/emr.rb +10 -0
  145. data/lib/emf/model/geometry/color.rb +67 -0
  146. data/lib/emf/model/geometry/matrix.rb +52 -0
  147. data/lib/emf/model/geometry/point.rb +41 -0
  148. data/lib/emf/model/geometry/point_f.rb +33 -0
  149. data/lib/emf/model/geometry/point_s.rb +33 -0
  150. data/lib/emf/model/geometry/rect.rb +57 -0
  151. data/lib/emf/model/geometry/rect_s.rb +49 -0
  152. data/lib/emf/model/geometry/size.rb +33 -0
  153. data/lib/emf/model/geometry.rb +16 -0
  154. data/lib/emf/model/metafile.rb +34 -0
  155. data/lib/emf/model/record.rb +19 -0
  156. data/lib/emf/model/visitor.rb +42 -0
  157. data/lib/emf/model.rb +11 -0
  158. data/lib/emf/version.rb +5 -0
  159. data/lib/emf/visitors/dump.rb +57 -0
  160. data/lib/emf/visitors/stats.rb +63 -0
  161. data/lib/emf/visitors.rb +8 -0
  162. data/lib/emf/wmf/binary.rb +9 -0
  163. data/lib/emf/wmf/parser.rb +13 -0
  164. data/lib/emf/wmf/serializer.rb +13 -0
  165. data/lib/emf/wmf.rb +9 -0
  166. data/lib/emf.rb +56 -0
  167. metadata +226 -0
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emf
4
+ module Model
5
+ module Geometry
6
+ class RectS
7
+ def initialize(left:, top:, right:, bottom:)
8
+ @left = left
9
+ @top = top
10
+ @right = right
11
+ @bottom = bottom
12
+ end
13
+
14
+ attr_reader :left, :top, :right, :bottom
15
+
16
+ def self.from_wire(wire)
17
+ new(left: wire.left, top: wire.top, right: wire.right, bottom: wire.bottom)
18
+ end
19
+
20
+ def to_wire
21
+ Binary::Types::RectS.new(left: left, top: top, right: right, bottom: bottom)
22
+ end
23
+
24
+ def width
25
+ right - left
26
+ end
27
+
28
+ def height
29
+ bottom - top
30
+ end
31
+
32
+ def empty?
33
+ width <= 0 || height <= 0
34
+ end
35
+
36
+ def ==(other)
37
+ other.is_a?(self.class) &&
38
+ left == other.left && top == other.top &&
39
+ right == other.right && bottom == other.bottom
40
+ end
41
+ alias eql? ==
42
+
43
+ def hash
44
+ [self.class, left, top, right, bottom].hash
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emf
4
+ module Model
5
+ module Geometry
6
+ class Size
7
+ def initialize(cx:, cy:)
8
+ @cx = cx
9
+ @cy = cy
10
+ end
11
+
12
+ attr_reader :cx, :cy
13
+
14
+ def self.from_wire(wire)
15
+ new(cx: wire.cx, cy: wire.cy)
16
+ end
17
+
18
+ def to_wire
19
+ Binary::Types::SizeL.new(cx: cx, cy: cy)
20
+ end
21
+
22
+ def ==(other)
23
+ other.is_a?(self.class) && cx == other.cx && cy == other.cy
24
+ end
25
+ alias eql? ==
26
+
27
+ def hash
28
+ [self.class, cx, cy].hash
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emf
4
+ module Model
5
+ module Geometry
6
+ autoload :Point, "emf/model/geometry/point"
7
+ autoload :PointF, "emf/model/geometry/point_f"
8
+ autoload :PointS, "emf/model/geometry/point_s"
9
+ autoload :Size, "emf/model/geometry/size"
10
+ autoload :Rect, "emf/model/geometry/rect"
11
+ autoload :RectS, "emf/model/geometry/rect_s"
12
+ autoload :Color, "emf/model/geometry/color"
13
+ autoload :Matrix, "emf/model/geometry/matrix"
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emf
4
+ module Model
5
+ class Metafile
6
+ include Enumerable
7
+
8
+ def initialize(format:, header:, records:, errors: [], emf_plus: nil, trailing: "")
9
+ @format = format
10
+ @header = header
11
+ @records = records.freeze
12
+ @errors = errors.freeze
13
+ @emf_plus = emf_plus
14
+ @trailing = trailing.freeze
15
+ end
16
+
17
+ attr_reader :format, :header, :records, :errors, :emf_plus, :trailing
18
+
19
+ def each(&block)
20
+ return to_enum unless block
21
+
22
+ @records.each(&block)
23
+ end
24
+
25
+ def errors?
26
+ !@errors.empty?
27
+ end
28
+
29
+ def ok?
30
+ @errors.empty?
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emf
4
+ module Model
5
+ class Record
6
+ def type_id
7
+ raise NotImplementedError, "subclass must return the integer record type code"
8
+ end
9
+
10
+ def accept(_visitor)
11
+ raise NotImplementedError, "subclass must implement #accept(visitor)"
12
+ end
13
+
14
+ def inspect
15
+ "#<#{self.class.name} type_id=#{type_id}>"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emf
4
+ module Model
5
+ class Visitor
6
+ @visit_methods = {}
7
+
8
+ class << self
9
+ # Record classes call this to declare a visit method name.
10
+ # The base class installs a no-op default so subclasses can override
11
+ # only what they need.
12
+ def register_visit(name, record_class)
13
+ @visit_methods[name] = record_class
14
+ return if method_defined?(name)
15
+
16
+ define_method(name) { |_| nil }
17
+ end
18
+
19
+ attr_reader :visit_methods
20
+
21
+ # Walk every record in the metafile (and a nested EMF+ sub-stream if any),
22
+ # dispatching to the matching visit_* method.
23
+ def visit_all(visitor, metafile)
24
+ metafile.each { |record| record.accept(visitor) }
25
+ nested = metafile.emf_plus
26
+ visit_all(visitor, nested) if nested.is_a?(Emf::Model::Metafile)
27
+ visitor
28
+ end
29
+ end
30
+
31
+ def visit(record)
32
+ record.accept(self)
33
+ self
34
+ end
35
+
36
+ def visit_all(metafile)
37
+ self.class.visit_all(self, metafile)
38
+ self
39
+ end
40
+ end
41
+ end
42
+ end
data/lib/emf/model.rb ADDED
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emf
4
+ module Model
5
+ autoload :Metafile, "emf/model/metafile"
6
+ autoload :Record, "emf/model/record"
7
+ autoload :Visitor, "emf/model/visitor"
8
+ autoload :Geometry, "emf/model/geometry"
9
+ autoload :Emr, "emf/model/emr"
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emf
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emf
4
+ module Visitors
5
+ # Human-readable record-by-record dump. Used by `emf dump` (TODO 19)
6
+ # and as a debugging tool.
7
+ class Dump < Emf::Model::Visitor
8
+ def initialize
9
+ @lines = []
10
+ end
11
+
12
+ attr_reader :lines
13
+
14
+ def to_s
15
+ @lines.join("\n")
16
+ end
17
+
18
+ def visit(record)
19
+ record.accept(self)
20
+ self
21
+ end
22
+
23
+ def visit_all(metafile)
24
+ @lines << format("Metafile format=%s records=%d errors=%d",
25
+ metafile.format, metafile.records.length, metafile.errors.length)
26
+ header = metafile.header
27
+ @lines << " Header: #{header.class}" if header
28
+ metafile.each { |record| record.accept(self) }
29
+ metafile.errors.each { |e| @lines << " Error: #{e.message}" }
30
+ self
31
+ end
32
+
33
+ def visit_emr_wire_record(adapter)
34
+ wire = adapter.wire
35
+ @lines << " rec[#{adapter.offset}] type_id=#{adapter.type_id} #{wire.class.name&.split('::')&.last}"
36
+ end
37
+
38
+ def method_missing(name, *args)
39
+ return super unless name.to_s.start_with?("visit_")
40
+
41
+ record = args.first
42
+ return unless record
43
+
44
+ type_id = begin
45
+ record.type_id
46
+ rescue StandardError
47
+ nil
48
+ end
49
+ @lines << format(" rec: %s type_id=%s", record.class.name&.split("::")&.last, type_id)
50
+ end
51
+
52
+ def respond_to_missing?(name, _include_private = false)
53
+ name.to_s.start_with?("visit_") || super
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emf
4
+ module Visitors
5
+ # Produces a record-class histogram for a Metafile. Used by spec assertions
6
+ # (TODO 16) and as a quick sanity-check dump via `emf stats` (TODO 19).
7
+ #
8
+ # The base Visitor auto-registers `visit_*` methods as no-ops. Stats
9
+ # overrides the generic dispatch to tally every record by its class name.
10
+ # Subclasses that override specific visit_* methods for richer behaviour
11
+ # still get tallied here because the record's accept calls the visit_*
12
+ # method, which (if not overridden) calls method_missing -> tally.
13
+ class Stats < Emf::Model::Visitor
14
+ def initialize
15
+ @counts = Hash.new(0)
16
+ end
17
+
18
+ attr_reader :counts
19
+
20
+ def histogram
21
+ @counts.sort.to_h
22
+ end
23
+
24
+ def total
25
+ @counts.values.sum
26
+ end
27
+
28
+ def to_s
29
+ lines = ["Total: #{total}", ""]
30
+ histogram.each { |klass, count| lines << format("%6d %s", count, klass) }
31
+ lines.join("\n")
32
+ end
33
+
34
+ def visit(record)
35
+ record.accept(self)
36
+ self
37
+ end
38
+
39
+ def visit_all(metafile)
40
+ metafile.each { |record| record.accept(self) }
41
+ self
42
+ end
43
+
44
+ # WireAdapter is the catch-all for unknown record types. Tally by the
45
+ # underlying wire class so the histogram is informative.
46
+ def visit_emr_wire_record(adapter)
47
+ wire_class = adapter.wire.class.name&.split("::")&.last || "Raw"
48
+ @counts["WireAdapter(#{wire_class})"] += 1
49
+ end
50
+
51
+ def method_missing(name, *args)
52
+ return super unless name.to_s.start_with?("visit_")
53
+
54
+ record = args.first
55
+ @counts[record.class.name&.split("::")&.last || record.class.to_s] += 1 if record
56
+ end
57
+
58
+ def respond_to_missing?(name, _include_private = false)
59
+ name.to_s.start_with?("visit_") || super
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emf
4
+ module Visitors
5
+ autoload :Stats, "emf/visitors/stats"
6
+ autoload :Dump, "emf/visitors/dump"
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Placeholder until TODO.impl/07-wmf-wire-domain-parser.md.
4
+ module Emf
5
+ module Wmf
6
+ module Binary
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emf
4
+ module Wmf
5
+ module Parser
6
+ module_function
7
+
8
+ def call(_bytes)
9
+ raise Error, "WMF parser not yet implemented — see TODO.impl/07-wmf-wire-domain-parser.md"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emf
4
+ module Wmf
5
+ module Serializer
6
+ module_function
7
+
8
+ def call(_metafile)
9
+ raise SerializeError, "WMF serializer not yet implemented — see TODO.impl/07-wmf-wire-domain-parser.md"
10
+ end
11
+ end
12
+ end
13
+ end
data/lib/emf/wmf.rb ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emf
4
+ module Wmf
5
+ autoload :Parser, "emf/wmf/parser"
6
+ autoload :Serializer, "emf/wmf/serializer"
7
+ autoload :Binary, "emf/wmf/binary"
8
+ end
9
+ end
data/lib/emf.rb ADDED
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bindata"
4
+
5
+ module Emf
6
+ autoload :VERSION, "emf/version"
7
+ autoload :Error, "emf/error"
8
+ autoload :FormatError, "emf/error"
9
+ autoload :ParseError, "emf/error"
10
+ autoload :SerializeError, "emf/error"
11
+ autoload :Detector, "emf/detector"
12
+ autoload :Binary, "emf/binary"
13
+ autoload :Model, "emf/model"
14
+ autoload :Visitors, "emf/visitors"
15
+ autoload :Wmf, "emf/wmf"
16
+ autoload :Emr, "emf/emr"
17
+ autoload :EmfPlus, "emf/emf_plus"
18
+
19
+ class << self
20
+ def parse(bytes)
21
+ case Detector.call(bytes)
22
+ when :wmf_apm, :wmf_standard then Wmf::Parser.call(bytes)
23
+ when :emf then Emr::Parser.call(bytes)
24
+ end
25
+ end
26
+
27
+ def parse_file(path)
28
+ parse(File.read(path, mode: "rb"))
29
+ end
30
+
31
+ def serialize(metafile)
32
+ case metafile.format
33
+ when :wmf then Wmf::Serializer.call(metafile)
34
+ when :emf, :emf_plus then Emr::Serializer.call(metafile)
35
+ else raise SerializeError, "unknown format: #{metafile.format.inspect}"
36
+ end
37
+ end
38
+
39
+ def serialize_file(metafile, path)
40
+ File.binwrite(path, serialize(metafile))
41
+ end
42
+
43
+ def detect_format(bytes)
44
+ case Detector.call(bytes)
45
+ when :wmf_apm, :wmf_standard then :wmf
46
+ when :emf then :emf
47
+ end
48
+ end
49
+ end
50
+
51
+ # Eager-load the shared bindata primitives so that BinData::RegisteredClasses
52
+ # knows about `rectl`, `point_l`, `color_ref`, etc. before any record class
53
+ # is autoloaded. Referencing the constant triggers the autoload of
54
+ # emf/binary/types, which calls register() for each primitive.
55
+ Binary::Types
56
+ end
metadata ADDED
@@ -0,0 +1,226 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: emf
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ribose Inc.
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: bindata
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '2.4'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '2.4'
26
+ description: Pure-Ruby parser for Windows Metafile (WMF), Enhanced Metafile (EMF),
27
+ and EMF+ binary formats. Produces an OOP domain model that downstream gems (such
28
+ as emfsvg) consume.
29
+ email:
30
+ - open.source@ribose.com
31
+ executables:
32
+ - emf
33
+ extensions: []
34
+ extra_rdoc_files: []
35
+ files:
36
+ - LICENSE.txt
37
+ - README.adoc
38
+ - exe/emf
39
+ - lib/emf.rb
40
+ - lib/emf/binary.rb
41
+ - lib/emf/binary/codec.rb
42
+ - lib/emf/binary/types.rb
43
+ - lib/emf/detector.rb
44
+ - lib/emf/emf_plus.rb
45
+ - lib/emf/emf_plus/binary.rb
46
+ - lib/emf/emf_plus/parser.rb
47
+ - lib/emf/emf_plus/serializer.rb
48
+ - lib/emf/emr.rb
49
+ - lib/emf/emr/binary.rb
50
+ - lib/emf/emr/binary/header.rb
51
+ - lib/emf/emr/binary/record.rb
52
+ - lib/emf/emr/binary/records.rb
53
+ - lib/emf/emr/binary/records/abort_path.rb
54
+ - lib/emf/emr/binary/records/alpha_blend.rb
55
+ - lib/emf/emr/binary/records/angle_arc.rb
56
+ - lib/emf/emr/binary/records/arc.rb
57
+ - lib/emf/emr/binary/records/arc_to.rb
58
+ - lib/emf/emr/binary/records/begin_path.rb
59
+ - lib/emf/emr/binary/records/bit_blt.rb
60
+ - lib/emf/emr/binary/records/chord.rb
61
+ - lib/emf/emr/binary/records/close_figure.rb
62
+ - lib/emf/emr/binary/records/color_correct_palette.rb
63
+ - lib/emf/emr/binary/records/colormatch_to_target_w.rb
64
+ - lib/emf/emr/binary/records/comment.rb
65
+ - lib/emf/emr/binary/records/create_brush_indirect.rb
66
+ - lib/emf/emr/binary/records/create_colorspace.rb
67
+ - lib/emf/emr/binary/records/create_colorspace_w.rb
68
+ - lib/emf/emr/binary/records/create_dib_pattern_brush_pt.rb
69
+ - lib/emf/emr/binary/records/create_font_indirect_w.rb
70
+ - lib/emf/emr/binary/records/create_mono_brush.rb
71
+ - lib/emf/emr/binary/records/create_palette.rb
72
+ - lib/emf/emr/binary/records/create_pen.rb
73
+ - lib/emf/emr/binary/records/delete_colorspace.rb
74
+ - lib/emf/emr/binary/records/delete_object.rb
75
+ - lib/emf/emr/binary/records/draw_escape.rb
76
+ - lib/emf/emr/binary/records/ellipse.rb
77
+ - lib/emf/emr/binary/records/end_path.rb
78
+ - lib/emf/emr/binary/records/eof.rb
79
+ - lib/emf/emr/binary/records/exclude_clip_rect.rb
80
+ - lib/emf/emr/binary/records/ext_create_pen.rb
81
+ - lib/emf/emr/binary/records/ext_escape.rb
82
+ - lib/emf/emr/binary/records/ext_flood_fill.rb
83
+ - lib/emf/emr/binary/records/ext_select_clip_rgn.rb
84
+ - lib/emf/emr/binary/records/ext_text_out_a.rb
85
+ - lib/emf/emr/binary/records/ext_text_out_w.rb
86
+ - lib/emf/emr/binary/records/fill_path.rb
87
+ - lib/emf/emr/binary/records/fill_rgn.rb
88
+ - lib/emf/emr/binary/records/flatten_path.rb
89
+ - lib/emf/emr/binary/records/force_ufi_mapping.rb
90
+ - lib/emf/emr/binary/records/frame_rgn.rb
91
+ - lib/emf/emr/binary/records/gls_bounded_record.rb
92
+ - lib/emf/emr/binary/records/gls_record.rb
93
+ - lib/emf/emr/binary/records/gradient_fill.rb
94
+ - lib/emf/emr/binary/records/intersect_clip_rect.rb
95
+ - lib/emf/emr/binary/records/invert_rgn.rb
96
+ - lib/emf/emr/binary/records/line_to.rb
97
+ - lib/emf/emr/binary/records/mask_blt.rb
98
+ - lib/emf/emr/binary/records/modify_world_transform.rb
99
+ - lib/emf/emr/binary/records/move_to_ex.rb
100
+ - lib/emf/emr/binary/records/named_escape.rb
101
+ - lib/emf/emr/binary/records/offset_clip_rgn.rb
102
+ - lib/emf/emr/binary/records/paint_rgn.rb
103
+ - lib/emf/emr/binary/records/pie.rb
104
+ - lib/emf/emr/binary/records/pixel_format.rb
105
+ - lib/emf/emr/binary/records/plg_blt.rb
106
+ - lib/emf/emr/binary/records/poly_bezier.rb
107
+ - lib/emf/emr/binary/records/poly_bezier16.rb
108
+ - lib/emf/emr/binary/records/poly_bezier_to.rb
109
+ - lib/emf/emr/binary/records/poly_bezier_to16.rb
110
+ - lib/emf/emr/binary/records/poly_draw.rb
111
+ - lib/emf/emr/binary/records/poly_draw16.rb
112
+ - lib/emf/emr/binary/records/poly_polygon.rb
113
+ - lib/emf/emr/binary/records/poly_polygon16.rb
114
+ - lib/emf/emr/binary/records/poly_polyline.rb
115
+ - lib/emf/emr/binary/records/poly_polyline16.rb
116
+ - lib/emf/emr/binary/records/poly_textout_a.rb
117
+ - lib/emf/emr/binary/records/poly_textout_w.rb
118
+ - lib/emf/emr/binary/records/polygon.rb
119
+ - lib/emf/emr/binary/records/polygon16.rb
120
+ - lib/emf/emr/binary/records/polyline.rb
121
+ - lib/emf/emr/binary/records/polyline16.rb
122
+ - lib/emf/emr/binary/records/polyline_to.rb
123
+ - lib/emf/emr/binary/records/polyline_to16.rb
124
+ - lib/emf/emr/binary/records/raw.rb
125
+ - lib/emf/emr/binary/records/realize_palette.rb
126
+ - lib/emf/emr/binary/records/rectangle.rb
127
+ - lib/emf/emr/binary/records/resize_palette.rb
128
+ - lib/emf/emr/binary/records/restore_dc.rb
129
+ - lib/emf/emr/binary/records/round_rect.rb
130
+ - lib/emf/emr/binary/records/save_dc.rb
131
+ - lib/emf/emr/binary/records/scale_viewport_ext_ex.rb
132
+ - lib/emf/emr/binary/records/scale_window_ext_ex.rb
133
+ - lib/emf/emr/binary/records/select_clip_path.rb
134
+ - lib/emf/emr/binary/records/select_object.rb
135
+ - lib/emf/emr/binary/records/select_palette.rb
136
+ - lib/emf/emr/binary/records/set_arc_direction.rb
137
+ - lib/emf/emr/binary/records/set_bk_color.rb
138
+ - lib/emf/emr/binary/records/set_bk_mode.rb
139
+ - lib/emf/emr/binary/records/set_brush_org_ex.rb
140
+ - lib/emf/emr/binary/records/set_colorspace.rb
141
+ - lib/emf/emr/binary/records/set_dibits_to_device.rb
142
+ - lib/emf/emr/binary/records/set_icm_mode.rb
143
+ - lib/emf/emr/binary/records/set_icm_profile_a.rb
144
+ - lib/emf/emr/binary/records/set_icm_profile_w.rb
145
+ - lib/emf/emr/binary/records/set_layout.rb
146
+ - lib/emf/emr/binary/records/set_linked_ufis.rb
147
+ - lib/emf/emr/binary/records/set_map_mode.rb
148
+ - lib/emf/emr/binary/records/set_mapper_flags.rb
149
+ - lib/emf/emr/binary/records/set_metargn.rb
150
+ - lib/emf/emr/binary/records/set_miter_limit.rb
151
+ - lib/emf/emr/binary/records/set_palette_entries.rb
152
+ - lib/emf/emr/binary/records/set_pixel_v.rb
153
+ - lib/emf/emr/binary/records/set_poly_fill_mode.rb
154
+ - lib/emf/emr/binary/records/set_rop2.rb
155
+ - lib/emf/emr/binary/records/set_stretch_blt_mode.rb
156
+ - lib/emf/emr/binary/records/set_text_align.rb
157
+ - lib/emf/emr/binary/records/set_text_color.rb
158
+ - lib/emf/emr/binary/records/set_text_justification.rb
159
+ - lib/emf/emr/binary/records/set_viewport_ext_ex.rb
160
+ - lib/emf/emr/binary/records/set_viewport_org_ex.rb
161
+ - lib/emf/emr/binary/records/set_window_ext_ex.rb
162
+ - lib/emf/emr/binary/records/set_window_org_ex.rb
163
+ - lib/emf/emr/binary/records/set_world_transform.rb
164
+ - lib/emf/emr/binary/records/small_text_out.rb
165
+ - lib/emf/emr/binary/records/stretch_blt.rb
166
+ - lib/emf/emr/binary/records/stretch_dibits.rb
167
+ - lib/emf/emr/binary/records/stroke_and_fill_path.rb
168
+ - lib/emf/emr/binary/records/stroke_path.rb
169
+ - lib/emf/emr/binary/records/transparent_blt.rb
170
+ - lib/emf/emr/binary/records/widen_path.rb
171
+ - lib/emf/emr/binary/type_codes.rb
172
+ - lib/emf/emr/binary/with_bounds.rb
173
+ - lib/emf/emr/parser.rb
174
+ - lib/emf/emr/path_association.rb
175
+ - lib/emf/emr/serializer.rb
176
+ - lib/emf/error.rb
177
+ - lib/emf/model.rb
178
+ - lib/emf/model/emr.rb
179
+ - lib/emf/model/emr/header.rb
180
+ - lib/emf/model/emr/records.rb
181
+ - lib/emf/model/geometry.rb
182
+ - lib/emf/model/geometry/color.rb
183
+ - lib/emf/model/geometry/matrix.rb
184
+ - lib/emf/model/geometry/point.rb
185
+ - lib/emf/model/geometry/point_f.rb
186
+ - lib/emf/model/geometry/point_s.rb
187
+ - lib/emf/model/geometry/rect.rb
188
+ - lib/emf/model/geometry/rect_s.rb
189
+ - lib/emf/model/geometry/size.rb
190
+ - lib/emf/model/metafile.rb
191
+ - lib/emf/model/record.rb
192
+ - lib/emf/model/visitor.rb
193
+ - lib/emf/version.rb
194
+ - lib/emf/visitors.rb
195
+ - lib/emf/visitors/dump.rb
196
+ - lib/emf/visitors/stats.rb
197
+ - lib/emf/wmf.rb
198
+ - lib/emf/wmf/binary.rb
199
+ - lib/emf/wmf/parser.rb
200
+ - lib/emf/wmf/serializer.rb
201
+ homepage: https://github.com/claricle/emf
202
+ licenses:
203
+ - BSD-2-Clause
204
+ metadata:
205
+ homepage_uri: https://github.com/claricle/emf
206
+ source_code_uri: https://github.com/claricle/emf
207
+ changelog_uri: https://github.com/claricle/emf/blob/main/CHANGELOG.adoc
208
+ rubygems_mfa_required: 'true'
209
+ rdoc_options: []
210
+ require_paths:
211
+ - lib
212
+ required_ruby_version: !ruby/object:Gem::Requirement
213
+ requirements:
214
+ - - ">="
215
+ - !ruby/object:Gem::Version
216
+ version: 3.1.0
217
+ required_rubygems_version: !ruby/object:Gem::Requirement
218
+ requirements:
219
+ - - ">="
220
+ - !ruby/object:Gem::Version
221
+ version: '0'
222
+ requirements: []
223
+ rubygems_version: 4.0.16
224
+ specification_version: 4
225
+ summary: Pure-Ruby parser for WMF, EMF, and EMF+ metafiles.
226
+ test_files: []