cornerstone-source 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/.gitignore +22 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE +22 -0
  4. data/README.md +20 -0
  5. data/Rakefile +8 -0
  6. data/config.rb +79 -0
  7. data/config.ru +4 -0
  8. data/cornerstone.gemspec +22 -0
  9. data/doc_scraper.rb +51 -0
  10. data/game.js +4293 -0
  11. data/lib/assets/javascripts/cornerstone.js +4719 -0
  12. data/lib/cornerstone.rb +11 -0
  13. data/lib/cornerstone/rails.rb +5 -0
  14. data/lib/cornerstone/sprockets.rb +2 -0
  15. data/lib/cornerstone/version.rb +3 -0
  16. data/manifest.json +15 -0
  17. data/pixie.json +12 -0
  18. data/source/javascripts/_cornerstone/_object_extensions.js.coffee +108 -0
  19. data/source/javascripts/_cornerstone/array_extensions.js.coffee +570 -0
  20. data/source/javascripts/_cornerstone/bindable.js.coffee +125 -0
  21. data/source/javascripts/_cornerstone/command_stack.js.coffee +36 -0
  22. data/source/javascripts/_cornerstone/core_object.js.coffee +183 -0
  23. data/source/javascripts/_cornerstone/function_extensions.js.coffee +60 -0
  24. data/source/javascripts/_cornerstone/logging.js.coffee +19 -0
  25. data/source/javascripts/_cornerstone/matrix.js.coffee +337 -0
  26. data/source/javascripts/_cornerstone/number_extensions.js.coffee +491 -0
  27. data/source/javascripts/_cornerstone/point.js.coffee +641 -0
  28. data/source/javascripts/_cornerstone/random.js.coffee +86 -0
  29. data/source/javascripts/_cornerstone/rectangle.js.coffee +35 -0
  30. data/source/javascripts/_cornerstone/string_extensions.js.coffee +232 -0
  31. data/source/javascripts/_cornerstone/stubs.js.coffee +1042 -0
  32. data/source/javascripts/_cornerstone/uuid.js +96 -0
  33. data/source/javascripts/_test/array_extensions.coffee +173 -0
  34. data/source/javascripts/_test/bindable.coffee +68 -0
  35. data/source/javascripts/_test/command_stack.coffee +99 -0
  36. data/source/javascripts/_test/core_object.coffee +95 -0
  37. data/source/javascripts/_test/function_extensions.coffee +50 -0
  38. data/source/javascripts/_test/logging.coffee +7 -0
  39. data/source/javascripts/_test/matrix.coffee +174 -0
  40. data/source/javascripts/_test/number_extensions.coffee +138 -0
  41. data/source/javascripts/_test/object_extensions.coffee +53 -0
  42. data/source/javascripts/_test/point.coffee +196 -0
  43. data/source/javascripts/_test/random.coffee +22 -0
  44. data/source/javascripts/_test/rectangle.coffee +70 -0
  45. data/source/javascripts/_test/string_extensions.coffee +59 -0
  46. data/source/javascripts/cornerstone.js.coffee +1 -0
  47. data/source/javascripts/cornerstone_tests.js.coffee +2 -0
  48. data/source/test.html.haml +13 -0
  49. data/vendor/javascripts/qunit.js +1275 -0
  50. data/vendor/stylesheets/qunit.css.sass +115 -0
  51. metadata +141 -0
