savage-transform 1.3.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.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.gitignore +22 -0
  4. data/.rspec +1 -0
  5. data/LICENSE +20 -0
  6. data/README.rdoc +108 -0
  7. data/Rakefile +1 -0
  8. data/VERSION +1 -0
  9. data/lib/savage.rb +3 -0
  10. data/lib/savage/direction.rb +56 -0
  11. data/lib/savage/direction_proxy.rb +19 -0
  12. data/lib/savage/directions/arc_to.rb +30 -0
  13. data/lib/savage/directions/close_path.rb +22 -0
  14. data/lib/savage/directions/coordinate_target.rb +21 -0
  15. data/lib/savage/directions/cubic_curve_to.rb +47 -0
  16. data/lib/savage/directions/horizontal_to.rb +31 -0
  17. data/lib/savage/directions/line_to.rb +15 -0
  18. data/lib/savage/directions/move_to.rb +15 -0
  19. data/lib/savage/directions/point_target.rb +22 -0
  20. data/lib/savage/directions/quadratic_curve_to.rb +44 -0
  21. data/lib/savage/directions/vertical_to.rb +31 -0
  22. data/lib/savage/parser.rb +108 -0
  23. data/lib/savage/path.rb +66 -0
  24. data/lib/savage/sub_path.rb +78 -0
  25. data/lib/savage/transformable.rb +59 -0
  26. data/lib/savage/utils.rb +7 -0
  27. data/savage-transform.gemspec +26 -0
  28. data/spec/savage/directions/arc_to_spec.rb +97 -0
  29. data/spec/savage/directions/close_path_spec.rb +30 -0
  30. data/spec/savage/directions/cubic_curve_to_spec.rb +146 -0
  31. data/spec/savage/directions/horizontal_to_spec.rb +10 -0
  32. data/spec/savage/directions/line_to_spec.rb +14 -0
  33. data/spec/savage/directions/move_to_spec.rb +10 -0
  34. data/spec/savage/directions/point_spec.rb +12 -0
  35. data/spec/savage/directions/quadratic_curve_spec.rb +123 -0
  36. data/spec/savage/directions/vertical_to_spec.rb +10 -0
  37. data/spec/savage/parser_spec.rb +250 -0
  38. data/spec/savage/path_spec.rb +105 -0
  39. data/spec/savage/sub_path_spec.rb +195 -0
  40. data/spec/savage/transformable_spec.rb +99 -0
  41. data/spec/savage_spec.rb +5 -0
  42. data/spec/shared/command.rb +13 -0
  43. data/spec/shared/coordinate_target.rb +36 -0
  44. data/spec/shared/direction.rb +29 -0
  45. data/spec/shared/point_target.rb +45 -0
  46. data/spec/spec_helper.rb +36 -0
  47. metadata +153 -0
