prawn-svg 0.21.0 → 0.22.1
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 +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
|