savage 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/savage/direction_proxy.rb +18 -0
- data/lib/savage/directions/arc_to.rb +4 -5
- data/lib/savage/directions/close_path.rb +5 -1
- data/lib/savage/directions/coordinate_target.rb +0 -3
- data/lib/savage/directions/cubic_curve_to.rb +22 -11
- data/lib/savage/directions/horizontal_to.rb +3 -4
- data/lib/savage/directions/line_to.rb +3 -4
- data/lib/savage/directions/move_to.rb +3 -4
- data/lib/savage/directions/point_target.rb +0 -3
- data/lib/savage/directions/quadratic_curve_to.rb +22 -11
- data/lib/savage/directions/vertical_to.rb +3 -4
- data/lib/savage/parser.rb +139 -0
- data/lib/savage/path.rb +33 -4
- data/lib/savage/sub_path.rb +29 -29
- data/lib/savage/utils.rb +6 -0
- data/lib/savage.rb +2 -2
- data/savage.gemspec +5 -2
- data/spec/savage/directions/cubic_curve_to_spec.rb +81 -53
- data/spec/savage/directions/quadratic_curve_spec.rb +83 -41
- data/spec/savage/parser_spec.rb +174 -0
- data/spec/savage/path_spec.rb +88 -7
- data/spec/savage/sub_path_spec.rb +73 -30
- data/spec/shared/direction.rb +13 -5
- metadata +6 -3
- data/lib/savage/core_extensions/string.rb +0 -8
@@ -17,13 +17,9 @@ describe CubicCurveTo do
|
|
17
17
|
@dir.respond_to?(:target).should == true
|
18
18
|
@dir.target.class.should == Point
|
19
19
|
end
|
20
|
-
it 'should have a
|
21
|
-
@dir.respond_to?(:
|
22
|
-
@dir.
|
23
|
-
end
|
24
|
-
it 'should have a first control point' do
|
25
|
-
@dir.respond_to?(:control_2).should == true
|
26
|
-
@dir.control_2.class.should == Point
|
20
|
+
it 'should have a control point' do
|
21
|
+
@dir.respond_to?(:control).should == true
|
22
|
+
@dir.control.class.should == Point
|
27
23
|
end
|
28
24
|
it 'should have an accessible target x, based on the constructor argument' do
|
29
25
|
@dir.target.x.should == 500
|
@@ -31,55 +27,60 @@ describe CubicCurveTo do
|
|
31
27
|
it 'should have an accessible target y, based on the constructor argument' do
|
32
28
|
@dir.target.y.should == 600
|
33
29
|
end
|
34
|
-
it 'should have an accessible first control x, based on the constructor argument' do
|
35
|
-
@dir.control_1.x.should == 100
|
36
|
-
end
|
37
|
-
it 'should have an accessible first control y, based on the constructor argument' do
|
38
|
-
@dir.control_1.y.should == 200
|
39
|
-
end
|
40
30
|
it 'should have an accessible second control x, based on the constructor argument' do
|
41
31
|
@dir.control_2.x.should == 300
|
42
32
|
end
|
43
33
|
it 'should have an accessible second control y, based on the constructor argument' do
|
44
34
|
@dir.control_2.y.should == 400
|
45
35
|
end
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
36
|
+
context 'when in verbose format' do
|
37
|
+
it 'should be constructed with at least target x and y, control 1 x and y, and control 2 x and y parameters' do
|
38
|
+
lambda { dir_class.new }.should raise_error
|
39
|
+
lambda { dir_class.new 45 }.should raise_error
|
40
|
+
lambda { dir_class.new 45, 50 }.should raise_error
|
41
|
+
lambda { dir_class.new 45, 50, 60 }.should raise_error
|
42
|
+
lambda { dir_class.new 45, 50, 60, 70, 80 }.should raise_error
|
43
|
+
lambda { dir_class.new 45, 50, 60, 70, 80, 90 }.should_not raise_error
|
44
|
+
lambda { dir_class.new 45, 50, 60, 70, 80, 90, true }.should_not raise_error
|
45
|
+
end
|
46
|
+
it 'should be relative if constructed with a false seventh parameter' do
|
47
|
+
direction = dir_class.new 45, 50, 60, 70, 80, 90, false
|
48
|
+
direction.absolute?.should == false
|
49
|
+
end
|
50
|
+
it 'should be absolute if constructed with a true seventh parameter' do
|
51
|
+
direction = dir_class.new 45, 50, 60, 70, 80, 90, true
|
52
|
+
direction.absolute?.should == true
|
53
|
+
end
|
54
|
+
it 'should be absolute if constructed with only six parameters' do
|
55
|
+
direction = dir_class.new 45, 50, 60, 70, 80, 90
|
56
|
+
direction.absolute?.should == true
|
57
|
+
end
|
58
|
+
it 'should have an accessible first control x, based on the constructor argument' do
|
59
|
+
@dir.control_1.x.should == 100
|
60
|
+
end
|
61
|
+
it 'should have an accessible first control y, based on the constructor argument' do
|
62
|
+
@dir.control_1.y.should == 200
|
63
|
+
end
|
64
|
+
describe '#to_command' do
|
65
|
+
it 'should start with a lower-case c when not absolute' do
|
66
|
+
extract_command(CubicCurveTo.new(100,200,300,400,500,600,false).to_command).should == 'c'
|
67
|
+
end
|
68
|
+
it 'should start with a capital C when absolute' do
|
69
|
+
extract_command(@dir.to_command).should == 'C'
|
70
|
+
end
|
70
71
|
it 'should have exactly 6 numerical parameters' do
|
71
72
|
extract_coordinates(@dir.to_command).length.should == 6
|
72
73
|
end
|
73
|
-
it 'should show the provided control
|
74
|
+
it 'should show the provided first control X value as the first parameter' do
|
74
75
|
extract_coordinates(@dir.to_command)[0].should == 100
|
75
76
|
end
|
76
|
-
it 'should show the provided control
|
77
|
+
it 'should show the provided first control Y value as the second parameter' do
|
77
78
|
extract_coordinates(@dir.to_command)[1].should == 200
|
78
79
|
end
|
79
|
-
it 'should show the provided control
|
80
|
+
it 'should show the provided second control X value as the third parameter' do
|
80
81
|
extract_coordinates(@dir.to_command)[2].should == 300
|
81
82
|
end
|
82
|
-
it 'should show the provided control
|
83
|
+
it 'should show the provided second control Y value as the fourth parameter' do
|
83
84
|
extract_coordinates(@dir.to_command)[3].should == 400
|
84
85
|
end
|
85
86
|
it 'should show the provided target X value as the fifth parameter' do
|
@@ -89,28 +90,55 @@ describe CubicCurveTo do
|
|
89
90
|
extract_coordinates(@dir.to_command)[5].should == 600
|
90
91
|
end
|
91
92
|
end
|
92
|
-
|
93
|
+
end
|
94
|
+
context 'when in shorthand format' do
|
95
|
+
before :each do
|
96
|
+
@dir = CubicCurveTo.new(100,200,300,400)
|
97
|
+
end
|
98
|
+
it 'should be constructed with at least target x and y parameters' do
|
99
|
+
lambda { dir_class.new }.should raise_error
|
100
|
+
lambda { dir_class.new 45 }.should raise_error
|
101
|
+
lambda { dir_class.new 45, 50 }.should raise_error
|
102
|
+
lambda { dir_class.new 45, 50, 60 }.should raise_error
|
103
|
+
lambda { dir_class.new 45, 50, 60, 70 }.should_not raise_error
|
104
|
+
lambda { dir_class.new 45, 50, 60, 70, true }.should_not raise_error
|
105
|
+
end
|
106
|
+
it 'should be relative if constructed with a false third parameter' do
|
107
|
+
direction = dir_class.new 45, 50, 60, 70, false
|
108
|
+
direction.absolute?.should == false
|
109
|
+
end
|
110
|
+
it 'should be absolute if constructed with a true third parameter' do
|
111
|
+
direction = dir_class.new 45, 50, 60, 70, true
|
112
|
+
direction.absolute?.should == true
|
113
|
+
end
|
114
|
+
it 'should be absolute if constructed with only two parameters' do
|
115
|
+
direction = dir_class.new 45, 50, 60, 70
|
116
|
+
direction.absolute?.should == true
|
117
|
+
end
|
118
|
+
it 'should have an nil first control, based on the constructor argument' do
|
119
|
+
@dir.control_1.should == nil
|
120
|
+
end
|
121
|
+
describe '#to_command' do
|
93
122
|
it 'should start with a lower-case s when not absolute' do
|
94
|
-
|
95
|
-
extract_command(rel_dir.to_command(true)).should == 's'
|
123
|
+
extract_command(CubicCurveTo.new(100,200,300,400,false).to_command).should == 's'
|
96
124
|
end
|
97
125
|
it 'should start with a capital S when absolute' do
|
98
|
-
extract_command(@dir.to_command
|
126
|
+
extract_command(@dir.to_command).should == 'S'
|
99
127
|
end
|
100
|
-
it 'should have exactly
|
101
|
-
extract_coordinates(@dir.to_command
|
128
|
+
it 'should have exactly 2 numerical parameters' do
|
129
|
+
extract_coordinates(@dir.to_command).length.should == 4
|
102
130
|
end
|
103
|
-
it 'should show the provided control
|
104
|
-
extract_coordinates(@dir.to_command
|
131
|
+
it 'should show the provided second control X value as the first parameter' do
|
132
|
+
extract_coordinates(@dir.to_command)[0].should == 100
|
105
133
|
end
|
106
|
-
it 'should show the provided control
|
107
|
-
extract_coordinates(@dir.to_command
|
134
|
+
it 'should show the provided second control Y value as the second parameter' do
|
135
|
+
extract_coordinates(@dir.to_command)[1].should == 200
|
108
136
|
end
|
109
137
|
it 'should show the provided target X value as the third parameter' do
|
110
|
-
extract_coordinates(@dir.to_command
|
138
|
+
extract_coordinates(@dir.to_command)[2].should == 300
|
111
139
|
end
|
112
140
|
it 'should show the provided target Y value as the fourth parameter' do
|
113
|
-
extract_coordinates(@dir.to_command
|
141
|
+
extract_coordinates(@dir.to_command)[3].should == 400
|
114
142
|
end
|
115
143
|
end
|
116
144
|
end
|
@@ -27,54 +27,96 @@ describe QuadraticCurveTo do
|
|
27
27
|
it 'should have an accessible target y, based on the constructor argument' do
|
28
28
|
@dir.target.y.should == 400
|
29
29
|
end
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
30
|
+
context 'when in verbose format' do
|
31
|
+
it 'should be constructed with at least target x and y and control x and y parameters' do
|
32
|
+
lambda { dir_class.new }.should raise_error
|
33
|
+
lambda { dir_class.new 45 }.should raise_error
|
34
|
+
lambda { dir_class.new 45, 50, 60 }.should raise_error
|
35
|
+
lambda { dir_class.new 45, 50, 60, 70 }.should_not raise_error
|
36
|
+
lambda { dir_class.new 45, 50, 60, 70, true }.should_not raise_error
|
37
|
+
end
|
38
|
+
it 'should be relative if constructed with a false fifth parameter' do
|
39
|
+
direction = dir_class.new 45, 50, 60, 70, false
|
40
|
+
direction.absolute?.should == false
|
41
|
+
end
|
42
|
+
it 'should be absolute if constructed with a true fifth parameter' do
|
43
|
+
direction = dir_class.new 45, 50, 60, 70, true
|
44
|
+
direction.absolute?.should == true
|
45
|
+
end
|
46
|
+
it 'should be absolute if constructed with only four parameters' do
|
47
|
+
direction = dir_class.new 45, 50, 60, 70
|
48
|
+
direction.absolute?.should == true
|
49
|
+
end
|
50
|
+
it 'should have an accessible first control x, based on the constructor argument' do
|
51
|
+
@dir.control.x.should == 100
|
52
|
+
end
|
53
|
+
it 'should have an accessible first control y, based on the constructor argument' do
|
54
|
+
@dir.control.y.should == 200
|
55
|
+
end
|
56
|
+
describe '#to_command' do
|
57
|
+
it 'should start with a lower-case q when not absolute' do
|
58
|
+
extract_command(QuadraticCurveTo.new(100,200,300,400,false).to_command).should == 'q'
|
59
|
+
end
|
60
|
+
it 'should start with a capital Q when absolute' do
|
61
|
+
extract_command(@dir.to_command).should == 'Q'
|
62
|
+
end
|
63
|
+
it 'should have exactly 4 numerical parameters' do
|
64
|
+
extract_coordinates(@dir.to_command).length.should == 4
|
65
|
+
end
|
66
|
+
it 'should show the provided control X value as the first parameter' do
|
67
|
+
extract_coordinates(@dir.to_command)[0].should == 100
|
68
|
+
end
|
69
|
+
it 'should show the provided control Y value as the second parameter' do
|
70
|
+
extract_coordinates(@dir.to_command)[1].should == 200
|
71
|
+
end
|
72
|
+
it 'should show the provided target X value as the third parameter' do
|
73
|
+
extract_coordinates(@dir.to_command)[2].should == 300
|
74
|
+
end
|
75
|
+
it 'should show the provided target Y value as the fourth parameter' do
|
76
|
+
extract_coordinates(@dir.to_command)[3].should == 400
|
77
|
+
end
|
78
|
+
end
|
55
79
|
end
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
extract_command(rel_dir.to_command(true)).should == 't'
|
80
|
+
context 'when in shorthand format' do
|
81
|
+
before :each do
|
82
|
+
@dir = QuadraticCurveTo.new(100,200)
|
60
83
|
end
|
61
|
-
it 'should
|
62
|
-
|
84
|
+
it 'should be constructed with at least target x and y parameters' do
|
85
|
+
lambda { dir_class.new }.should raise_error
|
86
|
+
lambda { dir_class.new 45 }.should raise_error
|
87
|
+
lambda { dir_class.new 45, 50 }.should_not raise_error
|
63
88
|
end
|
64
|
-
it 'should
|
65
|
-
|
89
|
+
it 'should be relative if constructed with a false third parameter' do
|
90
|
+
direction = dir_class.new 45, 50, false
|
91
|
+
direction.absolute?.should == false
|
66
92
|
end
|
67
|
-
it 'should
|
68
|
-
|
93
|
+
it 'should be absolute if constructed with a true third parameter' do
|
94
|
+
direction = dir_class.new 45, 50, true
|
95
|
+
direction.absolute?.should == true
|
69
96
|
end
|
70
|
-
it 'should
|
71
|
-
|
97
|
+
it 'should be absolute if constructed with only two parameters' do
|
98
|
+
direction = dir_class.new 45, 50
|
99
|
+
direction.absolute?.should == true
|
72
100
|
end
|
73
|
-
it 'should
|
74
|
-
|
101
|
+
it 'should have an nil control, based on the constructor argument' do
|
102
|
+
@dir.control.should == nil
|
75
103
|
end
|
76
|
-
|
77
|
-
|
104
|
+
describe '#to_command' do
|
105
|
+
it 'should start with a lower-case t when not absolute' do
|
106
|
+
extract_command(QuadraticCurveTo.new(100,200,false).to_command).should == 't'
|
107
|
+
end
|
108
|
+
it 'should start with a capital T when absolute' do
|
109
|
+
extract_command(@dir.to_command).should == 'T'
|
110
|
+
end
|
111
|
+
it 'should have exactly 2 numerical parameters' do
|
112
|
+
extract_coordinates(@dir.to_command).length.should == 2
|
113
|
+
end
|
114
|
+
it 'should show the provided target X value as the first parameter' do
|
115
|
+
extract_coordinates(@dir.to_command)[0].should == 100
|
116
|
+
end
|
117
|
+
it 'should show the provided target Y value as the second parameter' do
|
118
|
+
extract_coordinates(@dir.to_command)[1].should == 200
|
119
|
+
end
|
78
120
|
end
|
79
121
|
end
|
80
122
|
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
include Savage
|
4
|
+
|
5
|
+
describe Parser do
|
6
|
+
it 'should have a parse method' do
|
7
|
+
Parser.respond_to?(:parse).should == true
|
8
|
+
end
|
9
|
+
describe '.parse' do
|
10
|
+
it 'should accept a single string as argument' do
|
11
|
+
lambda { Parser.parse }.should raise_error
|
12
|
+
lambda { Parser.parse("M100 200") }.should_not raise_error
|
13
|
+
lambda { Parser.parse(2) }.should raise_error
|
14
|
+
end
|
15
|
+
it 'should return a path object with one subpath containing one move_to when the string is only a move_to command' do
|
16
|
+
path = Parser.parse("M100 200")
|
17
|
+
path.class.should == Path
|
18
|
+
path.subpaths.length.should == 1
|
19
|
+
path.subpaths.last.directions.length.should == 1
|
20
|
+
path.subpaths.last.directions.last.class.should == Directions::MoveTo
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should return a path object with one subpath containing a move_to and a line_to when the string is a move_to command followed by a line_to command' do
|
24
|
+
path = Parser.parse("M100 200l-342.65 21")
|
25
|
+
path.class.should == Path
|
26
|
+
path.subpaths.length.should == 1
|
27
|
+
path.subpaths.last.directions.length.should == 2
|
28
|
+
path.subpaths.last.directions[0].class.should == Directions::MoveTo
|
29
|
+
path.subpaths.last.directions[1].should_not be_absolute
|
30
|
+
path.subpaths.last.directions[1].class.should == Directions::LineTo
|
31
|
+
end
|
32
|
+
it 'should return a path object with one subpath containing a move_to and a horizontal_to when the string is a move_to command followed by a horizontal_to command' do
|
33
|
+
path = Parser.parse("M100 200H-342.65")
|
34
|
+
path.class.should == Path
|
35
|
+
path.subpaths.length.should == 1
|
36
|
+
path.subpaths.last.directions.length.should == 2
|
37
|
+
path.subpaths.last.directions[0].class.should == Directions::MoveTo
|
38
|
+
path.subpaths.last.directions[1].class.should == Directions::HorizontalTo
|
39
|
+
end
|
40
|
+
it 'should return a path object with one subpath containing a move_to and a vertical_to when the string is a move_to command followed by a vertical_to command' do
|
41
|
+
path = Parser.parse("M100 200V-342.65")
|
42
|
+
path.class.should == Path
|
43
|
+
path.subpaths.length.should == 1
|
44
|
+
path.subpaths.last.directions.length.should == 2
|
45
|
+
path.subpaths.last.directions[0].class.should == Directions::MoveTo
|
46
|
+
path.subpaths.last.directions[1].class.should == Directions::VerticalTo
|
47
|
+
end
|
48
|
+
it 'should return a path object with one subpath containing a move_to and a full cubic_curve_to when the string is a move_to command followed by a full cubic_curve_to command' do
|
49
|
+
path = Parser.parse("M100 200C-342.65-32 1.233-34 255 12")
|
50
|
+
path.class.should == Path
|
51
|
+
path.subpaths.length.should == 1
|
52
|
+
path.subpaths.last.directions.length.should == 2
|
53
|
+
path.subpaths.last.directions[0].class.should == Directions::MoveTo
|
54
|
+
path.subpaths.last.directions[1].class.should == Directions::CubicCurveTo
|
55
|
+
path.subpaths.last.directions[1].command_code.should == 'C'
|
56
|
+
end
|
57
|
+
it 'should return a path object with one subpath containing a move_to and a short cubic_curve_to when the string is a move_to command followed by a short cubic_curve_to command' do
|
58
|
+
path = Parser.parse("M100 200S1.233-34 255 12")
|
59
|
+
path.class.should == Path
|
60
|
+
path.subpaths.length.should == 1
|
61
|
+
path.subpaths.last.directions.length.should == 2
|
62
|
+
path.subpaths.last.directions[0].class.should == Directions::MoveTo
|
63
|
+
path.subpaths.last.directions[1].class.should == Directions::CubicCurveTo
|
64
|
+
path.subpaths.last.directions[1].command_code.should == 'S'
|
65
|
+
end
|
66
|
+
it 'should return a path object with one subpath containing a move_to and a full quadratic_curve_to when the string is a move_to command followed by a full quadratic_curve_to command' do
|
67
|
+
path = Parser.parse("M100 200Q1.233-34 255 12")
|
68
|
+
path.class.should == Path
|
69
|
+
path.subpaths.length.should == 1
|
70
|
+
path.subpaths.last.directions.length.should == 2
|
71
|
+
path.subpaths.last.directions[0].class.should == Directions::MoveTo
|
72
|
+
path.subpaths.last.directions[1].class.should == Directions::QuadraticCurveTo
|
73
|
+
path.subpaths.last.directions[1].command_code.should == 'Q'
|
74
|
+
end
|
75
|
+
it 'should return a path object with one subpath containing a move_to and a short quadratic_curve_to when the string is a move_to command followed by a short quadratic_curve_to command' do
|
76
|
+
path = Parser.parse("M100 200T255 12")
|
77
|
+
path.class.should == Path
|
78
|
+
path.subpaths.length.should == 1
|
79
|
+
path.subpaths.last.directions.length.should == 2
|
80
|
+
path.subpaths.last.directions[0].class.should == Directions::MoveTo
|
81
|
+
path.subpaths.last.directions[1].class.should == Directions::QuadraticCurveTo
|
82
|
+
path.subpaths.last.directions[1].command_code.should == 'T'
|
83
|
+
end
|
84
|
+
it 'should return a path object with one subpath containing a move_to and an arc_to when the string is a move_to command followed by an arc_to command' do
|
85
|
+
path = Parser.parse("M100 200A255 12-123 1 0 23-93.4")
|
86
|
+
path.class.should == Path
|
87
|
+
path.subpaths.length.should == 1
|
88
|
+
path.subpaths.last.directions.length.should == 2
|
89
|
+
path.subpaths.last.directions[0].class.should == Directions::MoveTo
|
90
|
+
path.subpaths.last.directions[1].class.should == Directions::ArcTo
|
91
|
+
path.subpaths.last.directions[1].command_code.should == 'A'
|
92
|
+
end
|
93
|
+
it 'should return a path object with one subpath containing a move_to, a line_to, and a close_path command when the string is a move_to command followed by a line_to followed by a close_path command' do
|
94
|
+
path = Parser.parse("M100 200l-342.65 21Z")
|
95
|
+
path.class.should == Path
|
96
|
+
path.subpaths.length.should == 1
|
97
|
+
path.subpaths.last.directions.length.should == 3
|
98
|
+
path.subpaths.last.directions[0].class.should == Directions::MoveTo
|
99
|
+
path.subpaths.last.directions[1].class.should == Directions::LineTo
|
100
|
+
path.subpaths.last.directions[2].class.should == Directions::ClosePath
|
101
|
+
path.subpaths.last.closed?.should == true
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'should return a path object with one subpath containing two line_to directions when the string is a line_to command followed by implicit coordinates' do
|
105
|
+
path = Parser.parse("L100 200 300 400")
|
106
|
+
path.class.should == Path
|
107
|
+
path.subpaths.length.should == 1
|
108
|
+
path.subpaths.last.directions.length.should == 2
|
109
|
+
path.subpaths.last.directions[0].class.should == Directions::LineTo
|
110
|
+
path.subpaths.last.directions[0].target.x.should == 100
|
111
|
+
path.subpaths.last.directions[0].target.y.should == 200
|
112
|
+
path.subpaths.last.directions[1].class.should == Directions::LineTo
|
113
|
+
path.subpaths.last.directions[1].target.x.should == 300
|
114
|
+
path.subpaths.last.directions[1].target.y.should == 400
|
115
|
+
end
|
116
|
+
it 'should return a path object with one subpath containing two line_to directions when the string is a line_to command followed by implicit coordinates' do
|
117
|
+
path = Parser.parse("L100 200 300 400")
|
118
|
+
path.class.should == Path
|
119
|
+
path.subpaths.length.should == 1
|
120
|
+
path.subpaths.last.directions.length.should == 2
|
121
|
+
path.subpaths.last.directions[0].class.should == Directions::LineTo
|
122
|
+
path.subpaths.last.directions[0].target.x.should == 100
|
123
|
+
path.subpaths.last.directions[0].target.y.should == 200
|
124
|
+
path.subpaths.last.directions[1].class.should == Directions::LineTo
|
125
|
+
path.subpaths.last.directions[1].target.x.should == 300
|
126
|
+
path.subpaths.last.directions[1].target.y.should == 400
|
127
|
+
end
|
128
|
+
it 'should return a path object with one subpath containing a move_to and a line_to direction when the string is a move_to command followed by implicit coordinates' do
|
129
|
+
path = Parser.parse("M100 200 300 400")
|
130
|
+
path.class.should == Path
|
131
|
+
path.subpaths.length.should == 1
|
132
|
+
path.subpaths.last.directions.length.should == 2
|
133
|
+
path.subpaths.last.directions[0].class.should == Directions::MoveTo
|
134
|
+
path.subpaths.last.directions[0].target.x.should == 100
|
135
|
+
path.subpaths.last.directions[0].target.y.should == 200
|
136
|
+
path.subpaths.last.directions[1].class.should == Directions::LineTo
|
137
|
+
path.subpaths.last.directions[1].target.x.should == 300
|
138
|
+
path.subpaths.last.directions[1].target.y.should == 400
|
139
|
+
end
|
140
|
+
it 'should return a path object with one subpath containing a move_to and two line_to directions when the string is a move_to command followed by more than one set of implicit coordinates' do
|
141
|
+
path = Parser.parse("M100 200 300 400 500 600 ")
|
142
|
+
path.class.should == Path
|
143
|
+
path.subpaths.length.should == 1
|
144
|
+
path.subpaths.last.directions.length.should == 3
|
145
|
+
path.subpaths.last.directions[0].class.should == Directions::MoveTo
|
146
|
+
path.subpaths.last.directions[0].target.x.should == 100
|
147
|
+
path.subpaths.last.directions[0].target.y.should == 200
|
148
|
+
path.subpaths.last.directions[1].class.should == Directions::LineTo
|
149
|
+
path.subpaths.last.directions[1].target.x.should == 300
|
150
|
+
path.subpaths.last.directions[1].target.y.should == 400
|
151
|
+
path.subpaths.last.directions[2].class.should == Directions::LineTo
|
152
|
+
path.subpaths.last.directions[2].target.x.should == 500
|
153
|
+
path.subpaths.last.directions[2].target.y.should == 600
|
154
|
+
end
|
155
|
+
it 'should return a path object with two subpaths containing one line_to directions each when the string is two move_to commands each followed by a line_to command' do
|
156
|
+
path = Parser.parse("M100 200 332 -12.3M594 230-423 11.1")
|
157
|
+
path.class.should == Path
|
158
|
+
path.subpaths.length.should == 2
|
159
|
+
path.subpaths[0].directions.length.should == 2
|
160
|
+
path.subpaths[0].directions[0].class.should == Directions::MoveTo
|
161
|
+
path.subpaths[0].directions[0].target.x.should == 100
|
162
|
+
path.subpaths[0].directions[0].target.y.should == 200
|
163
|
+
path.subpaths[0].directions[1].class.should == Directions::LineTo
|
164
|
+
path.subpaths[0].directions[1].target.x.should == 332
|
165
|
+
path.subpaths[0].directions[1].target.y.should == -12.3
|
166
|
+
path.subpaths[1].directions[0].class.should == Directions::MoveTo
|
167
|
+
path.subpaths[1].directions[0].target.x.should == 594
|
168
|
+
path.subpaths[1].directions[0].target.y.should == 230
|
169
|
+
path.subpaths[1].directions[1].class.should == Directions::LineTo
|
170
|
+
path.subpaths[1].directions[1].target.x.should == -423
|
171
|
+
path.subpaths[1].directions[1].target.y.should == 11.1
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
data/spec/savage/path_spec.rb
CHANGED
@@ -6,14 +6,61 @@ describe Path do
|
|
6
6
|
it 'should accept no parameters in a constructor for a new, empty path' do
|
7
7
|
lambda{ Path.new }.should_not raise_error
|
8
8
|
end
|
9
|
-
it 'should
|
10
|
-
|
9
|
+
it 'should be able to be constructed with a starting point (absolute move to)' do
|
10
|
+
path = Path.new(100,200)
|
11
|
+
path.subpaths.length.should == 1
|
12
|
+
path.subpaths.last.directions.length.should == 1
|
13
|
+
path.subpaths.last.directions.last.class.should == Directions::MoveTo
|
11
14
|
end
|
12
|
-
it 'should
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
it 'should be able to build itself in a block' do
|
16
|
+
path = Path.new(100,200) do |p|
|
17
|
+
p.line_to 300, 400
|
18
|
+
p.cubic_curve_to 500,600,700,800,900,1000
|
19
|
+
p.arc_to 100,200,123,1,1,300,400
|
20
|
+
end
|
21
|
+
path.subpaths.last.directions[0].class.should == Directions::MoveTo
|
22
|
+
path.subpaths.last.directions[1].class.should == Directions::LineTo
|
23
|
+
path.subpaths.last.directions[2].class.should == Directions::CubicCurveTo
|
24
|
+
path.subpaths.last.directions[3].class.should == Directions::ArcTo
|
25
|
+
|
26
|
+
path2 = Path.new do |p|
|
27
|
+
p.line_to 300, 400
|
28
|
+
p.cubic_curve_to 500,600,700,800,900,1000
|
29
|
+
p.arc_to 100,200,123,1,1,300,400
|
30
|
+
end
|
31
|
+
path2.subpaths.last.directions[0].class.should == Directions::LineTo
|
32
|
+
path2.subpaths.last.directions[1].class.should == Directions::CubicCurveTo
|
33
|
+
path2.subpaths.last.directions[2].class.should == Directions::ArcTo
|
34
|
+
end
|
35
|
+
it 'should have a directions list' do
|
36
|
+
Path.new.respond_to?(:directions).should == true
|
37
|
+
end
|
38
|
+
it 'should have a move_to method' do
|
39
|
+
Path.new.respond_to?(:move_to).should == true
|
40
|
+
end
|
41
|
+
it 'should have a line_to method' do
|
42
|
+
Path.new.respond_to?(:line_to).should == true
|
43
|
+
end
|
44
|
+
it 'should have a horizontal_to method' do
|
45
|
+
Path.new.respond_to?(:horizontal_to).should == true
|
46
|
+
end
|
47
|
+
it 'should have a vertical_to method' do
|
48
|
+
Path.new.respond_to?(:vertical_to).should == true
|
49
|
+
end
|
50
|
+
it 'should have a quadratic_curve_to method' do
|
51
|
+
Path.new.respond_to?(:quadratic_curve_to).should == true
|
52
|
+
end
|
53
|
+
it 'should have a cubic_curve_to method' do
|
54
|
+
Path.new.respond_to?(:cubic_curve_to).should == true
|
55
|
+
end
|
56
|
+
it 'should have a arc_to method' do
|
57
|
+
Path.new.respond_to?(:arc_to).should == true
|
58
|
+
end
|
59
|
+
it 'should have a close_path method' do
|
60
|
+
Path.new.respond_to?(:close_path).should == true
|
61
|
+
end
|
62
|
+
it 'should have a closed? method' do
|
63
|
+
Path.new.respond_to?(:closed?).should == true
|
17
64
|
end
|
18
65
|
it 'should have subpaths' do
|
19
66
|
Path.new.respond_to?(:subpaths).should == true
|
@@ -21,4 +68,38 @@ describe Path do
|
|
21
68
|
it 'should have a to_command method' do
|
22
69
|
Path.new.respond_to?(:to_command).should == true
|
23
70
|
end
|
71
|
+
describe '#move_to' do
|
72
|
+
it 'should create a new subpath with that movement therein if there is already a populated subpath' do
|
73
|
+
path = Path.new(200,300) do |p|
|
74
|
+
p.line_to(123,456)
|
75
|
+
p.close_path
|
76
|
+
end
|
77
|
+
path.move_to(200,300)
|
78
|
+
path.subpaths.length.should == 2
|
79
|
+
path.subpaths.last.directions.length.should == 1
|
80
|
+
path.subpaths.last.directions.last.class.should == Directions::MoveTo
|
81
|
+
end
|
82
|
+
it 'should create append the movement if the last subpath is empty a populated subpath' do
|
83
|
+
path = Path.new
|
84
|
+
path.move_to(200,300)
|
85
|
+
path.subpaths.length.should == 1
|
86
|
+
path.subpaths.last.directions.length.should == 1
|
87
|
+
path.subpaths.last.directions.last.class.should == Directions::MoveTo
|
88
|
+
end
|
89
|
+
end
|
90
|
+
describe '#to_command' do
|
91
|
+
it 'should concatenate all its subpaths command strings' do
|
92
|
+
path = Path.new(100,200) do |p|
|
93
|
+
p.line_to 300, 400
|
94
|
+
p.cubic_curve_to 500,600,700,800,900,1000
|
95
|
+
p.arc_to 100,200,123,1,1,300,400
|
96
|
+
p.close_path
|
97
|
+
p.move_to 499, 232
|
98
|
+
p.line_to 2433.4, -231
|
99
|
+
p.line_to -233, 122
|
100
|
+
end
|
101
|
+
concatenated = path.subpaths.collect { |subpath| subpath.to_command }.join
|
102
|
+
path.to_command.should == concatenated
|
103
|
+
end
|
104
|
+
end
|
24
105
|
end
|