@@ -237,11 +237,173 @@ extension CGRect {
237
237
y: - CGFloat. greatestFiniteMagnitude / 2 ,
238
238
width: CGFloat . greatestFiniteMagnitude,
239
239
height: CGFloat . greatestFiniteMagnitude)
240
+
241
+ public var width : CGFloat { return abs ( self . size. width) }
242
+ public var height : CGFloat { return abs ( self . size. height) }
243
+
244
+ public var minX : CGFloat { return self . origin. x + min( self . size. width, 0 ) }
245
+ public var midX : CGFloat { return ( self . minX + self . maxX) * 0.5 }
246
+ public var maxX : CGFloat { return self . origin. x + max( self . size. width, 0 ) }
247
+
248
+ public var minY : CGFloat { return self . origin. y + min( self . size. height, 0 ) }
249
+ public var midY : CGFloat { return ( self . minY + self . maxY) * 0.5 }
250
+ public var maxY : CGFloat { return self . origin. y + max( self . size. height, 0 ) }
251
+
252
+ public var isEmpty : Bool { return self . isNull || self . size. width == 0 || self . size. height == 0 }
253
+ public var isInfinite : Bool { return self == . infinite }
254
+ public var isNull : Bool { return self . origin. x == . infinity || self . origin. y == . infinity }
255
+
256
+ public func contains( _ point: CGPoint ) -> Bool {
257
+ if self . isNull || self . isEmpty { return false }
258
+
259
+ return ( self . minX..< self . maxX) . contains ( point. x) && ( self . minY..< self . maxY) . contains ( point. y)
260
+ }
261
+
262
+ public func contains( _ rect2: CGRect ) -> Bool {
263
+ return self . union ( rect2) == self
264
+ }
265
+
266
+ public var standardized : CGRect {
267
+ if self . isNull { return . null }
268
+
269
+ return CGRect ( x: self . minX,
270
+ y: self . minY,
271
+ width: self . width,
272
+ height: self . height)
273
+ }
274
+
275
+ public var integral : CGRect {
276
+ if self . isNull { return self }
277
+
278
+ let standardized = self . standardized
279
+ let x = standardized. origin. x. rounded ( . down)
280
+ let y = standardized. origin. y. rounded ( . down)
281
+ let width = ( standardized. origin. x + standardized. size. width) . rounded ( . up) - x
282
+ let height = ( standardized. origin. y + standardized. size. height) . rounded ( . up) - y
283
+ return CGRect ( x: x, y: y, width: width, height: height)
284
+ }
285
+
286
+ public func insetBy( dx: CGFloat , dy: CGFloat ) -> CGRect {
287
+ if self . isNull { return self }
288
+
289
+ var rect = self . standardized
290
+
291
+ rect. origin. x += dx
292
+ rect. origin. y += dy
293
+ rect. size. width -= 2 * dx
294
+ rect. size. height -= 2 * dy
295
+
296
+ if rect. size. width < 0 || rect. size. height < 0 {
297
+ return . null
298
+ }
299
+
300
+ return rect
301
+ }
302
+
303
+ public func union( _ r2: CGRect ) -> CGRect {
304
+ if self . isNull {
305
+ return r2
306
+ }
307
+ else if r2. isNull {
308
+ return self
309
+ }
310
+
311
+ let rect1 = self . standardized
312
+ let rect2 = r2. standardized
313
+
314
+ let minX = min ( rect1. minX, rect2. minX)
315
+ let minY = min ( rect1. minY, rect2. minY)
316
+ let maxX = max ( rect1. maxX, rect2. maxX)
317
+ let maxY = max ( rect1. maxY, rect2. maxY)
318
+
319
+ return CGRect ( x: minX,
320
+ y: minY,
321
+ width: maxX - minX,
322
+ height: maxY - minY)
323
+ }
324
+
325
+ public func intersection( _ r2: CGRect ) -> CGRect {
326
+ if self . isNull || r2. isNull { return . null }
327
+
328
+ let rect1 = self . standardized
329
+ let rect2 = r2. standardized
330
+
331
+ let rect1SpanH = rect1. minX... rect1. maxX
332
+ let rect1SpanV = rect1. minY... rect1. maxY
333
+
334
+ let rect2SpanH = rect2. minX... rect2. maxX
335
+ let rect2SpanV = rect2. minY... rect2. maxY
336
+
337
+ if !rect1SpanH. overlaps ( rect2SpanH) || !rect1SpanV. overlaps ( rect2SpanV) {
338
+ return . null
339
+ }
340
+
341
+ let overlapH = rect1SpanH. clamped ( to: rect2SpanH)
342
+ let overlapV = rect1SpanV. clamped ( to: rect2SpanV)
343
+
344
+ return CGRect ( x: overlapH. lowerBound,
345
+ y: overlapV. lowerBound,
346
+ width: overlapH. upperBound - overlapH. lowerBound,
347
+ height: overlapV. upperBound - overlapV. lowerBound)
348
+ }
349
+
350
+ public func intersects( _ r2: CGRect ) -> Bool {
351
+ return !self . intersection ( r2) . isNull
352
+ }
353
+
354
+ public func offsetBy( dx: CGFloat , dy: CGFloat ) -> CGRect {
355
+ if self . isNull { return self }
356
+
357
+ var rect = self . standardized
358
+ rect. origin. x += dx
359
+ rect. origin. y += dy
360
+ return rect
361
+ }
362
+
363
+ public func divided( atDistance: CGFloat , from fromEdge: CGRectEdge ) -> ( slice: CGRect , remainder: CGRect ) {
364
+ if self . isNull { return ( . null, . null) }
365
+
366
+ let splitLocation : CGFloat
367
+ switch fromEdge {
368
+ case . minXEdge: splitLocation = min ( max ( atDistance, 0 ) , self . width)
369
+ case . maxXEdge: splitLocation = min ( max ( self . width - atDistance, 0 ) , self . width)
370
+ case . minYEdge: splitLocation = min ( max ( atDistance, 0 ) , self . height)
371
+ case . maxYEdge: splitLocation = min ( max ( self . height - atDistance, 0 ) , self . height)
372
+ }
373
+
374
+ let rect = self . standardized
375
+ var rect1 = rect
376
+ var rect2 = rect
377
+
378
+ switch fromEdge {
379
+ case . minXEdge: fallthrough
380
+ case . maxXEdge:
381
+ rect1. size. width = splitLocation
382
+ rect2. origin. x = rect1. maxX
383
+ rect2. size. width = rect. width - splitLocation
384
+ case . minYEdge: fallthrough
385
+ case . maxYEdge:
386
+ rect1. size. height = splitLocation
387
+ rect2. origin. y = rect1. maxY
388
+ rect2. size. height = rect. height - splitLocation
389
+ }
390
+
391
+ switch fromEdge {
392
+ case . minXEdge: fallthrough
393
+ case . minYEdge: return ( rect1, rect2)
394
+ case . maxXEdge: fallthrough
395
+ case . maxYEdge: return ( rect2, rect1)
396
+ }
397
+ }
240
398
}
241
399
242
400
extension CGRect : Equatable {
243
401
public static func == ( lhs: CGRect , rhs: CGRect ) -> Bool {
244
- return lhs. origin == rhs. origin && lhs. size == rhs. size
402
+ if lhs. isNull && rhs. isNull { return true }
403
+
404
+ let r1 = lhs. standardized
405
+ let r2 = rhs. standardized
406
+ return r1. origin == r2. origin && r1. size == r2. size
245
407
}
246
408
}
247
409
0 commit comments