Class: Emfsvg::Svg::Stroke
- Inherits:
-
Object
- Object
- Emfsvg::Svg::Stroke
- Defined in:
- lib/emfsvg/svg/stroke.rb
Overview
Parsed SVG stroke style: color, width, dash pattern, line cap, line join. Maps directly to the EMF LOGPEN / EXTLOGPEN32 fields.
Pen style bits (per MS-WMF 2.1.1.8 / emr_visitor.rb mirror):
PS_SOLID=0, PS_DASH=1, PS_DOT=2, PS_DASHDOT=3, PS_DASHDOTDOT=4,
PS_NULL=5
bits 8-11: PS_ENDCAP_ROUND=0x0000, _SQUARE=0x0100, _FLAT=0x0200
bits 12-15: PS_JOIN_ROUND=0x0000, _BEVEL=0x1000, _MITER=0x2000
emfsvg's EMF→SVG renderer emits stroke-width="1px" (with the px
suffix) AND no linecap/linejoin attrs as the fallback for a NULL
pen with a solid brush. When the SVG→EMF side sees that exact
form, it round-trips back to a NULL pen to preserve the rendering.
Constant Summary collapse
- END_CAP_BITS =
{ "butt" => 0x0200, "round" => 0x0000, "square" => 0x0100 }.freeze
- LINE_JOIN_BITS =
{ "miter" => 0x2000, "round" => 0x0000, "bevel" => 0x1000 }.freeze
- NULL_PEN_WIDTH_SENTINEL =
"1px"- PS_GEOMETRIC =
0x00010000
Instance Attribute Summary collapse
-
#dash_array ⇒ Object
readonly
Returns the value of attribute dash_array.
-
#line_cap ⇒ Object
readonly
Returns the value of attribute line_cap.
-
#line_cap_explicit ⇒ Object
readonly
Returns the value of attribute line_cap_explicit.
-
#line_join ⇒ Object
readonly
Returns the value of attribute line_join.
-
#line_join_explicit ⇒ Object
readonly
Returns the value of attribute line_join_explicit.
-
#paint ⇒ Object
readonly
Returns the value of attribute paint.
-
#raw_width ⇒ Object
readonly
Returns the value of attribute raw_width.
-
#width ⇒ Object
readonly
Returns the value of attribute width.
Class Method Summary collapse
- .parse(stroke:, width:, dash_array:, line_cap:, line_join:) ⇒ Object
- .parse_dash_array(value) ⇒ Object
- .parse_width(value) ⇒ Object
Instance Method Summary collapse
-
#dash_style ⇒ Object
SVG dasharray is a comma/space separated list of lengths; "none" means solid.
-
#initialize(paint:, width: 1.0, dash_array: nil, line_cap: "round", line_join: "round", raw_width: nil, line_cap_explicit: false, line_join_explicit: false) ⇒ Stroke
constructor
A new instance of Stroke.
- #null_pen_sentinel? ⇒ Boolean
-
#pen_style ⇒ Object
Pen style bitmask (full 32 bits).
Constructor Details
#initialize(paint:, width: 1.0, dash_array: nil, line_cap: "round", line_join: "round", raw_width: nil, line_cap_explicit: false, line_join_explicit: false) ⇒ Stroke
Returns a new instance of Stroke.
28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/emfsvg/svg/stroke.rb', line 28 def initialize(paint:, width: 1.0, dash_array: nil, line_cap: "round", line_join: "round", raw_width: nil, line_cap_explicit: false, line_join_explicit: false) @paint = paint @width = width.to_f @dash_array = dash_array @line_cap = line_cap @line_join = line_join @raw_width = raw_width @line_cap_explicit = line_cap_explicit @line_join_explicit = line_join_explicit end |
Instance Attribute Details
#dash_array ⇒ Object (readonly)
Returns the value of attribute dash_array.
25 26 27 |
# File 'lib/emfsvg/svg/stroke.rb', line 25 def dash_array @dash_array end |
#line_cap ⇒ Object (readonly)
Returns the value of attribute line_cap.
25 26 27 |
# File 'lib/emfsvg/svg/stroke.rb', line 25 def line_cap @line_cap end |
#line_cap_explicit ⇒ Object (readonly)
Returns the value of attribute line_cap_explicit.
25 26 27 |
# File 'lib/emfsvg/svg/stroke.rb', line 25 def line_cap_explicit @line_cap_explicit end |
#line_join ⇒ Object (readonly)
Returns the value of attribute line_join.
25 26 27 |
# File 'lib/emfsvg/svg/stroke.rb', line 25 def line_join @line_join end |
#line_join_explicit ⇒ Object (readonly)
Returns the value of attribute line_join_explicit.
25 26 27 |
# File 'lib/emfsvg/svg/stroke.rb', line 25 def line_join_explicit @line_join_explicit end |
#paint ⇒ Object (readonly)
Returns the value of attribute paint.
25 26 27 |
# File 'lib/emfsvg/svg/stroke.rb', line 25 def paint @paint end |
#raw_width ⇒ Object (readonly)
Returns the value of attribute raw_width.
25 26 27 |
# File 'lib/emfsvg/svg/stroke.rb', line 25 def raw_width @raw_width end |
#width ⇒ Object (readonly)
Returns the value of attribute width.
25 26 27 |
# File 'lib/emfsvg/svg/stroke.rb', line 25 def width @width end |
Class Method Details
.parse(stroke:, width:, dash_array:, line_cap:, line_join:) ⇒ Object
66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/emfsvg/svg/stroke.rb', line 66 def self.parse(stroke:, width:, dash_array:, line_cap:, line_join:) new( paint: Paint.from_stroke(stroke), width: parse_width(width), dash_array: parse_dash_array(dash_array), line_cap: line_cap || "round", line_join: line_join || "round", raw_width: width, line_cap_explicit: !line_cap.nil?, line_join_explicit: !line_join.nil? ) end |
.parse_dash_array(value) ⇒ Object
99 100 101 102 103 104 |
# File 'lib/emfsvg/svg/stroke.rb', line 99 def self.parse_dash_array(value) return nil if value.nil? || value.strip == "none" || value.strip.empty? parts = value.split(/[\s,]+/).map(&:to_f) parts.empty? ? nil : parts end |
.parse_width(value) ⇒ Object
79 80 81 82 83 84 |
# File 'lib/emfsvg/svg/stroke.rb', line 79 def self.parse_width(value) return 1.0 if value.nil? || value.strip.empty? match = value.match(/\A(-?\d+(?:\.\d+)?)/) match ? match[1].to_f : 1.0 end |
Instance Method Details
#dash_style ⇒ Object
SVG dasharray is a comma/space separated list of lengths; "none" means solid. We map the first length to a discrete dash style: a single length matching roughly the width → PS_DOT, longer → PS_DASH. Anything more complex is approximated as PS_DASH for v1.
90 91 92 93 94 95 96 97 |
# File 'lib/emfsvg/svg/stroke.rb', line 90 def dash_style return 0 if dash_array.nil? || dash_array.empty? first = dash_array.first return 0 if first.zero? first < (width * 2) ? 2 : 1 # PS_DOT=2, PS_DASH=1 end |
#null_pen_sentinel? ⇒ Boolean
41 42 43 44 45 |
# File 'lib/emfsvg/svg/stroke.rb', line 41 def null_pen_sentinel? raw_width == NULL_PEN_WIDTH_SENTINEL && !line_cap_explicit && !line_join_explicit end |
#pen_style ⇒ Object
Pen style bitmask (full 32 bits). Includes:
* dash style (bits 0-7)
* end-cap (bits 8-11)
* line-join (bits 12-15)
* pen type GEOMETRIC (bit 16) — set when width > 1, so
emfsvg's EMF→SVG renderer uses the actual pen.width
instead of hardcoding 1.
56 57 58 59 60 61 62 63 64 |
# File 'lib/emfsvg/svg/stroke.rb', line 56 def pen_style base = if paint.null? || null_pen_sentinel? 5 # PS_NULL else dash_style end type_bit = width > 1.0 && !paint.null? ? PS_GEOMETRIC : 0 base | type_bit | END_CAP_BITS.fetch(line_cap, 0x0000) | LINE_JOIN_BITS.fetch(line_join, 0x0000) end |