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
@@ -1,15 +1,85 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "bindata"
4
+ require "emf/emr/binary/variable_buffers"
4
5
  require "emf/emr/binary/record"
5
6
 
6
7
  module Emf
7
8
  module Emr
8
9
  module Binary
9
10
  module Records
10
- # Stub: preserves full body bytes. Full layout lands with TODO 10.
11
+ # MS-EMF 2.3.11.16: name and profile lengths are byte counts.
11
12
  class SetIcmProfileW < Emf::Emr::Binary::Record
13
+ include Emf::Emr::Binary::VariableBuffers
14
+
15
+ fixed_layout 20
16
+ variable_buffer :icm_name_bytes, offset: 20, length: -> { u32_at(12) }
17
+ variable_buffer :icm_profile_bytes, offset: -> { 20 + u32_at(12) }, length: -> { u32_at(16) }
18
+
19
+ # Byte counts and opaque spans retain the original body layout.
12
20
  rest :body
21
+
22
+ def dw_flags
23
+ profile_prefix.unpack1("V")
24
+ end
25
+
26
+ def dw_flags=(value)
27
+ raise ArgumentError, "color profile flags must be an Integer" unless value.is_a?(Integer)
28
+ raise RangeError, "color profile flags must fit an unsigned 32-bit integer" unless (0..0xFFFFFFFF).cover?(value)
29
+
30
+ write_profile_bytes(0, 4, [value].pack("V"))
31
+ end
32
+
33
+ def cb_name
34
+ profile_prefix.byteslice(4, 4).unpack1("V")
35
+ end
36
+
37
+ def cb_data
38
+ profile_prefix.byteslice(8, 4).unpack1("V")
39
+ end
40
+
41
+ def name_bytes
42
+ read_profile_bytes(12, cb_name)
43
+ end
44
+
45
+ def name_bytes=(value)
46
+ write_profile_bytes(12, cb_name, value)
47
+ end
48
+
49
+ def profile_bytes
50
+ read_profile_bytes(12 + cb_name, cb_data)
51
+ end
52
+
53
+ def profile_bytes=(value)
54
+ write_profile_bytes(12 + cb_name, cb_data, value)
55
+ end
56
+
57
+ private
58
+
59
+ def profile_prefix
60
+ bytes = body.to_s
61
+ raise ArgumentError, "truncated color profile prefix" if bytes.bytesize < 12
62
+
63
+ bytes
64
+ end
65
+
66
+ def read_profile_bytes(offset, length)
67
+ bytes = profile_prefix
68
+ raise ArgumentError, "truncated color profile span" if offset + length > bytes.bytesize
69
+
70
+ bytes.byteslice(offset, length).b
71
+ end
72
+
73
+ def write_profile_bytes(offset, length, value)
74
+ read_profile_bytes(offset, length)
75
+ unless value.is_a?(String) && value.bytesize == length
76
+ raise ArgumentError, "color profile value must be a String of #{length} bytes"
77
+ end
78
+
79
+ bytes = body.to_s.b
80
+ bytes[offset, length] = value.b
81
+ self.body = bytes
82
+ end
13
83
  end
14
84
  end
15
85
  end
@@ -7,9 +7,57 @@ module Emf
7
7
  module Emr
8
8
  module Binary
9
9
  module Records
10
- # Stub: preserves full body bytes. Full layout lands with TODO 10.
10
+ # Linked identifiers preserve the declared count and ignored reserved bytes.
11
11
  class SetLinkedUfis < Emf::Emr::Binary::Record
12
12
  rest :body