@@ -0,0 +1,97 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ include Savage::Directions
4
+
5
+ describe ArcTo do
6
+ def dir_class; ArcTo; end
7
+ def create_relative; ArcTo.new(100,200,300,true,false,400,500,false); end
8
+ def command_code; 'a'; end
9
+
10
+ before :each do
11
+ @dir = dir_class.new(100,200,300,true,false,400,500)
12
+ end
13
+
14
+ include Command
15
+ it_behaves_like 'Direction'
16
+
17
+ it 'should have a target' do
18
+ @dir.respond_to?(:target).should == true
19
+ @dir.target.class.should == Point
20
+ end
21
+ it 'should have a radius' do
22
+ @dir.respond_to?(:radius).should == true
23
+ @dir.radius.class.should == Point
24
+ end
25
+ it 'should have a large arc based on the constructor argument' do
26
+ @dir.respond_to?(:large_arc).should == true
27
+ @dir.large_arc.should == true
28
+ end
29
+ it 'should have a sweep based on the constructor argument' do
30
+ @dir.respond_to?(:sweep).should == true
31
+ @dir.sweep.should == false
32
+ end
33
+ it 'should have a rotation based on the constructor arugment' do
34
+ @dir.respond_to?(:rotation).should == true
35
+ @dir.rotation.should == 300
36
+ end
37
+ it 'should have an accessible target x, based on the constructor argument' do
38
+ @dir.target.x.should == 400
39
+ end
40
+ it 'should have an accessible target y, based on the constructor argument' do
41
+ @dir.target.y.should == 500
42
+ end
43
+ it 'should have an accessible x radius, based on the constructor argument' do
44
+ @dir.radius.x.should == 100
45
+ end
46
+ it 'should have an accessible y radius, based on the constructor argument' do
47
+ @dir.radius.y.should == 200
48
+ end
49
+ it 'should be constructed with at least x and y radii, rotation, large arc, sweep, and target x and y parameters' do
50
+ lambda { dir_class.new }.should raise_error
51
+ lambda { dir_class.new 45 }.should raise_error
52
+ lambda { dir_class.new 45, 50 }.should raise_error
53
+ lambda { dir_class.new 45, 50, 60 }.should raise_error
54
+ lambda { dir_class.new 45, 50, 60, true }.should raise_error
55
+ lambda { dir_class.new 45, 50, 60, true, true }.should raise_error
56
+ lambda { dir_class.new 45, 50, 60, true, true, 100 }.should raise_error
57
+ lambda { dir_class.new 45, 50, 60, true, true, 100, 200 }.should_not raise_error
58
+ end
59
+ it 'should be relative if constructed with a false eighth parameter' do
60
+ direction = dir_class.new 45, 50, 60, true, true, 100, 200, false
61
+ direction.absolute?.should == false
62
+ end
63
+ it 'should be absolute if constructed with a true eighth parameter' do
64
+ direction = dir_class.new 45, 50, 60, true, true, 100, 200, true
65
+ direction.absolute?.should == true
66
+ end
67
+ it 'should be absolute if constructed with only seven parameters' do
68
+ direction = dir_class.new 45, 50, 60, true, true, 100, 200
69
+ direction.absolute?.should == true
70
+ end
71
+ describe '#to_command' do
72
+ it 'should have exactly 7 numerical parameters' do
73
+ extract_coordinates(@dir.to_command).length.should == 7
74
+ end
75
+ it 'should show the provided x radius value as the first parameter' do
76
+ extract_coordinates(@dir.to_command)[0].should == 100
77
+ end
78
+ it 'should show the provided y radius value as the second parameter' do
79
+ extract_coordinates(@dir.to_command)[1].should == 200
80
+ end
81
+ it 'should show the provided rotation value as the third parameter' do
82
+ extract_coordinates(@dir.to_command)[2].should == 300
83
+ end
84
+ it 'should show the integer interpretation of the provided large arc value as the fourth parameter' do
85
+ extract_coordinates(@dir.to_command)[3].should == 1
86
+ end
87
+ it 'should show the integer interpretation of the provided sweep value as the fifth parameter' do
88
+ extract_coordinates(@dir.to_command)[4].should == 0
89
+ end
90
+ it 'should show the provided target x value as the sixth parameter' do
91
+ extract_coordinates(@dir.to_command)[5].should == 400
92
+ end
93
+ it 'should show the provided target y value as the seventh parameter' do
94
+ extract_coordinates(@dir.to_command)[6].should == 500
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,30 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ include Savage::Directions
4
+
5
+ describe ClosePath do
6
+ before :each do
7
+ @dir = ClosePath.new()
8
+ end
9
+ def create_relative; ClosePath.new(false); end
10
+ def command_code; 'z'; end
11
+ include Command
12
+ it_behaves_like 'Direction'
13
+ it 'should be constructed with with either no parameters or a single boolean parameter' do
14
+ lambda { ClosePath.new }.should_not raise_error
15
+ lambda { ClosePath.new true }.should_not raise_error
16
+ lambda { ClosePath.new 45, 50 }.should raise_error
17
+ end
18
+ it 'should be relative if constructed with a false parameter' do
19
+ direction = ClosePath.new(false)
20
+ direction.absolute?.should == false
21
+ end
22
+ it 'should be absolute if constructed with a false parameter' do
23
+ direction = ClosePath.new(true)
24
+ direction.absolute?.should == true
25
+ end
26
+ it 'should be absolute if constructed with no parameters' do
27
+ direction = ClosePath.new()
28
+ direction.absolute?.should == true
29
+ end
30
+ end
@@ -0,0 +1,146 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ include Savage::Directions
4
+
5
+ describe CubicCurveTo do
6
+ def dir_class; CubicCurveTo; end
7
+ def create_relative; CubicCurveTo.new(100,200,300,400,500,600,false); end
8
+ def command_code; 'c'; end
9
+
10
+ before :each do
11
+ @dir = dir_class.new(100,200,300,400,500,600)
12
+ end
13
+
14
+ include Command
15
+ it_behaves_like 'Direction'
16
+
17
+ it 'should have a target' do
18
+ @dir.respond_to?(:target).should == true
19
+ @dir.target.class.should == Point
20
+ end
21
+ it 'should have a control point' do
22
+ @dir.respond_to?(:control).should == true
23
+ @dir.control.class.should == Point
24
+ end
25
+ it 'should have an accessible target x, based on the constructor argument' do
26
+ @dir.target.x.should == 500
27
+ end
28
+ it 'should have an accessible target y, based on the constructor argument' do
29
+ @dir.target.y.should == 600
30
+ end
31
+ it 'should have an accessible second control x, based on the constructor argument' do
32
+ @dir.control_2.x.should == 300
33
+ end
34
+ it 'should have an accessible second control y, based on the constructor argument' do
35
+ @dir.control_2.y.should == 400
36
+ end
37
+ context 'when in verbose format' do
38
+ it 'should be constructed with at least target x and y, control 1 x and y, and control 2 x and y parameters' do
39
+ lambda { dir_class.new }.should raise_error
40
+ lambda { dir_class.new 45 }.should raise_error
41
+ lambda { dir_class.new 45, 50 }.should raise_error
42
+ lambda { dir_class.new 45, 50, 60 }.should raise_error
43
+ lambda { dir_class.new 45, 50, 60, 70, 80 }.should raise_error
44
+ lambda { dir_class.new 45, 50, 60, 70, 80, 90 }.should_not raise_error
45
+ lambda { dir_class.new 45, 50, 60, 70, 80, 90, true }.should_not raise_error
46
+ end
47
+ it 'should be relative if constructed with a false seventh parameter' do
48
+ direction = dir_class.new 45, 50, 60, 70, 80, 90, false
49
+ direction.absolute?.should == false
50
+ end
51
+ it 'should be absolute if constructed with a true seventh parameter' do
52
+ direction = dir_class.new 45, 50, 60, 70, 80, 90, true
53
+ direction.absolute?.should == true
54
+ end
55
+ it 'should be absolute if constructed with only six parameters' do
56
+ direction = dir_class.new 45, 50, 60, 70, 80, 90
57
+ direction.absolute?.should == true
58
+ end
59
+ it 'should have an accessible first control x, based on the constructor argument' do
60
+ @dir.control_1.x.should == 100
61
+ end
62
+ it 'should have an accessible first control y, based on the constructor argument' do
63
+ @dir.control_1.y.should == 200
64
+ end
65
+ describe '#to_command' do
66
+ it 'should start with a lower-case c when not absolute' do
67
+ extract_command(CubicCurveTo.new(100,200,300,400,500,600,false).to_command).should == 'c'
68
+ end
69
+ it 'should start with a capital C when absolute' do
70
+ extract_command(@dir.to_command).should == 'C'
71
+ end
72
+ it 'should have exactly 6 numerical parameters' do
73
+ extract_coordinates(@dir.to_command).length.should == 6
74
+ end
75
+ it 'should show the provided first control X value as the first parameter' do
76
+ extract_coordinates(@dir.to_command)[0].should == 100
77
+ end
78
+ it 'should show the provided first control Y value as the second parameter' do
79
+ extract_coordinates(@dir.to_command)[1].should == 200
80
+ end
81
+ it 'should show the provided second control X value as the third parameter' do
82
+ extract_coordinates(@dir.to_command)[2].should == 300
83
+ end
84
+ it 'should show the provided second control Y value as the fourth parameter' do
85
+ extract_coordinates(@dir.to_command)[3].should == 400
86
+ end
87
+ it 'should show the provided target X value as the fifth parameter' do
88
+ extract_coordinates(@dir.to_command)[4].should == 500
89
+ end
90
+ it 'should show the provided target Y value as the sixth parameter' do
91
+ extract_coordinates(@dir.to_command)[5].should == 600
92
+ end
93
+ end
94
+ end
95
+ context 'when in shorthand format' do
96
+ before :each do
97
+ @dir = CubicCurveTo.new(100,200,300,400)
98
+ end
99
+ it 'should be constructed with at least target x and y parameters' do
100
+ lambda { dir_class.new }.should raise_error
101
+ lambda { dir_class.new 45 }.should raise_error
102
+ lambda { dir_class.new 45, 50 }.should raise_error
103
+ lambda { dir_class.new 45, 50, 60 }.should raise_error
104
+ lambda { dir_class.new 45, 50, 60, 70 }.should_not raise_error
105
+ lambda { dir_class.new 45, 50, 60, 70, true }.should_not raise_error
106
+ end
107
+ it 'should be relative if constructed with a false third parameter' do
108
+ direction = dir_class.new 45, 50, 60, 70, false
109
+ direction.absolute?.should == false
110
+ end
111
+ it 'should be absolute if constructed with a true third parameter' do
112
+ direction = dir_class.new 45, 50, 60, 70, true
113
+ direction.absolute?.should == true
114
+ end
115
+ it 'should be absolute if constructed with only two parameters' do
116
+ direction = dir_class.new 45, 50, 60, 70
117
+ direction.absolute?.should == true
118
+ end
119
+ it 'should have an nil first control, based on the constructor argument' do
120
+ @dir.control_1.should == nil
121
+ end
122
+ describe '#to_command' do
123
+ it 'should start with a lower-case s when not absolute' do
124
+ extract_command(CubicCurveTo.new(100,200,300,400,false).to_command).should == 's'
125
+ end
126
+ it 'should start with a capital S when absolute' do
127
+ extract_command(@dir.to_command).should == 'S'
128
+ end
129
+ it 'should have exactly 2 numerical parameters' do
130
+ extract_coordinates(@dir.to_command).length.should == 4
131
+ end
132
+ it 'should show the provided second control X value as the first parameter' do
133
+ extract_coordinates(@dir.to_command)[0].should == 100
134
+ end
135
+ it 'should show the provided second control Y value as the second parameter' do
136
+ extract_coordinates(@dir.to_command)[1].should == 200
137
+ end
138
+ it 'should show the provided target X value as the third parameter' do
139
+ extract_coordinates(@dir.to_command)[2].should == 300
140
+ end
141
+ it 'should show the provided target Y value as the fourth parameter' do
142
+ extract_coordinates(@dir.to_command)[3].should == 400
143
+ end
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,10 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ include Savage::Directions
4
+
5
+ describe HorizontalTo do
6
+ def dir_class; HorizontalTo; end
7
+ def create_relative; HorizontalTo.new(100,false); end
8
+ def command_code; 'h'; end
9
+ it_behaves_like 'CoordinateTarget'
10
+ end
@@ -0,0 +1,14 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ include Savage::Directions
4
+
5
+ describe LineTo do
6
+ def dir_class; LineTo; end
7
+ def create_relative; LineTo.new(100,200,false); end
8
+ def command_code; 'l'; end
9
+ it_behaves_like 'PointTarget'
10
+
11
+ it 'generates commands' do
12
+ LineTo.new(100, 300, true).to_command.should == "L100 300"
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ include Savage::Directions
4
+
5
+ describe MoveTo do
6
+ def dir_class; MoveTo; end
7
+ def create_relative; MoveTo.new(100,200,false); end
8
+ def command_code; 'm'; end
9
+ it_behaves_like 'PointTarget'
10
+ end
@@ -0,0 +1,12 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ include Savage::Directions
4
+
5
+ describe Point do
6
+ it 'should have an x' do
7
+ Point.new.respond_to?(:x).should == true;
8
+ end
9
+ it 'should have an y' do
10
+ Point.new.respond_to?(:y).should == true;
11
+ end
12
+ end
@@ -0,0 +1,123 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ include Savage::Directions
4
+
5
+ describe QuadraticCurveTo do
6
+ def dir_class; QuadraticCurveTo; end
7
+ def create_relative; QuadraticCurveTo.new(100,200,300,400,false); end
8
+ def command_code; 'q'; end
9
+
10
+ before :each do
11
+ @dir = dir_class.new(100,200,300,400)
12
+ end
13
+
14
+ include Command
15
+ it_behaves_like 'Direction'
16
+
17
+ it 'should have a target' do
18
+ @dir.respond_to?(:target).should == true
19
+ @dir.target.class.should == Point
20
+ end
21
+ it 'should have a control point' do
22
+ @dir.respond_to?(:control).should == true
23
+ @dir.control.class.should == Point
24
+ end
25
+ it 'should have an accessible target x, based on the constructor argument' do
26
+ @dir.target.x.should == 300
27
+ end
28
+ it 'should have an accessible target y, based on the constructor argument' do
29
+ @dir.target.y.should == 400
30
+ end
31
+ context 'when in verbose format' do
32
+ it 'should be constructed with at least target x and y and control x and y parameters' do
33
+ lambda { dir_class.new }.should raise_error
34
+ lambda { dir_class.new 45 }.should raise_error
35
+ lambda { dir_class.new 45, 50, 60 }.should raise_error
36
+ lambda { dir_class.new 45, 50, 60, 70 }.should_not raise_error
37
+ lambda { dir_class.new 45, 50, 60, 70, true }.should_not raise_error
38
+ end
39
+ it 'should be relative if constructed with a false fifth parameter' do
40
+ direction = dir_class.new 45, 50, 60, 70, false
41
+ direction.absolute?.should == false
42
+ end
43
+ it 'should be absolute if constructed with a true fifth parameter' do
44
+ direction = dir_class.new 45, 50, 60, 70, true
45
+ direction.absolute?.should == true
46
+ end
47
+ it 'should be absolute if constructed with only four parameters' do
48
+ direction = dir_class.new 45, 50, 60, 70
49
+ direction.absolute?.should == true
50
+ end
51
+ it 'should have an accessible first control x, based on the constructor argument' do
52
+ @dir.control.x.should == 100
53
+ end
54
+ it 'should have an accessible first control y, based on the constructor argument' do
55
+ @dir.control.y.should == 200
56
+ end
57
+ describe '#to_command' do
58
+ it 'should start with a lower-case q when not absolute' do
59
+ extract_command(QuadraticCurveTo.new(100,200,300,400,false).to_command).should == 'q'
60
+ end
61
+ it 'should start with a capital Q when absolute' do
62
+ extract_command(@dir.to_command).should == 'Q'
63
+ end
64
+ it 'should have exactly 4 numerical parameters' do
65
+ extract_coordinates(@dir.to_command).length.should == 4
66
+ end
67
+ it 'should show the provided control X value as the first parameter' do
68
+ extract_coordinates(@dir.to_command)[0].should == 100
69
+ end
70
+ it 'should show the provided control Y value as the second parameter' do
71
+ extract_coordinates(@dir.to_command)[1].should == 200
72
+ end
73
+ it 'should show the provided target X value as the third parameter' do
74
+ extract_coordinates(@dir.to_command)[2].should == 300
75
+ end
76
+ it 'should show the provided target Y value as the fourth parameter' do
77
+ extract_coordinates(@dir.to_command)[3].should == 400
78
+ end
79
+ end
80
+ end
81
+ context 'when in shorthand format' do
82
+ before :each do
83
+ @dir = QuadraticCurveTo.new(100,200)
84
+ end
85
+ it 'should be constructed with at least target x and y parameters' do
86
+ lambda { dir_class.new }.should raise_error
87
+ lambda { dir_class.new 45 }.should raise_error
88
+ lambda { dir_class.new 45, 50 }.should_not raise_error
89
+ end
90
+ it 'should be relative if constructed with a false third parameter' do
91
+ direction = dir_class.new 45, 50, false
92
+ direction.absolute?.should == false
93
+ end
94
+ it 'should be absolute if constructed with a true third parameter' do
95
+ direction = dir_class.new 45, 50, true
96
+ direction.absolute?.should == true
97
+ end
98
+ it 'should be absolute if constructed with only two parameters' do
99
+ direction = dir_class.new 45, 50
100
+ direction.absolute?.should == true
101
+ end
102
+ it 'should have an nil control, based on the constructor argument' do
103
+ @dir.control.should == nil
104
+ end
105
+ describe '#to_command' do
106
+ it 'should start with a lower-case t when not absolute' do
107
+ extract_command(QuadraticCurveTo.new(100,200,false).to_command).should == 't'
108
+ end
109
+ it 'should start with a capital T when absolute' do
110
+ extract_command(@dir.to_command).should == 'T'
111
+ end
112
+ it 'should have exactly 2 numerical parameters' do
113
+ extract_coordinates(@dir.to_command).length.should == 2
114
+ end
115
+ it 'should show the provided target X value as the first parameter' do
116
+ extract_coordinates(@dir.to_command)[0].should == 100
117
+ end
118
+ it 'should show the provided target Y value as the second parameter' do
119
+ extract_coordinates(@dir.to_command)[1].should == 200
120
+ end
121
+ end
122
+ end
123
+ end