1 // ========================================================================== 2 // Project: SproutCore - JavaScript Application Framework 3 // Copyright: ©2006-2011 Strobe Inc. and contributors. 4 // ©2008-2011 Apple Inc. All rights reserved. 5 // License: Licensed under MIT license (see license.js) 6 // ========================================================================== 7 SC.mixin( /** @scope SC */ { 8 /** A Point at {0,0} */ 9 ZERO_POINT: { x: 0, y: 0 }, 10 11 /** Check if the given point is inside the rect. */ 12 pointInRect: function(point, f) { 13 return (point.x >= SC.minX(f)) && 14 (point.y >= SC.minY(f)) && 15 (point.x <= SC.maxX(f)) && 16 (point.y <= SC.maxY(f)) ; 17 }, 18 19 /** Return true if the two frames match. You can also pass only points or sizes. 20 21 @param r1 {Rect} the first rect 22 @param r2 {Rect} the second rect 23 @param delta {Float} an optional delta that allows for rects that do not match exactly. Defaults to 0.1 24 @returns {Boolean} true if rects match 25 */ 26 rectsEqual: function(r1, r2, delta) { 27 if (!r1 || !r2) return (r1 == r2) ; 28 if (!delta && delta !== 0) delta = 0.1; 29 if ((r1.y != r2.y) && (Math.abs(r1.y - r2.y) > delta)) return NO ; 30 if ((r1.x != r2.x) && (Math.abs(r1.x - r2.x) > delta)) return NO ; 31 if ((r1.width != r2.width) && (Math.abs(r1.width - r2.width) > delta)) return NO ; 32 if ((r1.height != r2.height) && (Math.abs(r1.height - r2.height) > delta)) return NO ; 33 return YES ; 34 }, 35 36 /** Returns the insersection between two rectangles. 37 38 @param r1 {Rect} The first rect 39 @param r2 {Rect} the second rect 40 @returns {Rect} the intersection rect. width || height will be 0 if they do not interset. 41 */ 42 intersectRects: function(r1, r2) { 43 // find all four edges 44 var ret = { 45 x: Math.max(SC.minX(r1), SC.minX(r2)), 46 y: Math.max(SC.minY(r1), SC.minY(r2)), 47 width: Math.min(SC.maxX(r1), SC.maxX(r2)), 48 height: Math.min(SC.maxY(r1), SC.maxY(r2)) 49 } ; 50 51 // convert edges to w/h 52 ret.width = Math.max(0, ret.width - ret.x) ; 53 ret.height = Math.max(0, ret.height - ret.y) ; 54 return ret ; 55 }, 56 57 /** Returns the union between two rectangles 58 59 @param r1 {Rect} The first rect 60 @param r2 {Rect} The second rect 61 @returns {Rect} The union rect. 62 */ 63 unionRects: function(r1, r2) { 64 // find all four edges 65 var ret = { 66 x: Math.min(SC.minX(r1), SC.minX(r2)), 67 y: Math.min(SC.minY(r1), SC.minY(r2)), 68 width: Math.max(SC.maxX(r1), SC.maxX(r2)), 69 height: Math.max(SC.maxY(r1), SC.maxY(r2)) 70 } ; 71 72 // convert edges to w/h 73 ret.width = Math.max(0, ret.width - ret.x) ; 74 ret.height = Math.max(0, ret.height - ret.y) ; 75 return ret ; 76 }, 77 78 /** 79 Returns a copy of the passed rect, scaled by the specified scale, centered on the specified origin. 80 81 @param {Rect} rect The rectangle to scale. 82 @param {Number|Array|Hash} scale The scale (or [scaleX, scaleY], or { x: scaleX, y: scaleY}) to apply. Defaults to 1. 83 @param {Number} originX The horizontal scale origin. Defaults to 0.5 (center). 84 @param {Number} originY The vertical scale origin. Defaults to 0.5 (center). 85 @returns {Rect} The scaled rect. 86 */ 87 scaleRect: function(rect, scale, originX, originY) { 88 // Defaults 89 if (scale == null) scale = 1; 90 if (originX == null) originX = 0.5; 91 if (originY == null) originY = 0.5; 92 93 // Gatekeep: Identity scale. 94 if (scale === 1) return SC.cloneRect(rect); 95 96 // Unpack scale. 97 var scaleX, scaleY; 98 switch (SC.typeOf(scale)) { 99 case SC.T_ARRAY: 100 scaleX = scale[0]; 101 scaleY = scale[1]; 102 break; 103 case SC.T_HASH: 104 scaleX = scale.x; 105 scaleY = scale.y; 106 break; 107 default: 108 scaleX = scale; 109 scaleY = scale; 110 break; 111 } 112 113 var scaledHeight = rect.height * scaleY, 114 scaledWidth = rect.width * scaleX, 115 dHeight = scaledHeight - rect.height, 116 dWidth = scaledWidth - rect.width; 117 118 // X and Y positions change depending on the origin of the scale. For example, if the 119 // width scales down ten pixels and the origin is 50%, x will move five pixesl (10 * 0.5) 120 // to the right. 121 var scaledX = rect.x - (dWidth * originX), 122 scaledY = rect.y - (dHeight * originY); 123 124 return { 125 height: scaledHeight, 126 width: scaledWidth, 127 x: scaledX, 128 y: scaledY 129 }; 130 }, 131 132 /** 133 Duplicates the passed rect. 134 135 This is faster than Object.clone(). 136 137 @param r {Rect} The rect to clone. 138 @returns {Rect} The cloned rect 139 */ 140 cloneRect: function(r) { 141 return { x: r.x, y: r.y, width: r.width, height: r.height } ; 142 }, 143 144 /** Returns a string representation of the rect as {x, y, width, height}. 145 146 @param r {Rect} The rect to stringify. 147 @returns {String} A string representation of the rect. 148 */ 149 stringFromRect: function(r) { 150 if (!r) { 151 return "(null)"; 152 } 153 else { 154 return '{ x:'+r.x+', y:'+r.y+', width:'+r.width+', height:'+r.height+' }'; 155 } 156 } 157 158 159 }); 160