13
+
14
+ def u_num_linked_ufi
15
+ bytes = body.to_s
16
+ raise ArgumentError, "truncated linked UFI count" if bytes.bytesize < 4
17
+
18
+ bytes.unpack1("V")
19
+ end
20
+
21
+ [[:ufi_checksum, 0], [:ufi_index, 4]].each do |name, offset|
22
+ define_method(name) do |index|
23
+ position = ufi_position(index)
24
+ body.to_s.byteslice(position + offset, 4).unpack1("V")
25
+ end
26
+
27
+ define_method("set_#{name}") do |index, value|
28
+ position = ufi_position(index)
29
+ raise ArgumentError, "UFI value must be an Integer" unless value.is_a?(Integer)
30
+ raise RangeError, "UFI value must fit an unsigned 32-bit integer" unless (0..0xFFFFFFFF).cover?(value)
31
+
32
+ replace_ufi_bytes(position + offset, 4, [value].pack("V"))
33
+ end
34
+ end
35
+
36
+ def ufi_bytes(index)
37
+ body.to_s.byteslice(ufi_position(index), 8).b
38
+ end
39
+
40
+ def set_ufi_bytes(index, value)
41
+ replace_ufi_bytes(ufi_position(index), 8, value)
42
+ end
43
+
44
+ private
45
+
46
+ def ufi_position(index)
47
+ count = u_num_linked_ufi
48
+ raise ArgumentError, "truncated linked UFI array or reserved bytes" if 12 + (count * 8) > body.to_s.bytesize
49
+ raise ArgumentError, "UFI index must identify a declared entry" unless index.is_a?(Integer) && index >= 0 && index < count
50
+
51
+ 4 + (index * 8)
52
+ end
53
+
54
+ def replace_ufi_bytes(offset, length, value)
55
+ raise ArgumentError, "UFI value must be a String of #{length} bytes" unless value.is_a?(String) && value.bytesize == length
56
+
57
+ replacement = body.to_s.b
58
+ replacement[offset, length] = value.b
59
+ self.body = replacement
60
+ end
13
61
  end
14
62
  end
15
63
  end
@@ -8,7 +8,7 @@ module Emf
8
8
  module Binary
9
9
  module Records
10
10
  class SetMiterLimit < Emf::Emr::Binary::Record
11
- float :miter_limit
11
+ float32_le :miter_limit
12
12
  end
13
13
  end
14
14
  end
@@ -2,14 +2,32 @@
2
2
 
3
3
  require "bindata"
4
4
  require "emf/emr/binary/record"
5
+ require "emf/emr/binary/palette_body"
6
+ require "emf/emr/binary/palette_entry"
5
7
 
6
8
  module Emf
7
9
  module Emr
8
10
  module Binary
9
11
  module Records
10
- # Stub: preserves full body bytes. Full layout lands with TODO 10.
11
12
  class SetPaletteEntries < Emf::Emr::Binary::Record
12
- rest :body
13
+ uint32 :ih_pal
14
+ uint32 :start
15
+ uint32 :entry_count
16
+ array :palette_entries, type: :emr_palette_entry, initial_length: :entry_count
17
+ rest :trailing
18
+
19
+ def body
20
+ PaletteBody.new(self, to_binary_s.byteslice(8..))
21
+ end
22
+
23
+ def body=(value)
24
+ bytes = value.to_s
25
+ count = bytes.byteslice(8, 4)&.unpack1("V")
26
+ raise ArgumentError, "invalid palette body entry count" unless count && bytes.bytesize >= 12 + (count * 4)
27
+
28
+ replacement = self.class.read(to_binary_s.byteslice(0, 8) + bytes)
29
+ assign(replacement.snapshot)
30
+ end
13
31
  end
14
32
  end
15
33
  end
@@ -2,14 +2,20 @@
2
2
 
3
3
  require "bindata"
4
4
  require "emf/emr/binary/record"
5
+ require "emf/emr/binary/state_record_body"
5
6
 
6
7
  module Emf
7
8
  module Emr
8
9
  module Binary
9
10
  module Records
10
- # Stub: preserves full body bytes. Full layout lands with TODO 10.
11
11
  class SetTextJustification < Emf::Emr::Binary::Record
12
- rest :body
12
+ include StateRecordBody
13
+
14
+ BODY_SIZE = 8
15
+
16
+ int32 :n_break_extra
17
+ int32 :n_break_count
18
+ rest :trailing
13
19
  end
14
20
  end
15
21
  end
@@ -10,17 +10,68 @@ module Emf
10
10
  # EMRSMALLTEXTOUT (MS-EMF 2.3.5.37).
