prawn-svg 0.15.0.0 → 0.19.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +20 -12
- data/lib/prawn/svg/calculators/aspect_ratio.rb +58 -0
- data/lib/prawn/svg/calculators/document_sizing.rb +75 -0
- data/lib/prawn/svg/calculators/pixels.rb +21 -0
- data/lib/prawn/svg/document.rb +16 -43
- data/lib/prawn/svg/element.rb +71 -18
- data/lib/prawn/svg/extension.rb +3 -3
- data/lib/prawn/svg/interface.rb +80 -19
- data/lib/prawn/svg/parser/image.rb +9 -62
- data/lib/prawn/svg/parser/path.rb +19 -1
- data/lib/prawn/svg/parser/text.rb +2 -0
- data/lib/prawn/svg/parser.rb +53 -18
- data/lib/prawn/svg/url_loader.rb +34 -0
- data/lib/prawn/svg/version.rb +1 -1
- data/lib/prawn-svg.rb +4 -0
- data/prawn-svg.gemspec +7 -4
- data/spec/integration_spec.rb +83 -0
- data/spec/prawn/svg/calculators/aspect_ratio_spec.rb +95 -0
- data/spec/prawn/svg/calculators/document_sizing_spec.rb +73 -0
- data/spec/prawn/svg/document_spec.rb +21 -17
- data/spec/prawn/svg/element_spec.rb +1 -1
- data/spec/prawn/svg/interface_spec.rb +59 -0
- data/spec/prawn/svg/parser/path_spec.rb +89 -0
- data/spec/prawn/svg/url_loader_spec.rb +46 -0
- data/spec/sample_images/mushroom-long.jpg +0 -0
- data/spec/sample_images/mushroom-wide.jpg +0 -0
- data/spec/sample_svg/cap_styles.svg +13 -0
- data/spec/sample_svg/display_none.svg +13 -0
- data/spec/sample_svg/gistfile1.svg +36 -0
- data/spec/sample_svg/hidden_paths.svg +6 -0
- data/spec/sample_svg/image01.svg +31 -31
- data/spec/sample_svg/negminy.svg +25 -0
- data/spec/sample_svg/path.svg +5 -0
- data/spec/sample_svg/pie_piece.svg +7 -0
- data/spec/sample_svg/viewbox.svg +4 -0
- data/spec/sample_svg/viewport.svg +23 -0
- data/spec/spec_helper.rb +7 -0
- metadata +81 -25
- data/spec/lib/path_spec.rb +0 -54
- data/spec/lib/svg_spec.rb +0 -47
- /data/spec/{lib → prawn/svg}/parser_spec.rb +0 -0
@@ -0,0 +1,95 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../../spec_helper'
|
2
|
+
|
3
|
+
describe Prawn::Svg::Calculators::AspectRatio do
|
4
|
+
def test(*args)
|
5
|
+
aspect = Prawn::Svg::Calculators::AspectRatio.new(*args)
|
6
|
+
[[aspect.width, aspect.height], [aspect.x, aspect.y]]
|
7
|
+
end
|
8
|
+
|
9
|
+
it "handles none" do
|
10
|
+
expect(test "none", [50,80], [100,100]).to eq [[50, 80], [0, 0]]
|
11
|
+
expect(test "none", [100,100], [50,80]).to eq [[100, 100], [0, 0]]
|
12
|
+
end
|
13
|
+
|
14
|
+
context "using meet" do
|
15
|
+
context "with smaller containers than objects" do
|
16
|
+
let(:coords) { [[50,80], [100,100]] }
|
17
|
+
|
18
|
+
it "correctly calculates the result" do
|
19
|
+
expect(test "xMidYMid meet", *coords).to eq [[50, 50], [0, 15]]
|
20
|
+
expect(test "xMinYMin meet", *coords).to eq [[50, 50], [0, 0]]
|
21
|
+
expect(test "xMaxYMax meet", *coords).to eq [[50, 50], [0, 30]]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "with bigger containers than objects" do
|
26
|
+
let(:coords) { [[100,80], [50,50]] }
|
27
|
+
|
28
|
+
it "correctly calculates the result" do
|
29
|
+
expect(test "xMidYMid meet", *coords).to eq [[80, 80], [10, 0]]
|
30
|
+
expect(test "xMinYMin meet", *coords).to eq [[80, 80], [0, 0]]
|
31
|
+
expect(test "xMaxYMax meet", *coords).to eq [[80, 80], [20, 0]]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "with bigger square containers" do
|
36
|
+
let(:coords) { [[100,100], [50,80]] }
|
37
|
+
|
38
|
+
it "correctly calculates the result" do
|
39
|
+
expect(test "xMidYMid meet", *coords).to eq [[62.5, 100], [18.75, 0]]
|
40
|
+
expect(test "xMinYMin meet", *coords).to eq [[62.5, 100], [0, 0]]
|
41
|
+
expect(test "xMaxYMax meet", *coords).to eq [[62.5, 100], [37.5, 0]]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "with oddly shaped containers" do
|
46
|
+
let(:coords) { [[100,20], [50,50]] }
|
47
|
+
|
48
|
+
it "correctly calculates the result" do
|
49
|
+
expect(test "xMidYMid meet", *coords).to eq [[20, 20], [40, 0]]
|
50
|
+
expect(test "xMinYMin meet", *coords).to eq [[20, 20], [0, 0]]
|
51
|
+
expect(test "xMaxYMax meet", *coords).to eq [[20, 20], [80, 0]]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "using slice" do
|
57
|
+
context "with smaller containers than objects" do
|
58
|
+
let(:coords) { [[50,80], [100,100]] }
|
59
|
+
|
60
|
+
it "correctly calculates the result" do
|
61
|
+
expect(test "xMidYMid slice", *coords).to eq [[80, 80], [-15, 0]]
|
62
|
+
expect(test "xMinYMin slice", *coords).to eq [[80, 80], [0, 0]]
|
63
|
+
expect(test "xMaxYMax slice", *coords).to eq [[80, 80], [-30, 0]]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "with bigger containers than objects" do
|
68
|
+
let(:coords) { [[100,80], [50,50]] }
|
69
|
+
|
70
|
+
it "correctly calculates the result" do
|
71
|
+
expect(test "xMidYMid slice", *coords).to eq [[100, 100], [0, -10]]
|
72
|
+
expect(test "xMinYMin slice", *coords).to eq [[100, 100], [0, 0]]
|
73
|
+
expect(test "xMaxYMax slice", *coords).to eq [[100, 100], [0, -20]]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context "with oddly shaped containers" do
|
78
|
+
let(:coords) { [[100,20], [50,50]] }
|
79
|
+
|
80
|
+
it "correctly calculates the result" do
|
81
|
+
expect(test "xMidYMid slice", *coords).to eq [[100, 100], [0, -40]]
|
82
|
+
expect(test "xMinYMin slice", *coords).to eq [[100, 100], [0, 0]]
|
83
|
+
expect(test "xMaxYMax slice", *coords).to eq [[100, 100], [0, -80]]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
it "defaults to 'xMidYMid meet' if nothing is supplied" do
|
89
|
+
expect(test "", [50,80], [100,100]).to eq test "xMidYMid meet", [50,80], [100,100]
|
90
|
+
end
|
91
|
+
|
92
|
+
it "defaults to 'xMidYMid meet' if something invalid is supplied" do
|
93
|
+
expect(test "completely invalid", [50,80], [100,100]).to eq test "xMidYMid meet", [50,80], [100,100]
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../../spec_helper'
|
2
|
+
|
3
|
+
describe Prawn::Svg::Calculators::DocumentSizing do
|
4
|
+
let(:attributes) do
|
5
|
+
{"width" => "150", "height" => "200", "viewBox" => "0 -30 300 800", "preserveAspectRatio" => "xMaxYMid meet"}
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:bounds) { [1200, 800] }
|
9
|
+
|
10
|
+
let(:sizing) { Prawn::Svg::Calculators::DocumentSizing.new(bounds, attributes) }
|
11
|
+
|
12
|
+
describe "#initialize" do
|
13
|
+
it "takes bounds and a set of attributes and calls set_from_attributes" do
|
14
|
+
expect(sizing.instance_variable_get :@bounds).to eq bounds
|
15
|
+
expect(sizing.instance_variable_get :@document_width).to eq "150"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#set_from_attributes" do
|
20
|
+
let(:sizing) { Prawn::Svg::Calculators::DocumentSizing.new(bounds) }
|
21
|
+
|
22
|
+
it "sets ivars from the passed-in attributes hash" do
|
23
|
+
sizing.set_from_attributes(attributes)
|
24
|
+
expect(sizing.instance_variable_get :@document_width).to eq "150"
|
25
|
+
expect(sizing.instance_variable_get :@document_height).to eq "200"
|
26
|
+
expect(sizing.instance_variable_get :@view_box).to eq "0 -30 300 800"
|
27
|
+
expect(sizing.instance_variable_get :@preserve_aspect_ratio).to eq "xMaxYMid meet"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#calculate" do
|
32
|
+
it "calculates the document sizing measurements for a given set of inputs" do
|
33
|
+
sizing.calculate
|
34
|
+
expect(sizing.x_offset).to eq -75
|
35
|
+
expect(sizing.y_offset).to eq -30
|
36
|
+
expect(sizing.x_scale).to eq 0.25
|
37
|
+
expect(sizing.y_scale).to eq 0.25
|
38
|
+
expect(sizing.viewport_width).to eq 300
|
39
|
+
expect(sizing.viewport_height).to eq 800
|
40
|
+
expect(sizing.output_width).to eq 150
|
41
|
+
expect(sizing.output_height).to eq 200
|
42
|
+
end
|
43
|
+
|
44
|
+
it "scales again based on requested width" do
|
45
|
+
sizing.requested_width = 75
|
46
|
+
sizing.calculate
|
47
|
+
expect(sizing.x_scale).to eq 0.125
|
48
|
+
expect(sizing.y_scale).to eq 0.125
|
49
|
+
expect(sizing.viewport_width).to eq 300
|
50
|
+
expect(sizing.viewport_height).to eq 800
|
51
|
+
expect(sizing.output_width).to eq 75
|
52
|
+
expect(sizing.output_height).to eq 100
|
53
|
+
end
|
54
|
+
|
55
|
+
it "scales again based on requested height" do
|
56
|
+
sizing.requested_height = 100
|
57
|
+
sizing.calculate
|
58
|
+
expect(sizing.x_scale).to eq 0.125
|
59
|
+
expect(sizing.y_scale).to eq 0.125
|
60
|
+
expect(sizing.viewport_width).to eq 300
|
61
|
+
expect(sizing.viewport_height).to eq 800
|
62
|
+
expect(sizing.output_width).to eq 75
|
63
|
+
expect(sizing.output_height).to eq 100
|
64
|
+
end
|
65
|
+
|
66
|
+
it "correctly handles % values being passed in" do
|
67
|
+
sizing.document_width = sizing.document_height = "50%"
|
68
|
+
sizing.calculate
|
69
|
+
expect(sizing.output_width).to eq 600
|
70
|
+
expect(sizing.output_height).to eq 400
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -1,27 +1,31 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
2
|
|
3
3
|
describe Prawn::Svg::Document do
|
4
|
-
before
|
5
|
-
|
4
|
+
before do
|
5
|
+
sizing = instance_double(Prawn::Svg::Calculators::DocumentSizing, viewport_width: 600, viewport_height: 400, viewport_diagonal: 500, :requested_width= => nil, :requested_height= => nil)
|
6
|
+
expect(sizing).to receive(:calculate)
|
7
|
+
expect(Prawn::Svg::Calculators::DocumentSizing).to receive(:new).and_return(sizing)
|
6
8
|
end
|
7
9
|
|
10
|
+
let(:document) { Prawn::Svg::Document.new("<svg></svg>", [100, 100], {}) }
|
11
|
+
|
8
12
|
describe :points do
|
9
13
|
it "converts a variety of measurement units to points" do
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
14
|
+
document.send(:points, 32).should == 32.0
|
15
|
+
document.send(:points, 32.0).should == 32.0
|
16
|
+
document.send(:points, "32").should == 32.0
|
17
|
+
document.send(:points, "32unknown").should == 32.0
|
18
|
+
document.send(:points, "32pt").should == 32.0
|
19
|
+
document.send(:points, "32in").should == 32.0 * 72
|
20
|
+
document.send(:points, "32ft").should == 32.0 * 72 * 12
|
21
|
+
document.send(:points, "32pc").should == 32.0 * 15
|
22
|
+
document.send(:points, "32mm").should be_within(0.0001).of(32 * 72 * 0.0393700787)
|
23
|
+
document.send(:points, "32cm").should be_within(0.0001).of(32 * 72 * 0.393700787)
|
24
|
+
document.send(:points, "32m").should be_within(0.0001).of(32 * 72 * 39.3700787)
|
25
|
+
|
26
|
+
document.send(:points, "50%").should == 250
|
27
|
+
document.send(:points, "50%", :x).should == 300
|
28
|
+
document.send(:points, "50%", :y).should == 200
|
25
29
|
end
|
26
30
|
end
|
27
31
|
end
|
@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + '/../../spec_helper'
|
|
2
2
|
|
3
3
|
describe Prawn::Svg::Element do
|
4
4
|
before :each do
|
5
|
-
e = double(:attributes => {})
|
5
|
+
e = double(:attributes => {}, :name => "path")
|
6
6
|
|
7
7
|
@document = Struct.new(:fallback_font_name, :css_parser, :warnings).new("Courier", nil, [])
|
8
8
|
@element = Prawn::Svg::Element.new(@document, e, [], {})
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Prawn::Svg::Interface do
|
4
|
+
let(:bounds) { double(width: 800, height: 600) }
|
5
|
+
let(:prawn) { instance_double(Prawn::Document, font_families: {}, bounds: bounds, cursor: 600) }
|
6
|
+
let(:svg) { '<svg width="250" height="100"></svg>' }
|
7
|
+
|
8
|
+
describe "#initialize" do
|
9
|
+
describe "invalid option detection" do
|
10
|
+
it "rejects invalid options when debug is on" do
|
11
|
+
allow(Prawn).to receive(:debug).and_return(true)
|
12
|
+
|
13
|
+
expect {
|
14
|
+
Prawn::Svg::Interface.new(svg, prawn, :invalid => "option")
|
15
|
+
}.to raise_error(Prawn::Errors::UnknownOption)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "does nothing if an invalid option is given and debug is off" do
|
19
|
+
Prawn::Svg::Interface.new(svg, prawn, :invalid => "option")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#position" do
|
25
|
+
context "when options[:at] supplied" do
|
26
|
+
it "returns options[:at]" do
|
27
|
+
interface = Prawn::Svg::Interface.new(svg, prawn, at: [1, 2], position: :left)
|
28
|
+
|
29
|
+
expect(interface.position).to eq [1, 2]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "when only a position is supplied" do
|
34
|
+
let(:interface) { Prawn::Svg::Interface.new(svg, prawn, position: position) }
|
35
|
+
|
36
|
+
subject { interface.position }
|
37
|
+
|
38
|
+
context "(:left)" do
|
39
|
+
let(:position) { :left }
|
40
|
+
it { is_expected.to eq [0, 600] }
|
41
|
+
end
|
42
|
+
|
43
|
+
context "(:center)" do
|
44
|
+
let(:position) { :center }
|
45
|
+
it { is_expected.to eq [275, 600] }
|
46
|
+
end
|
47
|
+
|
48
|
+
context "(:right)" do
|
49
|
+
let(:position) { :right }
|
50
|
+
it { is_expected.to eq [550, 600] }
|
51
|
+
end
|
52
|
+
|
53
|
+
context "a number" do
|
54
|
+
let(:position) { 25.5 }
|
55
|
+
it { is_expected.to eq [25.5, 600] }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Prawn::Svg::Parser::Path do
|
4
|
+
let(:path) { Prawn::Svg::Parser::Path.new }
|
5
|
+
|
6
|
+
describe "command parsing" do
|
7
|
+
it "correctly parses a valid path" do
|
8
|
+
calls = []
|
9
|
+
path.stub(:run_path_command) {|*args| calls << args}
|
10
|
+
path.parse("A12.34 -56.78 89B4 5 12-34 -.5.7+3 2.3e3 4e4 4e+4 c31,-2e-5C 6,7 T QX 0 Z")
|
11
|
+
|
12
|
+
calls.should == [
|
13
|
+
["A", [12.34, -56.78, 89]],
|
14
|
+
["B", [4, 5, 12, -34, -0.5, 0.7, 3, 2.3e3, 4e4, 4e4]],
|
15
|
+
["c", [31, -2e-5]],
|
16
|
+
["C", [6, 7]],
|
17
|
+
["T", []],
|
18
|
+
["Q", []],
|
19
|
+
["X", [0]],
|
20
|
+
["Z", []]
|
21
|
+
]
|
22
|
+
end
|
23
|
+
|
24
|
+
it "treats subsequent points to m/M command as relative/absolute depending on command" do
|
25
|
+
[
|
26
|
+
["M", [1,2,3,4]],
|
27
|
+
["L", [3,4]],
|
28
|
+
["m", [5,6,7,8]],
|
29
|
+
["l", [7,8]]
|
30
|
+
].each do |args|
|
31
|
+
path.should_receive(:run_path_command).with(*args).and_call_original
|
32
|
+
end
|
33
|
+
|
34
|
+
path.parse("M 1,2 3,4 m 5,6 7,8")
|
35
|
+
end
|
36
|
+
|
37
|
+
it "correctly parses an empty path" do
|
38
|
+
path.should_not_receive(:run_path_command)
|
39
|
+
path.parse("").should == []
|
40
|
+
path.parse(" ").should == []
|
41
|
+
end
|
42
|
+
|
43
|
+
it "raises on invalid characters in the path" do
|
44
|
+
lambda {path.parse("M 10 % 20")}.should raise_error(Prawn::Svg::Parser::Path::InvalidError)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "raises on numerical data before a command letter" do
|
48
|
+
lambda {path.parse("10 P")}.should raise_error(Prawn::Svg::Parser::Path::InvalidError)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "when given an A path" do
|
53
|
+
it "uses bezier curves to approximate an arc path" do
|
54
|
+
result = path.parse("M 100 200 A 10 10 0 0 1 200 200")
|
55
|
+
|
56
|
+
expect(result).to eq [
|
57
|
+
["move_to", [100.0, 200.0]],
|
58
|
+
["curve_to", [150.0, 150.0, 100.0, 172.57081148225683, 122.57081148225683, 150.0]],
|
59
|
+
["curve_to", [200.0, 200.0, 177.42918851774317, 150.0, 200.0, 172.57081148225683]]
|
60
|
+
]
|
61
|
+
end
|
62
|
+
|
63
|
+
it "ignores a path that has an identical start and end point" do
|
64
|
+
result = path.parse("M 100 200 A 30 30 0 0 1 100 200")
|
65
|
+
|
66
|
+
expect(result).to eq [
|
67
|
+
["move_to", [100.0, 200.0]]
|
68
|
+
]
|
69
|
+
end
|
70
|
+
|
71
|
+
it "substitutes a line_to when rx is 0" do
|
72
|
+
result = path.parse("M 100 200 A 0 10 0 0 1 200 200")
|
73
|
+
|
74
|
+
expect(result).to eq [
|
75
|
+
["move_to", [100.0, 200.0]],
|
76
|
+
["line_to", [200.0, 200.0]]
|
77
|
+
]
|
78
|
+
end
|
79
|
+
|
80
|
+
it "substitutes a line_to when ry is 0" do
|
81
|
+
result = path.parse("M 100 200 A 10 0 0 0 1 200 200")
|
82
|
+
|
83
|
+
expect(result).to eq [
|
84
|
+
["move_to", [100.0, 200.0]],
|
85
|
+
["line_to", [200.0, 200.0]]
|
86
|
+
]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Prawn::Svg::UrlLoader do
|
4
|
+
let(:loader) { Prawn::Svg::UrlLoader.new(:enable_cache => true, :enable_web => true) }
|
5
|
+
|
6
|
+
describe "#initialize" do
|
7
|
+
it "sets options" do
|
8
|
+
expect(loader.enable_cache).to be true
|
9
|
+
expect(loader.enable_web).to be true
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#valid?" do
|
14
|
+
it "knows what a valid URL looks like" do
|
15
|
+
expect(loader.valid?("http://valid.example/url")).to be true
|
16
|
+
expect(loader.valid?("not/a/valid/url")).to be false
|
17
|
+
end
|
18
|
+
|
19
|
+
it "doesn't accept schemes it doesn't like" do
|
20
|
+
expect(loader.valid?("mail://valid.example/url")).to be false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#load" do
|
25
|
+
let(:url) { "http://hello/there" }
|
26
|
+
|
27
|
+
it "loads an HTTP URL and saves to the cache" do
|
28
|
+
o = double(:read => "hello!")
|
29
|
+
loader.should_receive(:open).with(url).and_return(o)
|
30
|
+
|
31
|
+
expect(loader.load(url)).to eq "hello!"
|
32
|
+
expect(loader.url_cache[url]).to eq "hello!"
|
33
|
+
end
|
34
|
+
|
35
|
+
it "loads an HTTP URL from the cache without calling open" do
|
36
|
+
loader.url_cache[url] = "hello"
|
37
|
+
loader.should_not_receive(:open)
|
38
|
+
expect(loader.load(url)).to eq "hello"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "loads a data URL" do
|
42
|
+
loader.should_not_receive(:open)
|
43
|
+
expect(loader.load("data:image/png;base64,aGVsbG8=")).to eq "hello"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
Binary file
|
Binary file
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1100" height="210">
|
2
|
+
<rect x="100" y="100" width="900" height="100" fill="none" stroke="blue" stroke-width="2" />
|
3
|
+
|
4
|
+
<g stroke="green" stroke-width="10">
|
5
|
+
<line x1="120" y1="110" x2="120" y2="190" />
|
6
|
+
<line x1="140" y1="110" x2="140" y2="190" stroke-linecap="butt" />
|
7
|
+
<line x1="160" y1="110" x2="160" y2="190" stroke-linecap="round" />
|
8
|
+
<line x1="180" y1="110" x2="180" y2="190" stroke-linecap="square" />
|
9
|
+
<line x1="200" y1="110" x2="200" y2="190" />
|
10
|
+
<line x1="220" y1="110" x2="220" y2="190" stroke-linecap="invalid" />
|
11
|
+
</g>
|
12
|
+
</svg>
|
13
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
2
|
+
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" width="800" height="600">
|
3
|
+
<g id="layer1" style="display:none">
|
4
|
+
<rect x="350" y="200" width="20" height="20" fill="green" />
|
5
|
+
<text x="361.80859" y="200" id="text2986" xml:space="preserve" style="font-size:24px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Helvetica">
|
6
|
+
<tspan x="361.80859" y="200" id="tspan2988">Hidden</tspan>
|
7
|
+
</text>
|
8
|
+
</g>
|
9
|
+
<g id="layer2">
|
10
|
+
<text x="365.24805" y="300" id="text2990" xml:space="preserve" style="font-size:24px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Helvetica">
|
11
|
+
<tspan x="365.24805" y="300" id="tspan2992">Visible</tspan></text>
|
12
|
+
</g>
|
13
|
+
</svg>
|
@@ -0,0 +1,36 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
2
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="205pt" style="width:362px;height:205px;" version="1.1" viewBox="0 0 362 205" width="362pt">
|
3
|
+
<g>
|
4
|
+
<line style="stroke: blue; stroke-width: 1.0; stroke-dasharray: 20,40;" x1="146" x2="146" y1="35.4883" y2="204.041"/>
|
5
|
+
<line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 5.0,5.0;" x1="204" x2="204" y1="35.4883" y2="204.041"/>
|
6
|
+
<rect fill="#FEFECE" height="30.4883" style="stroke: #A80036; stroke-width: 1.5;" width="47" x="121" y="0"/>
|
7
|
+
<text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="33" x="128" y="20.5352">Alice</text>
|
8
|
+
<rect fill="#FEFECE" height="30.4883" style="stroke: #A80036; stroke-width: 1.5;" width="40" x="182" y="0"/>
|
9
|
+
<text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="26" x="189" y="20.5352">Bob</text>
|
10
|
+
<polygon fill="#A80036" points="192,67.4883,202,71.4883,192,75.4883,196,71.4883" style="stroke: #A80036; stroke-width: 1.0;"/>
|
11
|
+
<line style="stroke: #A80036; stroke-width: 1.0;" x1="146.5" x2="198" y1="71.4883" y2="71.4883"/>
|
12
|
+
<text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="31" x="153.5" y="67.0566">hello</text>
|
13
|
+
<polygon fill="#FBFB77" points="5,50.4883,5,75.4883,138,75.4883,138,60.4883,128,50.4883,5,50.4883" style="stroke: #A80036; stroke-width: 1.0;"/>
|
14
|
+
<line style="stroke: #A80036; stroke-width: 1.0;" x1="128" x2="128" y1="50.4883" y2="60.4883"/>
|
15
|
+
<line style="stroke: #A80036; stroke-width: 1.0;" x1="138" x2="128" y1="60.4883" y2="60.4883"/>
|
16
|
+
<text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="112" x="11" y="68.0566">this is a first note</text>
|
17
|
+
<polygon fill="#A80036" points="157.5,106.7988,147.5,110.7988,157.5,114.7988,153.5,110.7988" style="stroke: #A80036; stroke-width: 1.0;"/>
|
18
|
+
<line style="stroke: #A80036; stroke-width: 1.0;" x1="151.5" x2="203" y1="110.7988" y2="110.7988"/>
|
19
|
+
<text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="16" x="163.5" y="106.3672">ok</text>
|
20
|
+
<polygon fill="#FBFB77" points="209,89.7988,209,114.7988,353,114.7988,353,99.7988,343,89.7988,209,89.7988" style="stroke: #A80036; stroke-width: 1.0;"/>
|
21
|
+
<line style="stroke: #A80036; stroke-width: 1.0;" x1="343" x2="343" y1="89.7988" y2="99.7988"/>
|
22
|
+
<line style="stroke: #A80036; stroke-width: 1.0;" x1="353" x2="343" y1="99.7988" y2="99.7988"/>
|
23
|
+
<text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="123" x="215" y="107.3672">this is another note</text>
|
24
|
+
<line style="stroke: #A80036; stroke-width: 1.0;" x1="204" x2="246" y1="159.2305" y2="159.2305"/>
|
25
|
+
<line style="stroke: #A80036; stroke-width: 1.0;" x1="246" x2="246" y1="159.2305" y2="172.2305"/>
|
26
|
+
<line style="stroke: #A80036; stroke-width: 1.0;" x1="205" x2="246" y1="172.2305" y2="172.2305"/>
|
27
|
+
<polygon fill="#A80036" points="215,168.2305,205,172.2305,215,176.2305,211,172.2305" style="stroke: #A80036; stroke-width: 1.0;"/>
|
28
|
+
<text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="84" x="211" y="154.4883">I am thinking</text>
|
29
|
+
<polygon fill="#FBFB77" points="52,129.1094,52,184.1094,195,184.1094,195,139.1094,185,129.1094,52,129.1094" style="stroke: #A80036; stroke-width: 1.0;"/>
|
30
|
+
<line style="stroke: #A80036; stroke-width: 1.0;" x1="185" x2="185" y1="129.1094" y2="139.1094"/>
|
31
|
+
<line style="stroke: #A80036; stroke-width: 1.0;" x1="195" x2="185" y1="139.1094" y2="139.1094"/>
|
32
|
+
<text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="39" x="58" y="146.6777">a note</text>
|
33
|
+
<text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="122" x="58" y="161.9883">can also be defined</text>
|
34
|
+
<text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="98" x="58" y="177.2988">on several lines</text>
|
35
|
+
</g>
|
36
|
+
</svg>
|
@@ -0,0 +1,6 @@
|
|
1
|
+
<svg style="fill: none;">
|
2
|
+
<g class="x axis" transform="translate(0,227.9359)">
|
3
|
+
<path class="domain" d="M0,0V0H470V0" style="fill: none; stroke: none;"></path>
|
4
|
+
<path d="M 44.82625 0 L 44.82625 -3 L 94 -3 L 94 0" class="cantilever" style="stroke: black; fill: none;"></path>
|
5
|
+
</g>
|
6
|
+
</svg>
|