comparison client/digitallibrary/jquery/dlGeometry.js @ 734:7773ccc93729 jquery

image-drag now with full background image :-) if your browser supports background-size. and some cleanups.
author robcast
date Wed, 02 Feb 2011 20:03:36 +0100
parents 3a7fbdc39f6c
children
comparison
equal deleted inserted replaced
733:f4f7a4b9b49d 734:7773ccc93729
1 /* digilib geometry classes 1 /* digilib geometry classes
2 * should be integrated into jquery.digilib.js 2 * should be integrated into jquery.digilib.js
3 */ 3 */
4 4
5 var dlGeometry = function() { 5 var dlGeometry = function() {
6 /* 6 /*
7 * Size class 7 * Size class
8 */ 8 */
9 var size = function (w, h) { 9 var size = function(w, h) {
10 var that = { 10 var that;
11 width : parseFloat(w), 11 if (typeof w === "object") {
12 height : parseFloat(h) 12 // assume its size
13 }; 13 that = {
14 that.equals = function(other) { 14 width : w.width,
15 return (this.width === other.width && this.height === other.height); 15 height : w.height
16 }; 16 };
17 that.toString = function() { 17 } else {
18 return (this.width + "x" + this.height); 18 that = {
19 }; 19 width : parseFloat(w),
20 return that; 20 height : parseFloat(h)
21 }; 21 };
22 22 }
23 /* 23 that.equals = function(other) {
24 * Position class 24 return (this.width === other.width && this.height === other.height);
25 */ 25 };
26 var position = function (x, y) { 26 that.toString = function() {
27 if (typeof x === "object") { 27 return (this.width + "x" + this.height);
28 if (x instanceof jQuery) { 28 };
29 // jQuery object 29 return that;
30 var pos = x.offset(); 30 };
31 var that = { 31
32 x : pos.left, 32 /*
33 y : pos.top 33 * Position class
34 }; 34 */
35 } else { 35 var position = function(x, y) {
36 // event object(?) 36 var that;
37 var that = { 37 if (typeof x === "object") {
38 x : x.pageX, 38 if (x instanceof jQuery) {
39 y : x.pageY 39 // jQuery object
40 var pos = x.offset();
41 that = {
42 x : pos.left,
43 y : pos.top
44 };
45 } else {
46 if (x.x != null) {
47 // position object
48 that = {
49 x : x.x,
50 y : x.y
40 }; 51 };
41 } 52 }
42 } else { 53 if (x.pageX != null) {
43 var that = { 54 // event object
44 x : parseFloat(x),
45 y : parseFloat(y)
46 };
47 }
48 that.equals = function (other) {
49 return (this.x === other.x && this.y === other.y);
50 };
51 // add position other to this
52 that.add = function (other) {
53 this.x += other.x;
54 this.y += other.y;
55 return this;
56 };
57 // returns new position that is the difference between this and other
58 that.delta = function (other) {
59 return position(other.x - this.x, other.y - this.y);
60 };
61 // adjusts position $elem to this position
62 that.adjustDiv = function ($elem) {
63 $elem.offset({left : this.x, top : this.y});
64 };
65 // returns distance of this position to pos (length if pos == null)
66 that.distance = function (pos) {
67 if (pos == null) {
68 pos = {x : 0, y : 0};
69 }
70 var dx = pos.x - this.x;
71 var dy = pos.y - this.y;
72 return Math.sqrt(dx * dx + dy * dy);
73 };
74 that.toString = function() {
75 return (this.x + "," + this.y);
76 };
77 return that;
78 };
79 /*
80 * Rectangle class
81 */
82 var rectangle = function (x, y, w, h) {
83 var that = {};
84 if (typeof x === "object") {
85 if (x instanceof jQuery) {
86 // jQuery object
87 var pos = x.offset();
88 that = { 55 that = {
89 x : pos.left, 56 x : x.pageX,
90 y : pos.top, 57 y : x.pageY
91 width : x.width(),
92 height : x.height()
93 };
94 } else {
95 // assume x and y are Position
96 that = {
97 x : Math.min(x.x, y.x),
98 y : Math.min(x.y, y.y),
99 width : Math.abs(y.x - x.x),
100 height : Math.abs(y.y - x.y)
101 }; 58 };
102 } 59 }
60 }
61 } else {
62 that = {
63 x : parseFloat(x),
64 y : parseFloat(y)
65 };
66 }
67 that.equals = function(other) {
68 return (this.x === other.x && this.y === other.y);
69 };
70 // add position other to this
71 that.add = function(other) {
72 this.x += other.x;
73 this.y += other.y;
74 return this;
75 };
76 // returns negative position
77 that.neg = function() {
78 return position({
79 x : -this.x,
80 y : -this.y
81 });
82 };
83 // returns new position that is the difference between this and other
84 that.delta = function(other) {
85 return position({
86 x : other.x - this.x,
87 y : other.y - this.y
88 });
89 };
90 // adjusts position $elem to this position
91 that.adjustDiv = function($elem) {
92 $elem.offset({
93 left : this.x,
94 top : this.y
95 });
96 };
97 // returns distance of this position to pos (length if pos == null)
98 that.distance = function(pos) {
99 if (pos == null) {
100 pos = {
101 x : 0,
102 y : 0
103 };
104 }
105 var dx = pos.x - this.x;
106 var dy = pos.y - this.y;
107 return Math.sqrt(dx * dx + dy * dy);
108 };
109 that.toString = function() {
110 return (this.x + "," + this.y);
111 };
112 return that;
113 };
114 /*
115 * Rectangle class
116 */
117 var rectangle = function(x, y, w, h) {
118 var that = {};
119 if (typeof x === "object") {
120 if (x instanceof jQuery) {
121 // jQuery object
122 var pos = x.offset();
123 that = {
124 x : pos.left,
125 y : pos.top,
126 width : x.width(),
127 height : x.height()
128 };
129 } else if (y == null) {
130 // assume x is rectangle
131 that = {
132 x : x.x,
133 y : x.y,
134 width : x.width,
135 height : x.height
136 };
103 } else { 137 } else {
138 // assume x and y are Position
104 that = { 139 that = {
105 x : parseFloat(x), 140 x : Math.min(x.x, y.x),
106 y : parseFloat(y), 141 y : Math.min(x.y, y.y),
107 width : parseFloat(w), 142 width : Math.abs(y.x - x.x),
108 height : parseFloat(h) 143 height : Math.abs(y.y - x.y)
109 }; 144 };
110 } 145 }
111 // returns a copy of this Rectangle 146 } else {
112 that.copy = function() { 147 that = {
113 return rectangle(this.x, this.y, this.width, this.height); 148 x : parseFloat(x),
114 }; 149 y : parseFloat(y),
115 // returns the position of this Rectangle 150 width : parseFloat(w),
116 that.getPosition = function() { 151 height : parseFloat(h)
117 return position(this.x, this.y); 152 };
118 }; 153 }
119 // returns the upper left corner position 154 // returns a copy of this Rectangle
120 that.getPt1 = that.getPosition; 155 that.copy = function() {
121 // returns the lower right corner position of this Rectangle 156 return rectangle(this);
122 that.getPt2 = function() { 157 };
123 return position(this.x + this.width, this.y + this.height); 158 // returns the position of this Rectangle
124 }; 159 that.getPosition = function() {
125 // sets the upper left corner position to pos 160 return position(this);
126 that.setPosition = function(pos) { 161 };
127 this.x = pos.x; 162 // returns the size of this Rectangle
128 this.y = pos.y; 163 that.getSize = function() {
129 return this; 164 return size(this);
130 }; 165 };
131 that.setPt1 = that.setPosition; // TODO: not really the same 166 // returns the upper left corner position
132 // adds pos to the position 167 that.getPt1 = that.getPosition;
133 that.addPosition = function(pos) { 168 // returns the lower right corner position of this Rectangle
134 this.x += pos.x; 169 that.getPt2 = function() {
135 this.y += pos.y; 170 return position({
136 return this; 171 x : this.x + this.width,
137 }; 172 y : this.y + this.height
138 // sets the lower right corner to position pos 173 });
139 that.setPt2 = function(pos) { 174 };
140 this.width = pos.x - this.x; 175 // sets the upper left corner position to pos
141 this.height = pos.y - this.y; 176 that.setPosition = function(pos) {
142 return this; 177 this.x = pos.x;
143 }; 178 this.y = pos.y;
144 // returns the center position of this Rectangle 179 return this;
145 that.getCenter = function() { 180 };
146 return position(this.x + this.width / 2, this.y + this.height / 2); 181 that.setPt1 = that.setPosition; // TODO: not really the same
147 }; 182 // adds pos to the position
148 // moves this Rectangle's center to position pos 183 that.addPosition = function(pos) {
149 that.setCenter = function(pos) { 184 this.x += pos.x;
150 this.x = pos.x - this.width / 2; 185 this.y += pos.y;
151 this.y = pos.y - this.height / 2; 186 return this;
152 return this; 187 };
153 }; 188 // sets the lower right corner to position pos
154 // returns the size of this Rectangle 189 that.setPt2 = function(pos) {
155 that.getSize = function() { 190 this.width = pos.x - this.x;
156 return size(this.width, this.height); 191 this.height = pos.y - this.y;
157 }; 192 return this;
158 that.equals = function(other) { 193 };
159 // equal props 194 // returns the center position of this Rectangle
160 var eq = (this.x === other.x && this.y === other.y && 195 that.getCenter = function() {
161 this.width === other.width); 196 return position({
162 return eq; 197 x : this.x + this.width / 2,
163 }; 198 y : this.y + this.height / 2
164 // returns the area of this Rectangle 199 });
165 that.getArea = function() { 200 };
166 return (this.width * this.height); 201 // moves this Rectangle's center to position pos
167 }; 202 that.setCenter = function(pos) {
168 // eliminates negative width and height 203 this.x = pos.x - this.width / 2;
169 that.normalize = function() { 204 this.y = pos.y - this.height / 2;
170 var p = this.getPt2(); 205 return this;
171 this.x = Math.min(this.x, p.x); 206 };
172 this.y = Math.min(this.y, p.y); 207 that.equals = function(other) {
173 this.width = Math.abs(this.width); 208 // equal props
174 this.height = Math.abs(this.height); 209 var eq = (this.x === other.x && this.y === other.y && this.width === other.width);
175 return this; 210 return eq;
176 }; 211 };
177 // returns if Position "pos" lies inside of this rectangle 212 // returns the area of this Rectangle
178 that.containsPosition = function(pos) { 213 that.getArea = function() {
179 var ct = ((pos.x >= this.x) && (pos.y >= this.y) && 214 return (this.width * this.height);
180 (pos.x <= this.x + this.width) && (pos.y <= this.y + this.height)); 215 };
181 return ct; 216 // eliminates negative width and height
182 }; 217 that.normalize = function() {
183 // returns if rectangle "rect" is contained in this rectangle 218 var p = this.getPt2();
184 that.containsRect = function(rect) { 219 this.x = Math.min(this.x, p.x);
185 return (this.containsPosition(rect.getPt1()) && this.containsPosition(rect.getPt2())); 220 this.y = Math.min(this.y, p.y);
186 }; 221 this.width = Math.abs(this.width);
187 // changes this rectangle's x/y values so it stays inside of rectangle rect 222 this.height = Math.abs(this.height);
188 // keeping the proportions 223 return this;
189 that.stayInside = function(rect) { 224 };
190 if (this.x < rect.x) { 225 // returns if Position "pos" lies inside of this rectangle
191 this.x = rect.x; 226 that.containsPosition = function(pos) {
227 var ct = ((pos.x >= this.x) && (pos.y >= this.y)
228 && (pos.x <= this.x + this.width) && (pos.y <= this.y
229 + this.height));
230 return ct;
231 };
232 // returns if rectangle "rect" is contained in this rectangle
233 that.containsRect = function(rect) {
234 return (this.containsPosition(rect.getPt1()) && this
235 .containsPosition(rect.getPt2()));
236 };
237 // changes this rectangle's x/y values so it stays inside of rectangle
238 // rect
239 // keeping the proportions
240 that.stayInside = function(rect) {
241 if (this.x < rect.x) {
242 this.x = rect.x;
243 }
244 if (this.y < rect.y) {
245 this.y = rect.y;
246 }
247 if (this.x + this.width > rect.x + rect.width) {
248 this.x = rect.x + rect.width - this.width;
249 }
250 if (this.y + this.height > rect.y + rect.height) {
251 this.y = rect.y + rect.height - this.height;
252 }
253 return this;
254 };
255 // clips this rectangle so it stays inside of rectangle rect
256 that.clipTo = function(rect) {
257 var p1 = rect.getPt1();
258 var p2 = rect.getPt2();
259 var this2 = this.getPt2();
260 this.setPosition(position(Math.max(this.x, p1.x), Math.max(this.y, p1.y)));
261 this.setPt2(position(Math.min(this2.x, p2.x), Math.min(this2.y, p2.y)));
262 return this;
263 };
264 // returns the intersection of the given Rectangle and this one
265 that.intersect = function(rect) {
266 // FIX ME: not really, it should return null if there is no overlap
267 var sec = rect.copy();
268 if (sec.x < this.x) {
269 sec.width = sec.width - (this.x - sec.x);
270 sec.x = this.x;
271 }
272 if (sec.y < this.y) {
273 sec.height = sec.height - (this.y - sec.y);
274 sec.y = this.y;
275 }
276 if (sec.x + sec.width > this.x + this.width) {
277 sec.width = (this.x + this.width) - sec.x;
278 }
279 if (sec.y + sec.height > this.y + this.height) {
280 sec.height = (this.y + this.height) - sec.y;
281 }
282 return sec;
283 };
284 // returns a Rectangle that fits into this one (by moving first)
285 that.fit = function(rect) {
286 var sec = rect.copy();
287 sec.x = Math.max(sec.x, this.x);
288 sec.y = Math.max(sec.y, this.x);
289 if (sec.x + sec.width > this.x + this.width) {
290 sec.x = this.x + this.width - sec.width;
291 }
292 if (sec.y + sec.height > this.y + this.height) {
293 sec.y = this.y + this.height - sec.height;
294 }
295 return sec.intersect(this);
296 };
297 // adjusts position and size of $elem to this rectangle
298 that.adjustDiv = function($elem) {
299 $elem.offset({
300 left : this.x,
301 top : this.y
302 });
303 $elem.width(this.width).height(this.height);
304 };
305 // returns size and position in css-compatible format
306 that.getAsCss = function() {
307 return {
308 left : this.x,
309 top : this.y,
310 width : this.width,
311 height : this.height
312 };
313 };
314 that.toString = function() {
315 return this.width + "x" + this.height + "@" + this.x + "," + this.y;
316 };
317 return that;
318 };
319
320 /*
321 * Transform class
322 *
323 * defines a class of affine transformations
324 */
325 var transform = function(spec) {
326 var that = {
327 m00 : 1.0,
328 m01 : 0.0,
329 m02 : 0.0,
330 m10 : 0.0,
331 m11 : 1.0,
332 m12 : 0.0,
333 m20 : 0.0,
334 m21 : 0.0,
335 m22 : 1.0
336 };
337 if (spec) {
338 jQuery.extend(that, spec);
339 }
340 ;
341 that.concat = function(trafA) {
342 // add Transform trafA to this Transform (i.e. this = trafC = trafA
343 // * this)
344 var trafC = {};
345 for ( var i = 0; i < 3; i++) {
346 for ( var j = 0; j < 3; j++) {
347 var c = 0.0;
348 for ( var k = 0; k < 3; k++) {
349 c += trafA["m" + i + k] * this["m" + k + j];
350 }
351 trafC["m" + i + j] = c;
192 } 352 }
193 if (this.y < rect.y) { 353 }
194 this.y = rect.y; 354 jQuery.extend(this, trafC);
195 } 355 return this;
196 if (this.x + this.width > rect.x + rect.width) { 356 };
197 this.x = rect.x + rect.width - this.width; 357 that.transform = function(rect) {
198 } 358 // returns transformed Rectangle or Position with this Transform
199 if (this.y + this.height > rect.y + rect.height) { 359 // applied
200 this.y = rect.y + rect.height - this.height; 360 var x = this.m00 * rect.x + this.m01 * rect.y + this.m02;
201 } 361 var y = this.m10 * rect.x + this.m11 * rect.y + this.m12;
202 return this; 362 var pt = position(x, y);
203 }; 363 if (rect.width) {
204 // clips this rectangle so it stays inside of rectangle rect 364 // transform the other corner point
205 that.clipTo = function(rect) { 365 var pt2 = this.transform(rect.getPt2());
206 var p1 = rect.getPt1(); 366 return rectangle(pt, pt2);
207 var p2 = rect.getPt2(); 367 }
208 var this2 = this.getPt2(); 368 return pt;
209 this.setPt1(position(Math.max(this.x, p1.x), Math.max(this.y, p1.y))); 369 };
210 this.setPt2(position(Math.min(this2.x, p2.x), Math.min(this2.y, p2.y))); 370 that.invtransform = function(rect) {
211 return this; 371 // returns transformed Rectangle or Position with the inverse of
212 }; 372 // this Transform applied
213 // returns the intersection of the given Rectangle and this one 373 var det = this.m00 * this.m11 - this.m01 * this.m10;
214 that.intersect = function(rect) { 374 var x = (this.m11 * rect.x - this.m01 * rect.y - this.m11
215 // FIX ME: not really, it should return null if there is no overlap 375 * this.m02 + this.m01 * this.m12)
216 var sec = rect.copy(); 376 / det;
217 if (sec.x < this.x) { 377 var y = (-this.m10 * rect.x + this.m00 * rect.y + this.m10
218 sec.width = sec.width - (this.x - sec.x); 378 * this.m02 - this.m00 * this.m12)
219 sec.x = this.x; 379 / det;
220 } 380 var pt = position(x, y);
221 if (sec.y < this.y) { 381 if (rect.width) {
222 sec.height = sec.height - (this.y - sec.y); 382 // transform the other corner point
223 sec.y = this.y; 383 var pt2 = this.invtransform(rect.getPt2());
224 } 384 return rectangle(pt, pt2);
225 if (sec.x + sec.width > this.x + this.width) { 385 }
226 sec.width = (this.x + this.width) - sec.x; 386 return pt;
227 } 387 };
228 if (sec.y + sec.height > this.y + this.height) { 388 that.toString = function(pretty) {
229 sec.height = (this.y + this.height) - sec.y; 389 var s = '[';
230 } 390 if (pretty)
231 return sec; 391 s += '\n';
232 }; 392 for ( var i = 0; i < 3; ++i) {
233 // returns a Rectangle that fits into this one (by moving first) 393 s += '[';
234 that.fit = function(rect) { 394 for ( var j = 0; j < 3; ++j) {
235 var sec = rect.copy(); 395 if (j)
236 sec.x = Math.max(sec.x, this.x); 396 s += ',';
237 sec.y = Math.max(sec.y, this.x); 397 s += this['m' + i + j];
238 if (sec.x + sec.width > this.x + this.width) {
239 sec.x = this.x + this.width - sec.width;
240 }
241 if (sec.y + sec.height > this.y + this.height) {
242 sec.y = this.y + this.height - sec.height;
243 }
244 return sec.intersect(this);
245 };
246 // adjusts position and size of $elem to this rectangle
247 that.adjustDiv = function ($elem) {
248 $elem.offset({left : this.x, top : this.y});
249 $elem.width(this.width).height(this.height);
250 };
251 // returns size and position in css-compatible format
252 that.getAsCss = function () {
253 return {left : this.x, top : this.y,
254 width : this.width, height : this.height};
255 };
256 that.toString = function() {
257 return this.width+"x"+this.height+"@"+this.x+","+this.y;
258 };
259 return that;
260 };
261
262 /*
263 * Transform class
264 *
265 * defines a class of affine transformations
266 */
267 var transform = function (spec) {
268 var that = {
269 m00 : 1.0,
270 m01 : 0.0,
271 m02 : 0.0,
272 m10 : 0.0,
273 m11 : 1.0,
274 m12 : 0.0,
275 m20 : 0.0,
276 m21 : 0.0,
277 m22 : 1.0
278 };
279 if (spec) {
280 jQuery.extend(that, spec);
281 };
282 that.concat = function(trafA) {
283 // add Transform trafA to this Transform (i.e. this = trafC = trafA * this)
284 var trafC = {};
285 for (var i = 0; i < 3; i++) {
286 for (var j = 0; j < 3; j++) {
287 var c = 0.0;
288 for (var k = 0; k < 3; k++) {
289 c += trafA["m"+i+k] * this["m"+k+j];
290 }
291 trafC["m"+i+j] = c;
292 }
293 }
294 jQuery.extend(this, trafC);
295 return this;
296 };
297 that.transform = function(rect) {
298 // returns transformed Rectangle or Position with this Transform applied
299 var x = this.m00 * rect.x + this.m01 * rect.y + this.m02;
300 var y = this.m10 * rect.x + this.m11 * rect.y + this.m12;
301 var pt = position(x, y);
302 if (rect.width) {
303 // transform the other corner point
304 var pt2 = this.transform(rect.getPt2());
305 return rectangle(pt, pt2);
306 }
307 return pt;
308 };
309 that.invtransform = function(rect) {
310 // returns transformed Rectangle or Position with the inverse of this Transform applied
311 var det = this.m00 * this.m11 - this.m01 * this.m10;
312 var x = (this.m11 * rect.x - this.m01 * rect.y - this.m11 * this.m02 + this.m01 * this.m12) / det;
313 var y = (-this.m10 * rect.x + this.m00 * rect.y + this.m10 * this.m02 - this.m00 * this.m12) / det;
314 var pt = position(x, y);
315 if (rect.width) {
316 // transform the other corner point
317 var pt2 = this.invtransform(rect.getPt2());
318 return rectangle(pt, pt2);
319 }
320 return pt;
321 };
322 that.toString = function (pretty) {
323 var s = '[';
324 if (pretty) s += '\n';
325 for (var i = 0; i < 3; ++i) {
326 s += '[';
327 for (var j = 0; j < 3; ++j) {
328 if (j) s += ',';
329 s += this['m'+i+j];
330 }
331 s += ']';
332 if (pretty) s += '\n';
333 } 398 }
334 s += ']'; 399 s += ']';
335 if (pretty) s += '\n'; 400 if (pretty)
336 return s; 401 s += '\n';
337 }; 402 }
338 // add class methods to instance 403 s += ']';
339 that.getRotation = transform.getRotation; 404 if (pretty)
340 that.getRotationAround = transform.getRotationAround; 405 s += '\n';
341 that.getTranslation = transform.getTranslation; 406 return s;
342 that.getMirror = transform.getMirror; 407 };
343 that.getScale = transform.getScale; 408 // add class methods to instance
344 409 that.getRotation = transform.getRotation;
345 return that; 410 that.getRotationAround = transform.getRotationAround;
346 }; 411 that.getTranslation = transform.getTranslation;
347 412 that.getMirror = transform.getMirror;
348 transform.getRotation = function (angle) { 413 that.getScale = transform.getScale;
349 // returns a Transform that is a rotation by angle degrees around [0,0] 414
350 if (angle !== 0) { 415 return that;
351 var t = Math.PI * parseFloat(angle) / 180.0; 416 };
352 var cost = Math.cos(t); 417
353 var sint = Math.sin(t); 418 transform.getRotation = function(angle) {
354 var traf = { 419 // returns a Transform that is a rotation by angle degrees around [0,0]
355 m00 : cost, 420 if (angle !== 0) {
356 m01 : -sint, 421 var t = Math.PI * parseFloat(angle) / 180.0;
357 m10 : sint, 422 var cost = Math.cos(t);
358 m11 : cost 423 var sint = Math.sin(t);
359 }; 424 var traf = {
360 return transform(traf); 425 m00 : cost,
361 } 426 m01 : -sint,
362 return transform(); 427 m10 : sint,
363 }; 428 m11 : cost
364 429 };
365 transform.getRotationAround = function (angle, pos) { 430 return transform(traf);
366 // returns a Transform that is a rotation by angle degrees around pos 431 }
367 var traf = transform.getTranslation({x : -pos.x, y : -pos.y}); 432 return transform();
368 traf.concat(transform.getRotation(angle)); 433 };
369 traf.concat(transform.getTranslation(pos)); 434
370 return traf; 435 transform.getRotationAround = function(angle, pos) {
371 }; 436 // returns a Transform that is a rotation by angle degrees around pos
372 437 var traf = transform.getTranslation(pos.neg());
373 transform.getTranslation = function (pos) { 438 traf.concat(transform.getRotation(angle));
374 // returns a Transform that is a translation by [pos.x, pos,y] 439 traf.concat(transform.getTranslation(pos));
375 var traf = { 440 return traf;
376 m02 : pos.x, 441 };
377 m12 : pos.y 442
378 }; 443 transform.getTranslation = function(pos) {
379 return transform(traf); 444 // returns a Transform that is a translation by [pos.x, pos,y]
380 }; 445 var traf = {
381 446 m02 : pos.x,
382 transform.getMirror = function (type) { 447 m12 : pos.y
383 // returns a Transform that is a mirror about the axis type 448 };
384 if (type === 'x') { 449 return transform(traf);
385 var traf = { 450 };
386 m00 : 1, 451
387 m11 : -1 452 transform.getMirror = function(type) {
388 }; 453 // returns a Transform that is a mirror about the axis type
389 } else { 454 if (type === 'x') {
390 var traf = { 455 var traf = {
391 m00 : -1, 456 m00 : 1,
392 m11 : 1 457 m11 : -1
393 }; 458 };
394 } 459 } else {
395 return transform(traf); 460 var traf = {
396 }; 461 m00 : -1,
397 462 m11 : 1
398 transform.getScale = function (size) { 463 };
399 // returns a Transform that is a scale by [size.width, size.height] 464 }
400 var traf = { 465 return transform(traf);
401 m00 : size.width, 466 };
402 m11 : size.height 467
403 }; 468 transform.getScale = function(size) {
404 return transform(traf); 469 // returns a Transform that is a scale by [size.width, size.height]
405 }; 470 var traf = {
406 471 m00 : size.width,
407 // export functions 472 m11 : size.height
408 var that = { 473 };
409 size : size, 474 return transform(traf);
410 position : position, 475 };
411 rectangle : rectangle, 476
412 transform : transform 477 // export functions
413 }; 478 var that = {
414 479 size : size,
415 return that; 480 position : position,
416 }; 481 rectangle : rectangle,
482 transform : transform
483 };
484
485 return that;
486 };