@@ -0,0 +1,125 @@
1
+ ###*
2
+ Bindable module.
3
+
4
+ player = Core
5
+ x: 5
6
+ y: 10
7
+
8
+ player.bind "update", ->
9
+ updatePlayer()
10
+ # => Uncaught TypeError: Object has no method 'bind'
11
+
12
+ player.include(Bindable)
13
+
14
+ player.bind "update", ->
15
+ updatePlayer()
16
+ # => this will call updatePlayer each time through the main loop
17
+
18
+ @name Bindable
19
+ @module
20
+ @constructor
21
+ ###
22
+ Bindable = (I={}, self) ->
23
+ eventCallbacks = {}
24
+
25
+ bind: (args...) ->
26
+ self.on(args...)
27
+
28
+ unbind: (args...) ->
29
+ self.off(args...)
30
+
31
+ ###*
32
+ Adds a function as an event listener.
33
+
34
+ # this will call coolEventHandler after
35
+ # yourObject.trigger "someCustomEvent" is called.
36
+ yourObject.on "someCustomEvent", coolEventHandler
37
+
38
+ #or
39
+ yourObject.on "anotherCustomEvent", ->
40
+ doSomething()
41
+
42
+ @name on
43
+ @methodOf Bindable#
44
+ @param {String} event The event to listen to.
45
+ @param {Function} callback The function to be called when the specified event
46
+ is triggered.
47
+ ###
48
+ on: (namespacedEvent, callback) ->
49
+ [event, namespace] = namespacedEvent.split(".")
50
+
51
+ # HACK: Here we annotate the callback function with namespace metadata
52
+ # This will probably lead to some strange edge cases, but should work fine
53
+ # for simple cases.
54
+ if namespace
55
+ callback.__PIXIE ||= {}
56
+ callback.__PIXIE[namespace] = true
57
+
58
+ eventCallbacks[event] ||= []
59
+ eventCallbacks[event].push(callback)
60
+
61
+ return this
62
+
63
+ ###*
64
+ Removes a specific event listener, or all event listeners if
65
+ no specific listener is given.
66
+
67
+ # removes the handler coolEventHandler from the event
68
+ # "someCustomEvent" while leaving the other events intact.
69
+ yourObject.off "someCustomEvent", coolEventHandler
70
+
71
+ # removes all handlers attached to "anotherCustomEvent"
72
+ yourObject.off "anotherCustomEvent"
73
+
74
+ @name off
75
+ @methodOf Bindable#
76
+ @param {String} event The event to remove the listener from.
77
+ @param {Function} [callback] The listener to remove.
78
+ ###
79
+ off: (namespacedEvent, callback) ->
80
+ [event, namespace] = namespacedEvent.split(".")
81
+
82
+ if event
83
+ eventCallbacks[event] ||= []
84
+
85
+ if namespace
86
+ # Select only the callbacks that do not have this namespace metadata
87
+ eventCallbacks[event] = eventCallbacks.select (callback) ->
88
+ !callback.__PIXIE?[namespace]?
89
+
90
+ else
91
+ if callback
92
+ eventCallbacks[event].remove(callback)
93
+ else
94
+ eventCallbacks[event] = []
95
+ else if namespace
96
+ # No event given
97
+ # Select only the callbacks that do not have this namespace metadata
98
+ # for any events bound
99
+ for key, callbacks of eventCallbacks
100
+ eventCallbacks[key] = callbacks.select (callback) ->
101
+ !callback.__PIXIE?[namespace]?
102
+
103
+ return this
104
+
105
+ ###*
106
+ Calls all listeners attached to the specified event.
107
+
108
+ # calls each event handler bound to "someCustomEvent"
109
+ yourObject.trigger "someCustomEvent"
110
+
111
+ @name trigger
112
+ @methodOf Bindable#
113
+ @param {String} event The event to trigger.
114
+ @param {Array} [parameters] Additional parameters to pass to the event listener.
115
+ ###
116
+ trigger: (event, parameters...) ->
117
+ callbacks = eventCallbacks[event]
118
+
119
+ if callbacks && callbacks.length
120
+ self = this
121
+
122
+ callbacks.each (callback) ->
123
+ callback.apply(self, parameters)
124
+
125
+ (exports ? this)["Bindable"] = Bindable
@@ -0,0 +1,36 @@
1
+ CommandStack = ->
2
+ stack = []
3
+ index = 0
4
+
5
+ execute: (command) ->
6
+ stack[index] = command
7
+ command.execute()
8
+
9
+ # Be sure to blast obsolete redos
10
+ stack.length = index += 1
11
+
12
+ undo: ->
13
+ if @canUndo()
14
+ index -= 1
15
+
16
+ command = stack[index]
17
+ command.undo()
18
+
19
+ return command
20
+
21
+ redo: ->
22
+ if @canRedo()
23
+ command = stack[index]
24
+ command.execute()
25
+
26
+ index += 1
27
+
28
+ return command
29
+
30
+ canUndo: ->
31
+ index > 0
32
+
33
+ canRedo: ->
34
+ stack[index]?
35
+
36
+ (exports ? this)["CommandStack"] = CommandStack
@@ -0,0 +1,183 @@
1
+ ###*
2
+ The Core class is used to add extended functionality to objects without
3
+ extending the object class directly. Inherit from Core to gain its utility
4
+ methods.
5
+
6
+ @name Core
7
+ @constructor
8
+
9
+ @param {Object} I Instance variables
10
+ ###
11
+
12
+ ( ->
13
+ root = exports ? this
14
+
15
+ root.Core = (I={}) ->
16
+ Object.reverseMerge I,
17
+ includedModules: []
18
+
19
+ self =
20
+ ###*
21
+ External access to instance variables. Use of this property should be avoided
22
+ in general, but can come in handy from time to time.
23
+
24
+ I =
25
+ r: 255
26
+ g: 0
27
+ b: 100
28
+
29
+ myObject = Core(I)
30
+
31
+ # a bad idea most of the time, but it's
32
+ # pretty convenient to have available.
33
+ myObject.I.r
34
+ # => 255
35
+
36
+ myObject.I.g
37
+ # => 0
38
+
39
+ myObject.I.b
40
+ # => 100
41
+
42
+ @name I
43
+ @fieldOf Core#
44
+ ###
45
+ I: I
46
+
47
+ ###*
48
+ Generates a public jQuery style getter / setter method for each
49
+ String argument.
50
+
51
+ myObject = Core
52
+ r: 255
53
+ g: 0
54
+ b: 100
55
+
56
+ myObject.attrAccessor "r", "g", "b"
57
+
58
+ myObject.r(254)
59
+ myObject.r()
60
+
61
+ => 254
62
+
63
+ @name attrAccessor
64
+ @methodOf Core#
65
+ ###
66
+ attrAccessor: (attrNames...) ->
67
+ attrNames.each (attrName) ->
68
+ self[attrName] = (newValue) ->
69
+ if newValue?
70
+ I[attrName] = newValue
71
+ return self
72
+ else
73
+ I[attrName]
74
+
75
+ ###*
76
+ Generates a public jQuery style getter method for each String argument.
77
+
78
+ myObject = Core
79
+ r: 255
80
+ g: 0
81
+ b: 100
82
+
83
+ myObject.attrReader "r", "g", "b"
84
+
85
+ myObject.r()
86
+ => 255
87
+
88
+ myObject.g()
89
+ => 0
90
+
91
+ myObject.b()
92
+ => 100
93
+
94
+ @name attrReader
95
+ @methodOf Core#
96
+ ###
97
+ attrReader: (attrNames...) ->
98
+ attrNames.each (attrName) ->
99
+ self[attrName] = ->
100
+ I[attrName]
101
+
102
+ ###*
103
+ Extends this object with methods from the passed in object. A shortcut for Object.extend(self, methods)
104
+
105
+ I =
106
+ x: 30
107
+ y: 40
108
+ maxSpeed: 5
109
+
110
+ # we are using extend to give player
111
+ # additional methods that Core doesn't have
112
+ player = Core(I).extend
113
+ increaseSpeed: ->
114
+ I.maxSpeed += 1
115
+
116
+ player.I.maxSpeed
117
+ => 5
118
+
119
+ player.increaseSpeed()
120
+
121
+ player.I.maxSpeed
122
+ => 6
123
+
124
+ @name extend
125
+ @methodOf Core#
126
+ @see Object.extend
127
+ @returns self
128
+ ###
129
+ extend: (options) ->
130
+ Object.extend self, options
131
+
132
+ return self
133
+
134
+ ###*
135
+ Includes a module in this object.
136
+
137
+ myObject = Core()
138
+ myObject.include(Bindable)
139
+
140
+ # now you can bind handlers to functions
141
+ myObject.bind "someEvent", ->
142
+ alert("wow. that was easy.")
143
+
144
+ @name include
145
+ @methodOf Core#
146
+ @param {String} Module the module to include. A module is a constructor that takes two parameters, I and self, and returns an object containing the public methods to extend the including object with.
147
+ ###
148
+ include: (modules...) ->
149
+ for Module in modules
150
+ if Module.isString?()
151
+ moduleName = Module
152
+ Module = Module.constantize()
153
+ else if moduleName = Module._name
154
+ # Nothing, captured name in if condition
155
+ else
156
+ # Attempt to look up module in global namespace
157
+ for key, value of root
158
+ if value is Module
159
+ Module._name = moduleName = key # Cache module name
160
+
161
+ if moduleName
162
+ unless I.includedModules.include moduleName
163
+ I.includedModules.push moduleName
164
+ self.extend Module(I, self)
165
+ else
166
+ warn "Unable to discover name for module: ", Module, "\nSerialization issues may occur."
167
+ self.extend Module(I, self)
168
+
169
+ return self
170
+
171
+ send: (name, args...) ->
172
+ self[name](args...)
173
+
174
+ # Include Bindable by default
175
+ self.include "Bindable"
176
+
177
+ # Initial module inclue, for reconstructing objects from JSON
178
+ for moduleName in I.includedModules
179
+ Module = moduleName.constantize()
180
+ self.extend Module(I, self)
181
+
182
+ return self
183
+ )()
@@ -0,0 +1,60 @@
1
+ Function::once = ->
2
+ func = this
3
+
4
+ ran = false
5
+ memo = undefined
6
+
7
+ return ->
8
+ return memo if ran
9
+ ran = true
10
+
11
+ return memo = func.apply(this, arguments)
12
+
13
+ ###*
14
+ Calling a debounced function will postpone its execution until after
15
+ wait milliseconds have elapsed since the last time the function was
16
+ invoked. Useful for implementing behavior that should only happen after
17
+ the input has stopped arriving. For example: rendering a preview of a
18
+ Markdown comment, recalculating a layout after the window has stopped
19
+ being resized...
20
+
21
+ lazyLayout = calculateLayout.debounce(300)
22
+ $(window).resize(lazyLayout)
23
+
24
+ @name debounce
25
+ @methodOf Function#
26
+ @returns {Function} The debounced version of this function.
27
+ ###
28
+ Function::debounce = (wait) ->
29
+ timeout = null
30
+ func = this
31
+
32
+ return ->
33
+ context = this
34
+ args = arguments
35
+
36
+ later = ->
37
+ timeout = null
38
+ func.apply(context, args)
39
+
40
+ clearTimeout(timeout)
41
+ timeout = setTimeout(later, wait)
42
+
43
+ # Not sure about the future of this, but trying it out
44
+ Function::returning = (x) ->
45
+ func = this
46
+
47
+ ->
48
+ func.apply(this, arguments)
49
+ return x
50
+
51
+ Function::delay = (wait, args...) ->
52
+ func = this
53
+
54
+ setTimeout ->
55
+ func.apply(null, args)
56
+ , wait
57
+
58
+ Function::defer = (args...) ->
59
+ this.delay.apply this, [1].concat(args)
60
+
@@ -0,0 +1,19 @@
1
+ ###*
2
+ @name Logging
3
+ @namespace
4
+
5
+ Gives you some convenience methods for outputting data while developing.
6
+
7
+ log "Testing123"
8
+ info "Hey, this is happening"
9
+ warn "Be careful, this might be a problem"
10
+ error "Kaboom!"
11
+ ###
12
+
13
+ ["log", "info", "warn", "error"].each (name) ->
14
+ if typeof console != "undefined"
15
+ (exports ? this)[name] = (args...) ->
16
+ if console[name]
17
+ console[name](args...)
18
+ else
19
+ (exports ? this)[name] = ->
@@ -0,0 +1,337 @@
1
+ ###*
2
+ * Matrix.js v1.3.0pre
3
+ *
4
+ * Copyright (c) 2010 STRd6
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ * of this software and associated documentation files (the "Software"), to deal
8
+ * in the Software without restriction, including without limitation the rights
9
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ * copies of the Software, and to permit persons to whom the Software is
11
+ * furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in
14
+ * all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ * THE SOFTWARE.
23
+ *
24
+ * Loosely based on flash:
25
+ * http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/flash/geom/Matrix.html
26
+ ###
27
+ ( ->
28
+ ###*
29
+ <pre>
30
+ _ _
31
+ | a c tx |
32
+ | b d ty |
33
+ |_0 0 1 _|
34
+ </pre>
35
+ Creates a matrix for 2d affine transformations.
36
+
37
+ concat, inverse, rotate, scale and translate return new matrices with the
38
+ transformations applied. The matrix is not modified in place.
39
+
40
+ Returns the identity matrix when called with no arguments.
41
+
42
+ @name Matrix
43
+ @param {Number} [a]
44
+ @param {Number} [b]
45
+ @param {Number} [c]
46
+ @param {Number} [d]
47
+ @param {Number} [tx]
48
+ @param {Number} [ty]
49
+ @constructor
50
+ ###
51
+ Matrix = (a, b, c, d, tx, ty) ->
52
+ if Object.isObject(a)
53
+ {a, b, c, d, tx, ty} = a
54
+
55
+ __proto__: Matrix::
56
+ ###*
57
+ @name a
58
+ @fieldOf Matrix#
59
+ ###
60
+ a: if a? then a else 1
61
+
62
+ ###*
63
+ @name b
64
+ @fieldOf Matrix#
65
+ ###
66
+ b: b || 0
67
+
68
+ ###*
69
+ @name c
70
+ @fieldOf Matrix#
71
+ ###
72
+ c: c || 0,
73
+
74
+ ###*
75
+ @name d
76
+ @fieldOf Matrix#
77
+ ###
78
+ d: if d? then d else 1
79
+
80
+ ###*
81
+ @name tx
82
+ @fieldOf Matrix#
83
+ ###
84
+ tx: tx || 0
85
+
86
+ ###*
87
+ @name ty
88
+ @fieldOf Matrix#
89
+ ###
90
+ ty: ty || 0
91
+
92
+ Matrix:: =
93
+ ###*
94
+ Returns the result of this matrix multiplied by another matrix
95
+ combining the geometric effects of the two. In mathematical terms,
96
+ concatenating two matrixes is the same as combining them using matrix multiplication.
97
+ If this matrix is A and the matrix passed in is B, the resulting matrix is A x B
98
+ http://mathworld.wolfram.com/MatrixMultiplication.html
99
+ @name concat
100
+ @methodOf Matrix#
101
+ @param {Matrix} matrix The matrix to multiply this matrix by.
102
+ @returns {Matrix} The result of the matrix multiplication, a new matrix.
103
+ ###
104
+ concat: (matrix) ->
105
+ Matrix(
106
+ @a * matrix.a + @c * matrix.b,
107
+ @b * matrix.a + @d * matrix.b,
108
+ @a * matrix.c + @c * matrix.d,
109
+ @b * matrix.c + @d * matrix.d,
110
+ @a * matrix.tx + @c * matrix.ty + @tx,
111
+ @b * matrix.tx + @d * matrix.ty + @ty
112
+ )
113
+
114
+ ###*
115
+ Copy this matrix.
116
+ @name copy
117
+ @methodOf Matrix#
118
+ @returns {Matrix} A copy of this matrix.
119
+ ###
120
+ copy: ->
121
+ Matrix(@a, @b, @c, @d, @tx, @ty)
122
+
123
+ ###*
124
+ Given a point in the pretransform coordinate space, returns the coordinates of
125
+ that point after the transformation occurs. Unlike the standard transformation
126
+ applied using the transformPoint() method, the deltaTransformPoint() method
127
+ does not consider the translation parameters tx and ty.
128
+ @name deltaTransformPoint
129
+ @methodOf Matrix#
130
+ @see #transformPoint
131
+ @return {Point} A new point transformed by this matrix ignoring tx and ty.
132
+ ###
133
+ deltaTransformPoint: (point) ->
134
+ Point(
135
+ @a * point.x + @c * point.y,
136
+ @b * point.x + @d * point.y
137
+ )
138
+
139
+ ###*
140
+ Returns the inverse of the matrix.
141
+ http://mathworld.wolfram.com/MatrixInverse.html
142
+ @name inverse
143
+ @methodOf Matrix#
144
+ @returns {Matrix} A new matrix that is the inverse of this matrix.
145
+ ###
146
+ inverse: ->
147
+ determinant = @a * @d - @b * @c
148
+
149
+ Matrix(
150
+ @d / determinant,
151
+ -@b / determinant,
152
+ -@c / determinant,
153
+ @a / determinant,
154
+ (@c * @ty - @d * @tx) / determinant,
155
+ (@b * @tx - @a * @ty) / determinant
156
+ )
157
+
158
+ ###*
159
+ Returns a new matrix that corresponds this matrix multiplied by a
160
+ a rotation matrix.
161
+ @name rotate
162
+ @methodOf Matrix#
163
+ @see Matrix.rotation
164
+ @param {Number} theta Amount to rotate in radians.
165
+ @param {Point} [aboutPoint] The point about which this rotation occurs. Defaults to (0,0).
166
+ @returns {Matrix} A new matrix, rotated by the specified amount.
167
+ ###
168
+ rotate: (theta, aboutPoint) ->
169
+ @concat(Matrix.rotation(theta, aboutPoint))
170
+
171
+ ###*
172
+ Returns a new matrix that corresponds this matrix multiplied by a
173
+ a scaling matrix.
174
+ @name scale
175
+ @methodOf Matrix#
176
+ @see Matrix.scale
177
+ @param {Number} sx
178
+ @param {Number} [sy]
179
+ @param {Point} [aboutPoint] The point that remains fixed during the scaling
180
+ @returns {Matrix} A new Matrix. The original multiplied by a scaling matrix.
181
+ ###
182
+ scale: (sx, sy, aboutPoint) ->
183
+ @concat(Matrix.scale(sx, sy, aboutPoint))
184
+
185
+ ###*
186
+ Returns a new matrix that corresponds this matrix multiplied by a
187
+ a skewing matrix.
188
+
189
+ @name skew
190
+ @methodOf Matrix#
191
+ @see Matrix.skew
192
+ @param {Number} skewX The angle of skew in the x dimension.
193
+ @param {Number} skewY The angle of skew in the y dimension.
194
+ ###
195
+ skew: (skewX, skewY) ->
196
+ @concat(Matrix.skew(skewX, skewY))
197
+
198
+ ###*
199
+ Returns a string representation of this matrix.
200
+
201
+ @name toString
202
+ @methodOf Matrix#
203
+ @returns {String} A string reperesentation of this matrix.
204
+ ###
205
+ toString: ->
206
+ "Matrix(#{@a}, #{@b}, #{@c}, #{@d}, #{@tx}, #{@ty})"
207
+
208
+ ###*
209
+ Returns the result of applying the geometric transformation represented by the
210
+ Matrix object to the specified point.
211
+ @name transformPoint
212
+ @methodOf Matrix#
213
+ @see #deltaTransformPoint
214
+ @returns {Point} A new point with the transformation applied.
215
+ ###
216
+ transformPoint: (point) ->
217
+ Point(
218
+ @a * point.x + @c * point.y + @tx,
219
+ @b * point.x + @d * point.y + @ty
220
+ )
221
+
222
+ ###*
223
+ Translates the matrix along the x and y axes, as specified by the tx and ty parameters.
224
+ @name translate
225
+ @methodOf Matrix#
226
+ @see Matrix.translation
227
+ @param {Number} tx The translation along the x axis.
228
+ @param {Number} ty The translation along the y axis.
229
+ @returns {Matrix} A new matrix with the translation applied.
230
+ ###
231
+ translate: (tx, ty) ->
232
+ @concat(Matrix.translation(tx, ty))
233
+
234
+ ###*
235
+ Creates a matrix transformation that corresponds to the given rotation,
236
+ around (0,0) or the specified point.
237
+ @see Matrix#rotate
238
+ @param {Number} theta Rotation in radians.
239
+ @param {Point} [aboutPoint] The point about which this rotation occurs. Defaults to (0,0).
240
+ @returns {Matrix} A new matrix rotated by the given amount.
241
+ ###
242
+ Matrix.rotate = Matrix.rotation = (theta, aboutPoint) ->
243
+ rotationMatrix = Matrix(
244
+ Math.cos(theta),
245
+ Math.sin(theta),
246
+ -Math.sin(theta),
247
+ Math.cos(theta)
248
+ )
249
+
250
+ if aboutPoint?
251
+ rotationMatrix =
252
+ Matrix.translation(aboutPoint.x, aboutPoint.y).concat(
253
+ rotationMatrix
254
+ ).concat(
255
+ Matrix.translation(-aboutPoint.x, -aboutPoint.y)
256
+ )
257
+
258
+ return rotationMatrix
259
+
260
+ ###*
261
+ Returns a matrix that corresponds to scaling by factors of sx, sy along
262
+ the x and y axis respectively.
263
+ If only one parameter is given the matrix is scaled uniformly along both axis.
264
+ If the optional aboutPoint parameter is given the scaling takes place
265
+ about the given point.
266
+ @see Matrix#scale
267
+ @param {Number} sx The amount to scale by along the x axis or uniformly if no sy is given.
268
+ @param {Number} [sy] The amount to scale by along the y axis.
269
+ @param {Point} [aboutPoint] The point about which the scaling occurs. Defaults to (0,0).
270
+ @returns {Matrix} A matrix transformation representing scaling by sx and sy.
271
+ ###
272
+ Matrix.scale = (sx, sy, aboutPoint) ->
273
+ sy = sy || sx
274
+
275
+ scaleMatrix = Matrix(sx, 0, 0, sy)
276
+
277
+ if aboutPoint
278
+ scaleMatrix =
279
+ Matrix.translation(aboutPoint.x, aboutPoint.y).concat(
280
+ scaleMatrix
281
+ ).concat(
282
+ Matrix.translation(-aboutPoint.x, -aboutPoint.y)
283
+ )
284
+
285
+ return scaleMatrix
286
+
287
+ ###*
288
+ Returns a matrix that corresponds to a skew of skewX, skewY.
289
+
290
+ @see Matrix#skew
291
+ @param {Number} skewX The angle of skew in the x dimension.
292
+ @param {Number} skewY The angle of skew in the y dimension.
293
+ @return {Matrix} A matrix transformation representing a skew by skewX and skewY.
294
+ ###
295
+ Matrix.skew = (skewX, skewY) ->
296
+ Matrix(0, Math.tan(skewY), Math.tan(skewX), 0)
297
+
298
+ ###*
299
+ Returns a matrix that corresponds to a translation of tx, ty.
300
+ @see Matrix#translate
301
+ @param {Number} tx The amount to translate in the x direction.
302
+ @param {Number} ty The amount to translate in the y direction.
303
+ @return {Matrix} A matrix transformation representing a translation by tx and ty.
304
+ ###
305
+ Matrix.translate = Matrix.translation = (tx, ty) ->
306
+ Matrix(1, 0, 0, 1, tx, ty)
307
+
308
+ ###*
309
+ A constant representing the identity matrix.
310
+ @name IDENTITY
311
+ @fieldOf Matrix
312
+ ###
313
+ Matrix.IDENTITY = Matrix()
314
+
315
+ ###*
316
+ A constant representing the horizontal flip transformation matrix.
317
+ @name HORIZONTAL_FLIP
318
+ @fieldOf Matrix
319
+ ###
320
+ Matrix.HORIZONTAL_FLIP = Matrix(-1, 0, 0, 1)
321
+
322
+ ###*
323
+ A constant representing the vertical flip transformation matrix.
324
+ @name VERTICAL_FLIP
325
+ @fieldOf Matrix
326
+ ###
327
+ Matrix.VERTICAL_FLIP = Matrix(1, 0, 0, -1)
328
+
329
+ if Object.freeze
330
+ Object.freeze Matrix.IDENTITY
331
+ Object.freeze Matrix.HORIZONTAL_FLIP
332
+ Object.freeze Matrix.VERTICAL_FLIP
333
+
334
+ # Export to window
335
+ (exports ? this)["Matrix"] = Matrix
336
+ )()
337
+