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
@@ -13,16 +13,142 @@ module Emf
13
13
  # `offset` is the byte offset within the source stream (for diagnostics).
14
14
  class WireAdapter < Emf::Model::Record
15
15
  Emf::Model::Visitor.register_visit(:visit_emr_wire_record, self)
16
+ include Emf::Model::Emr::WireValues
16
17
 
17
- def initialize(wire:, offset: nil)
18
+ # Internal native construction path; the source owns copied Ruby data only.
19
+ # One per parsed record, so it skips keyword construction; the suffix
20
+ # is the source's once the wire is made.
21
+ def self.lazy(source:, offset: nil)
22
+ allocate.__send__(:init_lazy, source, offset)
23
+ end
24
+
25
+ # Opt-in construction of a wire record from keyword attributes, with
26
+ # n_size set to the record's size, as `klass.new(**attrs)` followed by
27
+ # `n_size = num_bytes`. For a class with a PackPlan and attributes it
28
+ # accepts (values BinData stores unchanged), the adapter holds only the
29
+ # finished bytes; `to_binary_s` serves them until `#wire` is called,
30
+ # after which the adapter serializes that wire like any other. Any
31
+ # other class or attribute shape, or an error while packing, takes the
32
+ # BinData path unchanged, so the result and the errors are those of
33
+ # `klass.new`.
34
+ def self.build(klass, **attrs)
35
+ filler = Emf::Emr::Binary::FastFill.for_class(klass)
36
+ bytes = filler && packed_bytes(filler, attrs)
37
+ return allocate.__send__(:init_lazy, BuiltBytes.new(klass, filler, bytes), nil) if bytes
38
+
39
+ wire = klass.new(**attrs)
40
+ wire.n_size = wire.num_bytes
41
+ new(wire: wire)
42
+ end
43
+
44
+ def self.packed_bytes(filler, attrs)
45
+ filler.pack_plan&.pack(attrs)
46
+ rescue StandardError
47
+ nil
48
+ end
49
+ private_class_method :packed_bytes
50
+
51
+ # The lazy source of a record built by `build`: its bytes, and a
52
+ # wire read back from them when one is asked for.
53
+ class BuiltBytes
54
+ def initialize(klass, filler, bytes)
55
+ @klass = klass
56
+ @filler = filler
57
+ @bytes = (bytes.encoding == Encoding::BINARY ? bytes : bytes.b).freeze
58
+ end
59
+
60
+ def type_id
61
+ @bytes.unpack1("V")
62
+ end
63
+
64
+ def wire_class
65
+ @klass
66
+ end
67
+
68
+ def value_source
69
+ [@bytes, 0, true]
70
+ end
71
+
72
+ def to_binary_s
73
+ @bytes.dup
74
+ end
75
+
76
+ def append_to(out)
77
+ out << @bytes
78
+ end
79
+
80
+ def materialize
81
+ @filler.call_at(@bytes, 0, @bytes.bytesize)&.first || @klass.read(@bytes)
82
+ end
83
+
84
+ def suffix(_wire)
85
+ EMPTY_SUFFIX
86
+ end
87
+ end
88
+
89
+ # Bytes of a record that follow its typed layout (declared nSize larger
90
+ # than the layout consumes). Kept verbatim beside the wire.
91
+ EMPTY_SUFFIX = "".b.freeze
92
+ private_constant :EMPTY_SUFFIX
93
+
94
+ def self.suffix_of(record_bytes, wire)
95
+ extra = record_bytes.bytesize - wire.num_bytes
96
+ return EMPTY_SUFFIX unless extra.positive?
97
+
98
+ record_bytes.byteslice(-extra, extra).b.freeze
99
+ end
100
+
101
+ def initialize(wire:, offset: nil, suffix: EMPTY_SUFFIX)
18
102
  @wire = wire
19
103
  @offset = offset
104
+ @suffix = suffix
20
105
  end
21
106
 
