savage 0.1.0 → 0.2.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.
- 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
|