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.
- checksums.yaml +4 -4
- data/README.adoc +224 -19
- data/exe/emf +12 -0
- data/lib/emf/backend.rb +60 -0
- data/lib/emf/binary/class_field_accessors.rb +49 -0
- data/lib/emf/binary/float32_le.rb +54 -0
- data/lib/emf/binary/types.rb +40 -6
- data/lib/emf/conformance/context.rb +36 -0
- data/lib/emf/conformance/diagnostic.rb +18 -0
- data/lib/emf/conformance/manifest/emf_bitmap_misc.yml +622 -0
- data/lib/emf/conformance/manifest/emf_control_buffers.yml +61 -0
- data/lib/emf/conformance/manifest/emf_core.yml +117 -0
- data/lib/emf/conformance/manifest/emf_corpus_rules.yml +21 -0
- data/lib/emf/conformance/manifest/emf_objects_geometry.yml +229 -0
- data/lib/emf/conformance/manifest/emf_plus.yml +357 -0
- data/lib/emf/conformance/manifest/emf_plus_core.yml +33 -0
- data/lib/emf/conformance/manifest/emf_state_path.yml +403 -0
- data/lib/emf/conformance/manifest/emf_text.yml +97 -0
- data/lib/emf/conformance/manifest/wmf.yml +874 -0
- data/lib/emf/conformance/manifest.rb +79 -0
- data/lib/emf/conformance/profile.rb +35 -0
- data/lib/emf/conformance/record_types.rb +24 -0
- data/lib/emf/conformance/registry.rb +76 -0
- data/lib/emf/conformance/report.rb +83 -0
- data/lib/emf/conformance/rule.rb +16 -0
- data/lib/emf/conformance/rules/emf_bitmap.rb +357 -0
- data/lib/emf/conformance/rules/emf_comment_escape.rb +309 -0
- data/lib/emf/conformance/rules/emf_control_buffers.rb +137 -0
- data/lib/emf/conformance/rules/emf_corpus_named.rb +83 -0
- data/lib/emf/conformance/rules/emf_framing.rb +94 -0
- data/lib/emf/conformance/rules/emf_geometry.rb +282 -0
- data/lib/emf/conformance/rules/emf_header.rb +114 -0
- data/lib/emf/conformance/rules/emf_objects.rb +291 -0
- data/lib/emf/conformance/rules/emf_parse_recovery.rb +97 -0
- data/lib/emf/conformance/rules/emf_path_clip.rb +165 -0
- data/lib/emf/conformance/rules/emf_plus.rb +75 -0
- data/lib/emf/conformance/rules/emf_plus_common.rb +58 -0
- data/lib/emf/conformance/rules/emf_plus_drawing.rb +78 -0
- data/lib/emf/conformance/rules/emf_plus_effects.rb +104 -0
- data/lib/emf/conformance/rules/emf_plus_fields.rb +169 -0
- data/lib/emf/conformance/rules/emf_plus_fields_b.rb +102 -0
- data/lib/emf/conformance/rules/emf_plus_framing.rb +172 -0
- data/lib/emf/conformance/rules/emf_plus_objects.rb +97 -0
- data/lib/emf/conformance/rules/emf_plus_payloads.rb +320 -0
- data/lib/emf/conformance/rules/emf_plus_properties.rb +96 -0
- data/lib/emf/conformance/rules/emf_plus_state.rb +77 -0
- data/lib/emf/conformance/rules/emf_state.rb +244 -0
- data/lib/emf/conformance/rules/emf_text.rb +221 -0
- data/lib/emf/conformance/rules/emf_transform.rb +85 -0
- data/lib/emf/conformance/rules/wmf_buffers.rb +259 -0
- data/lib/emf/conformance/rules/wmf_framing.rb +146 -0
- data/lib/emf/conformance/rules/wmf_layout_records.rb +112 -0
- data/lib/emf/conformance/rules/wmf_objects.rb +168 -0
- data/lib/emf/conformance/rules/wmf_records.rb +191 -0
- data/lib/emf/conformance/rules/wmf_rejections.rb +184 -0
- data/lib/emf/conformance/runner.rb +61 -0
- data/lib/emf/conformance/ternary_raster_operations.rb +52 -0
- data/lib/emf/conformance.rb +31 -0
- data/lib/emf/emf_plus/effects/blur.rb +24 -0
- data/lib/emf/emf_plus/effects/brightness_contrast.rb +22 -0
- data/lib/emf/emf_plus/effects/color_balance.rb +24 -0
- data/lib/emf/emf_plus/effects/color_curve.rb +24 -0
- data/lib/emf/emf_plus/effects/color_lookup_table.rb +26 -0
- data/lib/emf/emf_plus/effects/color_matrix.rb +23 -0
- data/lib/emf/emf_plus/effects/effect.rb +50 -0
- data/lib/emf/emf_plus/effects/hue_saturation_lightness.rb +24 -0
- data/lib/emf/emf_plus/effects/levels.rb +24 -0
- data/lib/emf/emf_plus/effects/opaque.rb +19 -0
- data/lib/emf/emf_plus/effects/red_eye_correction.rb +35 -0
- data/lib/emf/emf_plus/effects/sharpen.rb +24 -0
- data/lib/emf/emf_plus/effects/tint.rb +22 -0
- data/lib/emf/emf_plus/effects.rb +45 -0
- data/lib/emf/emf_plus/frame.rb +41 -0
- data/lib/emf/emf_plus/links/effect_link.rb +16 -0
- data/lib/emf/emf_plus/links/get_dc_span.rb +18 -0
- data/lib/emf/emf_plus/links/link_error.rb +15 -0
- data/lib/emf/emf_plus/links.rb +77 -0
- data/lib/emf/emf_plus/object_chain.rb +108 -0
- data/lib/emf/emf_plus/object_table.rb +182 -0
- data/lib/emf/emf_plus/objects/brush.rb +296 -0
- data/lib/emf/emf_plus/objects/custom_line_cap.rb +106 -0
- data/lib/emf/emf_plus/objects/font.rb +47 -0
- data/lib/emf/emf_plus/objects/image.rb +68 -0
- data/lib/emf/emf_plus/objects/image_attributes.rb +28 -0
- data/lib/emf/emf_plus/objects/opaque.rb +19 -0
- data/lib/emf/emf_plus/objects/parts.rb +103 -0
- data/lib/emf/emf_plus/objects/path.rb +21 -0
- data/lib/emf/emf_plus/objects/pen.rb +132 -0
- data/lib/emf/emf_plus/objects/region.rb +39 -0
- data/lib/emf/emf_plus/objects/string_format.rb +55 -0
- data/lib/emf/emf_plus/objects/typed.rb +50 -0
- data/lib/emf/emf_plus/objects.rb +46 -0
- data/lib/emf/emf_plus/parser.rb +64 -2
- data/lib/emf/emf_plus/records/base.rb +107 -0
- data/lib/emf/emf_plus/records/begin_container.rb +31 -0
- data/lib/emf/emf_plus/records/begin_container_no_params.rb +20 -0
- data/lib/emf/emf_plus/records/body.rb +16 -0
- data/lib/emf/emf_plus/records/clear.rb +22 -0
- data/lib/emf/emf_plus/records/clip_transform_flags.rb +26 -0
- data/lib/emf/emf_plus/records/comment.rb +21 -0
- data/lib/emf/emf_plus/records/draw_arc.rb +33 -0
- data/lib/emf/emf_plus/records/draw_beziers.rb +31 -0
- data/lib/emf/emf_plus/records/draw_closed_curve.rb +34 -0
- data/lib/emf/emf_plus/records/draw_curve.rb +38 -0
- data/lib/emf/emf_plus/records/draw_driver_string.rb +61 -0
- data/lib/emf/emf_plus/records/draw_ellipse.rb +28 -0
- data/lib/emf/emf_plus/records/draw_image.rb +42 -0
- data/lib/emf/emf_plus/records/draw_image_points.rb +62 -0
- data/lib/emf/emf_plus/records/draw_lines.rb +34 -0
- data/lib/emf/emf_plus/records/draw_path.rb +23 -0
- data/lib/emf/emf_plus/records/draw_pie.rb +33 -0
- data/lib/emf/emf_plus/records/draw_rects.rb +30 -0
- data/lib/emf/emf_plus/records/draw_string.rb +41 -0
- data/lib/emf/emf_plus/records/end_container.rb +20 -0
- data/lib/emf/emf_plus/records/end_of_file.rb +17 -0
- data/lib/emf/emf_plus/records/fill_brush.rb +21 -0
- data/lib/emf/emf_plus/records/fill_closed_curve.rb +38 -0
- data/lib/emf/emf_plus/records/fill_ellipse.rb +29 -0
- data/lib/emf/emf_plus/records/fill_path.rb +23 -0
- data/lib/emf/emf_plus/records/fill_pie.rb +34 -0
- data/lib/emf/emf_plus/records/fill_polygon.rb +32 -0
- data/lib/emf/emf_plus/records/fill_rects.rb +31 -0
- data/lib/emf/emf_plus/records/fill_region.rb +23 -0
- data/lib/emf/emf_plus/records/get_dc.rb +18 -0
- data/lib/emf/emf_plus/records/header.rb +35 -0
- data/lib/emf/emf_plus/records/multiply_world_transform.rb +24 -0
- data/lib/emf/emf_plus/records/object.rb +32 -0
- data/lib/emf/emf_plus/records/offset_clip.rb +24 -0
- data/lib/emf/emf_plus/records/primitives/argb.rb +20 -0
- data/lib/emf/emf_plus/records/primitives/bitmap.rb +32 -0
- data/lib/emf/emf_plus/records/primitives/bitmap_data.rb +21 -0
- data/lib/emf/emf_plus/records/primitives/blend_colors.rb +22 -0
- data/lib/emf/emf_plus/records/primitives/blend_factors.rb +21 -0
- data/lib/emf/emf_plus/records/primitives/bounded_array.rb +38 -0
- data/lib/emf/emf_plus/records/primitives/byte_reader.rb +25 -0
- data/lib/emf/emf_plus/records/primitives/character_range.rb +20 -0
- data/lib/emf/emf_plus/records/primitives/compressed_image.rb +17 -0
- data/lib/emf/emf_plus/records/primitives/focus_scale_data.rb +20 -0
- data/lib/emf/emf_plus/records/primitives/graphics_version.rb +21 -0
- data/lib/emf/emf_plus/records/primitives/language_identifier.rb +22 -0
- data/lib/emf/emf_plus/records/primitives/metafile.rb +19 -0
- data/lib/emf/emf_plus/records/primitives/palette.rb +21 -0
- data/lib/emf/emf_plus/records/primitives/path.rb +89 -0
- data/lib/emf/emf_plus/records/primitives/path_point_type.rb +21 -0
- data/lib/emf/emf_plus/records/primitives/path_point_type_rle.rb +23 -0
- data/lib/emf/emf_plus/records/primitives/point.rb +18 -0
- data/lib/emf/emf_plus/records/primitives/point_array.rb +42 -0
- data/lib/emf/emf_plus/records/primitives/point_f.rb +19 -0
- data/lib/emf/emf_plus/records/primitives/point_r.rb +19 -0
- data/lib/emf/emf_plus/records/primitives/rect.rb +20 -0
- data/lib/emf/emf_plus/records/primitives/rect_array.rb +24 -0
- data/lib/emf/emf_plus/records/primitives/rect_f.rb +21 -0
- data/lib/emf/emf_plus/records/primitives/region_node.rb +68 -0
- data/lib/emf/emf_plus/records/primitives/region_node_child_nodes.rb +22 -0
- data/lib/emf/emf_plus/records/primitives/region_node_path.rb +37 -0
- data/lib/emf/emf_plus/records/primitives/relative_coordinate.rb +32 -0
- data/lib/emf/emf_plus/records/primitives/string_format_data.rb +23 -0
- data/lib/emf/emf_plus/records/primitives/transform_matrix.rb +23 -0
- data/lib/emf/emf_plus/records/primitives.rb +41 -0
- data/lib/emf/emf_plus/records/reset_clip.rb +17 -0
- data/lib/emf/emf_plus/records/reset_world_transform.rb +17 -0
- data/lib/emf/emf_plus/records/restore.rb +20 -0
- data/lib/emf/emf_plus/records/rotate_world_transform.rb +24 -0
- data/lib/emf/emf_plus/records/save.rb +20 -0
- data/lib/emf/emf_plus/records/scale_world_transform.rb +26 -0
- data/lib/emf/emf_plus/records/serializable_object.rb +32 -0
- data/lib/emf/emf_plus/records/set_anti_alias_mode.rb +25 -0
- data/lib/emf/emf_plus/records/set_clip_path.rb +20 -0
- data/lib/emf/emf_plus/records/set_clip_rect.rb +24 -0
- data/lib/emf/emf_plus/records/set_clip_region.rb +20 -0
- data/lib/emf/emf_plus/records/set_compositing_mode.rb +21 -0
- data/lib/emf/emf_plus/records/set_compositing_quality.rb +21 -0
- data/lib/emf/emf_plus/records/set_interpolation_mode.rb +21 -0
- data/lib/emf/emf_plus/records/set_page_transform.rb +25 -0
- data/lib/emf/emf_plus/records/set_pixel_offset_mode.rb +21 -0
- data/lib/emf/emf_plus/records/set_rendering_origin.rb +22 -0
- data/lib/emf/emf_plus/records/set_text_contrast.rb +24 -0
- data/lib/emf/emf_plus/records/set_text_rendering_hint.rb +21 -0
- data/lib/emf/emf_plus/records/set_ts_clip.rb +40 -0
- data/lib/emf/emf_plus/records/set_ts_graphics.rb +88 -0
- data/lib/emf/emf_plus/records/set_world_transform.rb +22 -0
- data/lib/emf/emf_plus/records/shape_flags.rb +23 -0
- data/lib/emf/emf_plus/records/translate_world_transform.rb +26 -0
- data/lib/emf/emf_plus/records/unknown.rb +20 -0
- data/lib/emf/emf_plus/records.rb +107 -0
- data/lib/emf/emf_plus/serializer.rb +9 -2
- data/lib/emf/emf_plus/stream/conformance.rb +68 -0
- data/lib/emf/emf_plus/stream/editor.rb +21 -0
- data/lib/emf/emf_plus/stream/emf_gap.rb +20 -0
- data/lib/emf/emf_plus/stream/link_index.rb +30 -0
- data/lib/emf/emf_plus/stream/rebuild.rb +47 -0
- data/lib/emf/emf_plus/stream/record_handle.rb +26 -0
- data/lib/emf/emf_plus/stream/segment.rb +70 -0
- data/lib/emf/emf_plus/stream.rb +153 -0
- data/lib/emf/emf_plus.rb +9 -0
- data/lib/emf/emr/binary/dib_header.rb +142 -0
- data/lib/emf/emr/binary/ext_text_out_fields.rb +43 -0
- data/lib/emf/emr/binary/extended_pen_buffers.rb +23 -0
- data/lib/emf/emr/binary/fast_fill.rb +1164 -0
- data/lib/emf/emr/binary/font.rb +159 -0
- data/lib/emf/emr/binary/lazy_utf16_array.rb +82 -0
- data/lib/emf/emr/binary/pack_plan.rb +144 -0
- data/lib/emf/emr/binary/pack_plan_check.rb +75 -0
- data/lib/emf/emr/binary/pack_plan_exact.rb +130 -0
- data/lib/emf/emr/binary/pack_plan_generate.rb +116 -0
- data/lib/emf/emr/binary/pack_plan_values.rb +92 -0
- data/lib/emf/emr/binary/palette_body.rb +19 -0
- data/lib/emf/emr/binary/palette_entry.rb +18 -0
- data/lib/emf/emr/binary/record.rb +33 -0
- data/lib/emf/emr/binary/records/alpha_blend.rb +43 -0
- data/lib/emf/emr/binary/records/angle_arc.rb +2 -2
- data/lib/emf/emr/binary/records/bit_blt.rb +14 -0
- data/lib/emf/emr/binary/records/color_correct_palette.rb +55 -1
- data/lib/emf/emr/binary/records/colormatch_to_target_w.rb +76 -1
- data/lib/emf/emr/binary/records/create_colorspace.rb +67 -1
- data/lib/emf/emr/binary/records/create_colorspace_w.rb +90 -1
- data/lib/emf/emr/binary/records/create_dib_pattern_brush_pt.rb +14 -0
- data/lib/emf/emr/binary/records/create_font_indirect_w.rb +6 -2
- data/lib/emf/emr/binary/records/create_mono_brush.rb +14 -0
- data/lib/emf/emr/binary/records/create_palette.rb +19 -1
- data/lib/emf/emr/binary/records/delete_colorspace.rb +22 -1
- data/lib/emf/emr/binary/records/draw_escape.rb +45 -1
- data/lib/emf/emr/binary/records/ellipse.rb +1 -1
- data/lib/emf/emr/binary/records/eof.rb +9 -0
- data/lib/emf/emr/binary/records/ext_create_pen.rb +80 -1
- data/lib/emf/emr/binary/records/ext_escape.rb +45 -1
- data/lib/emf/emr/binary/records/ext_flood_fill.rb +9 -2
- data/lib/emf/emr/binary/records/ext_select_clip_rgn.rb +9 -1
- data/lib/emf/emr/binary/records/ext_text_out_a.rb +16 -3
- data/lib/emf/emr/binary/records/ext_text_out_w.rb +14 -3
- data/lib/emf/emr/binary/records/fill_rgn.rb +11 -2
- data/lib/emf/emr/binary/records/force_ufi_mapping.rb +38 -1
- data/lib/emf/emr/binary/records/frame_rgn.rb +12 -2
- data/lib/emf/emr/binary/records/gls_bounded_record.rb +61 -1
- data/lib/emf/emr/binary/records/gls_record.rb +42 -1
- data/lib/emf/emr/binary/records/gradient_fill.rb +7 -0
- data/lib/emf/emr/binary/records/invert_rgn.rb +11 -3
- data/lib/emf/emr/binary/records/mask_blt.rb +66 -0
- data/lib/emf/emr/binary/records/named_escape.rb +78 -1
- data/lib/emf/emr/binary/records/paint_rgn.rb +11 -3
- data/lib/emf/emr/binary/records/pixel_format.rb +76 -1
- data/lib/emf/emr/binary/records/plg_blt.rb +66 -0
- data/lib/emf/emr/binary/records/poly_textout_a.rb +128 -1
- data/lib/emf/emr/binary/records/poly_textout_w.rb +128 -1
- data/lib/emf/emr/binary/records/raw.rb +3 -0
- data/lib/emf/emr/binary/records/realize_palette.rb +1 -0
- data/lib/emf/emr/binary/records/rectangle.rb +1 -1
- data/lib/emf/emr/binary/records/resize_palette.rb +16 -2
- data/lib/emf/emr/binary/records/round_rect.rb +2 -2
- data/lib/emf/emr/binary/records/select_palette.rb +1 -0
- data/lib/emf/emr/binary/records/set_color_adjustment.rb +136 -0
- data/lib/emf/emr/binary/records/set_colorspace.rb +22 -1
- data/lib/emf/emr/binary/records/set_dibits_to_device.rb +43 -0
- data/lib/emf/emr/binary/records/set_icm_profile_a.rb +71 -1
- data/lib/emf/emr/binary/records/set_icm_profile_w.rb +71 -1
- data/lib/emf/emr/binary/records/set_linked_ufis.rb +49 -1
- data/lib/emf/emr/binary/records/set_miter_limit.rb +1 -1
- data/lib/emf/emr/binary/records/set_palette_entries.rb +20 -2
- data/lib/emf/emr/binary/records/set_text_justification.rb +8 -2
- data/lib/emf/emr/binary/records/small_text_out.rb +55 -4
- data/lib/emf/emr/binary/records/stretch_blt.rb +14 -0
- data/lib/emf/emr/binary/records/stretch_dibits.rb +14 -0
- data/lib/emf/emr/binary/records/transparent_blt.rb +43 -0
- data/lib/emf/emr/binary/records.rb +4 -2
- data/lib/emf/emr/binary/region_data.rb +33 -0
- data/lib/emf/emr/binary/state_record_body.rb +33 -0
- data/lib/emf/emr/binary/thin_shell.rb +226 -0
- data/lib/emf/emr/binary/value_view/layout.rb +101 -0
- data/lib/emf/emr/binary/value_view/reader_source.rb +88 -0
- data/lib/emf/emr/binary/value_view.rb +173 -0
- data/lib/emf/emr/binary/variable_buffers.rb +87 -0
- data/lib/emf/emr/binary.rb +4 -0
- data/lib/emf/emr/filled_record.rb +77 -0
- data/lib/emf/emr/parser.rb +239 -50
- data/lib/emf/emr/serializer.rb +4 -5
- data/lib/emf/emr.rb +1 -0
- data/lib/emf/error.rb +24 -1
- data/lib/emf/model/diagnostic.rb +41 -0
- data/lib/emf/model/emr/header.rb +40 -1
- data/lib/emf/model/emr/records.rb +142 -6
- data/lib/emf/model/emr/wire_values.rb +43 -0
- data/lib/emf/model/emr.rb +1 -0
- data/lib/emf/model/geometry/color.rb +19 -1
- data/lib/emf/model/metafile.rb +22 -2
- data/lib/emf/model/wmf/bitmap_records.rb +155 -0
- data/lib/emf/model/wmf/brush_records.rb +45 -0
- data/lib/emf/model/wmf/dc_escape_records.rb +67 -0
- data/lib/emf/model/wmf/font_record.rb +40 -0
- data/lib/emf/model/wmf/geometry_records.rb +107 -0
- data/lib/emf/model/wmf/header.rb +36 -0
- data/lib/emf/model/wmf/object_records.rb +71 -0
- data/lib/emf/model/wmf/palette_records.rb +68 -0
- data/lib/emf/model/wmf/records.rb +247 -0
- data/lib/emf/model/wmf/region_records.rb +112 -0
- data/lib/emf/model/wmf/state_records.rb +188 -0
- data/lib/emf/model/wmf/text_records.rb +36 -0
- data/lib/emf/model/wmf.rb +11 -0
- data/lib/emf/model.rb +2 -0
- data/lib/emf/native/bitmap_fields.rb +58 -0
- data/lib/emf/native/diagnostic_contract.rb +39 -0
- data/lib/emf/native/diagnostics.rb +81 -0
- data/lib/emf/native/emf_plus_loader.rb +35 -0
- data/lib/emf/native/emf_plus_snapshot.rb +96 -0
- data/lib/emf/native/emf_plus_source.rb +20 -0
- data/lib/emf/native/emf_plus_stream.rb +150 -0
- data/lib/emf/native/fields.rb +369 -0
- data/lib/emf/native/font_fields.rb +87 -0
- data/lib/emf/native/gradient_fields.rb +23 -0
- data/lib/emf/native/header.rb +35 -0
- data/lib/emf/native/header_errors.rb +30 -0
- data/lib/emf/native/hydrator.rb +151 -0
- data/lib/emf/native/lazy_wire.rb +100 -0
- data/lib/emf/native/legacy_state_fields.rb +22 -0
- data/lib/emf/native/library_path.rb +68 -0
- data/lib/emf/native/loader.rb +120 -0
- data/lib/emf/native/palette_fields.rb +45 -0
- data/lib/emf/native/poly_text_fields.rb +116 -0
- data/lib/emf/native/resource_failure.rb +28 -0
- data/lib/emf/native/small_text_fields.rb +27 -0
- data/lib/emf/native/snapshot.rb +102 -0
- data/lib/emf/native/wmf_bitmap_fields.rb +58 -0
- data/lib/emf/native/wmf_brush_fields.rb +62 -0
- data/lib/emf/native/wmf_fields.rb +117 -0
- data/lib/emf/native/wmf_hydrator.rb +143 -0
- data/lib/emf/native/wmf_loading.rb +49 -0
- data/lib/emf/native/wmf_palette_fields.rb +60 -0
- data/lib/emf/native/wmf_region_fields.rb +92 -0
- data/lib/emf/native/wmf_rejection.rb +84 -0
- data/lib/emf/native/wmf_remaining_fields.rb +70 -0
- data/lib/emf/native/wmf_snapshot.rb +51 -0
- data/lib/emf/native/wmf_text_fields.rb +56 -0
- data/lib/emf/native.rb +61 -0
- data/lib/emf/parse_evidence.rb +57 -0
- data/lib/emf/resource_budget/bitmap.rb +66 -0
- data/lib/emf/resource_budget/gradient.rb +30 -0
- data/lib/emf/resource_budget/poly_text.rb +85 -0
- data/lib/emf/resource_budget.rb +382 -0
- data/lib/emf/resource_limits/emf_records.rb +130 -0
- data/lib/emf/resource_limits.rb +58 -0
- data/lib/emf/version.rb +1 -1
- data/lib/emf/visitors/dump.rb +4 -0
- data/lib/emf/visitors/stats.rb +6 -5
- data/lib/emf/wmf/binary.rb +150 -1
- data/lib/emf/wmf/bitmap_codec.rb +118 -0
- data/lib/emf/wmf/brush_codec.rb +102 -0
- data/lib/emf/wmf/dc_escape_codec.rb +75 -0
- data/lib/emf/wmf/dib.rb +187 -0
- data/lib/emf/wmf/embedded_emf.rb +137 -0
- data/lib/emf/wmf/escape_views.rb +89 -0
- data/lib/emf/wmf/evidence.rb +255 -0
- data/lib/emf/wmf/geometry_codec.rb +49 -0
- data/lib/emf/wmf/palette_codec.rb +85 -0
- data/lib/emf/wmf/parser.rb +147 -2
- data/lib/emf/wmf/recovery.rb +95 -0
- data/lib/emf/wmf/region_codec.rb +151 -0
- data/lib/emf/wmf/serializer.rb +164 -2
- data/lib/emf/wmf/text_codec.rb +123 -0
- data/lib/emf/wmf.rb +7 -0
- data/lib/emf.rb +13 -9
- metadata +287 -10
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Emf
|
|
4
|
+
module Emr
|
|
5
|
+
module Binary
|
|
6
|
+
# Straight-line `pack` for a PackPlan: one local per leaf, inline range
|
|
7
|
+
# checks, one Array#pack with a frozen format. It takes only symbol-keyed
|
|
8
|
+
# Hashes of known, in-range, non-nil values (nested structs as Hashes or
|
|
9
|
+
# as instances of their own class; the record's array as the plan takes
|
|
10
|
+
# it); for anything else (unknown keys, nil values, bad values) it hands
|
|
11
|
+
# the call to `pack_interpreted`, so declines and results stay the
|
|
12
|
+
# interpreter's.
|
|
13
|
+
module PackPlanGenerate
|
|
14
|
+
FALLBACK = "return pack_interpreted(attrs, size: size)"
|
|
15
|
+
private_constant :FALLBACK
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def generate_pack
|
|
20
|
+
@gen_depth = 0
|
|
21
|
+
@gen_classes = []
|
|
22
|
+
fields = @tree.reject { |_, node| node.equal?(@array) }
|
|
23
|
+
body = fields.map { |name, node| gen_node(name, node, "attrs", "seen", " ") }.join
|
|
24
|
+
values = (0...@leaves.size).map { |index| "v#{index}" }
|
|
25
|
+
values << "*coords" if @array
|
|
26
|
+
format = (@array ? @points_format : @format).inspect
|
|
27
|
+
# def pack(attrs, size: true)
|
|
28
|
+
# seen = 0
|
|
29
|
+
# <one read-and-check block per field>
|
|
30
|
+
# return pack_interpreted(attrs, size: size) unless seen == attrs.size
|
|
31
|
+
# v1 = <size> if size
|
|
32
|
+
# [v0, v1, ...].pack("<frozen format>")
|
|
33
|
+
# end
|
|
34
|
+
source = <<~RUBY
|
|
35
|
+
# frozen_string_literal: true
|
|
36
|
+
def pack(attrs, size: true)
|
|
37
|
+
#{gen_exact} seen = 0
|
|
38
|
+
#{body}#{gen_array} #{FALLBACK} unless seen == attrs.size
|
|
39
|
+
|
|
40
|
+
#{gen_size} [#{values.join(', ')}].pack(#{format})
|
|
41
|
+
end
|
|
42
|
+
RUBY
|
|
43
|
+
singleton_class.class_eval(source, __FILE__, __LINE__)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def gen_array
|
|
47
|
+
return "" unless @array
|
|
48
|
+
|
|
49
|
+
<<~RUBY.gsub(/^(?=.)/, " ")
|
|
50
|
+
coords = attrs[#{@array_name.inspect}]
|
|
51
|
+
unless coords.nil?
|
|
52
|
+
seen += 1
|
|
53
|
+
coords = catch(:decline) { coords_of(coords) } or #{FALLBACK}
|
|
54
|
+
end
|
|
55
|
+
#{FALLBACK} unless v#{@count} == (coords ? coords.size / 2 : 0)
|
|
56
|
+
RUBY
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def gen_size
|
|
60
|
+
bytes = @array ? " + (coords ? coords.size * #{@coord_bytes} : 0)" : ""
|
|
61
|
+
" v#{@n_size} = #{@size}#{bytes} if size\n"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def gen_node(name, node, container, counter, indent)
|
|
65
|
+
return gen_leaf(gen_read(container, name, indent), node.index, counter, indent) if node.is_a?(PackPlan::Leaf)
|
|
66
|
+
|
|
67
|
+
sub = "h#{@gen_depth += 1}"
|
|
68
|
+
@gen_classes << node.klass
|
|
69
|
+
klass = "@gen_classes[#{@gen_classes.size - 1}]"
|
|
70
|
+
inner = node.children.map { |child, n| gen_node(child, n, sub, "#{sub}_seen", "#{indent} ") }.join
|
|
71
|
+
"#{indent}#{sub} = #{container}[#{name.inspect}]\n" \
|
|
72
|
+
"#{indent}if #{sub}.instance_of?(#{klass})\n#{indent} #{counter} += 1\n#{gen_from(node, sub, "#{indent} ")}" \
|
|
73
|
+
"#{indent}else\n#{gen_hash(sub, counter, inner, indent)}#{indent}end\n"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def gen_hash(sub, counter, inner, indent)
|
|
77
|
+
"#{indent} if #{sub}.nil? then #{sub} = {}\n" \
|
|
78
|
+
"#{indent} elsif #{sub}.instance_of?(Hash) then #{counter} += 1\n" \
|
|
79
|
+
"#{indent} else #{FALLBACK}\n#{indent} end\n" \
|
|
80
|
+
"#{indent} #{sub}_seen = 0\n#{inner}" \
|
|
81
|
+
"#{indent} #{FALLBACK} unless #{sub}_seen == #{sub}.size\n"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# The leaves of a struct instance, read through `snapshot`.
|
|
85
|
+
def gen_from(branch, source, indent)
|
|
86
|
+
branch.children.map do |name, node|
|
|
87
|
+
if node.is_a?(PackPlan::Leaf)
|
|
88
|
+
gen_leaf("#{indent}v#{node.index} = #{source}.#{name}.snapshot\n", node.index, nil, indent)
|
|
89
|
+
else
|
|
90
|
+
gen_from(node, "#{source}.#{name}", indent)
|
|
91
|
+
end
|
|
92
|
+
end.join
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def gen_read(container, name, indent) = "#{indent}v = #{container}[#{name.inspect}]\n"
|
|
96
|
+
|
|
97
|
+
def gen_leaf(read, index, counter, indent)
|
|
98
|
+
var = "v#{index}"
|
|
99
|
+
read = read.sub(/\bv = /, "#{var} = ")
|
|
100
|
+
return "#{read}#{indent}#{FALLBACK} unless #{gen_valid(var, index)}\n" unless counter
|
|
101
|
+
|
|
102
|
+
"#{read}#{indent}if #{var}.nil? then #{var} = #{@defaults[index].inspect}\n" \
|
|
103
|
+
"#{indent}elsif #{gen_valid(var, index)} then #{counter} += 1\n" \
|
|
104
|
+
"#{indent}else #{FALLBACK}\n#{indent}end\n"
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def gen_valid(var, index)
|
|
108
|
+
low = @lows[index]
|
|
109
|
+
return "float32_exact?(#{var})" unless low
|
|
110
|
+
|
|
111
|
+
"#{var}.instance_of?(Integer) && #{var} >= #{low} && #{var} <= #{@highs[index]}"
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Emf
|
|
4
|
+
module Emr
|
|
5
|
+
module Binary
|
|
6
|
+
# Which attribute values a PackPlan takes: only those BinData stores
|
|
7
|
+
# unchanged, so the wire read back from the bytes is the wire it built.
|
|
8
|
+
module PackPlanValues
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def store(values, node, value)
|
|
12
|
+
case node
|
|
13
|
+
when PackPlan::Leaf then store_leaf(values, node.index, value)
|
|
14
|
+
else store_branch(values, node, value)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def store_leaf(values, index, value)
|
|
19
|
+
low = @lows[index]
|
|
20
|
+
if low
|
|
21
|
+
return unless value.instance_of?(Integer) && value >= low && value <= @highs[index]
|
|
22
|
+
else
|
|
23
|
+
return unless float32_exact?(value)
|
|
24
|
+
end
|
|
25
|
+
values[index] = value
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# A Float a float32 leaf stores unchanged: it reads back as the same
|
|
29
|
+
# bits (so not NaN, not past float32 range, not rounded).
|
|
30
|
+
def float32_exact?(value)
|
|
31
|
+
value.instance_of?(Float) && [value].pack("E") == [[value].pack("e").unpack1("e")].pack("E")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def store_branch(values, node, value)
|
|
35
|
+
if value.instance_of?(Hash)
|
|
36
|
+
value.each do |name, leaf|
|
|
37
|
+
child = node.children[name] or return false
|
|
38
|
+
next if leaf.nil?
|
|
39
|
+
|
|
40
|
+
store(values, child, leaf) or return false
|
|
41
|
+
end
|
|
42
|
+
true
|
|
43
|
+
elsif value.instance_of?(node.klass)
|
|
44
|
+
node.children.all? { |name, child| store_from(values, child, value.public_send(name)) }
|
|
45
|
+
else
|
|
46
|
+
false
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def store_from(values, node, source)
|
|
51
|
+
return store_branch_from(values, node, source) if node.is_a?(PackPlan::Branch)
|
|
52
|
+
|
|
53
|
+
store_leaf(values, node.index, source.snapshot)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def store_branch_from(values, node, source)
|
|
57
|
+
node.children.all? { |name, child| store_from(values, child, source.public_send(name)) }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Flat coordinates of an Array of {x:, y:} Hashes or points of the
|
|
61
|
+
# record's point class, all Integers in the point range; else declines.
|
|
62
|
+
# Each point is read in place: no per-point pair is allocated.
|
|
63
|
+
def coords_of(points)
|
|
64
|
+
throw :decline unless points.instance_of?(Array)
|
|
65
|
+
|
|
66
|
+
coords = []
|
|
67
|
+
points.each do |point|
|
|
68
|
+
if point.instance_of?(Hash)
|
|
69
|
+
throw :decline unless point.size == 2
|
|
70
|
+
|
|
71
|
+
x = point[:x]
|
|
72
|
+
y = point[:y]
|
|
73
|
+
elsif point.instance_of?(@point_class)
|
|
74
|
+
x = point.x.snapshot
|
|
75
|
+
y = point.y.snapshot
|
|
76
|
+
else
|
|
77
|
+
throw :decline
|
|
78
|
+
end
|
|
79
|
+
throw :decline unless in_point_range?(x) && in_point_range?(y)
|
|
80
|
+
|
|
81
|
+
coords << x << y
|
|
82
|
+
end
|
|
83
|
+
coords
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def in_point_range?(value)
|
|
87
|
+
value.instance_of?(Integer) && value >= @coord_low && value <= @coord_high
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Emf
|
|
4
|
+
module Emr
|
|
5
|
+
module Binary
|
|
6
|
+
class PaletteBody < String
|
|
7
|
+
def initialize(record, bytes)
|
|
8
|
+
@record = record
|
|
9
|
+
super(bytes)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def assign(bytes)
|
|
13
|
+
@record.body = bytes
|
|
14
|
+
replace(@record.body)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "bindata"
|
|
4
|
+
|
|
5
|
+
module Emf
|
|
6
|
+
module Emr
|
|
7
|
+
module Binary
|
|
8
|
+
class EmrPaletteEntry < BinData::Record
|
|
9
|
+
uint8 :red
|
|
10
|
+
uint8 :green
|
|
11
|
+
uint8 :blue
|
|
12
|
+
uint8 :flags
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
BinData::RegisteredClasses.register("emr_palette_entry", Emf::Emr::Binary::EmrPaletteEntry)
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "bindata"
|
|
4
|
+
require "emf/binary/class_field_accessors"
|
|
5
|
+
require "emf/emr/binary/thin_shell"
|
|
4
6
|
|
|
5
7
|
module Emf
|
|
6
8
|
module Emr
|
|
@@ -8,9 +10,40 @@ module Emf
|
|
|
8
10
|
# All EMR records share an 8-byte header: uint32 iType, uint32 nSize.
|
|
9
11
|
# Subclasses add their own fields after this.
|
|
10
12
|
class Record < BinData::Record
|
|
13
|
+
include ThinShell
|
|
14
|
+
prepend Emf::Binary::ClassFieldAccessors
|
|
15
|
+
|
|
16
|
+
# An assignment into the bytes a shell is still made from is taken
|
|
17
|
+
# before the field is made; anything else is the generic assignment.
|
|
18
|
+
module PackedAssignment
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def assign_field_at(index, val)
|
|
22
|
+
return val if (@field_objs.nil? || @field_objs[index].nil?) && packed_assign(index, val)
|
|
23
|
+
|
|
24
|
+
super
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
prepend PackedAssignment
|
|
28
|
+
|
|
11
29
|
endian :little
|
|
12
30
|
uint32 :i_type
|
|
13
31
|
uint32 :n_size
|
|
32
|
+
|
|
33
|
+
NO_ARG = Object.new.freeze
|
|
34
|
+
private_constant :NO_ARG
|
|
35
|
+
|
|
36
|
+
# `Klass.new(**attrs)` for a fixed-layout record builds from the
|
|
37
|
+
# FastFill template; every other call shape is BinData's constructor.
|
|
38
|
+
# BinData takes at most three positionals (value, parameters,
|
|
39
|
+
# parent), named here so the hot call allocates no splat array.
|
|
40
|
+
def self.new(value = NO_ARG, parameters = NO_ARG, parent = NO_ARG, **attrs)
|
|
41
|
+
if NO_ARG.equal?(value) && !attrs.empty? && (filler = FastFill.for_class(self))
|
|
42
|
+
wire = filler.build_packed(attrs) || filler.build(attrs)
|
|
43
|
+
return wire if wire
|
|
44
|
+
end
|
|
45
|
+
super(*[value, parameters, parent].take_while { |arg| !NO_ARG.equal?(arg) }, **attrs)
|
|
46
|
+
end
|
|
14
47
|
end
|
|
15
48
|
end
|
|
16
49
|
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 AlphaBlend < 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
|
|
@@ -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-length :string (NOT :rest, which would consume the
|
|
17
19
|
# whole tail).
|
|
18
20
|
class BitBlt < Emf::Emr::Binary::WithBounds
|
|
21
|
+
include Emf::Emr::Binary::VariableBuffers
|
|
22
|
+
|
|
23
|
+
fixed_layout 100
|
|
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
|
|
@@ -30,6 +38,12 @@ module Emf
|
|
|
30
38
|
uint32le :off_bits_src
|
|
31
39
|
uint32le :cb_bits_src
|
|
32
40
|
rest :body
|
|
41
|
+
|
|
42
|
+
# Read-only; computed from the current fields on each call.
|
|
43
|
+
def dib_header_view
|
|
44
|
+
DibHeader.view(off_bmi_src, cb_bmi_src, 100, body,
|
|
45
|
+
bits_offset: off_bits_src, bits_size: cb_bits_src)
|
|
46
|
+
end
|
|
33
47
|
end
|
|
34
48
|
end
|
|
35
49
|
end
|
|
@@ -1,15 +1,69 @@
|
|
|
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
11
|
class ColorCorrectPalette < Emf::Emr::Binary::Record
|
|
12
|
+
include Emf::Emr::Binary::VariableBuffers
|
|
13
|
+
|
|
14
|
+
fixed_layout 24
|
|
15
|
+
|
|
12
16
|
rest :body
|
|
17
|
+
|
|
18
|
+
def ih_palette
|
|
19
|
+
palette_body.byteslice(0, 4).unpack1("V")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def ih_palette=(value)
|
|
23
|
+
write_palette_value(0, value)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def first_entry
|
|
27
|
+
palette_body.byteslice(4, 4).unpack1("V")
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def first_entry=(value)
|
|
31
|
+
write_palette_value(4, value)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def entry_count
|
|
35
|
+
palette_body.byteslice(8, 4).unpack1("V")
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def entry_count=(value)
|
|
39
|
+
write_palette_value(8, value)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def reserved
|
|
43
|
+
palette_body.byteslice(12, 4).unpack1("V")
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def reserved=(value)
|
|
47
|
+
write_palette_value(12, value)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def palette_body
|
|
53
|
+
bytes = body.to_s
|
|
54
|
+
raise ArgumentError, "invalid color correct palette body length" if bytes.bytesize < 16
|
|
55
|
+
|
|
56
|
+
bytes
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def write_palette_value(offset, value)
|
|
60
|
+
bytes = palette_body.dup
|
|
61
|
+
raise ArgumentError, "palette value must be an Integer" unless value.is_a?(Integer)
|
|
62
|
+
raise RangeError, "palette value must fit an unsigned 32-bit integer" unless (0..0xffffffff).cover?(value)
|
|
63
|
+
|
|
64
|
+
bytes[offset, 4] = [value].pack("V")
|
|
65
|
+
self.body = bytes
|
|
66
|
+
end
|
|
13
67
|
end
|
|
14
68
|
end
|
|
15
69
|
end
|
|
@@ -7,9 +7,84 @@ module Emf
|
|
|
7
7
|
module Emr
|
|
8
8
|
module Binary
|
|
9
9
|
module Records
|
|
10
|
-
#
|
|
10
|
+
# Color matching profile names and data retain their original byte spans.
|
|
11
11
|
class ColorMatchToTargetW < Emf::Emr::Binary::Record
|
|
12
|
+
# Byte counts and opaque spans retain the original body layout.
|
|
12
13
|
rest :body
|
|
14
|
+
|
|
15
|
+
def dw_action
|
|
16
|
+
profile_prefix.unpack1("V")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def dw_action=(value)
|
|
20
|
+
write_profile_scalar(0, value)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def dw_flags
|
|
24
|
+
profile_prefix.byteslice(4, 4).unpack1("V")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def dw_flags=(value)
|
|
28
|
+
write_profile_scalar(4, value)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def cb_name
|
|
32
|
+
profile_prefix.byteslice(8, 4).unpack1("V")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def cb_data
|
|
36
|
+
profile_prefix.byteslice(12, 4).unpack1("V")
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def name_bytes
|
|
40
|
+
read_profile_bytes(16, cb_name)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def name_bytes=(value)
|
|
44
|
+
write_profile_bytes(16, cb_name, value)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def profile_bytes
|
|
48
|
+
read_profile_bytes(16 + cb_name, cb_data)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def profile_bytes=(value)
|
|
52
|
+
write_profile_bytes(16 + cb_name, cb_data, value)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def write_profile_scalar(offset, value)
|
|
58
|
+
raise ArgumentError, "color profile scalar must be an Integer" unless value.is_a?(Integer)
|
|
59
|
+
raise RangeError, "color profile scalar must fit an unsigned 32-bit integer" unless (0..0xFFFFFFFF).cover?(value)
|
|
60
|
+
|
|
61
|
+
write_profile_bytes(offset, 4, [value].pack("V"))
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def profile_prefix
|
|
65
|
+
bytes = body.to_s
|
|
66
|
+
raise ArgumentError, "truncated color profile prefix" if bytes.bytesize < 16
|
|
67
|
+
|
|
68
|
+
bytes
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def read_profile_bytes(offset, length)
|
|
72
|
+
bytes = profile_prefix
|
|
73
|
+
raise ArgumentError, "truncated color profile span" if offset + length > bytes.bytesize
|
|
74
|
+
|
|
75
|
+
bytes.byteslice(offset, length).b
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def write_profile_bytes(offset, length, value)
|
|
79
|
+
read_profile_bytes(offset, length)
|
|
80
|
+
unless value.is_a?(String) && value.bytesize == length
|
|
81
|
+
raise ArgumentError, "color profile value must be a String of #{length} bytes"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
bytes = body.to_s.b
|
|
85
|
+
bytes[offset, length] = value.b
|
|
86
|
+
self.body = bytes
|
|
87
|
+
end
|
|
13
88
|
end
|
|
14
89
|
end
|
|
15
90
|
end
|
|
@@ -7,9 +7,75 @@ module Emf
|
|
|
7
7
|
module Emr
|
|
8
8
|
module Binary
|
|
9
9
|
module Records
|
|
10
|
-
#
|
|
10
|
+
# Logical color space fields retain their original fixed-width wire bytes.
|
|
11
11
|
class CreateColorspace < Emf::Emr::Binary::Record
|
|
12
12
|
rest :body
|
|
13
|
+
|
|
14
|
+
[
|
|
15
|
+
[:ih_cs, 0, "V", 4],
|
|
16
|
+
[:lcs_signature, 4, "V", 332],
|
|
17
|
+
[:lcs_version, 8, "V", 332],
|
|
18
|
+
[:lcs_size, 12, "V", 332],
|
|
19
|
+
[:color_space_type, 16, "l<", 332],
|
|
20
|
+
[:intent, 20, "l<", 332],
|
|
21
|
+
[:gamma_red, 60, "V", 332],
|
|
22
|
+
[:gamma_green, 64, "V", 332],
|
|
23
|
+
[:gamma_blue, 68, "V", 332]
|
|
24
|
+
].each do |name, offset, format, required|
|
|
25
|
+
define_method(name) do
|
|
26
|
+
colorspace_body(required).byteslice(offset, 4).unpack1(format)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
define_method("#{name}=") do |value|
|
|
30
|
+
write_colorspace_value(offset, value, format, required)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def endpoints_bytes
|
|
35
|
+
colorspace_body(332).byteslice(24, 36).b
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def endpoints_bytes=(value)
|
|
39
|
+
replace_colorspace_bytes(24, 36, value, 332)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def filename_bytes
|
|
43
|
+
colorspace_body(332).byteslice(72, 260).b
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def filename_bytes=(value)
|
|
47
|
+
replace_colorspace_bytes(72, 260, value, 332)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def colorspace_body(required)
|
|
53
|
+
bytes = body.to_s
|
|
54
|
+
raise ArgumentError, "truncated logical color space body" if bytes.bytesize < required
|
|
55
|
+
|
|
56
|
+
bytes
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def write_colorspace_value(offset, value, format, required)
|
|
60
|
+
colorspace_body(required)
|
|
61
|
+
raise ArgumentError, "color space value must be an Integer" unless value.is_a?(Integer)
|
|
62
|
+
|
|
63
|
+
range = format == "l<" ? (-0x80000000..0x7fffffff) : (0..0xffffffff)
|
|
64
|
+
raise RangeError, "color space value must fit its 32-bit field" unless range.cover?(value)
|
|
65
|
+
|
|
66
|
+
replace_colorspace_bytes(offset, 4, [value].pack(format), required)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def replace_colorspace_bytes(offset, length, value, required)
|
|
70
|
+
bytes = colorspace_body(required)
|
|
71
|
+
unless value.is_a?(String) && value.bytesize == length
|
|
72
|
+
raise ArgumentError, "color space value must be a String of #{length} bytes"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
replacement = bytes.b
|
|
76
|
+
replacement[offset, length] = value.b
|
|
77
|
+
self.body = replacement
|
|
78
|
+
end
|
|
13
79
|
end
|
|
14
80
|
end
|
|
15
81
|
end
|