22
- attr_reader :wire, :offset
107
+ attr_reader :offset
108
+
109
+ def wire
110
+ return @wire if @wire
111
+
112
+ @wire = @wire_source.materialize
113
+ @suffix = @wire_source.suffix(@wire)
114
+ @wire_source = nil
115
+ @wire
116
+ end
117
+
118
+ def suffix
119
+ wire
120
+ @suffix
121
+ end
122
+
123
+ def to_binary_s
124
+ return @wire_source.to_binary_s unless @wire
125
+
126
+ bytes = @wire.to_binary_s
127
+ return bytes if @suffix.empty?
128
+
129
+ bytes[4, 4] = [bytes.bytesize + @suffix.bytesize].pack("V")
130
+ bytes + @suffix
131
+ end
132
+
133
+ # Appends this record's wire bytes to `out` (a binary String). A record
134
+ # still held as bytes appends them without a copy; once `#wire` has
135
+ # been made the wire is the truth and is packed, so an edit is never
136
+ # served from stale bytes.
137
+ def append_to(out)
138
+ return @wire_source.append_to(out) unless @wire
139
+
140
+ return out if @suffix.empty? && @wire.append_built_to?(out)
141
+
142
+ out << to_binary_s
143
+ end
23
144
 
24
145
  def type_id
25
- @wire.i_type
146
+ @wire ? @wire.i_type : @wire_source.type_id
147
+ end
148
+
149
+ # The wire class of the record, without making the wire.
150
+ def wire_class
151
+ @wire ? @wire.class : @wire_source.wire_class
26
152
  end
27
153
 
28
154
  def accept(visitor)
@@ -30,16 +156,26 @@ module Emf
30
156
  end
31
157
 
32
158
  def ==(other)
33
- other.is_a?(self.class) && wire.to_binary_s == other.wire.to_binary_s
159
+ other.is_a?(self.class) && to_binary_s == other.to_binary_s
34
160
  end
35
161
  alias eql? ==
36
162
 
37
163
  def hash
38
- [self.class, wire.to_binary_s].hash
164
+ [self.class, to_binary_s].hash
39
165
  end
40
166
 
41
167
  def inspect
42
- "#<#{self.class.name} type_id=#{type_id} (#{(@wire.class.name || '').split('::').last})>"
168
+ "#<#{self.class.name} type_id=#{type_id} (#{(wire.class.name || '').split('::').last})>"
169
+ end
170
+
171
+ private
172
+
173
+ def init_lazy(source, offset)
174
+ @wire = nil
175
+ @offset = offset
176
+ @suffix = EMPTY_SUFFIX
177
+ @wire_source = source
178
+ self
43
179
  end
44
180
  end
45
181
  end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emf
4
+ module Model
5
+ module Emr
6
+ # `WireAdapter#values`: the record's field values as plain frozen Ruby
7
+ # objects, without making BinData field objects. See
8
+ # Emf::Emr::Binary::ValueView for the shape.
9
+ module WireValues
10
+ # The field values the record holds now, or nil when its wire class
11
+ # has no value view (variable-layout records such as ExtTextOut,
12
+ # strings, bitmaps and Raw): use `wire` for those.
13
+ #
14
+ # A field of the wire not made yet is still the record's bytes, so
15
+ # the values are unpacked from them (one String#unpack; kept and
16
+ # returned again while no field has been made). A field made through
17
+ # `wire` may have been edited, so it is read from the wire and the
18
+ # rest from the bytes. An edit through `wire` is always reflected.
19
+ # Equal on the Ruby and native backends.
20
+ def values
21
+ view = Emf::Emr::Binary::ValueView.for_class(@wire ? @wire.class : @wire_source.wire_class)
22
+ return unless view
23
+
24
+ data, base, untouched = byte_source
25
+ if data
26
+ found = untouched ? (@values ||= view.from_bytes(data, base)) : view.from_mixed(data, base, @wire)
27
+ return found if found
28
+ end
29
+ view.from_wire(wire)
30
+ end
31
+
32
+ private
33
+
34
+ # [data, offset, untouched] of the bytes the record is filled from.
35
+ def byte_source
36
+ return @wire_source.value_source unless @wire
37
+
38
+ @wire.lazy_source if @wire.respond_to?(:lazy_source)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
data/lib/emf/model/emr.rb CHANGED
@@ -4,6 +4,7 @@ module Emf
4
4
  module Model
