prawn-svg 0.32.0 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.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
|