| Module | Magick::RVG::Stretchable |
| In: |
lib/rvg/stretchable.rb
|
# File lib/rvg/stretchable.rb, line 124
124: def initialize(*args, &block)
125: super()
126: @vbx_x, @vbx_y, @vbx_width, @vbx_height = nil
127: @meet_or_slice = 'meet'
128: @align = nil
129: end
Describe a user coordinate system to be imposed on the viewbox. The arguments must be numbers and the width and height arguments must be positive.
# File lib/rvg/stretchable.rb, line 137
137: def viewbox(x, y, width, height)
138: begin
139: @vbx_x = Float(x)
140: @vbx_y = Float(y)
141: @vbx_width = Float(width)
142: @vbx_height = Float(height)
143: rescue ArgumentError
144: raise ArgumentError, "arguments must be convertable to float (got #{x.class}, #{y.class}, #{width.class}, #{height.class})"
145: end
146: raise(ArgumentError, "viewbox width must be > 0 (#{width} given)") unless width >= 0
147: raise(ArgumentError, "viewbox height must be > 0 (#{height} given)") unless height >= 0
148:
149: # return the user-coordinate space attributes if defined
150: class << self
151: if not defined? @redefined then
152: @redefined = true
153: define_method(:x) { @vbx_x }
154: define_method(:y) { @vbx_y }
155: define_method(:width) { @vbx_width}
156: define_method(:height) { @vbx_height }
157: end
158: end
159:
160: yield(self) if block_given?
161: self
162: end
Establish the viewbox as necessary
# File lib/rvg/stretchable.rb, line 92
92: def add_viewbox_primitives(width, height, gc)
93: @vbx_width ||= width
94: @vbx_height ||= height
95: @vbx_x ||= 0.0
96: @vbx_y ||= 0.0
97:
98: if @align == 'none'
99: sx, sy = set_viewbox_none(width, height)
100: tx, ty = 0, 0
101: elsif @meet_or_slice == 'meet'
102: sx, sy = set_viewbox_meet(width, height)
103: tx, ty = align_to_viewport(width, height, sx, sy)
104: else
105: sx, sy = set_viewbox_slice(width, height)
106: tx, ty = align_to_viewport(width, height, sx, sy)
107: end
108:
109: # Establish clipping path around the current viewport
110: name = __id__.to_s
111: gc.define_clip_path(name) do
112: gc.path("M0,0 l#{width},0 l0,#{height} l-#{width},0 l0,-#{height}z")
113: end
114:
115: gc.clip_path(name)
116: # Add a non-scaled translation if meet or slice
117: gc.translate(tx, ty) if (tx.abs > 1.0e-10 || ty.abs > 1.0e-10)
118: # Scale viewbox as necessary
119: gc.scale(sx, sy) if (sx != 1.0 || sy != 1.0)
120: # Add a scaled translation if non-0 origin
121: gc.translate(-@vbx_x, -@vbx_y) if (@vbx_x.abs != 0.0 || @vbx_y.abs != 0)
122: end
Use align attribute to compute x- and y-offset from viewport‘s upper-left corner.
# File lib/rvg/stretchable.rb, line 58
58: def align_to_viewport(width, height, sx, sy)
59: tx = case @align
60: when /\AxMin/
61: 0
62: when NilClass, /\AxMid/
63: (width - @vbx_width*sx) / 2.0
64: when /\AxMax/
65: width - @vbx_width*sx
66: end
67:
68: ty = case @align
69: when /YMin\z/
70: 0
71: when NilClass, /YMid\z/
72: (height - @vbx_height*sy) / 2.0
73: when /YMax\z/
74: height - @vbx_height*sy
75: end
76: return [tx, ty]
77: end
Scale to fit
# File lib/rvg/stretchable.rb, line 44
44: def set_viewbox_none(width, height)
45: sx, sy = 1.0, 1.0
46:
47: if @vbx_width
48: sx = width / @vbx_width
49: end
50: if @vbx_height
51: sy = height / @vbx_height
52: end
53:
54: return [sx, sy]
55: end