5
5
  module Emr
6
6
  autoload :Header, "emf/model/emr/header"
7
+ autoload :WireValues, "emf/model/emr/wire_values"
7
8
  autoload :Records, "emf/model/emr/records"
8
9
  end
9
10
  end
@@ -4,6 +4,20 @@ module Emf
4
4
  module Model
5
5
  module Geometry
6
6
  class Color
7
+ # One instantiated ColorRef and its field slots, built on first use.
8
+ module WireTemplate
9
+ module_function
10
+
11
+ def get
12
+ @get ||= begin
13
+ sample = Binary::Types::ColorRef.new
14
+ sample.field_names.each { |name| sample.public_send(name) }
15
+ [sample, Emf::Emr::Binary::WireCopy.slots(sample)].freeze
16
+ end
17
+ end
18
+ end
19
+ private_constant :WireTemplate
20
+
7
21
  def initialize(red:, green:, blue:, alpha: 255)
8
22
  @red = coerce(red)
9
23
  @green = coerce(green)
@@ -17,8 +31,12 @@ module Emf
17
31
  new(red: wire.red, green: wire.green, blue: wire.blue, alpha: wire.reserved.zero? ? 255 : wire.reserved)
18
32
  end
19
33
 
34
+ # Same ColorRef as `ColorRef.new(red:, green:, blue:, reserved:)`,
35
+ # built from a copy of one instantiated ColorRef instead of BinData's
36
+ # lazy construction (the record builders call this once per color).
20
37
  def to_wire
21
- Binary::Types::ColorRef.new(red: red, green: green, blue: blue, reserved: alpha)
38
+ template, slots = WireTemplate.get
39
+ Emf::Emr::Binary::WireCopy.build(template, slots, { red: red, green: green, blue: blue, reserved: alpha })
22
40
  end
23
41
 
24
42
  def to_hex
@@ -5,16 +5,25 @@ module Emf
5
5
  class Metafile
6
6
  include Enumerable
7
7
 
8
- def initialize(format:, header:, records:, errors: [], emf_plus: nil, trailing: "")
8
+ def initialize(format:, header:, records:, errors: [], emf_plus: nil, trailing: "", emf_plus_source: nil, diagnostics: [])
9
9
  @format = format
10
10
  @header = header
11
11
  @records = records.freeze
12
12
  @errors = errors.freeze
13
+ @diagnostics = diagnostics.dup.freeze
13
14
  @emf_plus = emf_plus
14
15
  @trailing = trailing.freeze
16
+ @emf_plus_source = emf_plus_source
15
17
  end
16
18
 
17
- attr_reader :format, :header, :records, :errors, :emf_plus, :trailing
19
+ attr_reader :format, :header, :records, :errors, :emf_plus, :trailing, :diagnostics
20
+
21
+ # Return a new view while retaining backend-specific lazy sources.
22
+ def with_diagnostics(diagnostics)
23
+ copy = dup
24
+ copy.instance_variable_set(:@diagnostics, diagnostics.dup.freeze)
25
+ copy
26
+ end
18
27
 
19
28
  def each(&block)
20
29
  return to_enum unless block
@@ -22,6 +31,17 @@ module Emf
22
31
  @records.each(&block)
23
32
  end
24
33
 
34
+ # Typed EMF+ view; nil unless this is an EMF+ metafile. Memoised because
35
+ # the metafile is immutable; `reload: true` rebuilds it from the current comment bytes.
36
+ # A backend may supply `emf_plus_source` (called with the metafile and `reload`);
37
+ # a nil result falls back to the Ruby stream.
38
+ def emf_plus_stream(reload: false)
39
+ return unless format == :emf_plus
40
+
41
+ @emf_plus_stream = nil if reload
42
+ @emf_plus_stream ||= @emf_plus_source&.call(self, reload) || Emf::EmfPlus::Stream.from_metafile(self)
43
+ end
44
+
25
45
  def errors?
26
46
  !@errors.empty?
