prawn-svg 0.23.1 → 0.24.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/.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
|
-
|