prawn-svg 0.21.0 → 0.22.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +6 -0
- data/README.md +11 -4
- data/lib/prawn-svg.rb +9 -6
- data/lib/prawn/svg/attributes.rb +6 -0
- data/lib/prawn/svg/attributes/clip_path.rb +17 -0
- data/lib/prawn/svg/attributes/display.rb +5 -0
- data/lib/prawn/svg/attributes/font.rb +38 -0
- data/lib/prawn/svg/attributes/opacity.rb +15 -0
- data/lib/prawn/svg/attributes/stroke.rb +35 -0
- data/lib/prawn/svg/attributes/transform.rb +50 -0
- data/lib/prawn/svg/calculators/aspect_ratio.rb +1 -1
- data/lib/prawn/svg/calculators/document_sizing.rb +2 -2
- data/lib/prawn/svg/calculators/pixels.rb +1 -1
- data/lib/prawn/svg/color.rb +44 -14
- data/lib/prawn/svg/document.rb +6 -5
- data/lib/prawn/svg/elements.rb +33 -0
- data/lib/prawn/svg/elements/base.rb +228 -0
- data/lib/prawn/svg/elements/circle.rb +25 -0
- data/lib/prawn/svg/elements/container.rb +15 -0
- data/lib/prawn/svg/elements/ellipse.rb +23 -0
- data/lib/prawn/svg/elements/gradient.rb +117 -0
- data/lib/prawn/svg/elements/ignored.rb +5 -0
- data/lib/prawn/svg/elements/image.rb +85 -0
- data/lib/prawn/svg/elements/line.rb +16 -0
- data/lib/prawn/svg/elements/path.rb +405 -0
- data/lib/prawn/svg/elements/polygon.rb +17 -0
- data/lib/prawn/svg/elements/polyline.rb +22 -0
- data/lib/prawn/svg/elements/rect.rb +33 -0
- data/lib/prawn/svg/elements/root.rb +9 -0
- data/lib/prawn/svg/elements/style.rb +10 -0
- data/lib/prawn/svg/elements/text.rb +87 -0
- data/lib/prawn/svg/elements/use.rb +29 -0
- data/lib/prawn/svg/extension.rb +2 -2
- data/lib/prawn/svg/font.rb +3 -3
- data/lib/prawn/svg/interface.rb +12 -5
- data/lib/prawn/svg/url_loader.rb +1 -1
- data/lib/prawn/svg/version.rb +2 -2
- data/prawn-svg.gemspec +3 -3
- data/spec/integration_spec.rb +59 -2
- data/spec/prawn/svg/attributes/font_spec.rb +49 -0
- data/spec/prawn/svg/attributes/transform_spec.rb +56 -0
- data/spec/prawn/svg/calculators/aspect_ratio_spec.rb +2 -2
- data/spec/prawn/svg/calculators/document_sizing_spec.rb +3 -3
- data/spec/prawn/svg/color_spec.rb +36 -15
- data/spec/prawn/svg/document_spec.rb +4 -4
- data/spec/prawn/svg/elements/base_spec.rb +125 -0
- data/spec/prawn/svg/elements/gradient_spec.rb +61 -0
- data/spec/prawn/svg/elements/path_spec.rb +123 -0
- data/spec/prawn/svg/elements/style_spec.rb +23 -0
- data/spec/prawn/svg/{parser → elements}/text_spec.rb +7 -8
- data/spec/prawn/svg/font_spec.rb +12 -12
- data/spec/prawn/svg/interface_spec.rb +7 -7
- data/spec/prawn/svg/url_loader_spec.rb +2 -2
- data/spec/sample_svg/gradients.svg +40 -0
- data/spec/sample_svg/rect02.svg +8 -11
- data/spec/spec_helper.rb +1 -1
- metadata +46 -18
- data/lib/prawn/svg/element.rb +0 -304
- data/lib/prawn/svg/parser.rb +0 -268
- data/lib/prawn/svg/parser/image.rb +0 -81
- data/lib/prawn/svg/parser/path.rb +0 -392
- data/lib/prawn/svg/parser/text.rb +0 -80
- data/spec/prawn/svg/element_spec.rb +0 -127
- data/spec/prawn/svg/parser/path_spec.rb +0 -89
- data/spec/prawn/svg/parser_spec.rb +0 -55
@@ -1,9 +1,8 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../../../spec_helper'
|
2
2
|
|
3
|
-
describe Prawn::
|
4
|
-
let(:document) { Prawn::
|
5
|
-
let(:element) { Prawn::
|
6
|
-
let(:parser) { Prawn::Svg::Parser::Text.new }
|
3
|
+
describe Prawn::SVG::Elements::Text do
|
4
|
+
let(:document) { Prawn::SVG::Document.new(svg, [800, 600], {}) }
|
5
|
+
let(:element) { Prawn::SVG::Elements::Text.new(document, document.root, [], {}) }
|
7
6
|
|
8
7
|
describe "xml:space preserve" do
|
9
8
|
let(:svg) { %(<text#{attributes}>some\n\t text</text>) }
|
@@ -12,7 +11,7 @@ describe Prawn::Svg::Parser::Text do
|
|
12
11
|
let(:attributes) { ' xml:space="preserve"' }
|
13
12
|
|
14
13
|
it "converts newlines and tabs to spaces, and preserves spaces" do
|
15
|
-
|
14
|
+
element.process
|
16
15
|
|
17
16
|
expect(element.calls).to eq [
|
18
17
|
["draw_text", ["some text", {:style=>nil, :at=>[0.0, 150.0]}], []]
|
@@ -24,7 +23,7 @@ describe Prawn::Svg::Parser::Text do
|
|
24
23
|
let(:attributes) { '' }
|
25
24
|
|
26
25
|
it "strips space" do
|
27
|
-
|
26
|
+
element.process
|
28
27
|
|
29
28
|
expect(element.calls).to eq [
|
30
29
|
["draw_text", ["some text", {:style=>nil, :at=>[0.0, 150.0]}], []]
|
@@ -37,7 +36,7 @@ describe Prawn::Svg::Parser::Text do
|
|
37
36
|
let(:svg) { '<g text-anchor="middle" font-family="sans-serif" font-size="12"><text x="50" y="14">Text</text></g>' }
|
38
37
|
|
39
38
|
it "should inherit text-anchor from parent element" do
|
40
|
-
|
39
|
+
element.process
|
41
40
|
expect(element.state[:text_anchor]).to eq 'middle'
|
42
41
|
end
|
43
42
|
end
|
@@ -46,7 +45,7 @@ describe Prawn::Svg::Parser::Text do
|
|
46
45
|
let(:svg) { '<text letter-spacing="5">spaced</text>' }
|
47
46
|
|
48
47
|
it "calls character_spacing with the requested size" do
|
49
|
-
|
48
|
+
element.process
|
50
49
|
|
51
50
|
expect(element.base_calls).to eq [
|
52
51
|
["end_path", [], [
|
data/spec/prawn/svg/font_spec.rb
CHANGED
@@ -1,31 +1,31 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
2
|
|
3
|
-
describe Prawn::
|
3
|
+
describe Prawn::SVG::Font do
|
4
4
|
describe :load do
|
5
5
|
it "matches a built in font" do
|
6
|
-
Prawn::
|
6
|
+
Prawn::SVG::Font.load("blah, 'courier', nothing").name.should == 'Courier'
|
7
7
|
end
|
8
8
|
|
9
9
|
it "matches a default font" do
|
10
|
-
Prawn::
|
11
|
-
Prawn::
|
12
|
-
Prawn::
|
10
|
+
Prawn::SVG::Font.load("serif").name.should == 'Times-Roman'
|
11
|
+
Prawn::SVG::Font.load("blah, serif").name.should == 'Times-Roman'
|
12
|
+
Prawn::SVG::Font.load("blah, serif , test").name.should == 'Times-Roman'
|
13
13
|
end
|
14
14
|
|
15
|
-
if Prawn::
|
15
|
+
if Prawn::SVG::Font.installed_fonts["Verdana"]
|
16
16
|
it "matches a font installed on the system" do
|
17
|
-
Prawn::
|
18
|
-
Prawn::
|
19
|
-
Prawn::
|
20
|
-
Prawn::
|
17
|
+
Prawn::SVG::Font.load("verdana, sans-serif").name.should == 'Verdana'
|
18
|
+
Prawn::SVG::Font.load("VERDANA, sans-serif").name.should == 'Verdana'
|
19
|
+
Prawn::SVG::Font.load("something, \"Times New Roman\", serif").name.should == "Times New Roman"
|
20
|
+
Prawn::SVG::Font.load("something, Times New Roman, serif").name.should == "Times New Roman"
|
21
21
|
end
|
22
22
|
else
|
23
23
|
it "not running font test because we couldn't find Verdana installed on the system"
|
24
24
|
end
|
25
25
|
|
26
26
|
it "returns nil if it can't find any such font" do
|
27
|
-
Prawn::
|
28
|
-
Prawn::
|
27
|
+
Prawn::SVG::Font.load("blah, thing").should be_nil
|
28
|
+
Prawn::SVG::Font.load("").should be_nil
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Prawn::
|
3
|
+
describe Prawn::SVG::Interface do
|
4
4
|
let(:bounds) { double(width: 800, height: 600) }
|
5
5
|
let(:prawn) { instance_double(Prawn::Document, font_families: {}, bounds: bounds, cursor: 600) }
|
6
6
|
let(:svg) { '<svg width="250" height="100"></svg>' }
|
@@ -11,19 +11,19 @@ describe Prawn::Svg::Interface do
|
|
11
11
|
allow(Prawn).to receive(:debug).and_return(true)
|
12
12
|
|
13
13
|
expect {
|
14
|
-
Prawn::
|
14
|
+
Prawn::SVG::Interface.new(svg, prawn, :invalid => "option")
|
15
15
|
}.to raise_error(Prawn::Errors::UnknownOption)
|
16
16
|
end
|
17
17
|
|
18
18
|
it "does nothing if an invalid option is given and debug is off" do
|
19
|
-
Prawn::
|
19
|
+
Prawn::SVG::Interface.new(svg, prawn, :invalid => "option")
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
24
|
describe "#draw" do
|
25
25
|
context "when the sizing object indicates the sizes are invalid" do
|
26
|
-
let(:interface) { Prawn::
|
26
|
+
let(:interface) { Prawn::SVG::Interface.new('<svg width="0"></svg>', prawn, {}) }
|
27
27
|
|
28
28
|
it "doesn't draw anything and adds a warning" do
|
29
29
|
interface.draw
|
@@ -36,7 +36,7 @@ describe Prawn::Svg::Interface do
|
|
36
36
|
subject { interface.position }
|
37
37
|
|
38
38
|
context "when options[:at] supplied" do
|
39
|
-
let(:interface) { Prawn::
|
39
|
+
let(:interface) { Prawn::SVG::Interface.new(svg, prawn, at: [1, 2], position: :left) }
|
40
40
|
|
41
41
|
it "returns options[:at]" do
|
42
42
|
expect(subject).to eq [1, 2]
|
@@ -44,7 +44,7 @@ describe Prawn::Svg::Interface do
|
|
44
44
|
end
|
45
45
|
|
46
46
|
context "when only a position is supplied" do
|
47
|
-
let(:interface) { Prawn::
|
47
|
+
let(:interface) { Prawn::SVG::Interface.new(svg, prawn, position: position) }
|
48
48
|
|
49
49
|
context "(:left)" do
|
50
50
|
let(:position) { :left }
|
@@ -68,7 +68,7 @@ describe Prawn::Svg::Interface do
|
|
68
68
|
end
|
69
69
|
|
70
70
|
context "when a vposition is supplied" do
|
71
|
-
let(:interface) { Prawn::
|
71
|
+
let(:interface) { Prawn::SVG::Interface.new(svg, prawn, vposition: vposition) }
|
72
72
|
|
73
73
|
context "(:top)" do
|
74
74
|
let(:vposition) { :top }
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Prawn::
|
4
|
-
let(:loader) { Prawn::
|
3
|
+
describe Prawn::SVG::UrlLoader do
|
4
|
+
let(:loader) { Prawn::SVG::UrlLoader.new(:enable_cache => true, :enable_web => true) }
|
5
5
|
|
6
6
|
describe "#initialize" do
|
7
7
|
it "sets options" do
|
@@ -0,0 +1,40 @@
|
|
1
|
+
<svg width="240" height="240" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
2
|
+
<defs>
|
3
|
+
<style type="text/css"><![CDATA[
|
4
|
+
#rect1 { fill: url(#Gradient1); }
|
5
|
+
.stop1 { stop-color: red; }
|
6
|
+
.stop2 { stop-color: black; stop-opacity: 0; }
|
7
|
+
.stop3 { stop-color: blue; }
|
8
|
+
]]></style>
|
9
|
+
<linearGradient id="Gradient1">
|
10
|
+
<stop class="stop1" offset="0%"/>
|
11
|
+
<stop class="stop2" offset="50%"/>
|
12
|
+
<stop class="stop3" offset="100%"/>
|
13
|
+
</linearGradient>
|
14
|
+
<linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
|
15
|
+
<stop offset="25%" stop-color="red"/>
|
16
|
+
<stop offset="50%" stop-color="black" stop-opacity="0"/>
|
17
|
+
<stop offset="75%" stop-color="blue"/>
|
18
|
+
</linearGradient>
|
19
|
+
<linearGradient id="Gradient3" x1="0" x2="1" y1="0" y2="1">
|
20
|
+
<stop offset="0%" stop-color="red"/>
|
21
|
+
<stop offset="30%" stop-color="yellow"/>
|
22
|
+
<stop offset="60%" stop-color="orange"/>
|
23
|
+
<stop offset="100%" stop-color="blue"/>
|
24
|
+
</linearGradient>
|
25
|
+
<linearGradient id="userspace" gradientUnits="userSpaceOnUse" x1="160" y1="90" x2="220" y2="90">
|
26
|
+
<stop offset="0" stop-color="red"/>
|
27
|
+
<stop offset="1" stop-color="blue"/>
|
28
|
+
</linearGradient>
|
29
|
+
</defs>
|
30
|
+
|
31
|
+
<rect id="rect1" x="10" y="10" rx="15" ry="15" width="50" height="100" stroke="black"/>
|
32
|
+
<rect x="10" y="120" rx="15" ry="15" width="50" height="100" fill="url(#Gradient2)" stroke="black"/>
|
33
|
+
<circle cx="110" cy="40" r="30" stroke="black" fill="url(#Gradient3)"/>
|
34
|
+
<ellipse cx="110" cy="100" rx="30" ry="20" stroke="black" fill="url(#Gradient1)"/>
|
35
|
+
<line x1="65" y1="120" x2="200" y2="200" stroke="url(#Gradient3)" stroke-width="5"/>
|
36
|
+
<path d="M80,140l0,50l30,20l0-40z" stroke="url(#Gradient3)" fill="url(#Gradient1)" stroke-width="3"/>
|
37
|
+
<polygon points="150,30 170,80 190,55 200,10" fill="url(#Gradient1)"/>
|
38
|
+
<rect x="150" y="90" width="80" height="30" fill="url(#userspace)" stroke="black"/>
|
39
|
+
<polyline points="150,130 170,170 190,155 200,110" stroke="url(#Gradient1)" stroke-width="3" fill="none"/>
|
40
|
+
</svg>
|
data/spec/sample_svg/rect02.svg
CHANGED
@@ -1,16 +1,13 @@
|
|
1
1
|
<?xml version="1.0" standalone="no"?>
|
2
|
-
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
3
|
-
|
4
|
-
<svg width="12cm" height="4cm" viewBox="0 0 1200 400"
|
5
|
-
xmlns="http://www.w3.org/2000/svg" version="1.1">
|
2
|
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
3
|
+
<svg width="12cm" height="8cm" viewBox="0 0 1200 800" xmlns="http://www.w3.org/2000/svg" version="1.1">
|
6
4
|
<desc>Example rect02 - rounded rectangles</desc>
|
7
|
-
|
8
|
-
<rect x="1" y="1" width="1198" height="
|
9
|
-
|
10
|
-
<rect x="100" y="
|
11
|
-
|
5
|
+
|
6
|
+
<rect x="1" y="1" width="1198" height="798" fill="none" stroke="blue" stroke-width="2"/>
|
7
|
+
<rect x="100" y="100" width="400" height="200" rx="50" fill="green" />
|
8
|
+
<rect x="100" y="500" width="400" height="200" rx="100" ry="10" fill="orange" />
|
9
|
+
|
12
10
|
<g transform="translate(700 210) rotate(-30)">
|
13
|
-
<rect x="0" y="0" width="400" height="200" rx="50"
|
14
|
-
fill="none" stroke="purple" stroke-width="30" />
|
11
|
+
<rect x="0" y="0" width="400" height="200" rx="50" fill="none" stroke="purple" stroke-width="30" />
|
15
12
|
</g>
|
16
13
|
</svg>
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prawn-svg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.22.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Roger Nesbitt
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-10-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: prawn
|
@@ -16,7 +16,7 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.11.1
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
22
|
version: '3'
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 0.
|
29
|
+
version: 0.11.1
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: '3'
|
@@ -82,38 +82,61 @@ extra_rdoc_files: []
|
|
82
82
|
files:
|
83
83
|
- ".gitignore"
|
84
84
|
- ".rspec"
|
85
|
+
- ".travis.yml"
|
85
86
|
- Gemfile
|
86
87
|
- LICENSE
|
87
88
|
- README.md
|
88
89
|
- Rakefile
|
89
90
|
- lib/prawn-svg.rb
|
91
|
+
- lib/prawn/svg/attributes.rb
|
92
|
+
- lib/prawn/svg/attributes/clip_path.rb
|
93
|
+
- lib/prawn/svg/attributes/display.rb
|
94
|
+
- lib/prawn/svg/attributes/font.rb
|
95
|
+
- lib/prawn/svg/attributes/opacity.rb
|
96
|
+
- lib/prawn/svg/attributes/stroke.rb
|
97
|
+
- lib/prawn/svg/attributes/transform.rb
|
90
98
|
- lib/prawn/svg/calculators/aspect_ratio.rb
|
91
99
|
- lib/prawn/svg/calculators/document_sizing.rb
|
92
100
|
- lib/prawn/svg/calculators/pixels.rb
|
93
101
|
- lib/prawn/svg/color.rb
|
94
102
|
- lib/prawn/svg/document.rb
|
95
|
-
- lib/prawn/svg/
|
103
|
+
- lib/prawn/svg/elements.rb
|
104
|
+
- lib/prawn/svg/elements/base.rb
|
105
|
+
- lib/prawn/svg/elements/circle.rb
|
106
|
+
- lib/prawn/svg/elements/container.rb
|
107
|
+
- lib/prawn/svg/elements/ellipse.rb
|
108
|
+
- lib/prawn/svg/elements/gradient.rb
|
109
|
+
- lib/prawn/svg/elements/ignored.rb
|
110
|
+
- lib/prawn/svg/elements/image.rb
|
111
|
+
- lib/prawn/svg/elements/line.rb
|
112
|
+
- lib/prawn/svg/elements/path.rb
|
113
|
+
- lib/prawn/svg/elements/polygon.rb
|
114
|
+
- lib/prawn/svg/elements/polyline.rb
|
115
|
+
- lib/prawn/svg/elements/rect.rb
|
116
|
+
- lib/prawn/svg/elements/root.rb
|
117
|
+
- lib/prawn/svg/elements/style.rb
|
118
|
+
- lib/prawn/svg/elements/text.rb
|
119
|
+
- lib/prawn/svg/elements/use.rb
|
96
120
|
- lib/prawn/svg/extension.rb
|
97
121
|
- lib/prawn/svg/font.rb
|
98
122
|
- lib/prawn/svg/interface.rb
|
99
|
-
- lib/prawn/svg/parser.rb
|
100
|
-
- lib/prawn/svg/parser/image.rb
|
101
|
-
- lib/prawn/svg/parser/path.rb
|
102
|
-
- lib/prawn/svg/parser/text.rb
|
103
123
|
- lib/prawn/svg/url_loader.rb
|
104
124
|
- lib/prawn/svg/version.rb
|
105
125
|
- prawn-svg.gemspec
|
106
126
|
- spec/integration_spec.rb
|
127
|
+
- spec/prawn/svg/attributes/font_spec.rb
|
128
|
+
- spec/prawn/svg/attributes/transform_spec.rb
|
107
129
|
- spec/prawn/svg/calculators/aspect_ratio_spec.rb
|
108
130
|
- spec/prawn/svg/calculators/document_sizing_spec.rb
|
109
131
|
- spec/prawn/svg/color_spec.rb
|
110
132
|
- spec/prawn/svg/document_spec.rb
|
111
|
-
- spec/prawn/svg/
|
133
|
+
- spec/prawn/svg/elements/base_spec.rb
|
134
|
+
- spec/prawn/svg/elements/gradient_spec.rb
|
135
|
+
- spec/prawn/svg/elements/path_spec.rb
|
136
|
+
- spec/prawn/svg/elements/style_spec.rb
|
137
|
+
- spec/prawn/svg/elements/text_spec.rb
|
112
138
|
- spec/prawn/svg/font_spec.rb
|
113
139
|
- spec/prawn/svg/interface_spec.rb
|
114
|
-
- spec/prawn/svg/parser/path_spec.rb
|
115
|
-
- spec/prawn/svg/parser/text_spec.rb
|
116
|
-
- spec/prawn/svg/parser_spec.rb
|
117
140
|
- spec/prawn/svg/url_loader_spec.rb
|
118
141
|
- spec/sample_images/mushroom-long.jpg
|
119
142
|
- spec/sample_images/mushroom-wide.jpg
|
@@ -130,6 +153,7 @@ files:
|
|
130
153
|
- spec/sample_svg/ellipse01.svg
|
131
154
|
- spec/sample_svg/gistfile1.svg
|
132
155
|
- spec/sample_svg/google_charts.svg
|
156
|
+
- spec/sample_svg/gradients.svg
|
133
157
|
- spec/sample_svg/hidden_paths.svg
|
134
158
|
- spec/sample_svg/highcharts.svg
|
135
159
|
- spec/sample_svg/image01.svg
|
@@ -176,7 +200,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
176
200
|
requirements:
|
177
201
|
- - ">="
|
178
202
|
- !ruby/object:Gem::Version
|
179
|
-
version:
|
203
|
+
version: 2.0.0
|
180
204
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
181
205
|
requirements:
|
182
206
|
- - ">="
|
@@ -190,16 +214,19 @@ specification_version: 4
|
|
190
214
|
summary: SVG renderer for Prawn PDF library
|
191
215
|
test_files:
|
192
216
|
- spec/integration_spec.rb
|
217
|
+
- spec/prawn/svg/attributes/font_spec.rb
|
218
|
+
- spec/prawn/svg/attributes/transform_spec.rb
|
193
219
|
- spec/prawn/svg/calculators/aspect_ratio_spec.rb
|
194
220
|
- spec/prawn/svg/calculators/document_sizing_spec.rb
|
195
221
|
- spec/prawn/svg/color_spec.rb
|
196
222
|
- spec/prawn/svg/document_spec.rb
|
197
|
-
- spec/prawn/svg/
|
223
|
+
- spec/prawn/svg/elements/base_spec.rb
|
224
|
+
- spec/prawn/svg/elements/gradient_spec.rb
|
225
|
+
- spec/prawn/svg/elements/path_spec.rb
|
226
|
+
- spec/prawn/svg/elements/style_spec.rb
|
227
|
+
- spec/prawn/svg/elements/text_spec.rb
|
198
228
|
- spec/prawn/svg/font_spec.rb
|
199
229
|
- spec/prawn/svg/interface_spec.rb
|
200
|
-
- spec/prawn/svg/parser/path_spec.rb
|
201
|
-
- spec/prawn/svg/parser/text_spec.rb
|
202
|
-
- spec/prawn/svg/parser_spec.rb
|
203
230
|
- spec/prawn/svg/url_loader_spec.rb
|
204
231
|
- spec/sample_images/mushroom-long.jpg
|
205
232
|
- spec/sample_images/mushroom-wide.jpg
|
@@ -216,6 +243,7 @@ test_files:
|
|
216
243
|
- spec/sample_svg/ellipse01.svg
|
217
244
|
- spec/sample_svg/gistfile1.svg
|
218
245
|
- spec/sample_svg/google_charts.svg
|
246
|
+
- spec/sample_svg/gradients.svg
|
219
247
|
- spec/sample_svg/hidden_paths.svg
|
220
248
|
- spec/sample_svg/highcharts.svg
|
221
249
|
- spec/sample_svg/image01.svg
|
data/lib/prawn/svg/element.rb
DELETED
@@ -1,304 +0,0 @@
|
|
1
|
-
class Prawn::Svg::Element
|
2
|
-
attr_reader :document, :element, :parent_calls, :base_calls, :state, :attributes
|
3
|
-
attr_accessor :calls
|
4
|
-
|
5
|
-
def initialize(document, element, parent_calls, state)
|
6
|
-
@document = document
|
7
|
-
@element = element
|
8
|
-
@parent_calls = parent_calls
|
9
|
-
@state = state
|
10
|
-
@base_calls = @calls = []
|
11
|
-
|
12
|
-
combine_attributes_and_style_declarations
|
13
|
-
apply_styles
|
14
|
-
|
15
|
-
if id = @attributes["id"]
|
16
|
-
document.elements_by_id[id] = self
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def name
|
21
|
-
@name ||= element.name
|
22
|
-
end
|
23
|
-
|
24
|
-
def each_child_element
|
25
|
-
element.elements.each do |e|
|
26
|
-
yield self.class.new(@document, e, @calls, @state.dup)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def warnings
|
31
|
-
@document.warnings
|
32
|
-
end
|
33
|
-
|
34
|
-
def add_call(name, *arguments)
|
35
|
-
@calls << [name.to_s, arguments, []]
|
36
|
-
end
|
37
|
-
|
38
|
-
def add_call_and_enter(name, *arguments)
|
39
|
-
@calls << [name.to_s, arguments, []]
|
40
|
-
@calls = @calls.last.last
|
41
|
-
end
|
42
|
-
|
43
|
-
def append_calls_to_parent
|
44
|
-
@parent_calls.concat(@base_calls)
|
45
|
-
end
|
46
|
-
|
47
|
-
def add_calls_from_element(other)
|
48
|
-
@calls.concat other.base_calls
|
49
|
-
end
|
50
|
-
|
51
|
-
|
52
|
-
protected
|
53
|
-
def apply_styles
|
54
|
-
parse_transform_attribute_and_call
|
55
|
-
parse_opacity_attributes_and_call
|
56
|
-
parse_clip_path_attribute_and_call
|
57
|
-
draw_types = parse_fill_and_stroke_attributes_and_call
|
58
|
-
parse_stroke_attributes_and_call
|
59
|
-
parse_font_attributes_and_call
|
60
|
-
parse_display_attribute
|
61
|
-
apply_drawing_call(draw_types)
|
62
|
-
end
|
63
|
-
|
64
|
-
def apply_drawing_call(draw_types)
|
65
|
-
if !@state[:disable_drawing] && !container?
|
66
|
-
if draw_types.empty? || @state[:display] == "none"
|
67
|
-
add_call_and_enter("end_path")
|
68
|
-
else
|
69
|
-
add_call_and_enter(draw_types.join("_and_"))
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def container?
|
75
|
-
Prawn::Svg::Parser::CONTAINER_TAGS.include?(name)
|
76
|
-
end
|
77
|
-
|
78
|
-
def parse_transform_attribute_and_call
|
79
|
-
return unless transform = @attributes['transform']
|
80
|
-
|
81
|
-
parse_css_method_calls(transform).each do |name, arguments|
|
82
|
-
case name
|
83
|
-
when 'translate'
|
84
|
-
x, y = arguments
|
85
|
-
add_call_and_enter name, @document.distance(x.to_f, :x), -@document.distance(y.to_f, :y)
|
86
|
-
|
87
|
-
when 'rotate'
|
88
|
-
r, x, y = arguments.collect {|a| a.to_f}
|
89
|
-
case arguments.length
|
90
|
-
when 1
|
91
|
-
add_call_and_enter name, -r, :origin => [0, @document.y('0')]
|
92
|
-
when 3
|
93
|
-
add_call_and_enter name, -r, :origin => [@document.x(x), @document.y(y)]
|
94
|
-
else
|
95
|
-
@document.warnings << "transform 'rotate' must have either one or three arguments"
|
96
|
-
end
|
97
|
-
|
98
|
-
when 'scale'
|
99
|
-
x_scale = arguments[0].to_f
|
100
|
-
y_scale = (arguments[1] || x_scale).to_f
|
101
|
-
add_call_and_enter "transformation_matrix", x_scale, 0, 0, y_scale, 0, 0
|
102
|
-
|
103
|
-
when 'matrix'
|
104
|
-
if arguments.length != 6
|
105
|
-
@document.warnings << "transform 'matrix' must have six arguments"
|
106
|
-
else
|
107
|
-
a, b, c, d, e, f = arguments.collect {|argument| argument.to_f}
|
108
|
-
add_call_and_enter "transformation_matrix", a, -b, -c, d, @document.distance(e, :x), -@document.distance(f, :y)
|
109
|
-
end
|
110
|
-
else
|
111
|
-
@document.warnings << "Unknown transformation '#{name}'; ignoring"
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
def parse_opacity_attributes_and_call
|
117
|
-
# We can't do nested opacities quite like the SVG requires, but this is close enough.
|
118
|
-
fill_opacity = stroke_opacity = clamp(@attributes['opacity'].to_f, 0, 1) if @attributes['opacity']
|
119
|
-
fill_opacity = clamp(@attributes['fill-opacity'].to_f, 0, 1) if @attributes['fill-opacity']
|
120
|
-
stroke_opacity = clamp(@attributes['stroke-opacity'].to_f, 0, 1) if @attributes['stroke-opacity']
|
121
|
-
|
122
|
-
if fill_opacity || stroke_opacity
|
123
|
-
state[:fill_opacity] = (state[:fill_opacity] || 1) * (fill_opacity || 1)
|
124
|
-
state[:stroke_opacity] = (state[:stroke_opacity] || 1) * (stroke_opacity || 1)
|
125
|
-
|
126
|
-
add_call_and_enter 'transparent', state[:fill_opacity], state[:stroke_opacity]
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
def parse_clip_path_attribute_and_call
|
131
|
-
return unless clip_path = @attributes['clip-path']
|
132
|
-
|
133
|
-
if (matches = clip_path.strip.match(/\Aurl\(#(.*)\)\z/)).nil?
|
134
|
-
document.warnings << "Only clip-path attributes with the form 'url(#xxx)' are supported"
|
135
|
-
elsif (clip_path_element = @document.elements_by_id[matches[1]]).nil?
|
136
|
-
document.warnings << "clip-path ID '#{matches[1]}' not defined"
|
137
|
-
elsif clip_path_element.element.name != "clipPath"
|
138
|
-
document.warnings << "clip-path ID '#{matches[1]}' does not point to a clipPath tag"
|
139
|
-
else
|
140
|
-
add_call_and_enter 'save_graphics_state'
|
141
|
-
add_calls_from_element clip_path_element
|
142
|
-
add_call "clip"
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
def parse_fill_and_stroke_attributes_and_call
|
147
|
-
["fill", "stroke"].select do |type|
|
148
|
-
case keyword = attribute_value_as_keyword(type)
|
149
|
-
when nil
|
150
|
-
when 'inherit'
|
151
|
-
when 'none'
|
152
|
-
state[type.to_sym] = false
|
153
|
-
else
|
154
|
-
color_attribute = keyword == 'currentcolor' ? 'color' : type
|
155
|
-
color = @attributes[color_attribute]
|
156
|
-
|
157
|
-
begin
|
158
|
-
hex = Prawn::Svg::Color.color_to_hex(color)
|
159
|
-
state[type.to_sym] = true
|
160
|
-
add_call "#{type}_color", hex || '000000'
|
161
|
-
rescue Prawn::Svg::Color::UnresolvableURLWithNoFallbackError
|
162
|
-
state[type.to_sym] = false
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
state[type.to_sym]
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
CAP_STYLE_TRANSLATIONS = {"butt" => :butt, "round" => :round, "square" => :projecting_square}
|
171
|
-
|
172
|
-
def parse_stroke_attributes_and_call
|
173
|
-
if width = @attributes['stroke-width']
|
174
|
-
add_call('line_width', @document.distance(width))
|
175
|
-
end
|
176
|
-
|
177
|
-
if (linecap = attribute_value_as_keyword('stroke-linecap')) && linecap != 'inherit'
|
178
|
-
add_call('cap_style', CAP_STYLE_TRANSLATIONS.fetch(linecap, :butt))
|
179
|
-
end
|
180
|
-
|
181
|
-
if dasharray = attribute_value_as_keyword('stroke-dasharray')
|
182
|
-
case dasharray
|
183
|
-
when 'inherit'
|
184
|
-
# don't do anything
|
185
|
-
when 'none'
|
186
|
-
add_call('undash')
|
187
|
-
else
|
188
|
-
array = dasharray.split(Prawn::Svg::Parser::COMMA_WSP_REGEXP)
|
189
|
-
array *= 2 if array.length % 2 == 1
|
190
|
-
number_array = array.map {|value| @document.distance(value)}
|
191
|
-
|
192
|
-
if number_array.any? {|number| number < 0}
|
193
|
-
@document.warnings << "stroke-dasharray cannot have negative numbers; treating as 'none'"
|
194
|
-
add_call('undash')
|
195
|
-
elsif number_array.inject(0) {|a, b| a + b} == 0
|
196
|
-
add_call('undash')
|
197
|
-
else
|
198
|
-
add_call('dash', number_array)
|
199
|
-
end
|
200
|
-
end
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
def parse_font_attributes_and_call
|
205
|
-
if size = @attributes['font-size']
|
206
|
-
@state[:font_size] = size.to_f
|
207
|
-
end
|
208
|
-
if weight = @attributes['font-weight']
|
209
|
-
font_updated = true
|
210
|
-
@state[:font_weight] = Prawn::Svg::Font.weight_for_css_font_weight(weight)
|
211
|
-
end
|
212
|
-
if style = @attributes['font-style']
|
213
|
-
font_updated = true
|
214
|
-
@state[:font_style] = style == 'italic' ? :italic : nil
|
215
|
-
end
|
216
|
-
if (family = @attributes['font-family']) && family.strip != ""
|
217
|
-
font_updated = true
|
218
|
-
@state[:font_family] = family
|
219
|
-
end
|
220
|
-
if (anchor = @attributes['text-anchor'])
|
221
|
-
@state[:text_anchor] = anchor
|
222
|
-
end
|
223
|
-
|
224
|
-
if @state[:font_family] && font_updated
|
225
|
-
usable_font_families = [@state[:font_family], document.fallback_font_name]
|
226
|
-
|
227
|
-
font_used = usable_font_families.compact.detect do |name|
|
228
|
-
if font = Prawn::Svg::Font.load(name, @state[:font_weight], @state[:font_style])
|
229
|
-
@state[:font_subfamily] = font.subfamily
|
230
|
-
add_call_and_enter 'font', font.name, :style => @state[:font_subfamily]
|
231
|
-
true
|
232
|
-
end
|
233
|
-
end
|
234
|
-
|
235
|
-
if font_used.nil?
|
236
|
-
@document.warnings << "Font family '#{@state[:font_family]}' style '#{@state[:font_style] || 'normal'}' is not a known font, and the fallback font could not be found."
|
237
|
-
end
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
def parse_display_attribute
|
242
|
-
@state[:display] = @attributes['display'].strip if @attributes['display']
|
243
|
-
end
|
244
|
-
|
245
|
-
def parse_css_method_calls(string)
|
246
|
-
string.scan(/\s*(\w+)\(([^)]+)\)\s*/).collect do |call|
|
247
|
-
name, argument_string = call
|
248
|
-
arguments = argument_string.strip.split(/\s*[,\s]\s*/)
|
249
|
-
[name, arguments]
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
def clamp(value, min_value, max_value)
|
254
|
-
[[value, min_value].max, max_value].min
|
255
|
-
end
|
256
|
-
|
257
|
-
def combine_attributes_and_style_declarations
|
258
|
-
if @document && @document.css_parser
|
259
|
-
tag_style = @document.css_parser.find_by_selector(element.name)
|
260
|
-
id_style = @document.css_parser.find_by_selector("##{element.attributes["id"]}") if element.attributes["id"]
|
261
|
-
|
262
|
-
if classes = element.attributes["class"]
|
263
|
-
class_styles = classes.strip.split(/\s+/).collect do |class_name|
|
264
|
-
@document.css_parser.find_by_selector(".#{class_name}")
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
|
-
element_style = element.attributes['style']
|
269
|
-
|
270
|
-
style = [tag_style, class_styles, id_style, element_style].flatten.collect do |s|
|
271
|
-
s.nil? || s.strip == "" ? "" : "#{s}#{";" unless s.match(/;\s*\z/)}"
|
272
|
-
end.join
|
273
|
-
else
|
274
|
-
style = element.attributes['style'] || ""
|
275
|
-
end
|
276
|
-
|
277
|
-
@attributes = parse_css_declarations(style)
|
278
|
-
|
279
|
-
element.attributes.each do |name, value|
|
280
|
-
name = name.downcase
|
281
|
-
@attributes[name] = value unless @attributes[name]
|
282
|
-
end
|
283
|
-
end
|
284
|
-
|
285
|
-
def parse_css_declarations(declarations)
|
286
|
-
# copied from css_parser
|
287
|
-
declarations.gsub!(/(^[\s]*)|([\s]*$)/, '')
|
288
|
-
|
289
|
-
output = {}
|
290
|
-
declarations.split(/[\;$]+/m).each do |decs|
|
291
|
-
if matches = decs.match(/\s*(.[^:]*)\s*\:\s*(.[^;]*)\s*(;|\Z)/i)
|
292
|
-
property, value, _ = matches.captures
|
293
|
-
output[property.downcase] = value
|
294
|
-
end
|
295
|
-
end
|
296
|
-
output
|
297
|
-
end
|
298
|
-
|
299
|
-
def attribute_value_as_keyword(name)
|
300
|
-
if value = @attributes[name]
|
301
|
-
value.strip.downcase
|
302
|
-
end
|
303
|
-
end
|
304
|
-
end
|