motion-ui-geometry 0.5.1
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/.gitignore +20 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +224 -0
- data/Rakefile +20 -0
- data/lib/motion-ui-geometry.rb +9 -0
- data/lib/motion-ui-geometry/cgaffinetransform.rb +141 -0
- data/lib/motion-ui-geometry/cgpoint.rb +142 -0
- data/lib/motion-ui-geometry/cgrect.rb +246 -0
- data/lib/motion-ui-geometry/cgsize.rb +111 -0
- data/lib/motion-ui-geometry/float.rb +42 -0
- data/lib/motion-ui-geometry/nsdictionary.rb +21 -0
- data/lib/motion-ui-geometry/nsstring.rb +17 -0
- data/lib/motion-ui-geometry/spec_app_delegate.rb +7 -0
- data/lib/motion-ui-geometry/version.rb +7 -0
- data/motion-ui-geometry.gemspec +17 -0
- data/spec/cgaffinetransform_spec.rb +272 -0
- data/spec/cgpoint_spec.rb +210 -0
- data/spec/cgrect_spec.rb +352 -0
- data/spec/cgsize_spec.rb +174 -0
- data/spec/float_spec.rb +107 -0
- data/spec/helpers/no_exception_logging.rb +1 -0
- data/spec/nsdictionary_spec.rb +15 -0
- data/spec/nsstring_spec.rb +42 -0
- metadata +84 -0
@@ -0,0 +1,142 @@
|
|
1
|
+
class CGPoint
|
2
|
+
|
3
|
+
def ==(other)
|
4
|
+
other.is_a?(CGPoint) && x == other.x && y == other.y
|
5
|
+
end
|
6
|
+
|
7
|
+
def =~(other)
|
8
|
+
case other
|
9
|
+
when CGPoint
|
10
|
+
x =~ other.x && y =~ other.y
|
11
|
+
when CGSize
|
12
|
+
x =~ other.width && y =~ other.height
|
13
|
+
else
|
14
|
+
raise TypeError, "Right operand for =~ must be "\
|
15
|
+
"CGPoint or CGSize (got #{other})."
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
def +(other)
|
21
|
+
case other
|
22
|
+
when CGPoint
|
23
|
+
CGPointMake x + other.x, y + other.y
|
24
|
+
when CGSize
|
25
|
+
CGPointMake x + other.width, y + other.height
|
26
|
+
else
|
27
|
+
raise TypeError, "Right operand for + must be "\
|
28
|
+
"CGPoint or CGSize (got #{other})."
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def -(other)
|
33
|
+
case other
|
34
|
+
when CGPoint
|
35
|
+
CGPointMake x - other.x, y - other.y
|
36
|
+
when CGSize
|
37
|
+
CGPointMake x - other.width, y - other.height
|
38
|
+
else
|
39
|
+
raise TypeError, "Right operand for - must be "\
|
40
|
+
"CGPoint or CGSize (got #{other})."
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def -@
|
45
|
+
CGPointMake -x, -y
|
46
|
+
end
|
47
|
+
|
48
|
+
def apply(transform)
|
49
|
+
unless transform.is_a? CGAffineTransform
|
50
|
+
raise TypeError, "Parameter must be a CGAffineTransform, got #{transform}."
|
51
|
+
end
|
52
|
+
|
53
|
+
CGPointApplyAffineTransform(self, transform)
|
54
|
+
end
|
55
|
+
|
56
|
+
def *(other)
|
57
|
+
case other
|
58
|
+
when Fixnum, Float
|
59
|
+
CGPointMake(x * other, y * other)
|
60
|
+
when CGPoint
|
61
|
+
CGPointMake(x * other.x, y * other.y)
|
62
|
+
when CGSize
|
63
|
+
CGPointMake(x * other.width, y * other.height)
|
64
|
+
when CGAffineTransform
|
65
|
+
apply other
|
66
|
+
else
|
67
|
+
raise TypeError, "Right operand for * must be "\
|
68
|
+
"Fixnum, Float, CGPoint, CGSize or CGAffineTransform "\
|
69
|
+
"(got #{other})."
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def /(other)
|
74
|
+
case other
|
75
|
+
when Fixnum, Float
|
76
|
+
CGPointMake(x / other, y / other)
|
77
|
+
when CGPoint
|
78
|
+
CGPointMake(x / other.x, y / other.y)
|
79
|
+
when CGSize
|
80
|
+
CGPointMake(x / other.width, y / other.height)
|
81
|
+
when CGAffineTransform
|
82
|
+
apply self.invert
|
83
|
+
else
|
84
|
+
raise TypeError, "Right operand for / must be "\
|
85
|
+
"Fixnum, Float, CGPoint, CGSize or CGAffineTransform "\
|
86
|
+
"(got #{other})"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
def round
|
92
|
+
CGPointMake x.round, y.round
|
93
|
+
end
|
94
|
+
|
95
|
+
def floor
|
96
|
+
CGPointMake x.floor, y.floor
|
97
|
+
end
|
98
|
+
|
99
|
+
def distance_to(other)
|
100
|
+
unless other.is_a? CGPoint
|
101
|
+
raise TypeError, "Parameter must be a CGPoint, got #{other}."
|
102
|
+
end
|
103
|
+
|
104
|
+
dist_x = x - other.x
|
105
|
+
dist_y = y - other.y
|
106
|
+
|
107
|
+
Math.sqrt(dist_x ** 2 + dist_y ** 2).abs
|
108
|
+
end
|
109
|
+
|
110
|
+
def clamp_to_rect(rect)
|
111
|
+
unless rect.is_a? CGRect
|
112
|
+
raise TypeError, "Parameter must be a CGRect, got #{rect}."
|
113
|
+
end
|
114
|
+
|
115
|
+
p = CGPoint.new
|
116
|
+
p.x = x.clamp(rect.origin.x, rect.origin.x + rect.size.width)
|
117
|
+
p.y = y.clamp(rect.origin.y, rect.origin.y + rect.size.height)
|
118
|
+
p
|
119
|
+
end
|
120
|
+
|
121
|
+
def angle
|
122
|
+
Math.atan2 y, x
|
123
|
+
end
|
124
|
+
|
125
|
+
def to_size
|
126
|
+
CGSizeMake x, y
|
127
|
+
end
|
128
|
+
|
129
|
+
def to_dictionary
|
130
|
+
CGPointCreateDictionaryRepresentation self
|
131
|
+
end
|
132
|
+
|
133
|
+
def to_value
|
134
|
+
NSValue.valueWithCGPoint self
|
135
|
+
end
|
136
|
+
|
137
|
+
def to_s
|
138
|
+
NSStringFromCGPoint self
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
end
|
@@ -0,0 +1,246 @@
|
|
1
|
+
class CGRect
|
2
|
+
|
3
|
+
def initialize(origin = nil, size = nil)
|
4
|
+
if origin.nil? || size.nil?
|
5
|
+
raise ArgumentError, "Can't initialize CGRect without given origin and size."
|
6
|
+
end
|
7
|
+
|
8
|
+
unless origin.is_a?(CGPoint)
|
9
|
+
raise TypeError, "origin must be given as CGPoint."
|
10
|
+
end
|
11
|
+
|
12
|
+
unless size.is_a?(CGSize)
|
13
|
+
raise TypeError, "size must be given as CGSize."
|
14
|
+
end
|
15
|
+
|
16
|
+
self.origin = origin
|
17
|
+
self.size = size
|
18
|
+
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
def ==(other)
|
24
|
+
other.is_a?(CGRect) &&
|
25
|
+
origin.x == other.origin.x &&
|
26
|
+
origin.y == other.origin.y &&
|
27
|
+
size.width == other.size.width &&
|
28
|
+
size.height == other.size.height
|
29
|
+
end
|
30
|
+
|
31
|
+
def roughly_equal?(other, epsilon = Float::EPSILON)
|
32
|
+
unless other.is_a? CGRect
|
33
|
+
raise TypeError, "Right operand for =~ must be a CGRect (got #{other})."
|
34
|
+
end
|
35
|
+
|
36
|
+
origin.x.roughly_equal?(other.origin.x, epsilon) &&
|
37
|
+
origin.y.roughly_equal?(other.origin.y, epsilon) &&
|
38
|
+
size.width.roughly_equal?(other.size.width, epsilon) &&
|
39
|
+
size.height.roughly_equal?(other.size.height, epsilon)
|
40
|
+
end
|
41
|
+
|
42
|
+
def =~(other)
|
43
|
+
roughly_equal?(other)
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
def +(other)
|
48
|
+
case other
|
49
|
+
when CGPoint
|
50
|
+
CGRect.new origin + other, size
|
51
|
+
when CGSize
|
52
|
+
CGRect.new origin, size + other
|
53
|
+
else
|
54
|
+
raise TypeError, "Right operand for + and - must be a "\
|
55
|
+
"CGPoint or a CGRect (got #{other.class})."
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def -(other)
|
60
|
+
self + (-other)
|
61
|
+
end
|
62
|
+
|
63
|
+
def -@
|
64
|
+
CGRectMake -origin.x, -origin.y, -size.width, -size.height
|
65
|
+
end
|
66
|
+
|
67
|
+
def *(other)
|
68
|
+
case other
|
69
|
+
when Fixnum, Float
|
70
|
+
CGRectMake origin.x * other, origin.y * other,
|
71
|
+
size.width * other, size.height * other
|
72
|
+
when CGSize
|
73
|
+
CGRectMake origin.x * other.width, origin.y * other.height,
|
74
|
+
size.width * other.width, size.height * other.height
|
75
|
+
when CGPoint
|
76
|
+
CGRectMake origin.x * other.x, origin.y * other.y,
|
77
|
+
size.width * other.x, size.height * other.y
|
78
|
+
when CGAffineTransform
|
79
|
+
CGRectApplyAffineTransform self, other
|
80
|
+
else
|
81
|
+
raise TypeError, "Right operand for * must be Fixnum, "\
|
82
|
+
"Float, Array, CGPoint, CGSize or CGAffineTransform "\
|
83
|
+
"(got #{other.class})."
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def /(other)
|
88
|
+
case other
|
89
|
+
when Float
|
90
|
+
CGRectMake origin.x / other, origin.y / other,
|
91
|
+
size.width / other, size.height / other
|
92
|
+
when CGSize
|
93
|
+
CGRectMake origin.x / other.width, origin.y / other.height,
|
94
|
+
size.width / other.width, size.height / other.height
|
95
|
+
when CGPoint
|
96
|
+
CGRectMake origin.x / other.x, origin.y / other.y,
|
97
|
+
size.width / other.x, size.height / other.y
|
98
|
+
when CGAffineTransform
|
99
|
+
CGRectApplyAffineTransform self, other.inverse
|
100
|
+
else
|
101
|
+
raise TypeError, "Right operand for / must be Float, "\
|
102
|
+
"CGPoint, CGSize or CGAffineTransform (got #{other.class})."
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
def &(other)
|
108
|
+
intersection(other)
|
109
|
+
end
|
110
|
+
|
111
|
+
def |(other)
|
112
|
+
union(other)
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
def round
|
117
|
+
CGRect.new origin.round, size.round
|
118
|
+
end
|
119
|
+
|
120
|
+
def floor
|
121
|
+
CGRect.new origin.floor, size.floor
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
|
126
|
+
def inset(dx, dy)
|
127
|
+
CGRectInset self, dx, dy
|
128
|
+
end
|
129
|
+
|
130
|
+
def outset(dx, dy)
|
131
|
+
inset -dx, -dy
|
132
|
+
end
|
133
|
+
|
134
|
+
def union(rect)
|
135
|
+
unless rect.is_a? CGRect
|
136
|
+
raise TypeError, "Parameter must be a CGRect, got #{rect}."
|
137
|
+
end
|
138
|
+
|
139
|
+
CGRectUnion self, rect
|
140
|
+
end
|
141
|
+
alias :unionize :union
|
142
|
+
|
143
|
+
def intersection(rect)
|
144
|
+
unless rect.is_a? CGRect
|
145
|
+
raise TypeError, "Parameter must be a CGRect, got #{rect}."
|
146
|
+
end
|
147
|
+
|
148
|
+
CGRectIntersection self, rect
|
149
|
+
end
|
150
|
+
alias :intersect :intersection
|
151
|
+
|
152
|
+
def division(amount, edge = :left)
|
153
|
+
unless amount.is_a?(Float) || amount.is_a?(Fixnum)
|
154
|
+
raise ArgumentError, "amount must be given as Float or Fixnum, got #{amount}."
|
155
|
+
end
|
156
|
+
|
157
|
+
unless [:left, :right, :top, :bottom].include? edge
|
158
|
+
raise ArgumentError, "edge must be :left, :right, :top, or :bottom (got #{edge})."
|
159
|
+
end
|
160
|
+
|
161
|
+
slice = Pointer.new(CGRect.type)
|
162
|
+
remainder = Pointer.new(CGRect.type)
|
163
|
+
|
164
|
+
edge = case edge
|
165
|
+
when :left then CGRectMinXEdge
|
166
|
+
when :right then CGRectMaxXEdge
|
167
|
+
when :top then CGRectMinYEdge
|
168
|
+
when :bottom then CGRectMaxYEdge
|
169
|
+
end
|
170
|
+
|
171
|
+
CGRectDivide self, slice, remainder, amount, edge
|
172
|
+
|
173
|
+
[slice[0], remainder[0]]
|
174
|
+
end
|
175
|
+
alias :divide :division
|
176
|
+
|
177
|
+
def intersect?(other)
|
178
|
+
unless other.is_a? CGRect
|
179
|
+
raise TypeError, "Parameter must be a CGRect, got #{other}."
|
180
|
+
end
|
181
|
+
|
182
|
+
CGRectIntersectsRect self, other
|
183
|
+
end
|
184
|
+
|
185
|
+
def contain?(point_or_rect)
|
186
|
+
case point_or_rect
|
187
|
+
when CGPoint then CGRectContainsPoint self, point_or_rect
|
188
|
+
when CGRect then CGRectContainsRect self, point_or_rect
|
189
|
+
else raise TypeError, "Parameter must be a CGPoint or CGRect, got #{point_or_rect}."
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def empty?
|
194
|
+
CGRectIsEmpty self
|
195
|
+
end
|
196
|
+
|
197
|
+
def null?
|
198
|
+
CGRectIsNull self
|
199
|
+
end
|
200
|
+
|
201
|
+
# TODO: Does not work with CGRectInfinite, but should do so.
|
202
|
+
# def infinite?
|
203
|
+
# CGRectIsInfinite self
|
204
|
+
# end
|
205
|
+
|
206
|
+
|
207
|
+
def apply(transform)
|
208
|
+
CGRectApplyAffineTransform(self, transform)
|
209
|
+
end
|
210
|
+
|
211
|
+
|
212
|
+
def center
|
213
|
+
origin + size * 0.5
|
214
|
+
end
|
215
|
+
|
216
|
+
def top_left
|
217
|
+
origin
|
218
|
+
end
|
219
|
+
|
220
|
+
def bottom_left
|
221
|
+
CGPointMake(origin.x, origin.y + size.height)
|
222
|
+
end
|
223
|
+
|
224
|
+
def bottom_right
|
225
|
+
origin + size
|
226
|
+
end
|
227
|
+
|
228
|
+
def top_right
|
229
|
+
CGPointMake(origin.x + size.width, origin.y)
|
230
|
+
end
|
231
|
+
|
232
|
+
|
233
|
+
def to_dictionary
|
234
|
+
CGRectCreateDictionaryRepresentation self
|
235
|
+
end
|
236
|
+
|
237
|
+
def to_value
|
238
|
+
NSValue.valueWithCGRect self
|
239
|
+
end
|
240
|
+
|
241
|
+
def to_s
|
242
|
+
NSStringFromCGRect self
|
243
|
+
end
|
244
|
+
|
245
|
+
|
246
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
class CGSize
|
2
|
+
|
3
|
+
def ==(other)
|
4
|
+
other.is_a?(CGSize) && width == other.width && height == other.height
|
5
|
+
end
|
6
|
+
|
7
|
+
def =~(other)
|
8
|
+
case other
|
9
|
+
when CGPoint
|
10
|
+
width =~ other.x && height =~ other.y
|
11
|
+
when CGSize
|
12
|
+
width =~ other.width && height =~ other.height
|
13
|
+
else
|
14
|
+
raise TypeError, "Right operand for =~ must be CGPoint or CGSize. (got #{other.class})"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def +(other)
|
19
|
+
case other
|
20
|
+
when CGSize
|
21
|
+
CGSizeMake width + other.width, height + other.height
|
22
|
+
when CGPoint
|
23
|
+
CGSizeMake width + other.x, height + other.y
|
24
|
+
else
|
25
|
+
raise TypeError, "Right operand for + must be CGSize or CGPoint (got #{other.class})"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def -(other)
|
30
|
+
case other
|
31
|
+
when CGSize
|
32
|
+
CGSizeMake width - other.width, height - other.height
|
33
|
+
when CGPoint
|
34
|
+
CGSizeMake width - other.x, height - other.y
|
35
|
+
else
|
36
|
+
raise TypeError, "Right operand for - must be CGSize or CGPoint (got #{other.class})"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def -@
|
41
|
+
CGSizeMake -width, -height
|
42
|
+
end
|
43
|
+
|
44
|
+
def *(other)
|
45
|
+
case other
|
46
|
+
when Fixnum, Float
|
47
|
+
CGSizeMake other * width, other * height
|
48
|
+
when CGSize
|
49
|
+
CGSizeMake width * other.width, height * other.height
|
50
|
+
when CGPoint
|
51
|
+
CGSizeMake width * other.x, height * other.y
|
52
|
+
when CGAffineTransform
|
53
|
+
CGSizeApplyAffineTransform self, other
|
54
|
+
else
|
55
|
+
raise TypeError, "Right operand for * must be a Fixnum, Float, "\
|
56
|
+
"CGSize, CGPoint, or CGAffineTransform (got #{other.class})"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def /(other)
|
61
|
+
case other
|
62
|
+
when Float
|
63
|
+
CGSizeMake other / width, other / height
|
64
|
+
when CGSize
|
65
|
+
CGSizeMake width / other.width, height / other.height
|
66
|
+
when CGPoint
|
67
|
+
CGSizeMake width / other.x, height / other.y
|
68
|
+
when CGAffineTransform
|
69
|
+
CGSizeApplyAffineTransform self, other.inverse
|
70
|
+
else
|
71
|
+
raise TypeError, "Right operand for / must be a Float, "\
|
72
|
+
"CGSize, CGPoint, or CGAffineTransform (got #{other.class})"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
def round
|
78
|
+
CGSizeMake width.round, height.round
|
79
|
+
end
|
80
|
+
|
81
|
+
def floor
|
82
|
+
CGSizeMake width.floor, height.floor
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
def apply(transform)
|
87
|
+
CGSizeApplyAffineTransform(self, transform)
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
def to_point
|
92
|
+
CGPointMake width, height
|
93
|
+
end
|
94
|
+
|
95
|
+
def to_rect
|
96
|
+
CGRect.new CGPointZero, self
|
97
|
+
end
|
98
|
+
|
99
|
+
def to_dictionary
|
100
|
+
CGSizeCreateDictionaryRepresentation self
|
101
|
+
end
|
102
|
+
|
103
|
+
def to_value
|
104
|
+
NSValue.valueWithCGSize self
|
105
|
+
end
|
106
|
+
|
107
|
+
def to_s
|
108
|
+
NSStringFromCGSize self
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|