11
11
  # Layout: emr, Dest, cChars, fuOptions, iGraphicsMode, exScale (float),
12
12
  # eyScale (float), [optional RECTL], TextString (1 or 2 bytes per char).
13
- # The body bytes (after the fixed header) are deferred to the visitor
14
- # for parsing because the layout depends on fuOptions.
13
+ # Option-dependent bounds and text are exposed as raw bytes while the
14
+ # body retains the original wire layout and any trailing bytes.
15
15
  class SmallTextOut < Emf::Emr::Binary::Record
16
16
  int32 :x_dest
17
17
  int32 :y_dest
18
18
  uint32 :c_chars
19
19
  uint32 :fu_options
20
20
  uint32 :i_graphics_mode
21
- float :ex_scale
22
- float :ey_scale
21
+ float32_le :ex_scale
22
+ float32_le :ey_scale
23
23
  rest :body
24
+
25
+ def bounds
26
+ return nil if no_rectangle?
27
+
28
+ available_body(16).byteslice(0, 16).b
29
+ end
30
+
31
+ def bounds=(value)
32
+ raise ArgumentError, "small text output has no bounds rectangle" if no_rectangle?
33
+
34
+ write_body_bytes(0, 16, value)
35
+ end
36
+
37
+ def text_bytes
38
+ offset, length = text_region
39
+ available_body(offset + length).byteslice(offset, length).b
40
+ end
41
+
42
+ def text_bytes=(value)
43
+ offset, length = text_region
44
+ write_body_bytes(offset, length, value)
45
+ end
46
+
47
+ private
48
+
49
+ def no_rectangle?
50
+ fu_options.to_i.anybits?(0x100)
51
+ end
52
+
53
+ def text_region
54
+ width = fu_options.to_i.nobits?(0x200) ? 2 : 1
55
+ [no_rectangle? ? 0 : 16, c_chars.to_i * width]
56
+ end
57
+
58
+ def available_body(required_length)
59
+ bytes = body.to_s
60
+ raise ArgumentError, "truncated small text output body" if bytes.bytesize < required_length
61
+
62
+ bytes
63
+ end
64
+
65
+ def write_body_bytes(offset, length, value)
66
+ bytes = available_body(offset + length)
67
+ unless value.is_a?(String) && value.bytesize == length
68
+ raise ArgumentError, "small text output value must be a String of #{length} bytes"
69
+ end
70
+
71
+ replacement = bytes.b
72
+ replacement[offset, length] = value.b
73
+ self.body = replacement
74
+ end
24
75
  end
25
76
  end
26
77
  end
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "bindata"
4
+ require "emf/emr/binary/variable_buffers"
4
5
  require "emf/emr/binary/with_bounds"
6
+ require "emf/emr/binary/dib_header"
5
7
 
6
8
  module Emf
7
9
  module Emr
@@ -16,6 +18,12 @@ module Emf
16
18
  # a fixed-size :bytes buffer (NOT :rest, which would consume the
17
19
  # whole tail).
18
20
  class StretchBlt < Emf::Emr::Binary::WithBounds
21
+ include Emf::Emr::Binary::VariableBuffers
22
+
23
+ fixed_layout 108
24
+ variable_buffer :bmi_bytes, offset: :off_bmi_src, length: :cb_bmi_src
25
+ variable_buffer :bits_bytes, offset: :off_bits_src, length: :cb_bits_src
26
+
19
27
  int32le :x_dest
20
28
  int32le :y_dest
21
29
  int32le :cx_dest
@@ -32,6 +40,12 @@ module Emf
32
40
  int32le :cx_src
33
41
  int32le :cy_src
34
42
  rest :body
43
+
44
+ # Read-only; computed from the current fields on each call.
45
+ def dib_header_view
46
+ DibHeader.view(off_bmi_src, cb_bmi_src, 108, body,
47
+ bits_offset: off_bits_src, bits_size: cb_bits_src)
48
+ end
35
49
  end
36
50
  end
37
51
  end
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "bindata"
4
+ require "emf/emr/binary/variable_buffers"
4
5
  require "emf/emr/binary/with_bounds"
6
+ require "emf/emr/binary/dib_header"
5
7
 
