Module: Emfsvg::Translation::HeaderBuilder

Defined in:
lib/emfsvg/translation/header_builder.rb

Overview

Constructs Emf::Emr::Binary::Header values from a Svg::Document's viewport. The header carries the bounds/frame rectangle, device dimensions, and record counts that the EMF format requires.

Round-trip contract: the bounds we emit must reproduce the input SVG's viewport when emfsvg's EMF→SVG renderer reads it back.

Constant Summary collapse

DEFAULT_DPI =
96.0
MM_PER_INCH =
25.4

Class Method Summary collapse

Class Method Details

.bounds_for(document) ⇒ Object



44
45
46
47
48
49
50
51
52
# File 'lib/emfsvg/translation/header_builder.rb', line 44

def bounds_for(document)
  min_x, min_y, w, h = document.bounds
  Emf::Model::Geometry::Rect.new(
    left: min_x.to_i,
    top: min_y.to_i,
    right: (min_x + w).to_i,
    bottom: (min_y + h).to_i
  )
end

.build(document, n_records:, n_handles:) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/emfsvg/translation/header_builder.rb', line 19

def build(document, n_records:, n_handles:)
  bounds = bounds_for(document)
  frame = frame_for(bounds)
  Emf::Model::Emr::Header.new(
    bounds: bounds,
    frame: frame,
    signature: 0x464D4520, # " EMF"
    version: 0x00010000,
    n_bytes: 0, # filled in by serializer; placeholder
    n_records: n_records,
    n_handles: n_handles,
    s_reserved: 0,
    n_description: 0,
    off_description: 0,
    n_pal_entries: 0,
    device_pixels: device_pixels_for(document),
    device_mm: device_mm_for(document),
    cb_pixel_format: 0,
    off_pixel_format: 0,
    b_open_gl: 0,
    szl_micrometers: device_micrometers_for(document),
    n_size: 88
  )
end

.device_micrometers_for(document) ⇒ Object



81
82
83
84
85
86
# File 'lib/emfsvg/translation/header_builder.rb', line 81

def device_micrometers_for(document)
  Emf::Model::Geometry::Size.new(
    cx: ((document.width / DEFAULT_DPI) * MM_PER_INCH * 1000).to_i,
    cy: ((document.height / DEFAULT_DPI) * MM_PER_INCH * 1000).to_i
  )
end

.device_mm_for(document) ⇒ Object



73
74
75
76
77
78
79
# File 'lib/emfsvg/translation/header_builder.rb', line 73

def device_mm_for(document)
  px_per_mm = DEFAULT_DPI / MM_PER_INCH
  Emf::Model::Geometry::Size.new(
    cx: (document.width / px_per_mm).to_i,
    cy: (document.height / px_per_mm).to_i
  )
end

.device_pixels_for(document) ⇒ Object



66
67
68
69
70
71
# File 'lib/emfsvg/translation/header_builder.rb', line 66

def device_pixels_for(document)
  Emf::Model::Geometry::Size.new(
    cx: document.width.to_i,
    cy: document.height.to_i
  )
end

.frame_for(bounds) ⇒ Object

Frame is the bounding rectangle in 0.01mm units. Computed from bounds (pixels) using the document's effective DPI.



56
57
58
59
60
61
62
63
64
# File 'lib/emfsvg/translation/header_builder.rb', line 56

def frame_for(bounds)
  units_per_pixel = (100.0 * MM_PER_INCH) / DEFAULT_DPI # 0.01mm per pixel
  Emf::Model::Geometry::Rect.new(
    left: (bounds.left * units_per_pixel).to_i,
    top: (bounds.top * units_per_pixel).to_i,
    right: (bounds.right * units_per_pixel).to_i,
    bottom: (bounds.bottom * units_per_pixel).to_i
  )
end