prawn-svg 0.32.0 → 0.34.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +20 -3
- data/.gitignore +1 -0
- data/README.md +32 -24
- data/lib/prawn/svg/attributes/stroke.rb +5 -0
- data/lib/prawn/svg/color.rb +46 -22
- data/lib/prawn/svg/css/selector_parser.rb +11 -11
- data/lib/prawn/svg/css/stylesheets.rb +4 -4
- data/lib/prawn/svg/document.rb +20 -4
- data/lib/prawn/svg/elements/base.rb +10 -11
- data/lib/prawn/svg/elements/gradient.rb +2 -2
- data/lib/prawn/svg/elements/image.rb +54 -21
- data/lib/prawn/svg/elements/path.rb +0 -2
- data/lib/prawn/svg/elements/root.rb +1 -1
- data/lib/prawn/svg/elements/text_component.rb +12 -3
- data/lib/prawn/svg/elements/use.rb +20 -12
- data/lib/prawn/svg/elements.rb +1 -0
- data/lib/prawn/svg/gradients.rb +48 -0
- data/lib/prawn/svg/interface.rb +17 -187
- data/lib/prawn/svg/loaders/data.rb +4 -3
- data/lib/prawn/svg/properties.rb +2 -0
- data/lib/prawn/svg/renderer.rb +236 -0
- data/lib/prawn/svg/version.rb +1 -1
- data/lib/prawn-svg.rb +2 -0
- data/prawn-svg.gemspec +18 -16
- data/spec/prawn/svg/color_spec.rb +29 -16
- data/spec/prawn/svg/document_spec.rb +17 -0
- data/spec/prawn/svg/elements/marker_spec.rb +1 -1
- data/spec/prawn/svg/elements/root_spec.rb +28 -0
- data/spec/prawn/svg/elements/text_spec.rb +27 -0
- data/spec/prawn/svg/interface_spec.rb +10 -2
- data/spec/sample_images/image_svg_embed.svg +6 -0
- data/spec/sample_svg/cmyk.svg +5 -0
- data/spec/sample_svg/gradients-cmyk.svg +40 -0
- data/spec/sample_svg/image_svg.svg +9 -0
- data/spec/sample_svg/ordering.svg +12 -0
- data/spec/sample_svg/symbol.svg +12 -0
- data/spec/spec_helper.rb +29 -5
- metadata +67 -23
data/prawn-svg.gemspec
CHANGED
@@ -1,27 +1,29 @@
|
|
1
|
-
|
2
|
-
require File.expand_path('../lib/prawn/svg/version', __FILE__)
|
1
|
+
require File.expand_path('lib/prawn/svg/version', __dir__)
|
3
2
|
|
4
3
|
Gem::Specification.new do |gem|
|
5
4
|
gem.name = 'prawn-svg'
|
6
5
|
gem.version = Prawn::SVG::VERSION
|
7
|
-
gem.summary =
|
8
|
-
gem.description =
|
9
|
-
|
10
|
-
|
11
|
-
gem.
|
6
|
+
gem.summary = 'SVG renderer for Prawn PDF library'
|
7
|
+
gem.description = <<-EOT.strip
|
8
|
+
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
|
+
EOT
|
10
|
+
gem.author = 'Mog Nesbitt'
|
11
|
+
gem.email = 'mog@seriousorange.com'
|
12
|
+
gem.homepage = 'http://github.com/mogest/prawn-svg'
|
12
13
|
gem.license = 'MIT'
|
13
14
|
|
14
|
-
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
15
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
15
16
|
gem.files = `git ls-files`.split("\n")
|
16
17
|
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
-
gem.
|
18
|
-
gem.require_paths = ["lib"]
|
18
|
+
gem.require_paths = ['lib']
|
19
19
|
|
20
|
-
gem.required_ruby_version = '>= 2.
|
20
|
+
gem.required_ruby_version = '>= 2.5.0'
|
21
21
|
|
22
|
-
gem.add_runtime_dependency
|
23
|
-
gem.add_runtime_dependency
|
24
|
-
gem.add_runtime_dependency
|
25
|
-
gem.
|
26
|
-
gem.
|
22
|
+
gem.add_runtime_dependency 'base64', '~> 0.1.0'
|
23
|
+
gem.add_runtime_dependency 'css_parser', '~> 1.6'
|
24
|
+
gem.add_runtime_dependency 'matrix', '~> 0.4.2'
|
25
|
+
gem.add_runtime_dependency 'prawn', '>= 0.11.1', '< 3'
|
26
|
+
gem.add_runtime_dependency 'rexml', '~> 3.2'
|
27
|
+
gem.add_development_dependency 'rake', '~> 13.0'
|
28
|
+
gem.add_development_dependency 'rspec', '~> 3.0'
|
27
29
|
end
|
@@ -1,38 +1,43 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
2
|
|
3
3
|
describe Prawn::SVG::Color do
|
4
|
-
describe "::
|
4
|
+
describe "::css_color_to_prawn_color" do
|
5
5
|
it "converts #xxx to a hex value" do
|
6
|
-
Prawn::SVG::Color.
|
6
|
+
Prawn::SVG::Color.css_color_to_prawn_color("#9ab").should == "99aabb"
|
7
7
|
end
|
8
8
|
|
9
9
|
it "converts #xxxxxx to a hex value" do
|
10
|
-
Prawn::SVG::Color.
|
10
|
+
Prawn::SVG::Color.css_color_to_prawn_color("#9ab123").should == "9ab123"
|
11
11
|
end
|
12
12
|
|
13
13
|
it "converts an html colour name to a hex value" do
|
14
|
-
Prawn::SVG::Color.
|
14
|
+
Prawn::SVG::Color.css_color_to_prawn_color("White").should == "ffffff"
|
15
15
|
end
|
16
16
|
|
17
17
|
it "converts an rgb string to a hex value" do
|
18
|
-
Prawn::SVG::Color.
|
19
|
-
Prawn::SVG::Color.
|
18
|
+
Prawn::SVG::Color.css_color_to_prawn_color("rgb(16, 32, 48)").should == "102030"
|
19
|
+
Prawn::SVG::Color.css_color_to_prawn_color("rgb(-5, 50%, 120%)").should == "007fff"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "converts a CMYK string to an array of numbers" do
|
23
|
+
expect(Prawn::SVG::Color.css_color_to_prawn_color("device-cmyk(0, 0.32, 0.48, 1)")).to eq [0, 32, 48, 100]
|
24
|
+
expect(Prawn::SVG::Color.css_color_to_prawn_color("device-cmyk(-5, 50%, 120%, -5%)")).to eq [0, 50, 100, 0]
|
20
25
|
end
|
21
26
|
|
22
27
|
it "scans the string and finds the first colour it can parse" do
|
23
|
-
Prawn::SVG::Color.
|
28
|
+
Prawn::SVG::Color.css_color_to_prawn_color("function(#someurl, 0) nonexistent rgb( 3 ,4,5 ) white").should == "030405"
|
24
29
|
end
|
25
30
|
|
26
31
|
it "ignores url()s" do
|
27
|
-
expect(Prawn::SVG::Color.
|
32
|
+
expect(Prawn::SVG::Color.css_color_to_prawn_color("url(#someplace) red")).to eq 'ff0000'
|
28
33
|
end
|
29
34
|
|
30
35
|
it "returns black if the color doesn't exist" do
|
31
|
-
expect(Prawn::SVG::Color.
|
36
|
+
expect(Prawn::SVG::Color.css_color_to_prawn_color("blurble")).to eq '000000'
|
32
37
|
end
|
33
38
|
|
34
39
|
it "returns nil if there's no fallback after a url()" do
|
35
|
-
expect(Prawn::SVG::Color.
|
40
|
+
expect(Prawn::SVG::Color.css_color_to_prawn_color("url(#someplace)")).to be nil
|
36
41
|
end
|
37
42
|
end
|
38
43
|
|
@@ -42,19 +47,27 @@ describe Prawn::SVG::Color do
|
|
42
47
|
let(:drob_gradient) { double }
|
43
48
|
|
44
49
|
it "returns a list of all colors parsed, ignoring impossible or non-existent colors" do
|
45
|
-
results = Prawn::SVG::Color.parse("url(#nope) url(#flan) blurble green #123", gradients)
|
50
|
+
results = Prawn::SVG::Color.parse("url(#nope) url(#flan) blurble green #123", gradients, :rgb)
|
46
51
|
expect(results).to eq [
|
47
52
|
flan_gradient,
|
48
|
-
Prawn::SVG::Color::
|
49
|
-
Prawn::SVG::Color::
|
53
|
+
Prawn::SVG::Color::RGB.new("008000"),
|
54
|
+
Prawn::SVG::Color::RGB.new("112233")
|
50
55
|
]
|
51
56
|
end
|
52
57
|
|
53
58
|
it "appends black to the list if there aren't any url() references" do
|
54
|
-
results = Prawn::SVG::Color.parse("blurble green", gradients)
|
59
|
+
results = Prawn::SVG::Color.parse("blurble green", gradients, :rgb)
|
60
|
+
expect(results).to eq [
|
61
|
+
Prawn::SVG::Color::RGB.new("008000"),
|
62
|
+
Prawn::SVG::Color::RGB.new("000000")
|
63
|
+
]
|
64
|
+
end
|
65
|
+
|
66
|
+
it "works in CMYK color mode" do
|
67
|
+
results = Prawn::SVG::Color.parse("blurble green", gradients, :cmyk)
|
55
68
|
expect(results).to eq [
|
56
|
-
Prawn::SVG::Color::
|
57
|
-
Prawn::SVG::Color::
|
69
|
+
Prawn::SVG::Color::CMYK.new([100, 0, 100, 50]),
|
70
|
+
Prawn::SVG::Color::CMYK.new([0, 0, 0, 100])
|
58
71
|
]
|
59
72
|
end
|
60
73
|
end
|
@@ -5,6 +5,23 @@ describe Prawn::SVG::Document do
|
|
5
5
|
let(:options) { {} }
|
6
6
|
|
7
7
|
describe "#initialize" do
|
8
|
+
context "with a well-formed document" do
|
9
|
+
let(:svg) { "<svg></svg>" }
|
10
|
+
let(:options) { {color_mode: :cmyk} }
|
11
|
+
|
12
|
+
it "parses the XML and yields itself to its block" do
|
13
|
+
yielded = nil
|
14
|
+
|
15
|
+
document = Prawn::SVG::Document.new(svg, bounds, options) do |doc|
|
16
|
+
yielded = doc
|
17
|
+
end
|
18
|
+
|
19
|
+
expect(yielded).to eq document
|
20
|
+
expect(document.color_mode).to eq :cmyk
|
21
|
+
expect(document.root.name).to eq 'svg'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
8
25
|
context "when unparsable XML is provided" do
|
9
26
|
let(:svg) { "this isn't SVG data" }
|
10
27
|
|
@@ -73,10 +73,10 @@ RSpec.describe Prawn::SVG::Elements::Marker do
|
|
73
73
|
["stroke_color", ["000000"], {}, []],
|
74
74
|
["line_width", [100.0], {}, []],
|
75
75
|
["cap_style", [:butt], {}, []],
|
76
|
+
["join_style", [:miter], {}, []],
|
76
77
|
["undash", [], {}, []],
|
77
78
|
["save", [], {}, []],
|
78
79
|
["fill", [], {}, [
|
79
|
-
["join_style", [:bevel], {}, []],
|
80
80
|
["move_to", [[0.0, 600.0]], {}, []],
|
81
81
|
["line_to", [[10.0, 595.0]], {}, []],
|
82
82
|
["line_to", [[0.0, 590.0]], {}, []],
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Prawn::SVG::Elements::Root do
|
4
|
+
let(:color_mode) { :rgb }
|
5
|
+
let(:sizing) do
|
6
|
+
instance_double(Prawn::SVG::Calculators::DocumentSizing, x_offset: 0, y_offset: 0, x_scale: 1, y_scale: 1)
|
7
|
+
end
|
8
|
+
let(:document) do
|
9
|
+
instance_double(Prawn::SVG::Document, color_mode: color_mode, sizing: sizing)
|
10
|
+
end
|
11
|
+
let(:source) { double(name: 'svg', attributes: {}) }
|
12
|
+
let(:state) { Prawn::SVG::State.new }
|
13
|
+
let(:element) { Prawn::SVG::Elements::Root.new(document, source, [], state) }
|
14
|
+
|
15
|
+
it 'uses RGB black as the default color' do
|
16
|
+
element.apply
|
17
|
+
expect(element.calls.first).to eq ['fill_color', ['000000'], {}, []]
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'when in CMYK mode' do
|
21
|
+
let(:color_mode) { :cmyk }
|
22
|
+
|
23
|
+
it 'uses CMYK black as the default color' do
|
24
|
+
element.apply
|
25
|
+
expect(element.calls.first).to eq ['fill_color', [[0, 0, 0, 100]], {}, []]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -237,4 +237,31 @@ Even more
|
|
237
237
|
]
|
238
238
|
end
|
239
239
|
end
|
240
|
+
|
241
|
+
describe "when there's a comment inside the text element" do
|
242
|
+
let(:svg) { '<text>Hi <!-- comment --> there</text>' }
|
243
|
+
|
244
|
+
it "ignores the comment" do
|
245
|
+
element.process
|
246
|
+
|
247
|
+
expect(flatten_calls(element.calls)).to eq [
|
248
|
+
["text_group", [], {}],
|
249
|
+
["font", ["Helvetica"], {:style=>:normal}],
|
250
|
+
["draw_text",
|
251
|
+
["Hi "],
|
252
|
+
{:size=>16,
|
253
|
+
:style=>:normal,
|
254
|
+
:text_anchor=>"start",
|
255
|
+
:at=>[:relative, :relative],
|
256
|
+
:offset=>[0, 0]}],
|
257
|
+
["draw_text",
|
258
|
+
["there"],
|
259
|
+
{:size=>16,
|
260
|
+
:style=>:normal,
|
261
|
+
:text_anchor=>"start",
|
262
|
+
:at=>[:relative, :relative],
|
263
|
+
:offset=>[0, 0]}]
|
264
|
+
]
|
265
|
+
end
|
266
|
+
end
|
240
267
|
end
|
@@ -39,11 +39,19 @@ describe Prawn::SVG::Interface do
|
|
39
39
|
end
|
40
40
|
|
41
41
|
context "when fill_and_stroke is issued" do
|
42
|
+
def expect_rectangle
|
43
|
+
if RUBY_VERSION.start_with?("2.7.")
|
44
|
+
expect(prawn).to receive(:rectangle)
|
45
|
+
else
|
46
|
+
expect(prawn).to receive(:rectangle).with([0, 100], 10, 10)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
42
50
|
context "and fill rule is not set" do
|
43
51
|
let(:interface) { Prawn::SVG::Interface.new('<svg width="250" height="100"><rect width="10" height="10" stroke="red"></rect></svg>', prawn, {}) }
|
44
52
|
|
45
53
|
it "adds content 'B'" do
|
46
|
-
|
54
|
+
expect_rectangle
|
47
55
|
expect(prawn).to receive(:add_content).with("W n")
|
48
56
|
expect(prawn).to receive(:add_content).with("B")
|
49
57
|
interface.draw
|
@@ -54,7 +62,7 @@ describe Prawn::SVG::Interface do
|
|
54
62
|
let(:interface) { Prawn::SVG::Interface.new('<svg width="250" height="100"><rect width="10" height="10" stroke="red" fill-rule="evenodd"></rect></svg>', prawn, {}) }
|
55
63
|
|
56
64
|
it "adds content 'B*'" do
|
57
|
-
|
65
|
+
expect_rectangle
|
58
66
|
expect(prawn).to receive(:add_content).with("W n")
|
59
67
|
expect(prawn).to receive(:add_content).with("B*")
|
60
68
|
interface.draw
|
@@ -0,0 +1,6 @@
|
|
1
|
+
<?xml version="1.0" standalone="no"?>
|
2
|
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
3
|
+
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
|
4
|
+
<rect x="0" y="0" width="100" height="100" fill="red" stroke="blue" stroke-width="5" />
|
5
|
+
</svg>
|
6
|
+
|
@@ -0,0 +1,5 @@
|
|
1
|
+
<svg width="154" height="28" viewBox="0 0 154 28" xmlns="http://www.w3.org/2000/svg">
|
2
|
+
<g fill="device-cmyk(0.5, 50%, 0.0, 0)" fill-rule="evenodd">
|
3
|
+
<path d="m19.88 23.715-4.083 3.337a4.243 4.243 0 0 1-1.626-.965c-.463-.44-.768-.943-.915-1.508l-3.185 1.812c-.125.068-.336.138-.635.212a3.29 3.29 0 0 1-.754.11c-2.451 0-4.476-.841-6.073-2.524C1.011 22.506.212 20.168.212 17.175c0-2.846.83-5.192 2.491-7.039 1.66-1.847 3.777-2.77 6.353-2.77 1.027 0 1.988.203 2.88.61.892.407 1.479.768 1.762 1.084l2.948-1.067 1.034.305V19.92c0 1.016.178 1.824.533 2.422.354.599.91 1.057 1.667 1.373zm-7.166-2.541v-7.945a4.404 4.404 0 0 0-1.33-1.087c-.548-.303-1.217-.454-2.008-.454-1.141 0-2.086.416-2.837 1.248-.751.831-1.126 2.208-1.126 4.131 0 1.527.35 2.752 1.05 3.674.7.922 1.683 1.383 2.948 1.383.723 0 1.4-.113 2.033-.339.632-.227 1.055-.431 1.27-.611zM39.463 26.51h-3.947l-1.118-1.66-2.728 1.491c-.226.125-.553.217-.982.28a7.964 7.964 0 0 1-1.118.093c-2.666 0-4.69-.897-6.073-2.693s-2.081-4.049-2.092-6.759c-.011-2.937.822-5.274 2.499-7.014 1.677-1.739 3.894-2.609 6.649-2.609.79 0 1.485.062 2.083.187a5.903 5.903 0 0 1 1.728.661V.491h5.099V26.51zm-5.099-5.607v-8.03c-.283-.35-.751-.652-1.406-.906a5.855 5.855 0 0 0-2.134-.381c-1.423 0-2.482.415-3.177 1.245-.694.83-1.042 2.149-1.042 3.956 0 1.841.37 3.216 1.109 4.125.74.91 1.742 1.364 3.007 1.364.813 0 1.527-.135 2.143-.406.616-.271 1.116-.595 1.5-.967zM67.009 26.51h-5.184V15.075c0-.666-.237-1.256-.711-1.77-.475-.514-1.203-.771-2.186-.771-.938 0-1.722.195-2.354.584-.633.39-1.135.754-1.508 1.093V26.51h-5.184V8.299l5.184-.373v1.779l2.155-1.237a7.47 7.47 0 0 1 1.976-.805 8.464 8.464 0 0 1 2.01-.246c1.798 0 3.215.557 4.25 1.669 1.035 1.112 1.553 2.578 1.553 4.396V26.51h-.001zM89.303 17.057c0 2.993-.857 5.376-2.572 7.149-1.716 1.773-4.068 2.66-7.059 2.66-3.216 0-5.625-.892-7.227-2.677-1.603-1.784-2.404-4.162-2.404-7.132 0-2.699.863-5.008 2.59-6.929 1.726-1.92 4.073-2.88 7.041-2.88 2.979 0 5.328.887 7.05 2.66 1.72 1.774 2.581 4.156 2.581 7.149zm-5.252 0c0-1.479-.387-2.795-1.16-3.947-.773-1.152-1.844-1.728-3.21-1.728-1.57 0-2.694.525-3.372 1.575-.677 1.05-1.016 2.417-1.016 4.1 0 1.57.406 2.908 1.22 4.015.813 1.107 1.903 1.66 3.27 1.66 1.524 0 2.617-.449 3.278-1.347.66-.897.99-2.34.99-4.328zM101.145 23.325l-3.762 3.541c-1.559-.643-2.727-1.581-3.506-2.814-.779-1.233-1.17-2.708-1.17-4.42v-7.944H90.98V8.3h1.727V2.286l5.185-.373v6.404h2.71v3.354h-2.71v6.486c0 1.295.294 2.37.881 3.226.587.856 1.377 1.503 2.372 1.942zM121.981 23.715l-4.083 3.337a4.243 4.243 0 0 1-1.626-.965c-.464-.44-.769-.943-.915-1.508l-3.185 1.812c-.124.068-.337.138-.636.212a3.29 3.29 0 0 1-.754.11c-2.451 0-4.475-.841-6.072-2.524-1.599-1.683-2.398-4.021-2.398-7.014 0-2.846.83-5.192 2.491-7.039 1.66-1.847 3.777-2.77 6.353-2.77 1.027 0 1.988.203 2.88.61.892.407 1.479.768 1.762 1.084l2.948-1.067 1.033.305V19.92c0 1.016.178 1.824.533 2.422.355.598.913 1.057 1.669 1.373zm-7.166-2.541v-7.945a4.412 4.412 0 0 0-1.329-1.087c-.549-.303-1.218-.454-2.008-.454-1.141 0-2.087.416-2.838 1.248-.752.831-1.127 2.208-1.127 4.131 0 1.527.35 2.752 1.051 3.674.7.922 1.683 1.383 2.947 1.383.723 0 1.4-.113 2.033-.339.634-.227 1.057-.431 1.271-.611zM153.068 26.51h-5.15V15.075c0-.666-.229-1.256-.687-1.77-.457-.514-1.177-.771-2.159-.771-.803 0-1.52.155-2.152.466a4.972 4.972 0 0 0-1.592 1.211V26.51h-5.15V15.075c0-.666-.229-1.256-.686-1.77-.458-.514-1.178-.771-2.16-.771-.926 0-1.705.189-2.338.567-.633.378-1.096.749-1.389 1.11V26.51h-5.15V8.299l5.15-.373v1.779l2.016-1.237c.666-.406 1.32-.683 1.965-.83a8.86 8.86 0 0 1 1.965-.22c1.197 0 2.219.246 3.066.737a4.986 4.986 0 0 1 1.948 2.024l2.796-1.711a6.749 6.749 0 0 1 1.846-.788 8.17 8.17 0 0 1 2.084-.263c1.795 0 3.207.557 4.234 1.669 1.028 1.112 1.543 2.578 1.543 4.396V26.51zm0 0"/>
|
4
|
+
</g>
|
5
|
+
</svg>
|
@@ -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: device-cmyk(0, 1, 1, 0); }
|
6
|
+
.stop2 { stop-color: device-cmyk(0, 0, 0, 1); stop-opacity: 0; }
|
7
|
+
.stop3 { stop-color: device-cmyk(1, 0, 1, 0); }
|
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="device-cmyk(0, 1, 1, 0)"/>
|
16
|
+
<stop offset="50%" stop-color="device-cmyk(0, 0, 0, 1)" stop-opacity="0"/>
|
17
|
+
<stop offset="75%" stop-color="device-cmyk(1, 0, 1, 0)"/>
|
18
|
+
</linearGradient>
|
19
|
+
<linearGradient id="Gradient3" x1="0" x2="1" y1="0" y2="1">
|
20
|
+
<stop offset="0%" stop-color="device-cmyk(0, 1, 1, 0)"/>
|
21
|
+
<stop offset="30%" stop-color="device-cmyk(1, 0, 1, 0)"/>
|
22
|
+
<stop offset="60%" stop-color="device-cmyk(1, 0, 1, 0)"/>
|
23
|
+
<stop offset="100%" stop-color="device-cmyk(1, 0, 1, 0)"/>
|
24
|
+
</linearGradient>
|
25
|
+
<linearGradient id="userspace" gradientUnits="userSpaceOnUse" x1="160" y1="90" x2="220" y2="90">
|
26
|
+
<stop offset="0" stop-color="device-cmyk(0, 1, 1, 0)"/>
|
27
|
+
<stop offset="1" stop-color="device-cmyk(1, 0, 1, 0)"/>
|
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>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<?xml version="1.0" standalone="no"?>
|
2
|
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
3
|
+
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
|
4
|
+
<rect x="20" y="20" width="960" height="460" stroke="black" fill="white" />
|
5
|
+
<image xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgd2lkdGg9IjExMDAiIGhlaWdodD0iNDAwIj4KICA8cmVjdCB4PSIxMDAiIHk9IjEwMCIgd2lkdGg9IjkwMCIgaGVpZ2h0PSIzMDAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmx1ZSIgc3Ryb2tlLXdpZHRoPSIyIiAvPgoKICA8cGF0aCBkPSJNMjAwIDIwMCBMODAwIDMwMCBMODAwIDIwMCIgc3Ryb2tlPSJncmVlbiIgc3Ryb2tlLXdpZHRoPSIxMCIgZmlsbD0icmVkIiAvPgo8L3N2Zz4K" x="100" y="200" width="200" height="200" />
|
6
|
+
<image xlink:href="sample_images/image_svg_embed.svg" x="400" y="200" width="200" height="200" />
|
7
|
+
<image xlink:href="sample_images/image_svg_embed.svg" x="650" y="200" width="100" height="200" />
|
8
|
+
<image xlink:href="sample_images/image_svg_embed.svg" x="800" y="200" width="100" height="200" preserveAspectRatio="none" />
|
9
|
+
</svg>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<svg width="177.649" height="244.929" version="1.1" viewBox="0 0 177.649 244.929" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
3
|
+
<g transform="translate(-21.1667 -31.75)">
|
4
|
+
<rect x="21.1667" y="31.75" width="177.649" height="244.929" fill="url(#linearGradient18)" stroke-width=".264583"/>
|
5
|
+
</g>
|
6
|
+
<defs>
|
7
|
+
<linearGradient id="linearGradient18" x1="109.032" x2="109.74" y1="34.6919" y2="273.287" gradientUnits="userSpaceOnUse">
|
8
|
+
<stop stop-color="orange" offset="0"/>
|
9
|
+
<stop stop-color="blue" offset="1"/>
|
10
|
+
</linearGradient>
|
11
|
+
</defs>
|
12
|
+
</svg>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
2
|
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
3
|
+
<svg viewBox="0 0 1000 1000" xmlns="http://www.w3.org/2000/svg" xmlns:xlink='http://www.w3.org/1999/xlink' version="1.1">
|
4
|
+
<symbol id="rects" viewBox="0 0 100 100">
|
5
|
+
<rect x="10" y="10" width="80" height="80" fill="none" stroke="red"/>
|
6
|
+
<rect x="20" y="20" width="60" height="60" fill="none" stroke="green"/>
|
7
|
+
<rect x="30" y="30" width="40" height="40" fill="none" stroke="blue"/>
|
8
|
+
</symbol>
|
9
|
+
<rect width="1000" height="1000" fill="none" stroke="black"/>
|
10
|
+
<use x="100" y="100" width="800" height="800" xlink:href="#rects"/>
|
11
|
+
<use x="400" y="400" width="200" height="200" xlink:href="#rects"/>
|
12
|
+
</svg>
|
data/spec/spec_helper.rb
CHANGED
@@ -3,12 +3,12 @@ Bundler.require(:default, :development)
|
|
3
3
|
|
4
4
|
# Requires supporting files with custom matchers and macros, etc,
|
5
5
|
# in ./support/ and its subdirectories.
|
6
|
-
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
6
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
7
7
|
|
8
8
|
module Support
|
9
|
-
def flatten_calls(
|
9
|
+
def flatten_calls(_calls)
|
10
10
|
[].tap do |flattened_calls|
|
11
|
-
add =
|
11
|
+
add = lambda do |local_calls|
|
12
12
|
local_calls.each do |call|
|
13
13
|
flattened_calls << call[0..2]
|
14
14
|
add.call call[3]
|
@@ -28,12 +28,36 @@ end
|
|
28
28
|
|
29
29
|
RSpec.configure do |config|
|
30
30
|
config.mock_with :rspec do |c|
|
31
|
-
c.syntax = [
|
31
|
+
c.syntax = %i[should expect]
|
32
32
|
end
|
33
33
|
|
34
34
|
config.expect_with :rspec do |c|
|
35
|
-
c.syntax = [
|
35
|
+
c.syntax = %i[should expect]
|
36
36
|
end
|
37
37
|
|
38
38
|
config.include Support
|
39
|
+
|
40
|
+
config.before(:suite) do
|
41
|
+
# calculate the MD5 of all files in spec/sample_output and store in a hash
|
42
|
+
$hashes = {}
|
43
|
+
|
44
|
+
Dir["#{File.dirname(__FILE__)}/sample_output/*.pdf"].each do |file|
|
45
|
+
hash = Digest::MD5.file(file).hexdigest
|
46
|
+
$hashes[file] = hash
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
config.after(:suite) do
|
51
|
+
# print out the PDFs that have changed
|
52
|
+
changed = $hashes.select do |file, hash|
|
53
|
+
new_hash = Digest::MD5.file(file).hexdigest
|
54
|
+
new_hash != hash
|
55
|
+
end
|
56
|
+
|
57
|
+
if changed.any?
|
58
|
+
puts "\nThese PDFs have changed since the last test run:"
|
59
|
+
cwd = "#{Dir.pwd}/"
|
60
|
+
changed.each { |file, _| puts " #{file.sub(cwd, '')}" }
|
61
|
+
end
|
62
|
+
end
|
39
63
|
end
|