6
8
  module Emf
7
9
  module Emr
@@ -20,6 +22,12 @@ module Emf
20
22
  # cxDest, cyDest (int32)
21
23
  # [trailing BITMAPINFO + pixel array]
22
24
  class StretchDIBits < Emf::Emr::Binary::WithBounds
25
+ include Emf::Emr::Binary::VariableBuffers
26
+
27
+ fixed_layout 80
28
+ variable_buffer :bmi_bytes, offset: :off_bmi_src, length: :cb_bmi_src
29
+ variable_buffer :bits_bytes, offset: :off_bits_src, length: :cb_bits_src
30
+
23
31
  int32 :x_dest
24
32
  int32 :y_dest
25
33
  int32 :x_src
@@ -35,6 +43,12 @@ module Emf
35
43
  int32 :cx_dest
36
44
  int32 :cy_dest
37
45
  rest :trailing
46
+
47
+ # Read-only; computed from the current fields on each call.
48
+ def dib_header_view
49
+ DibHeader.view(off_bmi_src, cb_bmi_src, 80, trailing,
50
+ bits_offset: off_bits_src, bits_size: cb_bits_src)
51
+ end
38
52
  end
39
53
  end
40
54
  end
@@ -1,15 +1,58 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "bindata"
4
+ require "emf/emr/binary/variable_buffers"
4
5
  require "emf/emr/binary/with_bounds"
6
+ require "emf/emr/binary/dib_header"
5
7
 
6
8
  module Emf
7
9
  module Emr
8
10
  module Binary
9
11
  module Records
10
12
  # Stub: leading fields per MS-EMF, body captures remaining bytes.
13
+ # The fixed part is 108 bytes including the EMR header; the bitmap
14
+ # pointers are read from body without declaring fields.
11
15
  class TransparentBlt < Emf::Emr::Binary::WithBounds
16
+ include Emf::Emr::Binary::VariableBuffers
17
+
18
+ fixed_layout 108
19
+ variable_buffer :bmi_bytes, offset: :off_bmi_src, length: :cb_bmi_src
20
+ variable_buffer :bits_bytes, offset: :off_bits_src, length: :cb_bits_src
21
+
12
22
  rest :body
23
+
24
+ # Read-only accessors computed from body on each call; body starts at
25
+ # record offset 24, so a record offset maps to (offset - 24) in body.
26
+ def off_bmi_src
27
+ pointers(60)[0]
28
+ end
29
+
30
+ def cb_bmi_src
31
+ pointers(60)[1]
32
+ end
33
+
34
+ def off_bits_src
35
+ pointers(60)[2]
36
+ end
37
+
38
+ def cb_bits_src
39
+ pointers(60)[3]
40
+ end
41
+
42
+ def dib_header_view
43
+ DibHeader.view(off_bmi_src, cb_bmi_src, 108, after_fixed,
44
+ bits_offset: off_bits_src, bits_size: cb_bits_src)
45
+ end
46
+
47
+ private
48
+
49
+ def after_fixed
50
+ body.to_s.byteslice(84..).to_s
51
+ end
52
+
53
+ def pointers(offset)
54
+ body.to_s.byteslice(offset, 16).to_s.unpack("V4").map(&:to_i)
55
+ end
13
56
  end
14
57
  end
15
58
  end
@@ -12,6 +12,7 @@ module Emf
12
12
  autoload :Raw, "emf/emr/binary/records/raw"
13
13
  autoload :Eof, "emf/emr/binary/records/eof"
14
14
  autoload :SetTextColor, "emf/emr/binary/records/set_text_color"
15
+ autoload :SetColorAdjustment, "emf/emr/binary/records/set_color_adjustment"
15
16
  autoload :SetBkColor, "emf/emr/binary/records/set_bk_color"
16
17
  autoload :SetBkMode, "emf/emr/binary/records/set_bk_mode"
17
18
  autoload :SetMapMode, "emf/emr/binary/records/set_map_mode"
@@ -99,7 +100,7 @@ module Emf
99
100
  autoload :StretchBlt, "emf/emr/binary/records/stretch_blt"
