prawn-svg 0.23.1 → 0.24.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -3
- data/README.md +15 -9
- data/lib/prawn-svg.rb +3 -0
- data/lib/prawn/svg/attributes.rb +1 -1
- data/lib/prawn/svg/attributes/clip_path.rb +6 -7
- data/lib/prawn/svg/attributes/opacity.rb +3 -3
- data/lib/prawn/svg/attributes/stroke.rb +6 -4
- data/lib/prawn/svg/calculators/arc_to_bezier_curve.rb +114 -0
- data/lib/prawn/svg/elements.rb +4 -1
- data/lib/prawn/svg/elements/base.rb +76 -69
- data/lib/prawn/svg/elements/container.rb +5 -6
- data/lib/prawn/svg/elements/gradient.rb +4 -4
- data/lib/prawn/svg/elements/image.rb +1 -1
- data/lib/prawn/svg/elements/line.rb +15 -7
- data/lib/prawn/svg/elements/marker.rb +72 -0
- data/lib/prawn/svg/elements/path.rb +23 -147
- data/lib/prawn/svg/elements/polygon.rb +14 -6
- data/lib/prawn/svg/elements/polyline.rb +12 -11
- data/lib/prawn/svg/elements/root.rb +3 -1
- data/lib/prawn/svg/elements/text.rb +38 -17
- data/lib/prawn/svg/font.rb +6 -6
- data/lib/prawn/svg/interface.rb +3 -0
- data/lib/prawn/svg/pathable.rb +130 -0
- data/lib/prawn/svg/properties.rb +122 -0
- data/lib/prawn/svg/state.rb +7 -29
- data/lib/prawn/svg/version.rb +1 -1
- data/spec/prawn/svg/elements/base_spec.rb +19 -32
- data/spec/prawn/svg/elements/line_spec.rb +37 -0
- data/spec/prawn/svg/elements/marker_spec.rb +90 -0
- data/spec/prawn/svg/elements/path_spec.rb +10 -10
- data/spec/prawn/svg/elements/polygon_spec.rb +49 -0
- data/spec/prawn/svg/elements/polyline_spec.rb +47 -0
- data/spec/prawn/svg/elements/style_spec.rb +1 -1
- data/spec/prawn/svg/elements/text_spec.rb +37 -5
- data/spec/prawn/svg/pathable_spec.rb +92 -0
- data/spec/prawn/svg/properties_spec.rb +186 -0
- data/spec/sample_svg/arrows.svg +73 -0
- data/spec/sample_svg/marker.svg +32 -0
- data/spec/sample_svg/polygon01.svg +25 -5
- metadata +23 -8
- data/lib/prawn/svg/attributes/color.rb +0 -5
- data/lib/prawn/svg/attributes/display.rb +0 -5
- data/lib/prawn/svg/attributes/font.rb +0 -38
- data/spec/prawn/svg/attributes/font_spec.rb +0 -52
@@ -1,12 +1,11 @@
|
|
1
1
|
class Prawn::SVG::Elements::Container < Prawn::SVG::Elements::Base
|
2
2
|
def parse
|
3
|
-
state.disable_drawing = true if name ==
|
4
|
-
end
|
5
|
-
|
6
|
-
def apply
|
7
|
-
process_child_elements
|
3
|
+
state.disable_drawing = true if name == 'clipPath'
|
8
4
|
|
9
|
-
|
5
|
+
if %w(symbol defs clipPath).include?(name)
|
6
|
+
properties.display = 'none'
|
7
|
+
computed_properties.display = 'none'
|
8
|
+
end
|
10
9
|
end
|
11
10
|
|
12
11
|
def container?
|
@@ -51,16 +51,16 @@ class Prawn::SVG::Elements::Gradient < Prawn::SVG::Elements::Base
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def load_gradient_configuration
|
54
|
-
@units = attributes["
|
54
|
+
@units = attributes["gradientUnits"] == 'userSpaceOnUse' ? :user_space : :bounding_box
|
55
55
|
|
56
|
-
if transform = attributes["
|
56
|
+
if transform = attributes["gradientTransform"]
|
57
57
|
matrix = transform.split(COMMA_WSP_REGEXP).map(&:to_f)
|
58
58
|
if matrix != [1, 0, 0, 1, 0, 0]
|
59
59
|
raise SkipElementError, "prawn-svg does not yet support gradients with a non-identity gradientTransform attribute"
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
if (spread_method = attributes['
|
63
|
+
if (spread_method = attributes['spreadMethod']) && spread_method != "pad"
|
64
64
|
warnings << "prawn-svg only currently supports the 'pad' spreadMethod attribute value"
|
65
65
|
end
|
66
66
|
end
|
@@ -98,7 +98,7 @@ class Prawn::SVG::Elements::Gradient < Prawn::SVG::Elements::Base
|
|
98
98
|
offset = result.last.first
|
99
99
|
end
|
100
100
|
|
101
|
-
if color_hex = Prawn::SVG::Color.color_to_hex(child.
|
101
|
+
if color_hex = Prawn::SVG::Color.color_to_hex(child.properties.stop_color)
|
102
102
|
result << [offset, color_hex]
|
103
103
|
end
|
104
104
|
end
|
@@ -13,7 +13,7 @@ class Prawn::SVG::Elements::Image < Prawn::SVG::Elements::Base
|
|
13
13
|
def parse
|
14
14
|
require_attributes 'width', 'height'
|
15
15
|
|
16
|
-
raise SkipElementQuietly if state.display == "none"
|
16
|
+
raise SkipElementQuietly if state.computed_properties.display == "none"
|
17
17
|
|
18
18
|
@url = attributes['xlink:href'] || attributes['href']
|
19
19
|
if @url.nil?
|
@@ -1,16 +1,24 @@
|
|
1
1
|
class Prawn::SVG::Elements::Line < Prawn::SVG::Elements::Base
|
2
|
+
include Prawn::SVG::Pathable
|
3
|
+
|
2
4
|
def parse
|
3
|
-
@x1 =
|
4
|
-
@y1 =
|
5
|
-
@x2 =
|
6
|
-
@y2 =
|
5
|
+
@x1 = points(attributes['x1'] || '0', :x)
|
6
|
+
@y1 = points(attributes['y1'] || '0', :y)
|
7
|
+
@x2 = points(attributes['x2'] || '0', :x)
|
8
|
+
@y2 = points(attributes['y2'] || '0', :y)
|
7
9
|
end
|
8
10
|
|
9
11
|
def apply
|
10
|
-
|
12
|
+
apply_commands
|
13
|
+
apply_markers
|
11
14
|
end
|
12
15
|
|
13
|
-
|
14
|
-
|
16
|
+
protected
|
17
|
+
|
18
|
+
def commands
|
19
|
+
@commands ||= [
|
20
|
+
Prawn::SVG::Pathable::Move.new([@x1, @y1]),
|
21
|
+
Prawn::SVG::Pathable::Line.new([@x2, @y2])
|
22
|
+
]
|
15
23
|
end
|
16
24
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
class Prawn::SVG::Elements::Marker < Prawn::SVG::Elements::Base
|
2
|
+
def parse
|
3
|
+
properties.display = 'none'
|
4
|
+
computed_properties.display = 'none'
|
5
|
+
end
|
6
|
+
|
7
|
+
def container?
|
8
|
+
true
|
9
|
+
end
|
10
|
+
|
11
|
+
def apply_marker(element, point: nil, angle: 0)
|
12
|
+
sizing = Prawn::SVG::Calculators::DocumentSizing.new([0, 0], attributes)
|
13
|
+
sizing.document_width = attributes["markerWidth"] || 3
|
14
|
+
sizing.document_height = attributes["markerHeight"] || 3
|
15
|
+
sizing.calculate
|
16
|
+
|
17
|
+
if sizing.invalid?
|
18
|
+
document.warnings << "<marker> cannot be rendered due to invalid sizing information"
|
19
|
+
return
|
20
|
+
end
|
21
|
+
|
22
|
+
element.new_call_context_from_base do
|
23
|
+
element.add_call 'save'
|
24
|
+
|
25
|
+
# LATER : these will probably change when we separate out properties from attributes
|
26
|
+
element.parse_transform_attribute_and_call
|
27
|
+
element.parse_opacity_attributes_and_call
|
28
|
+
element.parse_clip_path_attribute_and_call
|
29
|
+
|
30
|
+
element.add_call 'transformation_matrix', 1, 0, 0, 1, point[0], -point[1]
|
31
|
+
|
32
|
+
if attributes['orient'] != 'auto'
|
33
|
+
angle = attributes['orient'].to_f # defaults to 0 if not specified
|
34
|
+
end
|
35
|
+
|
36
|
+
element.push_call_position
|
37
|
+
element.add_call_and_enter 'rotate', -angle, origin: [0, y('0')] if angle != 0
|
38
|
+
|
39
|
+
if attributes['markerUnits'] != 'userSpaceOnUse'
|
40
|
+
scale = element.state.stroke_width
|
41
|
+
element.add_call 'transformation_matrix', scale, 0, 0, scale, 0, 0
|
42
|
+
end
|
43
|
+
|
44
|
+
ref_x = document.distance(attributes['refX']) || 0
|
45
|
+
ref_y = document.distance(attributes['refY']) || 0
|
46
|
+
|
47
|
+
element.add_call 'transformation_matrix', 1, 0, 0, 1, -ref_x * sizing.x_scale, ref_y * sizing.y_scale
|
48
|
+
|
49
|
+
# `overflow: visible` must be on the <marker> element
|
50
|
+
if properties.overflow != 'visible'
|
51
|
+
point = [sizing.x_offset * sizing.x_scale, y(sizing.y_offset * sizing.y_scale)]
|
52
|
+
element.add_call "rectangle", point, sizing.output_width, sizing.output_height
|
53
|
+
element.add_call "clip"
|
54
|
+
end
|
55
|
+
|
56
|
+
element.add_call 'transformation_matrix', sizing.x_scale, 0, 0, sizing.y_scale, 0, 0
|
57
|
+
|
58
|
+
new_state = state.dup
|
59
|
+
new_state.computed_properties = computed_properties.dup
|
60
|
+
|
61
|
+
container = Prawn::SVG::Elements::Container.new(document, nil, [], new_state)
|
62
|
+
container.properties.compute_properties(new_state.computed_properties)
|
63
|
+
container.parse_and_apply
|
64
|
+
container.add_calls_from_element(self)
|
65
|
+
|
66
|
+
element.add_calls_from_element(container)
|
67
|
+
|
68
|
+
element.pop_call_position
|
69
|
+
element.add_call 'restore'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -1,4 +1,7 @@
|
|
1
1
|
class Prawn::SVG::Elements::Path < Prawn::SVG::Elements::Base
|
2
|
+
include Prawn::SVG::Calculators::ArcToBezierCurve
|
3
|
+
include Prawn::SVG::Pathable
|
4
|
+
|
2
5
|
INSIDE_SPACE_REGEXP = /[ \t\r\n,]*/
|
3
6
|
OUTSIDE_SPACE_REGEXP = /[ \t\r\n]*/
|
4
7
|
INSIDE_REGEXP = /#{INSIDE_SPACE_REGEXP}([+-]?(?:[0-9]+(?:\.[0-9]*)?|\.[0-9]+)(?:(?<=[0-9])e[+-]?[0-9]+)?)/
|
@@ -24,36 +27,20 @@ class Prawn::SVG::Elements::Path < Prawn::SVG::Elements::Base
|
|
24
27
|
matched_values = match_all(matched_command[2], VALUES_REGEXP)
|
25
28
|
raise "should be impossible to have invalid inside data, but we ended up here" if matched_values.nil?
|
26
29
|
values = matched_values.collect {|value| value[1].to_f}
|
27
|
-
|
30
|
+
parse_path_command(command, values)
|
28
31
|
end
|
29
32
|
end
|
30
33
|
|
31
34
|
def apply
|
32
35
|
add_call 'join_style', :bevel
|
33
36
|
|
34
|
-
|
35
|
-
|
36
|
-
point_to = [x(args[0]), y(args[1])]
|
37
|
-
if command == 'curve_to'
|
38
|
-
opts = {:bounds => [[x(args[2]), y(args[3])], [x(args[4]), y(args[5])]]}
|
39
|
-
end
|
40
|
-
add_call command, point_to, opts
|
41
|
-
else
|
42
|
-
add_call command
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def bounding_box
|
48
|
-
x1, x2 = @commands.map {|_, args| x(args[0]) if args}.compact.minmax
|
49
|
-
y2, y1 = @commands.map {|_, args| y(args[1]) if args}.compact.minmax
|
50
|
-
|
51
|
-
[x1, y1, x2, y2]
|
37
|
+
apply_commands
|
38
|
+
apply_markers
|
52
39
|
end
|
53
40
|
|
54
41
|
protected
|
55
42
|
|
56
|
-
def
|
43
|
+
def parse_path_command(command, values)
|
57
44
|
upcase_command = command.upcase
|
58
45
|
relative = command != upcase_command
|
59
46
|
|
@@ -67,16 +54,14 @@ class Prawn::SVG::Elements::Path < Prawn::SVG::Elements::Base
|
|
67
54
|
y += @last_point.last
|
68
55
|
end
|
69
56
|
|
70
|
-
@
|
71
|
-
|
57
|
+
@subpath_initial_point = [x, y]
|
58
|
+
push_command Prawn::SVG::Pathable::Move.new(@subpath_initial_point)
|
72
59
|
|
73
|
-
return
|
60
|
+
return parse_path_command(relative ? 'l' : 'L', values) if values.any?
|
74
61
|
|
75
62
|
when 'Z' # closepath
|
76
63
|
if @subpath_initial_point
|
77
|
-
|
78
|
-
@commands << ["close_path"]
|
79
|
-
@last_point = @subpath_initial_point
|
64
|
+
push_command Prawn::SVG::Pathable::Close.new(@subpath_initial_point)
|
80
65
|
end
|
81
66
|
|
82
67
|
when 'L' # lineto
|
@@ -87,24 +72,22 @@ class Prawn::SVG::Elements::Path < Prawn::SVG::Elements::Base
|
|
87
72
|
x += @last_point.first
|
88
73
|
y += @last_point.last
|
89
74
|
end
|
90
|
-
|
91
|
-
|
75
|
+
|
76
|
+
push_command Prawn::SVG::Pathable::Line.new([x, y])
|
92
77
|
end
|
93
78
|
|
94
79
|
when 'H' # horizontal lineto
|
95
80
|
while values.any?
|
96
81
|
x = values.shift
|
97
82
|
x += @last_point.first if relative && @last_point
|
98
|
-
|
99
|
-
@commands << ["line_to", @last_point]
|
83
|
+
push_command Prawn::SVG::Pathable::Line.new([x, @last_point.last])
|
100
84
|
end
|
101
85
|
|
102
86
|
when 'V' # vertical lineto
|
103
87
|
while values.any?
|
104
88
|
y = values.shift
|
105
89
|
y += @last_point.last if relative && @last_point
|
106
|
-
|
107
|
-
@commands << ["line_to", @last_point]
|
90
|
+
push_command Prawn::SVG::Pathable::Line.new([@last_point.first, y])
|
108
91
|
end
|
109
92
|
|
110
93
|
when 'C' # curveto
|
@@ -119,9 +102,8 @@ class Prawn::SVG::Elements::Path < Prawn::SVG::Elements::Base
|
|
119
102
|
y2 += @last_point.last
|
120
103
|
end
|
121
104
|
|
122
|
-
@last_point = [x, y]
|
123
105
|
@previous_control_point = [x2, y2]
|
124
|
-
|
106
|
+
push_command Prawn::SVG::Pathable::Curve.new([x, y], [x1, y1], [x2, y2])
|
125
107
|
end
|
126
108
|
|
127
109
|
when 'S' # shorthand/smooth curveto
|
@@ -141,9 +123,8 @@ class Prawn::SVG::Elements::Path < Prawn::SVG::Elements::Base
|
|
141
123
|
x1, y1 = @last_point
|
142
124
|
end
|
143
125
|
|
144
|
-
@last_point = [x, y]
|
145
126
|
@previous_control_point = [x2, y2]
|
146
|
-
|
127
|
+
push_command Prawn::SVG::Pathable::Curve.new([x, y], [x1, y1], [x2, y2])
|
147
128
|
end
|
148
129
|
|
149
130
|
when 'Q', 'T' # quadratic curveto
|
@@ -176,10 +157,9 @@ class Prawn::SVG::Elements::Path < Prawn::SVG::Elements::Base
|
|
176
157
|
cx2 = cx1 + (x - @last_point.first) / 3.0
|
177
158
|
cy2 = cy1 + (y - @last_point.last) / 3.0
|
178
159
|
|
179
|
-
@last_point = [x, y]
|
180
160
|
@previous_quadratic_control_point = [x1, y1]
|
181
161
|
|
182
|
-
|
162
|
+
push_command Prawn::SVG::Pathable::Curve.new([x, y], [cx1, cy1], [cx2, cy2])
|
183
163
|
end
|
184
164
|
|
185
165
|
when 'A'
|
@@ -206,8 +186,7 @@ class Prawn::SVG::Elements::Path < Prawn::SVG::Elements::Base
|
|
206
186
|
|
207
187
|
# F.6.2: If rx = 0 or ry = 0 then this arc is treated as a straight line segment (a "lineto") joining the endpoints.
|
208
188
|
if within_float_delta?(rx, 0) || within_float_delta?(ry, 0)
|
209
|
-
|
210
|
-
@commands << ["line_to", @last_point]
|
189
|
+
push_command Prawn::SVG::Pathable::Line.new([x2, y2])
|
211
190
|
return
|
212
191
|
end
|
213
192
|
|
@@ -271,8 +250,7 @@ class Prawn::SVG::Elements::Path < Prawn::SVG::Elements::Base
|
|
271
250
|
theta_2 = theta_1 + d_theta
|
272
251
|
|
273
252
|
calculate_bezier_curve_points_for_arc(cx, cy, rx, ry, theta_1, theta_2, phi).each do |points|
|
274
|
-
|
275
|
-
@last_point = points[:p2]
|
253
|
+
push_command Prawn::SVG::Pathable::Curve.new(points[:p2], points[:q1], points[:q2])
|
276
254
|
end
|
277
255
|
end
|
278
256
|
end
|
@@ -296,110 +274,8 @@ class Prawn::SVG::Elements::Path < Prawn::SVG::Elements::Base
|
|
296
274
|
result
|
297
275
|
end
|
298
276
|
|
299
|
-
def
|
300
|
-
|
301
|
-
|
302
|
-
eta2 = Math.atan2(Math.sin(lambda_2) / b, Math.cos(lambda_2) / a)
|
303
|
-
|
304
|
-
# ensure eta1 <= eta2 <= eta1 + 2*PI
|
305
|
-
eta2 -= 2 * Math::PI * ((eta2 - eta1) / (2 * Math::PI)).floor
|
306
|
-
eta2 += 2 * Math::PI if lambda_2 - lambda_1 > Math::PI && eta2 - eta1 < Math::PI
|
307
|
-
|
308
|
-
[eta1, eta2]
|
309
|
-
end
|
310
|
-
|
311
|
-
# Convert the elliptical arc to a cubic bézier curve using this algorithm:
|
312
|
-
# http://www.spaceroots.org/documents/ellipse/elliptical-arc.pdf
|
313
|
-
def calculate_bezier_curve_points_for_arc(cx, cy, a, b, lambda_1, lambda_2, theta)
|
314
|
-
e = lambda do |eta|
|
315
|
-
[
|
316
|
-
cx + a * Math.cos(theta) * Math.cos(eta) - b * Math.sin(theta) * Math.sin(eta),
|
317
|
-
cy + a * Math.sin(theta) * Math.cos(eta) + b * Math.cos(theta) * Math.sin(eta)
|
318
|
-
]
|
319
|
-
end
|
320
|
-
|
321
|
-
ep = lambda do |eta|
|
322
|
-
[
|
323
|
-
-a * Math.cos(theta) * Math.sin(eta) - b * Math.sin(theta) * Math.cos(eta),
|
324
|
-
-a * Math.sin(theta) * Math.sin(eta) + b * Math.cos(theta) * Math.cos(eta)
|
325
|
-
]
|
326
|
-
end
|
327
|
-
|
328
|
-
iterations = 1
|
329
|
-
d_lambda = lambda_2 - lambda_1
|
330
|
-
|
331
|
-
while iterations < 1024
|
332
|
-
if d_lambda.abs <= Math::PI / 2.0
|
333
|
-
# TODO : run error algorithm, see whether it meets threshold or not
|
334
|
-
# puts "error = #{calculate_curve_approximation_error(a, b, eta1, eta1 + d_eta)}"
|
335
|
-
break
|
336
|
-
end
|
337
|
-
iterations *= 2
|
338
|
-
d_lambda = (lambda_2 - lambda_1) / iterations
|
339
|
-
end
|
340
|
-
|
341
|
-
(0...iterations).collect do |iteration|
|
342
|
-
eta_a, eta_b = calculate_eta_from_lambda(a, b, lambda_1+iteration*d_lambda, lambda_1+(iteration+1)*d_lambda)
|
343
|
-
d_eta = eta_b - eta_a
|
344
|
-
|
345
|
-
alpha = Math.sin(d_eta) * ((Math.sqrt(4 + 3 * Math.tan(d_eta / 2) ** 2) - 1) / 3)
|
346
|
-
|
347
|
-
x1, y1 = e[eta_a]
|
348
|
-
x2, y2 = e[eta_b]
|
349
|
-
|
350
|
-
ep_eta1_x, ep_eta1_y = ep[eta_a]
|
351
|
-
q1_x = x1 + alpha * ep_eta1_x
|
352
|
-
q1_y = y1 + alpha * ep_eta1_y
|
353
|
-
|
354
|
-
ep_eta2_x, ep_eta2_y = ep[eta_b]
|
355
|
-
q2_x = x2 - alpha * ep_eta2_x
|
356
|
-
q2_y = y2 - alpha * ep_eta2_y
|
357
|
-
|
358
|
-
{:p2 => [x2, y2], :q1 => [q1_x, q1_y], :q2 => [q2_x, q2_y]}
|
359
|
-
end
|
360
|
-
end
|
361
|
-
|
362
|
-
ERROR_COEFFICIENTS_A = [
|
363
|
-
[
|
364
|
-
[3.85268, -21.229, -0.330434, 0.0127842],
|
365
|
-
[-1.61486, 0.706564, 0.225945, 0.263682],
|
366
|
-
[-0.910164, 0.388383, 0.00551445, 0.00671814],
|
367
|
-
[-0.630184, 0.192402, 0.0098871, 0.0102527]
|
368
|
-
],
|
369
|
-
[
|
370
|
-
[-0.162211, 9.94329, 0.13723, 0.0124084],
|
371
|
-
[-0.253135, 0.00187735, 0.0230286, 0.01264],
|
372
|
-
[-0.0695069, -0.0437594, 0.0120636, 0.0163087],
|
373
|
-
[-0.0328856, -0.00926032, -0.00173573, 0.00527385]
|
374
|
-
]
|
375
|
-
]
|
376
|
-
|
377
|
-
ERROR_COEFFICIENTS_B = [
|
378
|
-
[
|
379
|
-
[0.0899116, -19.2349, -4.11711, 0.183362],
|
380
|
-
[0.138148, -1.45804, 1.32044, 1.38474],
|
381
|
-
[0.230903, -0.450262, 0.219963, 0.414038],
|
382
|
-
[0.0590565, -0.101062, 0.0430592, 0.0204699]
|
383
|
-
],
|
384
|
-
[
|
385
|
-
[0.0164649, 9.89394, 0.0919496, 0.00760802],
|
386
|
-
[0.0191603, -0.0322058, 0.0134667, -0.0825018],
|
387
|
-
[0.0156192, -0.017535, 0.00326508, -0.228157],
|
388
|
-
[-0.0236752, 0.0405821, -0.0173086, 0.176187]
|
389
|
-
]
|
390
|
-
]
|
391
|
-
|
392
|
-
def calculate_curve_approximation_error(a, b, eta1, eta2)
|
393
|
-
b_over_a = b / a
|
394
|
-
coefficents = b_over_a < 0.25 ? ERROR_COEFFICIENTS_A : ERROR_COEFFICIENTS_B
|
395
|
-
|
396
|
-
c = lambda do |i|
|
397
|
-
(0..3).inject(0) do |accumulator, j|
|
398
|
-
coef = coefficents[i][j]
|
399
|
-
accumulator + ((coef[0] * b_over_a**2 + coef[1] * b_over_a + coef[2]) / (b_over_a * coef[3])) * Math.cos(j * (eta1 + eta2))
|
400
|
-
end
|
401
|
-
end
|
402
|
-
|
403
|
-
((0.001 * b_over_a**2 + 4.98 * b_over_a + 0.207) / (b_over_a * 0.0067)) * a * Math.exp(c[0] + c[1] * (eta2 - eta1))
|
277
|
+
def push_command(command)
|
278
|
+
@commands << command
|
279
|
+
@last_point = command.destination
|
404
280
|
end
|
405
281
|
end
|
@@ -1,17 +1,25 @@
|
|
1
1
|
class Prawn::SVG::Elements::Polygon < Prawn::SVG::Elements::Base
|
2
|
+
include Prawn::SVG::Pathable
|
3
|
+
|
2
4
|
def parse
|
3
5
|
require_attributes('points')
|
4
6
|
@points = parse_points(attributes['points'])
|
5
7
|
end
|
6
8
|
|
7
9
|
def apply
|
8
|
-
|
10
|
+
apply_commands
|
11
|
+
apply_markers
|
9
12
|
end
|
10
13
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
14
|
+
protected
|
15
|
+
|
16
|
+
def commands
|
17
|
+
@commands ||= [
|
18
|
+
Prawn::SVG::Pathable::Move.new(@points[0])
|
19
|
+
] + @points[1..-1].map { |point|
|
20
|
+
Prawn::SVG::Pathable::Line.new(point)
|
21
|
+
} + [
|
22
|
+
Prawn::SVG::Pathable::Close.new(@points[0])
|
23
|
+
]
|
15
24
|
end
|
16
25
|
end
|
17
|
-
|