27
47
  end
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emf
4
+ module Model
5
+ module Wmf
6
+ module Records
7
+ # Typed bitmap interior (Emf::Wmf::BitmapImage.of); raw `bitmap` stays authoritative.
8
+ module TypedImage
9
+ def typed_image = Emf::Wmf::BitmapImage.of(self)
10
+ end
11
+
12
+ class BitBlt < Record
13
+ include TypedImage
14
+
15
+ def initialize(raster_operation:, source_y:, source_x:, height:, width:, destination_y:, destination_x:, bitmap: nil,
16
+ reserved: 0, suffix: "".b, offset: nil, type_id: 0x0922)
17
+ super(type_id: type_id, offset: offset)
18
+ @raster_operation = raster_operation
19
+ @source_y = source_y
20
+ @source_x = source_x
21
+ @height = height
22
+ @width = width
23
+ @destination_y = destination_y
24
+ @destination_x = destination_x
25
+ @bitmap = bitmap
26
+ @reserved = reserved
27
+ @suffix = suffix
28
+ end
29
+
30
+ attr_accessor :raster_operation, :source_y, :source_x, :height, :width, :destination_y, :destination_x, :bitmap, :reserved,
31
+ :suffix
32
+ end
33
+
34
+ class DibBitBlt < Record
35
+ include TypedImage
36
+
37
+ def initialize(raster_operation:, source_y:, source_x:, height:, width:, destination_y:, destination_x:, bitmap: nil,
38
+ reserved: 0, suffix: "".b, offset: nil, type_id: 0x0940)
39
+ super(type_id: type_id, offset: offset)
40
+ @raster_operation = raster_operation
41
+ @source_y = source_y
42
+ @source_x = source_x
43
+ @height = height
44
+ @width = width
45
+ @destination_y = destination_y
46
+ @destination_x = destination_x
47
+ @bitmap = bitmap
48
+ @reserved = reserved
49
+ @suffix = suffix
50
+ end
51
+
52
+ attr_accessor :raster_operation, :source_y, :source_x, :height, :width, :destination_y, :destination_x, :bitmap, :reserved,
53
+ :suffix
54
+ end
55
+
56
+ class StretchBlt < Record
57
+ include TypedImage
58
+
59
+ def initialize(raster_operation:, source_height:, source_width:, source_y:, source_x:, destination_height:,
60
+ destination_width:, destination_y:, destination_x:, bitmap: nil, reserved: 0, suffix: "".b, offset: nil,
61
+ type_id: 0x0B23)
62
+ super(type_id: type_id, offset: offset)
63
+ @raster_operation = raster_operation
64
+ @source_height = source_height
65
+ @source_width = source_width
66
+ @source_y = source_y
67
+ @source_x = source_x
68
+ @destination_height = destination_height
69
+ @destination_width = destination_width
70
+ @destination_y = destination_y
71
+ @destination_x = destination_x
72
+ @bitmap = bitmap
73
+ @reserved = reserved
74
+ @suffix = suffix
75
+ end
76
+
77
+ attr_accessor :raster_operation, :source_height, :source_width, :source_y, :source_x, :destination_height, :destination_width,
78
+ :destination_y, :destination_x, :bitmap, :reserved, :suffix
79
+ end
80
+
81
+ class DibStretchBlt < Record
82
+ include TypedImage
83
+
84
+ def initialize(raster_operation:, source_height:, source_width:, source_y:, source_x:, destination_height:,
85
+ destination_width:, destination_y:, destination_x:, bitmap: nil, reserved: 0, suffix: "".b, offset: nil,
86
+ type_id: 0x0B41)
87
+ super(type_id: type_id, offset: offset)
88
+ @raster_operation = raster_operation
89
+ @source_height = source_height
90
+ @source_width = source_width
91
+ @source_y = source_y
92
+ @source_x = source_x
93
+ @destination_height = destination_height
94
+ @destination_width = destination_width
95
+ @destination_y = destination_y
96
+ @destination_x = destination_x
97
+ @bitmap = bitmap
98
+ @reserved = reserved
99
+ @suffix = suffix
100
+ end
101
+
102
+ attr_accessor :raster_operation, :source_height, :source_width, :source_y, :source_x, :destination_height, :destination_width,
103
+ :destination_y, :destination_x, :bitmap, :reserved, :suffix
104
+ end
105
+
106
+ class SetDibToDev < Record
107
+ include TypedImage
108
+
109
+ def initialize(color_usage:, scan_count:, start_scan:, source_y:, source_x:, height:, width:, destination_y:,
110
+ destination_x:, bitmap:, suffix: "".b, offset: nil, type_id: 0x0D33)
111
+ super(type_id: type_id, offset: offset)
112
+ @color_usage = color_usage
113
+ @scan_count = scan_count
114
+ @start_scan = start_scan
115
+ @source_y = source_y
116
+ @source_x = source_x
117
+ @height = height
118
+ @width = width
119
+ @destination_y = destination_y
120
+ @destination_x = destination_x
121
+ @bitmap = bitmap
122
+ @suffix = suffix
123
+ end
124
+
125
+ attr_accessor :color_usage, :scan_count, :start_scan, :source_y, :source_x, :height, :width, :destination_y, :destination_x,
126
+ :bitmap, :suffix
127
+ end
128
+
129
+ class StretchDib < Record
130
+ include TypedImage
131
+
132
+ def initialize(raster_operation:, color_usage:, source_height:, source_width:, source_y:, source_x:, destination_height:,
133
+ destination_width:, destination_y:, destination_x:, bitmap:, suffix: "".b, offset: nil, type_id: 0x0F43)
134
+ super(type_id: type_id, offset: offset)
135
+ @raster_operation = raster_operation
136
+ @color_usage = color_usage
137
+ @source_height = source_height
138
+ @source_width = source_width
139
+ @source_y = source_y
140
+ @source_x = source_x
141
+ @destination_height = destination_height
142
+ @destination_width = destination_width
143
+ @destination_y = destination_y
144
+ @destination_x = destination_x
145
+ @bitmap = bitmap
146
+ @suffix = suffix
147
+ end
148
+
149
+ attr_accessor :raster_operation, :color_usage, :source_height, :source_width, :source_y, :source_x, :destination_height,
150
+ :destination_width, :destination_y, :destination_x, :bitmap, :suffix
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emf
4
+ module Model
5
+ module Wmf
6
+ module Records
7
+ class CreatePatternBrush < Record
8
+ def initialize(bitmap_type:, width:, height:, width_bytes:, planes:, bits_pixel:, bits:, reserved:, pattern:,
9
+ offset: nil, suffix: "".b, type_id: 0x01F9)
10
+ super(type_id: type_id, offset: offset)
11
+ @bitmap_type = bitmap_type
12
+ @width = width
13
+ @height = height
14
+ @width_bytes = width_bytes
15
+ @planes = planes
16
+ @bits_pixel = bits_pixel
17
+ @bits = bits
18
+ @reserved = reserved
19
+ @pattern = pattern
20
+ @suffix = suffix
21
+ end
22
+
23
+ attr_accessor :bitmap_type, :width, :height, :width_bytes, :planes, :bits_pixel, :bits, :reserved, :pattern, :suffix
24
+ end
25
+
26
+ class DibCreatePatternBrush < Record
27
+ def initialize(style:, color_usage:, target:, offset: nil, type_id: 0x0142)
28
+ super(type_id: type_id, offset: offset)
29
+ @style = style
30
+ @color_usage = color_usage
31
+ @target = target
32
+ end
33
+
34
+ attr_accessor :style, :color_usage, :target
35
+
36
+ # BS_PATTERN (style 3) ignores the stored color usage and always uses RGB colors.
37
+ def effective_color_usage = style == 3 ? 0 : color_usage
38
+
39
+ # Packed DIB view of the raw target (Emf::Wmf::Dib::Image), or nil if unsupported.
40
+ def target_dib = Emf::Wmf::Dib.parse(target, effective_color_usage)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emf
4
+ module Model
5
+ module Wmf
6
+ module Records
7
+ class SaveDc < StateRecord
8
+ WIRE_FIELDS = [].freeze
9
+ WIRE_TYPES = [].freeze
10
+ WIRE_FORMAT = ""
11
+ PAYLOAD_BYTES = 0
12
+
13
+ def initialize(offset: nil, suffix: "".b, type_id: 0x001E)
14
+ super
15
+ end
16
+ end
17
+
18
+ class RestoreDc < StateRecord
19
+ WIRE_FIELDS = %i[saved_dc].freeze
20
+ WIRE_TYPES = %i[int16].freeze
21
+ WIRE_FORMAT = "s<"
22
+ PAYLOAD_BYTES = 2
23
+
24
+ def initialize(saved_dc:, offset: nil, suffix: "".b, type_id: 0x0127)
25
+ super(type_id: type_id, offset: offset, suffix: suffix)
26
+ @saved_dc = saved_dc
27
+ end
28
+
29
+ attr_accessor :saved_dc
30
+ end
31
+
32
+ # Reserved record: every body byte belongs to the preserved suffix.
33
+ class SetRelAbs < StateRecord
34
+ WIRE_FIELDS = [].freeze
35
+ WIRE_TYPES = [].freeze
36
+ WIRE_FORMAT = ""
37
+ PAYLOAD_BYTES = 0
38
+
39
+ def initialize(offset: nil, suffix: "".b, type_id: 0x0105)
40
+ super
41
+ end
42
+ end
43
+
44
+ # Escape data stays inert, including recognized driver subfunctions.
45
+ class Escape < Record
46
+ def initialize(escape_function:, data:, padding: nil, offset: nil, suffix: "".b, type_id: 0x0626)
47
+ super(type_id: type_id, offset: offset)
48
+ @escape_function = escape_function
49
+ @data = data
50
+ @padding = padding
51
+ @suffix = suffix
52
+ end
53
+
54
+ attr_accessor :escape_function, :data, :padding, :suffix
55
+
56
+ # Read-only typed views; each returns nil when the subtype or layout does not match.
57
+ def typed_payload = Emf::Wmf::EscapeViews.typed_payload(self)
58
+ def typed_counted_payload = Emf::Wmf::EscapeViews.typed_counted_payload(self)
59
+ def typed_special_passthrough2_payload = Emf::Wmf::EscapeViews.typed_special_passthrough2_payload(self)
60
+
61
+ # Validated 0x000F segment; raises Emf::Wmf::EmbeddedEmf::Invalid with a reason.
62
+ def embedded_emf_segment = Emf::Wmf::EmbeddedEmf.segment(self)
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emf
4
+ module Model
5
+ module Wmf
6
+ module Records
7
+ class CreateFontIndirect < ObjectRecord
8
+ SIGNED_FIELDS = %i[height width escapement orientation weight].freeze
9
+ BYTE_FIELDS = %i[italic underline strike_out char_set out_precision clip_precision quality pitch_and_family].freeze
10
+ WIRE_FIELDS = (SIGNED_FIELDS + BYTE_FIELDS + [:face_name]).freeze
11
+ WIRE_FORMAT = "s<5C8a32"
12
+ PAYLOAD_BYTES = 50
13
+
14
+ def initialize(height:, width:, escapement:, orientation:, weight:, italic:, underline:, strike_out:,
15
+ char_set:, out_precision:, clip_precision:, quality:, pitch_and_family:, face_name:,
16
+ offset: nil, type_id: 0x02FB, suffix: "")
17
+ super(type_id: type_id, offset: offset)
18
+ @height = height
19
+ @width = width
20
+ @escapement = escapement
21
+ @orientation = orientation
22
+ @weight = weight
23
+ @italic = italic
24
+ @underline = underline
25
+ @strike_out = strike_out
26
+ @char_set = char_set
27
+ @out_precision = out_precision
28
+ @clip_precision = clip_precision
29
+ @quality = quality
30
+ @pitch_and_family = pitch_and_family
31
+ @face_name = face_name
32
+ @suffix = suffix
33
+ end
34
+
35
+ attr_accessor(*WIRE_FIELDS, :suffix)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end