100
101
  autoload :MaskBlt, "emf/emr/binary/records/mask_blt"
101
102
  autoload :PlgBlt, "emf/emr/binary/records/plg_blt"
102
- autoload :SetDIBitsToDevice, "emf/emr/binary/records/set_dibits_to_device"
103
+ autoload :SetDibitsToDevice, "emf/emr/binary/records/set_dibits_to_device"
103
104
  autoload :AlphaBlend, "emf/emr/binary/records/alpha_blend"
104
105
  autoload :TransparentBlt, "emf/emr/binary/records/transparent_blt"
105
106
  autoload :SetLayout, "emf/emr/binary/records/set_layout"
@@ -218,7 +219,7 @@ module Emf
218
219
  Binary::TypeCodes::STRETCHBLT => :StretchBlt,
219
220
  Binary::TypeCodes::MASKBLT => :MaskBlt,
220
221
  Binary::TypeCodes::PLGBLT => :PlgBlt,
221
- Binary::TypeCodes::SETDIBITSTODEVICE => :SetDIBitsToDevice,
222
+ Binary::TypeCodes::SETDIBITSTODEVICE => :SetDibitsToDevice,
222
223
  Binary::TypeCodes::ALPHABLEND => :AlphaBlend,
223
224
  Binary::TypeCodes::SETLAYOUT => :SetLayout,
224
225
  Binary::TypeCodes::TRANSPARENTBLT => :TransparentBlt,
@@ -239,6 +240,7 @@ module Emf
239
240
  Binary::TypeCodes::CREATECOLORSPACEW => :CreateColorspaceW,
240
241
  Binary::TypeCodes::CREATECOLORSPACE => :CreateColorspace,
241
242
  Binary::TypeCodes::SETCOLORSPACE => :SetColorspace,
243
+ Binary::TypeCodes::SETCOLORADJUSTMENT => :SetColorAdjustment,
242
244
  Binary::TypeCodes::DELETECOLORSPACE => :DeleteColorspace,
243
245
  Binary::TypeCodes::GLSRECORD => :GlsRecord,
244
246
  Binary::TypeCodes::GLSBOUNDEDRECORD => :GlsBoundedRecord,
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bindata"
4
+ require "emf/binary/types"
5
+
6
+ module Emf
7
+ module Emr
8
+ module Binary
9
+ # MS-EMF 2.2.24: a 32-byte header followed by RectL objects.
10
+ class RegionData < BinData::Record
11
+ mandatory_parameter :byte_length
12
+ endian :little
13
+ uint32 :header_size, initial_value: 32
14
+ uint32 :region_type
15
+ uint32 :count_rects
16
+ uint32 :rgn_size
17
+ rectl :bounds
18
+ array :rectangles, type: :rectl, initial_length: :bounded_rectangle_count
19
+ string :trailing, read_length: -> { [eval_parameter(:byte_length) - 32 - (count_rects * 16), 0].max }
20
+
21
+ def bounded_rectangle_count
22
+ length = eval_parameter(:byte_length)
23
+ count = count_rects.to_i
24
+ raise BinData::ValidityError, "region rectangles exceed declared region data length" if length < 32 || count * 16 > length - 32
25
+
26
+ count
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ BinData::RegisteredClasses.register("region_data", Emf::Emr::Binary::RegionData)
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emf
4
+ module Emr
5
+ module Binary
6
+ module StateRecordBody
7
+ class Body < String
8
+ def initialize(record, bytes)
9
+ @record = record
10
+ super(bytes)
11
+ end
12
+
13
+ def assign(bytes)
14
+ @record.body = bytes
15
+ replace(@record.body)
16
+ end
17
+ end
18
+
19
+ def body
20
+ Body.new(self, to_binary_s.byteslice(8..))
21
+ end
22
+
23
+ def body=(value)
24
+ bytes = value.to_s
25
+ raise ArgumentError, "invalid state record body length" if bytes.bytesize < self.class::BODY_SIZE
26
+
27
+ replacement = self.class.read(to_binary_s.byteslice(0, 8) + bytes)
28
+ assign(replacement.snapshot)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end