summaryrefslogtreecommitdiffstats
path: root/src/matrix.js
blob: e2afbefbe916763e8eee6b9574702c096e03b1a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
SVG.Matrix = SVG.invent({
	// Initialize
	create: function(source) {
		var i, base = arrayToMatrix([1, 0, 0, 1, 0, 0])

		// Ensure source as object
		source = source && source.node && source.node.getCTM ?
			source.node.getCTM() :
		typeof source === 'string' ?
			arrayToMatrix(source.replace(/\s/g, '').split(',')) :
		arguments.length == 6 ?
			arrayToMatrix([].slice.call(arguments)) :
		typeof source === 'object' ?
			source : base

		// Merge source
		for (i = abcdef.length - 1; i >= 0; i--)
			this[abcdef[i]] = typeof source[abcdef[i]] === 'number' ?
				source[abcdef[i]] : base[abcdef[i]]
		
	}
	
	// Add methods
, extend: {
		// Extract individual transformations
	  extract: function() {
			// Find transform points
			var px 		= deltaTransformPoint(this, 0, 1)
				, py 		= deltaTransformPoint(this, 1, 0)
				, skewX = 180 / Math.PI * Math.atan2(px.y, px.x) - 90
	
			return {
				// Translation
				x: 				this.e
			, y: 				this.f
				// Skew
			, skewX: 		skewX
			, skewY: 		180 / Math.PI * Math.atan2(py.y, py.x)
				// Scale
			, scaleX: 	Math.sqrt(this.a * this.a + this.b * this.b)
			, scaleY: 	Math.sqrt(this.c * this.c + this.d * this.d)
				// Rotation
			, rotation: skewX
			}
		}
		// Multiply
	, multiply: function(matrix) {
			return new SVG.Matrix(this.native().multiply(matrix.native()))
		}
		// Inverse
	, inverse: function() {
			return new SVG.Matrix(this.native().inverse())
		}
		// Translate
	, translate: function(x, y) {
			return new SVG.Matrix(this.native().translate(x || 0, y || 0))	
		}
		// Scale
	, scale: function(x, y, cx, cy) {
			// Support universal scale
			if (arguments.length == 1 || arguments.length == 3)
				y = x
			if (arguments.length == 3) {
				cy = cx
				cx = y
			}

			return this
				.multiply(new SVG.Matrix(1, 0, 0, 1, cx || 0, cy || 0))
				.multiply(new SVG.Matrix(x, 0, 0, y, 0, 0))
				.multiply(new SVG.Matrix(1, 0, 0, 1, -cx || 0, -cy || 0))
		}
		// Rotate
	, rotate: function(d, cx, cy) {
			// Convert degrees to radians
			d = SVG.utils.radians(d)
			
			return this
				.multiply(new SVG.Matrix(1, 0, 0, 1, cx || 0, cy || 0))
				.multiply(new SVG.Matrix(Math.cos(d), Math.sin(d), -Math.sin(d), Math.cos(d), 0, 0))
				.multiply(new SVG.Matrix(1, 0, 0, 1, -cx || 0, -cy || 0))
		}
		// Flip
	, flip: function(a) {
			return new SVG.Matrix(this.native()['flip' + a.toUpperCase()]())
		}
		// Skew
	, skew: function(x, y, cx, cy) {
			// IMPLEMENT SKEW CENTER POINT
			return new SVG.Matrix(this.native().skewX(x || 0).skewY(y || 0))
		}
		// Convert this to SVGMatrix
	, native: function() {
			// Create new matrix
			var i, matrix = SVG.parser.draw.node.createSVGMatrix()
	
			// Update with current values
			for (i = abcdef.length - 1; i >= 0; i--)
				matrix[abcdef[i]] = this[abcdef[i]]

			return matrix
		}
		// Convert array to string
	, toString: function() {
			return 'matrix(' + [this.a, this.b, this.c, this.d, this.e, this.f].join() + ')'
		}
	}

	// Define parent
, parent: SVG.Element

	// Add parent method
, construct: {
		// Get current matrix
		ctm: function() {
			return new SVG.Matrix(this)
		}
	
	}

})