emf 0.1.2 → 0.2.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 (360) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +224 -19
  3. data/exe/emf +12 -0
  4. data/lib/emf/backend.rb +60 -0
  5. data/lib/emf/binary/class_field_accessors.rb +49 -0
  6. data/lib/emf/binary/float32_le.rb +54 -0
  7. data/lib/emf/binary/types.rb +40 -6
  8. data/lib/emf/conformance/context.rb +36 -0
  9. data/lib/emf/conformance/diagnostic.rb +18 -0
  10. data/lib/emf/conformance/manifest/emf_bitmap_misc.yml +622 -0
  11. data/lib/emf/conformance/manifest/emf_control_buffers.yml +61 -0
  12. data/lib/emf/conformance/manifest/emf_core.yml +117 -0
  13. data/lib/emf/conformance/manifest/emf_corpus_rules.yml +21 -0
  14. data/lib/emf/conformance/manifest/emf_objects_geometry.yml +229 -0
  15. data/lib/emf/conformance/manifest/emf_plus.yml +357 -0
  16. data/lib/emf/conformance/manifest/emf_plus_core.yml +33 -0
  17. data/lib/emf/conformance/manifest/emf_state_path.yml +403 -0
  18. data/lib/emf/conformance/manifest/emf_text.yml +97 -0
  19. data/lib/emf/conformance/manifest/wmf.yml +874 -0
  20. data/lib/emf/conformance/manifest.rb +79 -0
  21. data/lib/emf/conformance/profile.rb +35 -0
  22. data/lib/emf/conformance/record_types.rb +24 -0
  23. data/lib/emf/conformance/registry.rb +76 -0
  24. data/lib/emf/conformance/report.rb +83 -0
  25. data/lib/emf/conformance/rule.rb +16 -0
  26. data/lib/emf/conformance/rules/emf_bitmap.rb +357 -0
  27. data/lib/emf/conformance/rules/emf_comment_escape.rb +309 -0
  28. data/lib/emf/conformance/rules/emf_control_buffers.rb +137 -0
  29. data/lib/emf/conformance/rules/emf_corpus_named.rb +83 -0
  30. data/lib/emf/conformance/rules/emf_framing.rb +94 -0
  31. data/lib/emf/conformance/rules/emf_geometry.rb +282 -0
  32. data/lib/emf/conformance/rules/emf_header.rb +114 -0
  33. data/lib/emf/conformance/rules/emf_objects.rb +291 -0
  34. data/lib/emf/conformance/rules/emf_parse_recovery.rb +97 -0
  35. data/lib/emf/conformance/rules/emf_path_clip.rb +165 -0
  36. data/lib/emf/conformance/rules/emf_plus.rb +75 -0
  37. data/lib/emf/conformance/rules/emf_plus_common.rb +58 -0
  38. data/lib/emf/conformance/rules/emf_plus_drawing.rb +78 -0
  39. data/lib/emf/conformance/rules/emf_plus_effects.rb +104 -0
  40. data/lib/emf/conformance/rules/emf_plus_fields.rb +169 -0
  41. data/lib/emf/conformance/rules/emf_plus_fields_b.rb +102 -0
  42. data/lib/emf/conformance/rules/emf_plus_framing.rb +172 -0
  43. data/lib/emf/conformance/rules/emf_plus_objects.rb +97 -0
  44. data/lib/emf/conformance/rules/emf_plus_payloads.rb +320 -0
  45. data/lib/emf/conformance/rules/emf_plus_properties.rb +96 -0
  46. data/lib/emf/conformance/rules/emf_plus_state.rb +77 -0
  47. data/lib/emf/conformance/rules/emf_state.rb +244 -0
  48. data/lib/emf/conformance/rules/emf_text.rb +221 -0
  49. data/lib/emf/conformance/rules/emf_transform.rb +85 -0
  50. data/lib/emf/conformance/rules/wmf_buffers.rb +259 -0
  51. data/lib/emf/conformance/rules/wmf_framing.rb +146 -0
  52. data/lib/emf/conformance/rules/wmf_layout_records.rb +112 -0
  53. data/lib/emf/conformance/rules/wmf_objects.rb +168 -0
  54. data/lib/emf/conformance/rules/wmf_records.rb +191 -0
  55. data/lib/emf/conformance/rules/wmf_rejections.rb +184 -0
  56. data/lib/emf/conformance/runner.rb +61 -0
  57. data/lib/emf/conformance/ternary_raster_operations.rb +52 -0
  58. data/lib/emf/conformance.rb +31 -0
  59. data/lib/emf/emf_plus/effects/blur.rb +24 -0
  60. data/lib/emf/emf_plus/effects/brightness_contrast.rb +22 -0
  61. data/lib/emf/emf_plus/effects/color_balance.rb +24 -0
  62. data/lib/emf/emf_plus/effects/color_curve.rb +24 -0
  63. data/lib/emf/emf_plus/effects/color_lookup_table.rb +26 -0
  64. data/lib/emf/emf_plus/effects/color_matrix.rb +23 -0
  65. data/lib/emf/emf_plus/effects/effect.rb +50 -0
  66. data/lib/emf/emf_plus/effects/hue_saturation_lightness.rb +24 -0
  67. data/lib/emf/emf_plus/effects/levels.rb +24 -0
  68. data/lib/emf/emf_plus/effects/opaque.rb +19 -0
  69. data/lib/emf/emf_plus/effects/red_eye_correction.rb +35 -0
  70. data/lib/emf/emf_plus/effects/sharpen.rb +24 -0
  71. data/lib/emf/emf_plus/effects/tint.rb +22 -0
  72. data/lib/emf/emf_plus/effects.rb +45 -0
  73. data/lib/emf/emf_plus/frame.rb +41 -0
  74. data/lib/emf/emf_plus/links/effect_link.rb +16 -0
  75. data/lib/emf/emf_plus/links/get_dc_span.rb +18 -0
  76. data/lib/emf/emf_plus/links/link_error.rb +15 -0
  77. data/lib/emf/emf_plus/links.rb +77 -0
  78. data/lib/emf/emf_plus/object_chain.rb +108 -0
  79. data/lib/emf/emf_plus/object_table.rb +182 -0
  80. data/lib/emf/emf_plus/objects/brush.rb +296 -0
  81. data/lib/emf/emf_plus/objects/custom_line_cap.rb +106 -0
  82. data/lib/emf/emf_plus/objects/font.rb +47 -0
  83. data/lib/emf/emf_plus/objects/image.rb +68 -0
  84. data/lib/emf/emf_plus/objects/image_attributes.rb +28 -0
  85. data/lib/emf/emf_plus/objects/opaque.rb +19 -0
  86. data/lib/emf/emf_plus/objects/parts.rb +103 -0
  87. data/lib/emf/emf_plus/objects/path.rb +21 -0
  88. data/lib/emf/emf_plus/objects/pen.rb +132 -0
  89. data/lib/emf/emf_plus/objects/region.rb +39 -0
  90. data/lib/emf/emf_plus/objects/string_format.rb +55 -0
  91. data/lib/emf/emf_plus/objects/typed.rb +50 -0
  92. data/lib/emf/emf_plus/objects.rb +46 -0
  93. data/lib/emf/emf_plus/parser.rb +64 -2
  94. data/lib/emf/emf_plus/records/base.rb +107 -0
  95. data/lib/emf/emf_plus/records/begin_container.rb +31 -0
  96. data/lib/emf/emf_plus/records/begin_container_no_params.rb +20 -0
  97. data/lib/emf/emf_plus/records/body.rb +16 -0
  98. data/lib/emf/emf_plus/records/clear.rb +22 -0
  99. data/lib/emf/emf_plus/records/clip_transform_flags.rb +26 -0
  100. data/lib/emf/emf_plus/records/comment.rb +21 -0
  101. data/lib/emf/emf_plus/records/draw_arc.rb +33 -0
  102. data/lib/emf/emf_plus/records/draw_beziers.rb +31 -0
  103. data/lib/emf/emf_plus/records/draw_closed_curve.rb +34 -0
  104. data/lib/emf/emf_plus/records/draw_curve.rb +38 -0
  105. data/lib/emf/emf_plus/records/draw_driver_string.rb +61 -0
  106. data/lib/emf/emf_plus/records/draw_ellipse.rb +28 -0
  107. data/lib/emf/emf_plus/records/draw_image.rb +42 -0
  108. data/lib/emf/emf_plus/records/draw_image_points.rb +62 -0
  109. data/lib/emf/emf_plus/records/draw_lines.rb +34 -0
  110. data/lib/emf/emf_plus/records/draw_path.rb +23 -0
  111. data/lib/emf/emf_plus/records/draw_pie.rb +33 -0
  112. data/lib/emf/emf_plus/records/draw_rects.rb +30 -0
  113. data/lib/emf/emf_plus/records/draw_string.rb +41 -0
  114. data/lib/emf/emf_plus/records/end_container.rb +20 -0
  115. data/lib/emf/emf_plus/records/end_of_file.rb +17 -0
  116. data/lib/emf/emf_plus/records/fill_brush.rb +21 -0
  117. data/lib/emf/emf_plus/records/fill_closed_curve.rb +38 -0
  118. data/lib/emf/emf_plus/records/fill_ellipse.rb +29 -0
  119. data/lib/emf/emf_plus/records/fill_path.rb +23 -0
  120. data/lib/emf/emf_plus/records/fill_pie.rb +34 -0
  121. data/lib/emf/emf_plus/records/fill_polygon.rb +32 -0
  122. data/lib/emf/emf_plus/records/fill_rects.rb +31 -0
  123. data/lib/emf/emf_plus/records/fill_region.rb +23 -0
  124. data/lib/emf/emf_plus/records/get_dc.rb +18 -0
  125. data/lib/emf/emf_plus/records/header.rb +35 -0
  126. data/lib/emf/emf_plus/records/multiply_world_transform.rb +24 -0
  127. data/lib/emf/emf_plus/records/object.rb +32 -0
  128. data/lib/emf/emf_plus/records/offset_clip.rb +24 -0
  129. data/lib/emf/emf_plus/records/primitives/argb.rb +20 -0
  130. data/lib/emf/emf_plus/records/primitives/bitmap.rb +32 -0
  131. data/lib/emf/emf_plus/records/primitives/bitmap_data.rb +21 -0
  132. data/lib/emf/emf_plus/records/primitives/blend_colors.rb +22 -0
  133. data/lib/emf/emf_plus/records/primitives/blend_factors.rb +21 -0
  134. data/lib/emf/emf_plus/records/primitives/bounded_array.rb +38 -0
  135. data/lib/emf/emf_plus/records/primitives/byte_reader.rb +25 -0
  136. data/lib/emf/emf_plus/records/primitives/character_range.rb +20 -0
  137. data/lib/emf/emf_plus/records/primitives/compressed_image.rb +17 -0
  138. data/lib/emf/emf_plus/records/primitives/focus_scale_data.rb +20 -0
  139. data/lib/emf/emf_plus/records/primitives/graphics_version.rb +21 -0
  140. data/lib/emf/emf_plus/records/primitives/language_identifier.rb +22 -0
  141. data/lib/emf/emf_plus/records/primitives/metafile.rb +19 -0
  142. data/lib/emf/emf_plus/records/primitives/palette.rb +21 -0
  143. data/lib/emf/emf_plus/records/primitives/path.rb +89 -0
  144. data/lib/emf/emf_plus/records/primitives/path_point_type.rb +21 -0
  145. data/lib/emf/emf_plus/records/primitives/path_point_type_rle.rb +23 -0
  146. data/lib/emf/emf_plus/records/primitives/point.rb +18 -0
  147. data/lib/emf/emf_plus/records/primitives/point_array.rb +42 -0
  148. data/lib/emf/emf_plus/records/primitives/point_f.rb +19 -0
  149. data/lib/emf/emf_plus/records/primitives/point_r.rb +19 -0
  150. data/lib/emf/emf_plus/records/primitives/rect.rb +20 -0
  151. data/lib/emf/emf_plus/records/primitives/rect_array.rb +24 -0
  152. data/lib/emf/emf_plus/records/primitives/rect_f.rb +21 -0
  153. data/lib/emf/emf_plus/records/primitives/region_node.rb +68 -0
  154. data/lib/emf/emf_plus/records/primitives/region_node_child_nodes.rb +22 -0
  155. data/lib/emf/emf_plus/records/primitives/region_node_path.rb +37 -0
  156. data/lib/emf/emf_plus/records/primitives/relative_coordinate.rb +32 -0
  157. data/lib/emf/emf_plus/records/primitives/string_format_data.rb +23 -0
  158. data/lib/emf/emf_plus/records/primitives/transform_matrix.rb +23 -0
  159. data/lib/emf/emf_plus/records/primitives.rb +41 -0
  160. data/lib/emf/emf_plus/records/reset_clip.rb +17 -0
  161. data/lib/emf/emf_plus/records/reset_world_transform.rb +17 -0
  162. data/lib/emf/emf_plus/records/restore.rb +20 -0
  163. data/lib/emf/emf_plus/records/rotate_world_transform.rb +24 -0
  164. data/lib/emf/emf_plus/records/save.rb +20 -0
  165. data/lib/emf/emf_plus/records/scale_world_transform.rb +26 -0
  166. data/lib/emf/emf_plus/records/serializable_object.rb +32 -0
  167. data/lib/emf/emf_plus/records/set_anti_alias_mode.rb +25 -0
  168. data/lib/emf/emf_plus/records/set_clip_path.rb +20 -0
  169. data/lib/emf/emf_plus/records/set_clip_rect.rb +24 -0
  170. data/lib/emf/emf_plus/records/set_clip_region.rb +20 -0
  171. data/lib/emf/emf_plus/records/set_compositing_mode.rb +21 -0
  172. data/lib/emf/emf_plus/records/set_compositing_quality.rb +21 -0
  173. data/lib/emf/emf_plus/records/set_interpolation_mode.rb +21 -0
  174. data/lib/emf/emf_plus/records/set_page_transform.rb +25 -0
  175. data/lib/emf/emf_plus/records/set_pixel_offset_mode.rb +21 -0
  176. data/lib/emf/emf_plus/records/set_rendering_origin.rb +22 -0
  177. data/lib/emf/emf_plus/records/set_text_contrast.rb +24 -0
  178. data/lib/emf/emf_plus/records/set_text_rendering_hint.rb +21 -0
  179. data/lib/emf/emf_plus/records/set_ts_clip.rb +40 -0
  180. data/lib/emf/emf_plus/records/set_ts_graphics.rb +88 -0
  181. data/lib/emf/emf_plus/records/set_world_transform.rb +22 -0
  182. data/lib/emf/emf_plus/records/shape_flags.rb +23 -0
  183. data/lib/emf/emf_plus/records/translate_world_transform.rb +26 -0
  184. data/lib/emf/emf_plus/records/unknown.rb +20 -0
  185. data/lib/emf/emf_plus/records.rb +107 -0
  186. data/lib/emf/emf_plus/serializer.rb +9 -2
  187. data/lib/emf/emf_plus/stream/conformance.rb +68 -0
  188. data/lib/emf/emf_plus/stream/editor.rb +21 -0
  189. data/lib/emf/emf_plus/stream/emf_gap.rb +20 -0
  190. data/lib/emf/emf_plus/stream/link_index.rb +30 -0
  191. data/lib/emf/emf_plus/stream/rebuild.rb +47 -0
  192. data/lib/emf/emf_plus/stream/record_handle.rb +26 -0
  193. data/lib/emf/emf_plus/stream/segment.rb +70 -0
  194. data/lib/emf/emf_plus/stream.rb +153 -0
  195. data/lib/emf/emf_plus.rb +9 -0
  196. data/lib/emf/emr/binary/dib_header.rb +142 -0
  197. data/lib/emf/emr/binary/ext_text_out_fields.rb +43 -0
  198. data/lib/emf/emr/binary/extended_pen_buffers.rb +23 -0
  199. data/lib/emf/emr/binary/fast_fill.rb +1164 -0
  200. data/lib/emf/emr/binary/font.rb +159 -0
  201. data/lib/emf/emr/binary/lazy_utf16_array.rb +82 -0
  202. data/lib/emf/emr/binary/pack_plan.rb +144 -0
  203. data/lib/emf/emr/binary/pack_plan_check.rb +75 -0
  204. data/lib/emf/emr/binary/pack_plan_exact.rb +130 -0
  205. data/lib/emf/emr/binary/pack_plan_generate.rb +116 -0
  206. data/lib/emf/emr/binary/pack_plan_values.rb +92 -0
  207. data/lib/emf/emr/binary/palette_body.rb +19 -0
  208. data/lib/emf/emr/binary/palette_entry.rb +18 -0
  209. data/lib/emf/emr/binary/record.rb +33 -0
  210. data/lib/emf/emr/binary/records/alpha_blend.rb +43 -0
  211. data/lib/emf/emr/binary/records/angle_arc.rb +2 -2
  212. data/lib/emf/emr/binary/records/bit_blt.rb +14 -0
  213. data/lib/emf/emr/binary/records/color_correct_palette.rb +55 -1
  214. data/lib/emf/emr/binary/records/colormatch_to_target_w.rb +76 -1
  215. data/lib/emf/emr/binary/records/create_colorspace.rb +67 -1
  216. data/lib/emf/emr/binary/records/create_colorspace_w.rb +90 -1
  217. data/lib/emf/emr/binary/records/create_dib_pattern_brush_pt.rb +14 -0
  218. data/lib/emf/emr/binary/records/create_font_indirect_w.rb +6 -2
  219. data/lib/emf/emr/binary/records/create_mono_brush.rb +14 -0
  220. data/lib/emf/emr/binary/records/create_palette.rb +19 -1
  221. data/lib/emf/emr/binary/records/delete_colorspace.rb +22 -1
  222. data/lib/emf/emr/binary/records/draw_escape.rb +45 -1
  223. data/lib/emf/emr/binary/records/ellipse.rb +1 -1
  224. data/lib/emf/emr/binary/records/eof.rb +9 -0
  225. data/lib/emf/emr/binary/records/ext_create_pen.rb +80 -1
  226. data/lib/emf/emr/binary/records/ext_escape.rb +45 -1
  227. data/lib/emf/emr/binary/records/ext_flood_fill.rb +9 -2
  228. data/lib/emf/emr/binary/records/ext_select_clip_rgn.rb +9 -1
  229. data/lib/emf/emr/binary/records/ext_text_out_a.rb +16 -3
  230. data/lib/emf/emr/binary/records/ext_text_out_w.rb +14 -3
  231. data/lib/emf/emr/binary/records/fill_rgn.rb +11 -2
  232. data/lib/emf/emr/binary/records/force_ufi_mapping.rb +38 -1
  233. data/lib/emf/emr/binary/records/frame_rgn.rb +12 -2
  234. data/lib/emf/emr/binary/records/gls_bounded_record.rb +61 -1
  235. data/lib/emf/emr/binary/records/gls_record.rb +42 -1
  236. data/lib/emf/emr/binary/records/gradient_fill.rb +7 -0
  237. data/lib/emf/emr/binary/records/invert_rgn.rb +11 -3
  238. data/lib/emf/emr/binary/records/mask_blt.rb +66 -0
  239. data/lib/emf/emr/binary/records/named_escape.rb +78 -1
  240. data/lib/emf/emr/binary/records/paint_rgn.rb +11 -3
  241. data/lib/emf/emr/binary/records/pixel_format.rb +76 -1
  242. data/lib/emf/emr/binary/records/plg_blt.rb +66 -0
  243. data/lib/emf/emr/binary/records/poly_textout_a.rb +128 -1
  244. data/lib/emf/emr/binary/records/poly_textout_w.rb +128 -1
  245. data/lib/emf/emr/binary/records/raw.rb +3 -0
  246. data/lib/emf/emr/binary/records/realize_palette.rb +1 -0
  247. data/lib/emf/emr/binary/records/rectangle.rb +1 -1
  248. data/lib/emf/emr/binary/records/resize_palette.rb +16 -2
  249. data/lib/emf/emr/binary/records/round_rect.rb +2 -2
  250. data/lib/emf/emr/binary/records/select_palette.rb +1 -0
  251. data/lib/emf/emr/binary/records/set_color_adjustment.rb +136 -0
  252. data/lib/emf/emr/binary/records/set_colorspace.rb +22 -1
  253. data/lib/emf/emr/binary/records/set_dibits_to_device.rb +43 -0
  254. data/lib/emf/emr/binary/records/set_icm_profile_a.rb +71 -1
  255. data/lib/emf/emr/binary/records/set_icm_profile_w.rb +71 -1
  256. data/lib/emf/emr/binary/records/set_linked_ufis.rb +49 -1
  257. data/lib/emf/emr/binary/records/set_miter_limit.rb +1 -1
  258. data/lib/emf/emr/binary/records/set_palette_entries.rb +20 -2
  259. data/lib/emf/emr/binary/records/set_text_justification.rb +8 -2
  260. data/lib/emf/emr/binary/records/small_text_out.rb +55 -4
  261. data/lib/emf/emr/binary/records/stretch_blt.rb +14 -0
  262. data/lib/emf/emr/binary/records/stretch_dibits.rb +14 -0
  263. data/lib/emf/emr/binary/records/transparent_blt.rb +43 -0
  264. data/lib/emf/emr/binary/records.rb +4 -2
  265. data/lib/emf/emr/binary/region_data.rb +33 -0
  266. data/lib/emf/emr/binary/state_record_body.rb +33 -0
  267. data/lib/emf/emr/binary/thin_shell.rb +226 -0
  268. data/lib/emf/emr/binary/value_view/layout.rb +101 -0
  269. data/lib/emf/emr/binary/value_view/reader_source.rb +88 -0
  270. data/lib/emf/emr/binary/value_view.rb +173 -0
  271. data/lib/emf/emr/binary/variable_buffers.rb +87 -0
  272. data/lib/emf/emr/binary.rb +4 -0
  273. data/lib/emf/emr/filled_record.rb +77 -0
  274. data/lib/emf/emr/parser.rb +239 -50
  275. data/lib/emf/emr/serializer.rb +4 -5
  276. data/lib/emf/emr.rb +1 -0
  277. data/lib/emf/error.rb +24 -1
  278. data/lib/emf/model/diagnostic.rb +41 -0
  279. data/lib/emf/model/emr/header.rb +40 -1
  280. data/lib/emf/model/emr/records.rb +142 -6
  281. data/lib/emf/model/emr/wire_values.rb +43 -0
  282. data/lib/emf/model/emr.rb +1 -0
  283. data/lib/emf/model/geometry/color.rb +19 -1
  284. data/lib/emf/model/metafile.rb +22 -2
  285. data/lib/emf/model/wmf/bitmap_records.rb +155 -0
  286. data/lib/emf/model/wmf/brush_records.rb +45 -0
  287. data/lib/emf/model/wmf/dc_escape_records.rb +67 -0
  288. data/lib/emf/model/wmf/font_record.rb +40 -0
  289. data/lib/emf/model/wmf/geometry_records.rb +107 -0
  290. data/lib/emf/model/wmf/header.rb +36 -0
  291. data/lib/emf/model/wmf/object_records.rb +71 -0
  292. data/lib/emf/model/wmf/palette_records.rb +68 -0
  293. data/lib/emf/model/wmf/records.rb +247 -0
  294. data/lib/emf/model/wmf/region_records.rb +112 -0
  295. data/lib/emf/model/wmf/state_records.rb +188 -0
  296. data/lib/emf/model/wmf/text_records.rb +36 -0
  297. data/lib/emf/model/wmf.rb +11 -0
  298. data/lib/emf/model.rb +2 -0
  299. data/lib/emf/native/bitmap_fields.rb +58 -0
  300. data/lib/emf/native/diagnostic_contract.rb +39 -0
  301. data/lib/emf/native/diagnostics.rb +81 -0
  302. data/lib/emf/native/emf_plus_loader.rb +35 -0
  303. data/lib/emf/native/emf_plus_snapshot.rb +96 -0
  304. data/lib/emf/native/emf_plus_source.rb +20 -0
  305. data/lib/emf/native/emf_plus_stream.rb +150 -0
  306. data/lib/emf/native/fields.rb +369 -0
  307. data/lib/emf/native/font_fields.rb +87 -0
  308. data/lib/emf/native/gradient_fields.rb +23 -0
  309. data/lib/emf/native/header.rb +35 -0
  310. data/lib/emf/native/header_errors.rb +30 -0
  311. data/lib/emf/native/hydrator.rb +151 -0
  312. data/lib/emf/native/lazy_wire.rb +100 -0
  313. data/lib/emf/native/legacy_state_fields.rb +22 -0
  314. data/lib/emf/native/library_path.rb +68 -0
  315. data/lib/emf/native/loader.rb +120 -0
  316. data/lib/emf/native/palette_fields.rb +45 -0
  317. data/lib/emf/native/poly_text_fields.rb +116 -0
  318. data/lib/emf/native/resource_failure.rb +28 -0
  319. data/lib/emf/native/small_text_fields.rb +27 -0
  320. data/lib/emf/native/snapshot.rb +102 -0
  321. data/lib/emf/native/wmf_bitmap_fields.rb +58 -0
  322. data/lib/emf/native/wmf_brush_fields.rb +62 -0
  323. data/lib/emf/native/wmf_fields.rb +117 -0
  324. data/lib/emf/native/wmf_hydrator.rb +143 -0
  325. data/lib/emf/native/wmf_loading.rb +49 -0
  326. data/lib/emf/native/wmf_palette_fields.rb +60 -0
  327. data/lib/emf/native/wmf_region_fields.rb +92 -0
  328. data/lib/emf/native/wmf_rejection.rb +84 -0
  329. data/lib/emf/native/wmf_remaining_fields.rb +70 -0
  330. data/lib/emf/native/wmf_snapshot.rb +51 -0
  331. data/lib/emf/native/wmf_text_fields.rb +56 -0
  332. data/lib/emf/native.rb +61 -0
  333. data/lib/emf/parse_evidence.rb +57 -0
  334. data/lib/emf/resource_budget/bitmap.rb +66 -0
  335. data/lib/emf/resource_budget/gradient.rb +30 -0
  336. data/lib/emf/resource_budget/poly_text.rb +85 -0
  337. data/lib/emf/resource_budget.rb +382 -0
  338. data/lib/emf/resource_limits/emf_records.rb +130 -0
  339. data/lib/emf/resource_limits.rb +58 -0
  340. data/lib/emf/version.rb +1 -1
  341. data/lib/emf/visitors/dump.rb +4 -0
  342. data/lib/emf/visitors/stats.rb +6 -5
  343. data/lib/emf/wmf/binary.rb +150 -1
  344. data/lib/emf/wmf/bitmap_codec.rb +118 -0
  345. data/lib/emf/wmf/brush_codec.rb +102 -0
  346. data/lib/emf/wmf/dc_escape_codec.rb +75 -0
  347. data/lib/emf/wmf/dib.rb +187 -0
  348. data/lib/emf/wmf/embedded_emf.rb +137 -0
  349. data/lib/emf/wmf/escape_views.rb +89 -0
  350. data/lib/emf/wmf/evidence.rb +255 -0
  351. data/lib/emf/wmf/geometry_codec.rb +49 -0
  352. data/lib/emf/wmf/palette_codec.rb +85 -0
  353. data/lib/emf/wmf/parser.rb +147 -2
  354. data/lib/emf/wmf/recovery.rb +95 -0
  355. data/lib/emf/wmf/region_codec.rb +151 -0
  356. data/lib/emf/wmf/serializer.rb +164 -2
  357. data/lib/emf/wmf/text_codec.rb +123 -0
  358. data/lib/emf/wmf.rb +7 -0
  359. data/lib/emf.rb +13 -9
  360. metadata +287 -10
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bindata"
4
+ require "emf/binary/float32_le"
5
+ require "emf/emf_plus/records/primitives/bounded_array"
6
+
7
+ module Emf
8
+ module EmfPlus
9
+ module Records
10
+ module Primitives
11
+ # EmfPlusBlendFactors (2.2.2.5).
12
+ class BlendFactors < Body
13
+ endian :little
14
+ uint32 :position_count
15
+ bounded_array :blend_positions, type: :float32_le, element_size: 4, initial_length: :position_count
16
+ bounded_array :blend_factors, type: :float32_le, element_size: 4, initial_length: :position_count
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bindata"
4
+
5
+ module Emf
6
+ module EmfPlus
7
+ module Records
8
+ module Primitives
9
+ # A BinData array whose untrusted `initial_length` is checked against
10
+ # the bytes left in the stream before any element is built. Each
11
+ # element takes at least `element_size` bytes, so a count that cannot
12
+ # fit raises EOFError (an IOError, the signal a short read already
13
+ # gives) instead of allocating count elements.
14
+ class BoundedArray < BinData::Array
15
+ # Extended onto each instance after the initial-length plugin, so
16
+ # its do_read runs first.
17
+ module Guard
18
+ def do_read(io)
19
+ count = eval_parameter(:initial_length)
20
+ needed = count * eval_parameter(:element_size)
21
+ left = io.num_bytes_remaining
22
+ raise EOFError, "#{count} elements need at least #{needed} bytes, #{left} left" if needed > left
23
+
24
+ super
25
+ end
26
+ end
27
+
28
+ mandatory_parameter :element_size
29
+
30
+ def initialize_shared_instance
31
+ super
32
+ extend Guard
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emf
4
+ module EmfPlus
5
+ module Records
6
+ module Primitives
7
+ # Reads exact byte counts from a StringIO for the hand-parsed
8
+ # structures; a short read raises EOFError (an IOError), the same
9
+ # signal BinData gives, so callers map it to ParseError once.
10
+ module ByteReader
11
+ private
12
+
13
+ def take(io, count, what)
14
+ bytes = io.read(count)
15
+ return bytes if bytes && bytes.bytesize == count
16
+
17
+ raise EOFError, "#{what} needs #{count} bytes, #{io.size - io.pos} left"
18
+ end
19
+
20
+ def remaining(io) = io.size - io.pos
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bindata"
4
+
5
+ module Emf
6
+ module EmfPlus
7
+ module Records
8
+ module Primitives
9
+ # EmfPlusCharacterRange (2.2.2.8).
10
+ # BinData reserves `first` and `length`, so the spec names First and
11
+ # Length are first_position and range_length here.
12
+ class CharacterRange < Body
13
+ endian :little
14
+ int32 :first_position
15
+ int32 :range_length
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bindata"
4
+
5
+ module Emf
6
+ module EmfPlus
7
+ module Records
8
+ module Primitives
9
+ # EmfPlusCompressedImage (2.2.2.10).
10
+ class CompressedImage < Body
11
+ endian :little
12
+ rest :compressed_image_data
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bindata"
4
+ require "emf/binary/float32_le"
5
+
6
+ module Emf
7
+ module EmfPlus
8
+ module Records
9
+ module Primitives
10
+ # EmfPlusFocusScaleData (2.2.2.18).
11
+ class FocusScaleData < Body
12
+ endian :little
13
+ uint32 :focus_scale_count
14
+ float32_le :focus_scale_x
15
+ float32_le :focus_scale_y
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bindata"
4
+
5
+ module Emf
6
+ module EmfPlus
7
+ module Records
8
+ module Primitives
9
+ # EmfPlusGraphicsVersion (2.2.2.19): 20-bit MetafileSignature (0xDBC01)
10
+ # above a 12-bit GraphicsVersion in one little-endian dword.
11
+ class GraphicsVersion < Body
12
+ endian :little
13
+ uint32 :raw
14
+
15
+ def metafile_signature = raw >> 12
16
+ def graphics_version = raw & 0xFFF
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bindata"
4
+
5
+ module Emf
6
+ module EmfPlus
7
+ module Records
8
+ module Primitives
9
+ # EmfPlusLanguageIdentifier (2.2.2.23): 6-bit SubLanguageId above a
10
+ # 10-bit PrimaryLanguageId. The containing objects reserve a full
11
+ # dword for it, so the whole dword is kept.
12
+ class LanguageIdentifier < Body
13
+ endian :little
14
+ uint32 :raw
15
+
16
+ def primary_language_id = raw & 0x3FF
17
+ def sub_language_id = (raw >> 10) & 0x3F
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bindata"
4
+
5
+ module Emf
6
+ module EmfPlus
7
+ module Records
8
+ module Primitives
9
+ # EmfPlusMetafile (2.2.2.27).
10
+ class Metafile < Body
11
+ endian :little
12
+ uint32 :metafile_type
13
+ uint32 :metafile_data_size
14
+ string :metafile_data, read_length: :metafile_data_size
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bindata"
4
+ require "emf/emf_plus/records/primitives/bounded_array"
5
+ require "emf/emf_plus/records/primitives/argb"
6
+
7
+ module Emf
8
+ module EmfPlus
9
+ module Records
10
+ module Primitives
11
+ # EmfPlusPalette (2.2.2.28).
12
+ class Palette < Body
13
+ endian :little
14
+ uint32 :palette_style_flags
15
+ uint32 :palette_count
16
+ bounded_array :palette_entries, type: :argb, element_size: 4, initial_length: :palette_count
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "stringio"
4
+ require "emf/emf_plus/records/primitives/byte_reader"
5
+ require "emf/emf_plus/records/primitives/graphics_version"
6
+ require "emf/emf_plus/records/primitives/path_point_type"
7
+ require "emf/emf_plus/records/primitives/path_point_type_rle"
8
+ require "emf/emf_plus/records/primitives/point_array"
9
+
10
+ module Emf
11
+ module EmfPlus
12
+ module Records
13
+ module Primitives
14
+ # EmfPlusPath (2.2.1.6) without its AlignmentPadding, which the caller
15
+ # keeps. Same surface as a BinData record (`read`, `num_bytes`,
16
+ # `to_binary_s`); hand-parsed because the point and type encodings are
17
+ # chosen by the flags and the RLE run list has no stored length.
18
+ class Path
19
+ include ByteReader
20
+
21
+ RELATIVE_FLAG = 0x0800
22
+ COMPRESSED_FLAG = 0x4000
23
+ HEADER_SIZE = 12
24
+ MIN_POINT_SIZE = { relative: 2, compressed: 4, float: 8 }.freeze
25
+ private_constant :MIN_POINT_SIZE
26
+
27
+ attr_reader :version, :point_count, :flags, :points, :point_types
28
+
29
+ def read(source)
30
+ io = StringIO.new(source)
31
+ @version = GraphicsVersion.new.read(io)
32
+ @point_count, @flags = take(io, 8, "PathPointCount and PathPointFlags").unpack("VV")
33
+ require_room(io)
34
+ @points = PointArray.new(point_count: point_count, relative: relative?, compressed: compressed?).read(io)
35
+ @point_types = relative? ? read_runs(io) : read_types(io)
36
+ @size = io.pos
37
+ self
38
+ end
39
+
40
+ def relative? = flags.anybits?(RELATIVE_FLAG)
41
+ # The C flag is undefined, and ignored, when R is set.
42
+ def compressed? = !relative? && flags.anybits?(COMPRESSED_FLAG)
43
+ def num_bytes = @size
44
+
45
+ def to_binary_s
46
+ version.to_binary_s + [point_count, flags].pack("VV") + points.to_binary_s +
47
+ point_types.map(&:to_binary_s).join
48
+ end
49
+
50
+ private
51
+
52
+ def point_kind
53
+ if relative? then :relative
54
+ elsif compressed? then :compressed
55
+ else :float
56
+ end
57
+ end
58
+
59
+ def require_room(io)
60
+ needed = (point_count * MIN_POINT_SIZE.fetch(point_kind)) + min_type_bytes
61
+ return if needed <= remaining(io)
62
+
63
+ raise EOFError, "#{point_count} path points need at least #{needed} bytes, #{remaining(io)} left"
64
+ end
65
+
66
+ def min_type_bytes
67
+ return point_count unless relative?
68
+
69
+ point_count.zero? ? 0 : PathPointTypeRLE.new.num_bytes
70
+ end
71
+
72
+ def read_types(io)
73
+ Array.new(point_count) { PathPointType.new.read(io) }
74
+ end
75
+
76
+ def read_runs(io)
77
+ covered = 0
78
+ runs = []
79
+ while covered < point_count
80
+ runs << PathPointTypeRLE.new.read(io)
81
+ covered += runs.last.run_count
82
+ end
83
+ runs
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bindata"
4
+
5
+ module Emf
6
+ module EmfPlus
7
+ module Records
8
+ module Primitives
9
+ # EmfPlusPathPointType (2.2.2.31): flags in the high nibble, the
10
+ # PathPointType enumeration in the low nibble.
11
+ class PathPointType < Body
12
+ endian :little
13
+ uint8 :raw
14
+
15
+ def flags = raw >> 4
16
+ def type = raw & 0x0F
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bindata"
4
+ require "emf/emf_plus/records/primitives/path_point_type"
5
+
6
+ module Emf
7
+ module EmfPlus
8
+ module Records
9
+ module Primitives
10
+ # EmfPlusPathPointTypeRLE (2.2.2.32): a Bezier bit, a reserved bit and
11
+ # a 6-bit run count, then the type shared by that many points.
12
+ class PathPointTypeRLE < Body
13
+ endian :little
14
+ uint8 :header
15
+ path_point_type :point_type
16
+
17
+ def bezier? = header.anybits?(0x80)
18
+ def run_count = header & 0x3F
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bindata"
4
+
5
+ module Emf
6
+ module EmfPlus
7
+ module Records
8
+ module Primitives
9
+ # EmfPlusPoint (2.2.2.35): 16-bit signed, the "compressed" form.
10
+ class Point < Body
11
+ endian :little
12
+ int16 :x
13
+ int16 :y
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bindata"
4
+ require "emf/emf_plus/records/primitives/bounded_array"
5
+ require "emf/emf_plus/records/primitives/point"
6
+ require "emf/emf_plus/records/primitives/point_f"
7
+ require "emf/emf_plus/records/primitives/point_r"
8
+
9
+ module Emf
10
+ module EmfPlus
11
+ module Records
12
+ module Primitives
13
+ # `point_count` points in the form the record flags select: relative
14
+ # (PointR) wins over compressed (Point); otherwise PointF.
15
+ class PointArray < Body
16
+ endian :little
17
+ mandatory_parameter :point_count, :relative, :compressed
18
+ bounded_array :relative_points, type: PointR, element_size: 2, initial_length: :point_count, onlyif: -> { relative }
19
+ bounded_array :compressed_points, type: Point, element_size: 4, initial_length: :point_count, onlyif: lambda {
20
+ !relative && compressed
21
+ }
22
+ bounded_array :float_points, type: PointF, element_size: 8, initial_length: :point_count, onlyif: -> { !relative && !compressed }
23
+
24
+ def points
25
+ if relative
26
+ relative_points
27
+ elsif compressed
28
+ compressed_points
29
+ else
30
+ float_points
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def relative = eval_parameter(:relative)
37
+ def compressed = eval_parameter(:compressed)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bindata"
4
+ require "emf/binary/float32_le"
5
+
6
+ module Emf
7
+ module EmfPlus
8
+ module Records
9
+ module Primitives
10
+ # EmfPlusPointF (2.2.2.36): 32-bit floats.
11
+ class PointF < Body
12
+ endian :little
13
+ float32_le :x
14
+ float32_le :y
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bindata"
4
+ require "emf/emf_plus/records/primitives/relative_coordinate"
5
+
6
+ module Emf
7
+ module EmfPlus
8
+ module Records
9
+ module Primitives
10
+ # EmfPlusPointR (2.2.2.37): relative location, each axis 7 or 15 bits.
11
+ class PointR < Body
12
+ endian :little
13
+ relative_coordinate :x
14
+ relative_coordinate :y
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bindata"
4
+
5
+ module Emf
6
+ module EmfPlus
7
+ module Records
8
+ module Primitives
9
+ # EmfPlusRect (2.2.2.39): 16-bit signed, the "compressed" form.
10
+ class Rect < Body
11
+ endian :little
12
+ int16 :x
13
+ int16 :y
14
+ int16 :width
15
+ int16 :height
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bindata"
4
+ require "emf/emf_plus/records/primitives/bounded_array"
5
+ require "emf/emf_plus/records/primitives/rect"
6
+ require "emf/emf_plus/records/primitives/rect_f"
7
+
8
+ module Emf
9
+ module EmfPlus
10
+ module Records
11
+ module Primitives
12
+ # `rect_count` rectangles, Rect when compressed and RectF otherwise.
13
+ class RectArray < Body
14
+ endian :little
15
+ mandatory_parameter :rect_count, :compressed
16
+ bounded_array :compressed_rects, type: Rect, element_size: 8, initial_length: :rect_count, onlyif: -> { compressed }
17
+ bounded_array :float_rects, type: RectF, element_size: 16, initial_length: :rect_count, onlyif: -> { !compressed }
18
+
19
+ def rects = eval_parameter(:compressed) ? compressed_rects : float_rects
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bindata"
4
+ require "emf/binary/float32_le"
5
+
6
+ module Emf
7
+ module EmfPlus
8
+ module Records
9
+ module Primitives
10
+ # EmfPlusRectF (2.2.2.40): 32-bit floats.
11
+ class RectF < Body
12
+ endian :little
13
+ float32_le :x
14
+ float32_le :y
15
+ float32_le :width
16
+ float32_le :height
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "stringio"
4
+ require "bindata"
5
+ require "emf/emf_plus/records/primitives/byte_reader"
6
+ require "emf/emf_plus/records/primitives/rect_f"
7
+ require "emf/emf_plus/records/primitives/region_node_child_nodes"
8
+ require "emf/emf_plus/records/primitives/region_node_path"
9
+
10
+ module Emf
11
+ module EmfPlus
12
+ module Records
13
+ module Primitives
14
+ # EmfPlusRegionNode (2.2.2.40): a RegionNodeDataType, then data chosen
15
+ # by it: two child nodes (And/Or/Xor/Exclude/Complement), a RectF, a
16
+ # RegionNodePath, or nothing (Empty/Infinite).
17
+ class RegionNode
18
+ include ByteReader
19
+
20
+ COMBINING = [0x1, 0x2, 0x3, 0x4, 0x5].freeze
21
+ RECT = 0x10000000
22
+ PATH = 0x10000001
23
+ EMPTY = 0x10000002
24
+ INFINITE = 0x10000003
25
+ MAX_DEPTH = 256
26
+
27
+ attr_reader :type, :data
28
+
29
+ def initialize(depth = 0)
30
+ @depth = depth
31
+ end
32
+
33
+ def read(io)
34
+ raise BinData::ValidityError, "region nodes nested deeper than #{MAX_DEPTH} levels" if @depth > MAX_DEPTH
35
+
36
+ @type = take(io, 4, "RegionNode Type").unpack1("V")
37
+ @data = read_data(io)
38
+ self
39
+ end
40
+
41
+ def combining? = COMBINING.include?(type)
42
+ def to_binary_s = [type].pack("V") + (data ? data.to_binary_s : "".b)
43
+
44
+ # Nodes in this subtree, itself included.
45
+ def node_count = 1 + (combining? ? data.left.node_count + data.right.node_count : 0)
46
+
47
+ private
48
+
49
+ def read_data(io)
50
+ case type
51
+ when *COMBINING then read_children(io)
52
+ when RECT then RectF.new.read(io)
53
+ when PATH then RegionNodePath.new.read(io)
54
+ when EMPTY, INFINITE then nil
55
+ else raise BinData::ValidityError, "unknown RegionNodeDataType 0x#{type.to_s(16)}"
56
+ end
57
+ end
58
+
59
+ def read_children(io)
60
+ RegionNodeChildNodes.new(child(io), child(io))
61
+ end
62
+
63
+ def child(io) = self.class.new(@depth + 1).read(io)
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emf
4
+ module EmfPlus
5
+ module Records
6
+ module Primitives
7
+ # EmfPlusRegionNodeChildNodes (2.2.2.41): the two subtrees of a
8
+ # combining node. RegionNode builds it, since the subtrees are nodes.
9
+ class RegionNodeChildNodes
10
+ attr_reader :left, :right
11
+
12
+ def initialize(left, right)
13
+ @left = left
14
+ @right = right
15
+ end
16
+
17
+ def to_binary_s = left.to_binary_s + right.to_binary_s
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "stringio"
4
+ require "emf/emf_plus/records/primitives/byte_reader"
5
+ require "emf/emf_plus/records/primitives/path"
6
+
7
+ module Emf
8
+ module EmfPlus
9
+ module Records
10
+ module Primitives
11
+ # EmfPlusRegionNodePath (2.2.2.42): a byte length, then an EmfPlusPath
12
+ # filling it. Bytes of the length the path does not use (its
13
+ # alignment padding) stay in `padding`.
14
+ class RegionNodePath
15
+ include ByteReader
16
+
17
+ attr_reader :path, :padding
18
+
19
+ def read(io)
20
+ length = take(io, 4, "RegionNodePathLength").unpack1("l<")
21
+ raise BinData::ValidityError, "negative RegionNodePathLength #{length}" if length.negative?
22
+
23
+ bytes = take(io, length, "RegionNodePath of #{length} bytes")
24
+ @path = Path.new.read(bytes)
25
+ @padding = bytes.byteslice(path.num_bytes..)
26
+ self
27
+ end
28
+
29
+ def to_binary_s
30
+ body = path.to_binary_s + padding
31
+ [body.bytesize].pack("V") + body
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end