prawn-svg 0.28.0 → 0.32.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/test.yml +18 -0
- data/LICENSE +1 -1
- data/README.md +14 -9
- data/lib/prawn-svg.rb +4 -0
- data/lib/prawn/svg/attributes/opacity.rb +4 -4
- data/lib/prawn/svg/attributes/transform.rb +2 -44
- data/lib/prawn/svg/calculators/document_sizing.rb +2 -2
- data/lib/prawn/svg/css/stylesheets.rb +40 -19
- data/lib/prawn/svg/elements.rb +2 -0
- data/lib/prawn/svg/elements/base.rb +11 -5
- data/lib/prawn/svg/elements/call_duplicator.rb +1 -1
- data/lib/prawn/svg/elements/gradient.rb +83 -25
- data/lib/prawn/svg/elements/image.rb +2 -2
- data/lib/prawn/svg/elements/path.rb +42 -29
- data/lib/prawn/svg/elements/root.rb +4 -1
- data/lib/prawn/svg/elements/text_component.rb +21 -5
- data/lib/prawn/svg/elements/use.rb +23 -7
- data/lib/prawn/svg/extensions/additional_gradient_transforms.rb +23 -0
- data/lib/prawn/svg/interface.rb +38 -8
- data/lib/prawn/svg/loaders/data.rb +1 -1
- data/lib/prawn/svg/loaders/file.rb +4 -2
- data/lib/prawn/svg/properties.rb +1 -0
- data/lib/prawn/svg/transform_parser.rb +72 -0
- data/lib/prawn/svg/version.rb +1 -1
- data/prawn-svg.gemspec +3 -3
- data/spec/integration_spec.rb +24 -24
- data/spec/prawn/svg/attributes/opacity_spec.rb +85 -0
- data/spec/prawn/svg/attributes/transform_spec.rb +30 -35
- data/spec/prawn/svg/calculators/document_sizing_spec.rb +4 -4
- data/spec/prawn/svg/css/stylesheets_spec.rb +17 -6
- data/spec/prawn/svg/elements/base_spec.rb +16 -16
- data/spec/prawn/svg/elements/gradient_spec.rb +79 -4
- data/spec/prawn/svg/elements/line_spec.rb +12 -12
- data/spec/prawn/svg/elements/marker_spec.rb +27 -27
- data/spec/prawn/svg/elements/path_spec.rb +29 -17
- data/spec/prawn/svg/elements/polygon_spec.rb +9 -9
- data/spec/prawn/svg/elements/polyline_spec.rb +7 -7
- data/spec/prawn/svg/elements/text_spec.rb +65 -50
- data/spec/prawn/svg/loaders/data_spec.rb +8 -0
- data/spec/prawn/svg/pathable_spec.rb +4 -4
- data/spec/prawn/svg/transform_parser_spec.rb +94 -0
- data/spec/sample_svg/double_opacity.svg +6 -0
- data/spec/sample_svg/gradient_transform.svg +19 -0
- data/spec/sample_svg/links.svg +18 -0
- data/spec/sample_svg/radgrad01-bounding.svg +26 -0
- data/spec/sample_svg/radgrad01.svg +26 -0
- data/spec/sample_svg/svg_fill.svg +5 -0
- data/spec/sample_svg/text-decoration.svg +4 -0
- data/spec/sample_svg/transform.svg +20 -0
- data/spec/sample_svg/use_disordered.svg +17 -0
- data/spec/spec_helper.rb +2 -2
- metadata +48 -11
- data/.travis.yml +0 -6
data/lib/prawn/svg/properties.rb
CHANGED
@@ -37,6 +37,7 @@ class Prawn::SVG::Properties
|
|
37
37
|
"stroke-opacity" => Config.new("1", true),
|
38
38
|
"stroke-width" => Config.new("1", true),
|
39
39
|
"text-anchor" => Config.new("start", true, %w(inherit start middle end), true),
|
40
|
+
'text-decoration' => Config.new('none', true, %w(inherit none underline), true),
|
40
41
|
}.freeze
|
41
42
|
|
42
43
|
PROPERTIES.each do |name, value|
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Prawn::SVG::TransformParser
|
2
|
+
def parse_transform_attribute(transform)
|
3
|
+
matrix = Matrix.identity(3)
|
4
|
+
|
5
|
+
parse_css_method_calls(transform).each do |name, arguments|
|
6
|
+
case name
|
7
|
+
when 'translate'
|
8
|
+
x, y = arguments
|
9
|
+
matrix *= Matrix[[1, 0, x_pixels(x.to_f)], [0, 1, -y_pixels(y.to_f)], [0, 0, 1]]
|
10
|
+
|
11
|
+
when 'translateX'
|
12
|
+
x = arguments.first
|
13
|
+
matrix *= Matrix[[1, 0, x_pixels(x.to_f)], [0, 1, 0], [0, 0, 1]]
|
14
|
+
|
15
|
+
when 'translateY'
|
16
|
+
y = arguments.first
|
17
|
+
matrix *= Matrix[[1, 0, 0], [0, 1, -y_pixels(y.to_f)], [0, 0, 1]]
|
18
|
+
|
19
|
+
when 'rotate'
|
20
|
+
angle, x, y = arguments.collect { |a| a.to_f }
|
21
|
+
angle = angle * Math::PI / 180.0
|
22
|
+
|
23
|
+
case arguments.length
|
24
|
+
when 1
|
25
|
+
matrix *= Matrix[[Math.cos(angle), Math.sin(angle), 0], [-Math.sin(angle), Math.cos(angle), 0], [0, 0, 1]]
|
26
|
+
when 3
|
27
|
+
matrix *= Matrix[[1, 0, x_pixels(x.to_f)], [0, 1, -y_pixels(y.to_f)], [0, 0, 1]]
|
28
|
+
matrix *= Matrix[[Math.cos(angle), Math.sin(angle), 0], [-Math.sin(angle), Math.cos(angle), 0], [0, 0, 1]]
|
29
|
+
matrix *= Matrix[[1, 0, -x_pixels(x.to_f)], [0, 1, y_pixels(y.to_f)], [0, 0, 1]]
|
30
|
+
else
|
31
|
+
warnings << "transform 'rotate' must have either one or three arguments"
|
32
|
+
end
|
33
|
+
|
34
|
+
when 'scale'
|
35
|
+
x_scale = arguments[0].to_f
|
36
|
+
y_scale = (arguments[1] || x_scale).to_f
|
37
|
+
matrix *= Matrix[[x_scale, 0, 0], [0, y_scale, 0], [0, 0, 1]]
|
38
|
+
|
39
|
+
when 'skewX'
|
40
|
+
angle = arguments[0].to_f * Math::PI / 180.0
|
41
|
+
matrix *= Matrix[[1, -Math.tan(angle), 0], [0, 1, 0], [0, 0, 1]]
|
42
|
+
|
43
|
+
when 'skewY'
|
44
|
+
angle = arguments[0].to_f * Math::PI / 180.0
|
45
|
+
matrix *= Matrix[[1, 0, 0], [-Math.tan(angle), 1, 0], [0, 0, 1]]
|
46
|
+
|
47
|
+
when 'matrix'
|
48
|
+
if arguments.length != 6
|
49
|
+
warnings << "transform 'matrix' must have six arguments"
|
50
|
+
else
|
51
|
+
a, b, c, d, e, f = arguments.collect { |argument| argument.to_f }
|
52
|
+
matrix *= Matrix[[a, -c, e], [-b, d, -f], [0, 0, 1]]
|
53
|
+
end
|
54
|
+
|
55
|
+
else
|
56
|
+
warnings << "Unknown/unsupported transformation '#{name}'; ignoring"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
matrix.to_a[0..1].transpose.flatten
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def parse_css_method_calls(string)
|
66
|
+
string.scan(/\s*(\w+)\(([^)]+)\)\s*/).collect do |call|
|
67
|
+
name, argument_string = call
|
68
|
+
arguments = argument_string.strip.split(/\s*[,\s]\s*/)
|
69
|
+
[name, arguments]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/prawn/svg/version.rb
CHANGED
data/prawn-svg.gemspec
CHANGED
@@ -6,7 +6,6 @@ Gem::Specification.new do |gem|
|
|
6
6
|
gem.version = Prawn::SVG::VERSION
|
7
7
|
gem.summary = "SVG renderer for Prawn PDF library"
|
8
8
|
gem.description = "This gem allows you to render SVG directly into a PDF using the 'prawn' gem. Since PDF is vector-based, you'll get nice scaled graphics if you use SVG instead of an image."
|
9
|
-
gem.has_rdoc = false
|
10
9
|
gem.author = "Roger Nesbitt"
|
11
10
|
gem.email = "roger@seriousorange.com"
|
12
11
|
gem.homepage = "http://github.com/mogest/prawn-svg"
|
@@ -18,10 +17,11 @@ Gem::Specification.new do |gem|
|
|
18
17
|
gem.name = "prawn-svg"
|
19
18
|
gem.require_paths = ["lib"]
|
20
19
|
|
21
|
-
gem.required_ruby_version = '>= 2.
|
20
|
+
gem.required_ruby_version = '>= 2.3.0'
|
22
21
|
|
23
22
|
gem.add_runtime_dependency "prawn", ">= 0.11.1", "< 3"
|
24
23
|
gem.add_runtime_dependency "css_parser", "~> 1.6"
|
24
|
+
gem.add_runtime_dependency "rexml", "~> 3.2"
|
25
25
|
gem.add_development_dependency "rspec", "~> 3.0"
|
26
|
-
gem.add_development_dependency "rake", "~>
|
26
|
+
gem.add_development_dependency "rake", "~> 13.0"
|
27
27
|
end
|
data/spec/integration_spec.rb
CHANGED
@@ -28,34 +28,34 @@ describe "Integration test" do
|
|
28
28
|
element.process
|
29
29
|
|
30
30
|
expect(element.calls).to eq [
|
31
|
-
["fill_color", ["000000"], []],
|
32
|
-
["transformation_matrix", [1, 0, 0, 1, 0, 0], []],
|
33
|
-
["transformation_matrix", [1, 0, 0, 1, 0, 0], []],
|
34
|
-
["save", [], []], ["restore", [], []],
|
35
|
-
["save", [], []],
|
36
|
-
["fill_color", ["0000ff"], []],
|
37
|
-
["fill", [], [
|
38
|
-
["rectangle", [[0.0, 200.0], 10.0, 10.0], []]
|
31
|
+
["fill_color", ["000000"], {}, []],
|
32
|
+
["transformation_matrix", [1, 0, 0, 1, 0, 0], {}, []],
|
33
|
+
["transformation_matrix", [1, 0, 0, 1, 0, 0], {}, []],
|
34
|
+
["save", [], {}, []], ["restore", [], {}, []],
|
35
|
+
["save", [], {}, []],
|
36
|
+
["fill_color", ["0000ff"], {}, []],
|
37
|
+
["fill", [], {}, [
|
38
|
+
["rectangle", [[0.0, 200.0], 10.0, 10.0], {}, []]
|
39
39
|
]],
|
40
|
-
["restore", [], []],
|
41
|
-
["save", [], []],
|
42
|
-
["fill_color", ["008000"], []],
|
43
|
-
["fill", [], [
|
44
|
-
["rectangle", [[10.0, 200.0], 10.0, 10.0], []]
|
40
|
+
["restore", [], {}, []],
|
41
|
+
["save", [], {}, []],
|
42
|
+
["fill_color", ["008000"], {}, []],
|
43
|
+
["fill", [], {}, [
|
44
|
+
["rectangle", [[10.0, 200.0], 10.0, 10.0], {}, []]
|
45
45
|
]],
|
46
|
-
["restore", [], []],
|
47
|
-
["save", [], []],
|
48
|
-
["fill_color", ["ff0000"], []],
|
49
|
-
["fill", [], [
|
50
|
-
["rectangle", [[20.0, 200.0], 10.0, 10.0], []]
|
46
|
+
["restore", [], {}, []],
|
47
|
+
["save", [], {}, []],
|
48
|
+
["fill_color", ["ff0000"], {}, []],
|
49
|
+
["fill", [], {}, [
|
50
|
+
["rectangle", [[20.0, 200.0], 10.0, 10.0], {}, []]
|
51
51
|
]],
|
52
|
-
["restore", [], []],
|
53
|
-
["save", [], []],
|
54
|
-
["fill_color", ["ffff00"], []],
|
55
|
-
["fill", [], [
|
56
|
-
["rectangle", [[30.0, 200.0], 10.0, 10.0], []]
|
52
|
+
["restore", [], {}, []],
|
53
|
+
["save", [], {}, []],
|
54
|
+
["fill_color", ["ffff00"], {}, []],
|
55
|
+
["fill", [], {}, [
|
56
|
+
["rectangle", [[30.0, 200.0], 10.0, 10.0], {}, []]
|
57
57
|
]],
|
58
|
-
["restore", [], []]
|
58
|
+
["restore", [], {}, []]
|
59
59
|
]
|
60
60
|
end
|
61
61
|
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Prawn::SVG::Attributes::Opacity do
|
4
|
+
class OpacityTestElement
|
5
|
+
include Prawn::SVG::Attributes::Opacity
|
6
|
+
|
7
|
+
attr_accessor :properties, :state
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@properties = ::Prawn::SVG::Properties.new
|
11
|
+
@state = ::Prawn::SVG::State.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def clamp(value, min_value, max_value)
|
15
|
+
[[value, min_value].max, max_value].min
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
let(:element) { OpacityTestElement.new }
|
20
|
+
|
21
|
+
describe "#parse_opacity_attributes_and_call" do
|
22
|
+
subject { element.parse_opacity_attributes_and_call }
|
23
|
+
|
24
|
+
context "with no opacity specified" do
|
25
|
+
it "does nothing" do
|
26
|
+
expect(element).not_to receive(:add_call_and_enter)
|
27
|
+
subject
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "with opacity" do
|
32
|
+
it "sets fill and stroke opacity" do
|
33
|
+
element.properties.opacity = '0.4'
|
34
|
+
|
35
|
+
expect(element).to receive(:add_call_and_enter).with('transparent', 0.4, 0.4)
|
36
|
+
subject
|
37
|
+
|
38
|
+
expect(element.state.fill_opacity).to eq 0.4
|
39
|
+
expect(element.state.stroke_opacity).to eq 0.4
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context "with just fill opacity" do
|
44
|
+
it "sets fill opacity and sets stroke opacity to 1" do
|
45
|
+
element.properties.fill_opacity = '0.4'
|
46
|
+
|
47
|
+
expect(element).to receive(:add_call_and_enter).with('transparent', 0.4, 1)
|
48
|
+
subject
|
49
|
+
|
50
|
+
expect(element.state.fill_opacity).to eq 0.4
|
51
|
+
expect(element.state.stroke_opacity).to eq 1
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "with an existing fill/stroke opacity" do
|
56
|
+
it "multiplies the new opacity by the old" do
|
57
|
+
element.state.fill_opacity = 0.5
|
58
|
+
element.state.stroke_opacity = 0.8
|
59
|
+
|
60
|
+
element.properties.fill_opacity = '0.4'
|
61
|
+
element.properties.stroke_opacity = '0.5'
|
62
|
+
|
63
|
+
expect(element).to receive(:add_call_and_enter).with('transparent', 0.2, 0.4)
|
64
|
+
subject
|
65
|
+
|
66
|
+
expect(element.state.fill_opacity).to eq 0.2
|
67
|
+
expect(element.state.stroke_opacity).to eq 0.4
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "with stroke, fill, and opacity all specified" do
|
72
|
+
it "choses the lower of them" do
|
73
|
+
element.properties.fill_opacity = '0.4'
|
74
|
+
element.properties.stroke_opacity = '0.6'
|
75
|
+
element.properties.opacity = '0.5'
|
76
|
+
|
77
|
+
expect(element).to receive(:add_call_and_enter).with('transparent', 0.4, 0.5)
|
78
|
+
subject
|
79
|
+
|
80
|
+
expect(element.state.fill_opacity).to eq 0.4
|
81
|
+
expect(element.state.stroke_opacity).to eq 0.5
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -14,43 +14,38 @@ describe Prawn::SVG::Attributes::Transform do
|
|
14
14
|
|
15
15
|
let(:element) { TransformTestElement.new }
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
17
|
+
subject { element.send :parse_transform_attribute_and_call }
|
18
|
+
|
19
|
+
context "when a non-identity matrix is requested" do
|
20
|
+
let(:transform) { 'translate(-5.5)' }
|
21
|
+
|
22
|
+
it "passes the transform and executes the returned matrix" do
|
23
|
+
expect(element).to receive(:parse_transform_attribute).with(transform).and_return([1, 2, 3, 4, 5, 6])
|
24
|
+
expect(element).to receive(:add_call_and_enter).with('transformation_matrix', 1, 2, 3, 4, 5, 6)
|
25
|
+
|
26
|
+
element.attributes['transform'] = transform
|
27
|
+
subject
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "when an identity matrix is requested" do
|
32
|
+
let(:transform) { 'translate(0)' }
|
33
|
+
|
34
|
+
it "does not execute any commands" do
|
35
|
+
expect(element).to receive(:parse_transform_attribute).with(transform).and_return([1, 0, 0, 1, 0, 0])
|
36
|
+
expect(element).not_to receive(:add_call_and_enter)
|
37
|
+
|
38
|
+
element.attributes['transform'] = transform
|
39
|
+
subject
|
29
40
|
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context "when transform is blank" do
|
44
|
+
it "does nothing" do
|
45
|
+
expect(element).not_to receive(:parse_transform_attribute)
|
46
|
+
expect(element).not_to receive(:add_call_and_enter)
|
30
47
|
|
31
|
-
|
32
|
-
it "handles a single angle argument" do
|
33
|
-
expect(element).to receive(:add_call_and_enter).with('rotate', -5.5, :origin => [0, 0])
|
34
|
-
expect(element).to receive(:y).with('0').and_return(0)
|
35
|
-
|
36
|
-
element.attributes['transform'] = 'rotate(5.5)'
|
37
|
-
subject
|
38
|
-
end
|
39
|
-
|
40
|
-
it "handles three arguments" do
|
41
|
-
expect(element).to receive(:add_call_and_enter).with('rotate', -5.5, :origin => [1.0, 2.0])
|
42
|
-
expect(element).to receive(:x).with(1.0).and_return(1.0)
|
43
|
-
expect(element).to receive(:y).with(2.0).and_return(2.0)
|
44
|
-
|
45
|
-
element.attributes['transform'] = 'rotate(5.5 1 2)'
|
46
|
-
subject
|
47
|
-
end
|
48
|
-
|
49
|
-
it "does nothing and warns if two arguments" do
|
50
|
-
expect(element).to receive(:warnings).and_return([])
|
51
|
-
element.attributes['transform'] = 'rotate(5.5 1)'
|
52
|
-
subject
|
53
|
-
end
|
48
|
+
subject
|
54
49
|
end
|
55
50
|
end
|
56
51
|
end
|
@@ -31,8 +31,8 @@ describe Prawn::SVG::Calculators::DocumentSizing do
|
|
31
31
|
describe "#calculate" do
|
32
32
|
it "calculates the document sizing measurements for a given set of inputs" do
|
33
33
|
sizing.calculate
|
34
|
-
expect(sizing.x_offset).to eq
|
35
|
-
expect(sizing.y_offset).to eq
|
34
|
+
expect(sizing.x_offset).to eq(-75 / 0.25)
|
35
|
+
expect(sizing.y_offset).to eq(-30)
|
36
36
|
expect(sizing.x_scale).to eq 0.25
|
37
37
|
expect(sizing.y_scale).to eq 0.25
|
38
38
|
expect(sizing.viewport_width).to eq 300
|
@@ -74,12 +74,12 @@ describe Prawn::SVG::Calculators::DocumentSizing do
|
|
74
74
|
context "when a viewBox is specified" do
|
75
75
|
let(:attributes) { {"viewBox" => "0 0 100 200"} }
|
76
76
|
|
77
|
-
it "defaults to 100% width and height" do
|
77
|
+
it "defaults to 100% width and uses the viewbox ratio for height" do
|
78
78
|
sizing.calculate
|
79
79
|
expect(sizing.viewport_width).to eq 100
|
80
80
|
expect(sizing.viewport_height).to eq 200
|
81
81
|
expect(sizing.output_width).to eq 1200
|
82
|
-
expect(sizing.output_height).to eq
|
82
|
+
expect(sizing.output_height).to eq 2400
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
@@ -11,6 +11,7 @@ RSpec.describe Prawn::SVG::CSS::Stylesheets do
|
|
11
11
|
rect { fill: #ff0000; }
|
12
12
|
rect ~ rect { fill: #330000; }
|
13
13
|
rect + rect { fill: #440000; }
|
14
|
+
rect:first-child:last-child { fill: #441234; }
|
14
15
|
|
15
16
|
circle:first-child { fill: #550000; }
|
16
17
|
circle:nth-child(2) { fill: #660000; }
|
@@ -37,9 +38,13 @@ RSpec.describe Prawn::SVG::CSS::Stylesheets do
|
|
37
38
|
<rect width="6" height="6" />
|
38
39
|
</g>
|
39
40
|
|
40
|
-
<circle width="
|
41
|
-
|
42
|
-
<
|
41
|
+
<circle width="100" />
|
42
|
+
|
43
|
+
<g id="circles">
|
44
|
+
<circle width="7" />
|
45
|
+
<circle width="8" />
|
46
|
+
<circle width="9" />
|
47
|
+
</g>
|
43
48
|
</g>
|
44
49
|
|
45
50
|
<square width="10" chocolate="hi there" />
|
@@ -56,13 +61,17 @@ RSpec.describe Prawn::SVG::CSS::Stylesheets do
|
|
56
61
|
result = Prawn::SVG::CSS::Stylesheets.new(CssParser::Parser.new, REXML::Document.new(svg)).load
|
57
62
|
width_and_styles = result.map { |k, v| [k.attributes["width"].to_i, v] }.sort_by(&:first)
|
58
63
|
|
59
|
-
|
64
|
+
expected = [
|
60
65
|
[1, [["fill", "#ff0000", false]]],
|
61
66
|
[2, [["fill", "#ff0000", false], ["fill", "#330000", false], ["fill", "#440000", false], ["fill", "#220000", false]]],
|
62
67
|
[3, [["fill", "#ff0000", false], ["fill", "#00ff00", false]]],
|
63
68
|
[4, [["fill", "#ff0000", false], ["fill", "#330000", false], ["fill", "#440000", false], ["fill", "#00ff00", false]]],
|
64
|
-
|
65
|
-
|
69
|
+
]
|
70
|
+
|
71
|
+
expected << [5, [["fill", "#ff0000", false], ["fill", "#330000", false], ["fill", "#330000", false], ["fill", "#440000", false], ["fill", "#00ff00", false]]]
|
72
|
+
|
73
|
+
expected.concat [
|
74
|
+
[6, [["fill", "#ff0000", false], ["fill", "#441234", false], ["fill", "#0000ff", false]]],
|
66
75
|
[7, [["fill", "#550000", false]]],
|
67
76
|
[8, [["fill", "#660000", false]]],
|
68
77
|
[9, [["fill", "#770000", false]]],
|
@@ -74,6 +83,8 @@ RSpec.describe Prawn::SVG::CSS::Stylesheets do
|
|
74
83
|
[15, [["fill", "#dd0000", false]]],
|
75
84
|
[16, [["fill", "#ee0000", false]]],
|
76
85
|
]
|
86
|
+
|
87
|
+
expect(width_and_styles).to eq(expected)
|
77
88
|
end
|
78
89
|
end
|
79
90
|
|
@@ -25,19 +25,19 @@ describe Prawn::SVG::Elements::Base do
|
|
25
25
|
describe "applying calls from the standard attributes" do
|
26
26
|
let(:svg) do
|
27
27
|
<<-SVG
|
28
|
-
<something transform="
|
28
|
+
<something transform="scale(2)" fill-opacity="0.5" fill="red" stroke="blue" stroke-width="5"/>
|
29
29
|
SVG
|
30
30
|
end
|
31
31
|
|
32
32
|
it "appends the relevant calls" do
|
33
33
|
element.process
|
34
34
|
expect(element.base_calls).to eq [
|
35
|
-
["
|
36
|
-
["transparent", [0.5, 1], [
|
37
|
-
["fill_color", ["ff0000"], []],
|
38
|
-
["stroke_color", ["0000ff"], []],
|
39
|
-
["line_width", [5.0], []],
|
40
|
-
["fill_and_stroke", [], []]
|
35
|
+
["transformation_matrix", [2, 0, 0, 2, 0, 0], {}, [
|
36
|
+
["transparent", [0.5, 1], {}, [
|
37
|
+
["fill_color", ["ff0000"], {}, []],
|
38
|
+
["stroke_color", ["0000ff"], {}, []],
|
39
|
+
["line_width", [5.0], {}, []],
|
40
|
+
["fill_and_stroke", [], {}, []]
|
41
41
|
]]
|
42
42
|
]]
|
43
43
|
]
|
@@ -50,37 +50,37 @@ describe Prawn::SVG::Elements::Base do
|
|
50
50
|
|
51
51
|
context "with neither fill nor stroke" do
|
52
52
|
let(:svg) { '<rect style="fill: none;"></rect>' }
|
53
|
-
it { is_expected.to eq ['end_path', [], []] }
|
53
|
+
it { is_expected.to eq ['end_path', [], {}, []] }
|
54
54
|
end
|
55
55
|
|
56
56
|
context "with a fill only" do
|
57
57
|
let(:svg) { '<rect style="fill: black;"></rect>' }
|
58
|
-
it { is_expected.to eq ['fill', [], []] }
|
58
|
+
it { is_expected.to eq ['fill', [], {}, []] }
|
59
59
|
end
|
60
60
|
|
61
61
|
context "with a stroke only" do
|
62
62
|
let(:svg) { '<rect style="fill: none; stroke: black;"></rect>' }
|
63
|
-
it { is_expected.to eq ['stroke', [], []] }
|
63
|
+
it { is_expected.to eq ['stroke', [], {}, []] }
|
64
64
|
end
|
65
65
|
|
66
66
|
context "with fill and stroke" do
|
67
67
|
let(:svg) { '<rect style="fill: black; stroke: black;"></rect>' }
|
68
|
-
it { is_expected.to eq ['fill_and_stroke', [], []] }
|
68
|
+
it { is_expected.to eq ['fill_and_stroke', [], {}, []] }
|
69
69
|
end
|
70
70
|
|
71
71
|
context "with fill with evenodd fill rule" do
|
72
72
|
let(:svg) { '<rect style="fill: black; fill-rule: evenodd;"></rect>' }
|
73
|
-
it { is_expected.to eq ['fill', [{fill_rule: :even_odd}
|
73
|
+
it { is_expected.to eq ['fill', [], {fill_rule: :even_odd}, []] }
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
77
|
it "appends calls to the parent element" do
|
78
78
|
expect(element).to receive(:apply) do
|
79
|
-
element.send :add_call, "test", "argument"
|
79
|
+
element.send :add_call, "test", "argument", kw: 'argument'
|
80
80
|
end
|
81
81
|
|
82
82
|
element.process
|
83
|
-
expect(element.parent_calls).to eq [["fill", [], [["test", ["argument"], []]]]]
|
83
|
+
expect(element.parent_calls).to eq [["fill", [], {}, [["test", ["argument"], {kw: 'argument'}, []]]]]
|
84
84
|
end
|
85
85
|
|
86
86
|
it "quietly absorbs a SkipElementQuietly exception" do
|
@@ -149,8 +149,8 @@ describe Prawn::SVG::Elements::Base do
|
|
149
149
|
it "uses the parent's color element if 'currentColor' fill attribute provided" do
|
150
150
|
element.process
|
151
151
|
|
152
|
-
expect(flattened_calls).to include ['fill_color', ['ff0000']]
|
153
|
-
expect(flattened_calls).not_to include ['fill_color', ['00ff00']]
|
152
|
+
expect(flattened_calls).to include ['fill_color', ['ff0000'], {}]
|
153
|
+
expect(flattened_calls).not_to include ['fill_color', ['00ff00'], {}]
|
154
154
|
end
|
155
155
|
end
|
156
156
|
|