Thu, 14 Mar 2013 21:41:18 -0700
Incorporate feedback from Robert O'Callahan.
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <title>Transformation matrix interface</title>
5 <meta charset='utf-8'>
6 <!--<script src='respec-w3c-common.js' class='remove'></script>-->
7 <script src="respec/respec.js" class="remove"></script>
8 <script class='remove'>
9 var respecConfig = {
10 specStatus: "ED",
11 shortName: "matrix",
12 edDraftURI: "https://dvcs.w3.org/hg/FXTF/raw-file/default/matrix/index.html",
13 editors: {name: "none"},//[
14 //{ name: "Dirk Schulze", mailto: "dschulze@adobe.com",
15 // company: "Adobe Systems Inc.", companyURL: "http://adobe.com/" },
16 //],
17 extraCSS: ["respec/respec.css",
18 "matrix.css"],
19 // Turning off inlineCSS for now since if extraCSS points to
20 // a relative URL your testing from a file URL the XHR will fail.
21 // Probably should turn this back on once this is hosted on a server
22 // somewhere.
23 inlineCSS: false,
24 wg: [ "CSS Working Group",
25 "SVG Working Group" ],
26 wgURI: [ "http://dev.w3.org/Style/CSS/members",
27 "http://www.w3.org/Graphics/SVG/WG" ],
29 wgActivity: [
30 [ "Style", "http://www.w3.org/Style/Activity" ],
31 [ "Graphics", "http://www.w3.org/Graphics/Activity" ]
32 ],
33 // name (without the @w3c.org) of the public mailing to which comments are due
34 wgPublicList: "public-fx",
35 wgPatentURI: "",
36 noIDLIn: true,
37 };
38 </script>
39 </head>
40 <body>
41 <section id='abstract'>
42 <p>
43 This specification describes a transformation matrix interface with the dimension of 3x2 and 4x4.
44 </p>
46 <p>
47 The transformation matrix interface replaces the SVGMatrix interface from SVG [[SVG11]]. It is a common interface used to describe 2D and 3D transformations on a graphical context for SVG, Context2D [[CANVAS-2D]], CSS3 Transforms [[CSS3-TRANSFORMS]] and WebGL [[WEBGL]].
48 </p>
49 </section>
51 <section>
52 <h2>Definitions</h2>
53 <dl>
54 <dt><dfn>post-multiply</dfn></dt>
55 <dd>Term A post-multiplied by term B is equal to A · B.</dd>
56 <dt><dfn>pre-multiply</dfn></dt>
57 <dd>Term A pre-multiplied by term B is equal to B · A.</dd>
58 <dt><dfn>multiply</dfn></dt>
59 <dd>Multiply term A by term B is equal to A · B.</dd>
60 </dl>
61 </section>
63 <section>
64 <h2>The <a>Point</a> dictionary</h2>
65 <p>
66 A 2D points and 3D points are represented by the following WebIDL dictionary:
67 </p>
69 <dl title='dictionary Point' class='idl'>
70 <dt>double x = 0</dt>
71 <dd>
72 The x coordinate of the point.
73 </dd>
74 <dt>double y = 0</dt>
75 <dd>
76 The y coordinate of the point.
77 </dd>
78 <dt>double z = 0</dt>
79 <dd>
80 The z coordinate of the point.
81 </dd>
82 <dt>double w = 1</dt>
83 <dd>
84 The perspective of the point.
85 <p class='issue'>
86 A multiplication of a point with a matrix requires 4 values. Implementations usually normalize the point by w. It should be considered to do this here as well.
87 </p>
88 </dd>
89 </dl>
90 </section>
92 <section>
93 <h2>The <a>DecomposedMatrix</a> dictionary</h2>
94 <p>
95 The resulting values of a decomposed matrix as defined by <a href="#decomposing-the-matrix">Decomposing the matrix</a> and used in CSS Transforms [[CSS3-TRANSFORMS]] are represented by the following DecomposedMatrix dictionary:
96 </p>
98 <dl title='dictionary DecomposedMatrix' class='idl'>
99 <dt>sequence<double> translation</dt>
100 <dd>
101 Is an sequence of three double items for the translation of the matrix.
102 </dd>
103 <dt>sequence<double> scale</dt>
104 <dd>
105 Is an sequence of three double items for the scaling of the matrix.
106 </dd>
107 <dt>sequence<double> skew</dt>
108 <dd>
109 Is an sequence of three double items representing the shear of the matrix.
110 </dd>
111 <dt>sequence<double> perspective</dt>
112 <dd>
113 Is an sequence of four double items representing the perspective of the matrix.
114 </dd>
115 <dt>sequence<double> quaternions</dt>
116 <dd>
117 Is an sequence of four double items representing the quaternions for the rotation of the matrix.
118 </dd>
119 </dl>
121 <p class='issue'>Define initial values.</p>
123 <p class='issue'>
124 It is doubtful that this can be very useful for authors. On the other hand, it allows scripted animations similar to the animations by CSS3 Transforms.
125 </p>
126 </section>
128 <section>
129 <h2>The <a>Matrix</a> interface</h2>
131 <p>
132 The <a>Matrix</a> interface represents a mathematical matrix with the purpose of describing transformations a graphical contexts. The following sections describe the details of the interface. For the full interface see <a href="#webidl-ref">Interface summary</a>.
133 </p>
135 <section>
136 <h3>The constructors</h3>
138 <p>
139 A series of constructors to create a <a>Matrix</a> object.
140 </p>
142 <dl title='interface Matrix' class='idl'>
143 <dt>Constructor()</dt>
144 <dd>Creates an identity matrix.</dd>
145 <dt>Constructor()</dt>
146 <dd>
147 <dl class='parameters'>
148 <dt>DOMString transformList</dt>
149 <dd>A DOMString of transformation functions with the syntax and specifies defined in CSS Transforms [[!CSS3-TRANSFORMS]]. One CSS pixel length maps to one unit less value in the matrix.</dd>
150 </dl>
151 The DOMString must consist of a transform function list as specified by CSS Transforms.
152 <div class='example'>
153 <p>In the following example a CSS Transform string is passed to the Matrix constructor.</p>
154 <pre><code>var matrix = new Matrix("translate(20px,20px), scale(2,3), rotate(45deg)"</code></pre>
155 <p>The resulting matrix is equal to the following sequence of method calls:</p>
156 <pre><code>
157 var matrix = new Matrix();
158 matrix.translateBy(20,20);
159 matrix.scaleNonUniformBy(2,3);
160 matrix.rotateBy(45);
161 </code></pre>
162 </div>
163 <p class='issue'>Should it be postponed to avoid CSS3 Transforms dependency?</p>
164 <p class='issue'>Should unit-less values (like for SVG transform presentation attribute) be allowed too? <code>"translate(20,20)"</code></p>
165 <p>Throws a <var>DOMException</var> with name <code>SyntaxError</code> if the <code>DOMString</code> parameter does not validate to a transform list [[!CSS3-TRANSFORMS]].
166 </dd>
167 <dt>Constructor()</dt>
168 <dd>
169 <dl class='parameters'>
170 <dt>Matrix other</dt>
171 <dd>All element values of the current matrix are set to the element values of the other matrix.</dd>
172 </dl>
173 </dd>
174 <dt>Constructor()</dt>
175 <dd>
176 <dl class='parameters'>
177 <dt>DecomposedMatrix decomposedValues</dt>
178 <dd>
179 Recomposes the decomposed values as specified in <a href="#recomposing-the-matrix">Recomposing the matrix</a> and sets the element values of the current matrix.
180 </dd>
181 </dl>
182 </dd>
183 <dt>Constructor()</dt>
184 <dd>
185 <dl class='parameters'>
186 <dt>Float32array array</dt>
187 <dd>
188 Create an identity matrix first. An Float32array [[!TYPED-ARRAYS]] of 6 items sets the element values <code>a</code> to <code>f</code>. An array of 16 items sets the element values <code>m11</code> to <code>m44</code>.
189 </dd>
190 </dl>
191 <p>Throws a <var>DOMException</var> with name <code>SyntaxError</code> if the <code>Float32array</code> parameter does not consist of 6 or 16 items.
192 </dd>
193 <dt>Constructor()</dt>
194 <dd>
195 <dl class='parameters'>
196 <dt>Float64array array</dt>
197 <dd>
198 Create an identity matrix first. An Float64array [[!TYPED-ARRAYS]] of 6 items sets the element values <code>a</code> to <code>f</code>. An array of 16 items sets the element values <code>m11</code> to <code>m44</code>.
199 </dd>
200 </dl>
201 <p>Throws a <var>DOMException</var> with name <code>SyntaxError</code> if the <code>Float64array</code> parameter does not consist of 6 or 16 items.
202 </dd>
203 <dt>Constructor()</dt>
204 <dd>
205 <dl class='parameters'>
206 <dt>sequence<double> numberSequence</dt>
207 <dd>
208 Create an identity matrix first. A sequence of 6 items sets the element values <code>a</code> to <code>f</code>. A sequence of 16 items sets the element values <code>m11</code> to <code>m44</code>.
209 </dd>
210 </dl>
211 <p>Throws a <var>DOMException</var> with name <code>SyntaxError</code> if the number sequence parameter does not consist of 6 or 16 items.
212 </dd>
213 </section>
215 <section>
216 <h3>Two-dimensional attributes</h3>
218 <p>
219 If a <a>Matrix</a> just consists of 2D transformations the 6 values <code>a</code> to <code>f</code> can represent the transformation matrix. If the <a>Matrix</a> object is immutable, a <var>DOMException</var> with name <code>NoModificationAllowedError</code> must be thrown on setting the attributes.
220 </p>
222 <p>
223 The following attributes <code>a</code> to <code>f</code> are aliases to the two-dimensional elements of the 4x4 matrix.
224 </p>
226 <dl title='partial interface Matrix' class='idl'>
227 <dt>// These attributes are simple aliases for certain elements of the 4x4 matrix</dt>
228 <dd></dd>
229 <dt>attribute double a</dt>
230 <dd>
231 <p>Corresponds to the attribute <span>m11</span> of the Matrix interface.</p>
232 </dd>
233 <dt>attribute double b</dt>
234 <dd>
235 <p>Corresponds to the attribute <span>m12</span> of the Matrix interface.</p>
236 </dd>
237 <dt>attribute double c</dt>
238 <dd>
239 <p>Corresponds to the attribute <span>m21</span> of the Matrix interface.</p>
240 </dd>
241 <dt>attribute double d</dt>
242 <dd>
243 <p>Corresponds to the attribute <span>m22</span> of the Matrix interface.</p>
244 </dd>
245 <dt>attribute double e</dt>
246 <dd>
247 <p>Corresponds to the attribute <span>m41</span> of the Matrix interface.</p>
248 </dd>
249 <dt>attribute double f</dt>
250 <dd>
251 <p>Corresponds to the attribute <span>m42</span> of the Matrix interface.</p>
252 </dd>
253 </dl>
254 </section>
256 <section>
257 <h3>Three-dimensional attributes</h3>
259 <p>
260 The following attributes <code>m11</code> to <code>m44</code> represent the elements of the 4x4 matrix. The coordinates are in column-major order. If the <a>Matrix</a> object is immutable, a <var>DOMException</var> with name <code>NoModificationAllowedError</code> must be thrown on setting the attributes.
261 </p>
263 <dl title='partial interface Matrix' class='idl'>
264 <dt>attribute double m11</dt>
265 <dd>
266 <p>
267 The value of the element in column 1, row 1 of the matrix.
268 </p>
269 </dd>
270 <dt>attribute double m12</dt>
271 <dd>
272 <p>
273 The value of the element in column 1, row 2 of the matrix.
274 </p>
275 </dd>
276 <dt>attribute double m13</dt>
277 <dd>
278 <p>
279 The value of the element in column 1, row 3 of the matrix.
280 </p>
281 </dd>
282 <dt>attribute double m14</dt>
283 <dd>
284 <p>
285 The value of the element in column 1, row 4 of the matrix.
286 </p>
287 </dd>
288 <dt>attribute double m21</dt>
289 <dd>
290 <p>
291 The value of the element in column 2, row 1 of the matrix.
292 </p>
293 </dd>
294 <dt>attribute double m22</dt>
295 <dd>
296 <p>
297 The value of the element in column 2, row 2 of the matrix.
298 </p>
299 </dd>
300 <dt>attribute double m23</dt>
301 <dd>
302 <p>
303 The value of the element in column 2, row 3 of the matrix.
304 </p>
305 </dd>
306 <dt>attribute double m24</dt>
307 <dd>
308 <p>
309 The value of the element in column 2, row 4 of the matrix.
310 </p>
311 </dd>
312 <dt>attribute double m31</dt>
313 <dd>
314 <p>
315 The value of the element in column 3, row 1 of the matrix.
316 </p>
317 </dd>
318 <dt>attribute double m32</dt>
319 <dd>
320 <p>
321 The value of the element in column 3, row 2 of the matrix.
322 </p>
323 </dd>
324 <dt>attribute double m33</dt>
325 <dd>
326 <p>
327 The value of the element in column 3, row 3 of the matrix.
328 </p>
329 </dd>
330 <dt>attribute double m34</dt>
331 <dd>
332 <p>
333 The value of the element in column 3, row 4 of the matrix.
334 </p>
335 </dd>
336 <dt>attribute double m41</dt>
337 <dd>
338 <p>
339 The value of the element in column 4, row 1 of the matrix.
340 </p>
341 </dd>
342 <dt>attribute double m42</dt>
343 <dd>
344 <p>
345 The value of the element in column 4, row 2 of the matrix.
346 </p>
347 </dd>
348 <dt>attribute double m43</dt>
349 <dd>
350 <p>
351 The value of the element in column 4, row 3 of the matrix.
352 </p>
353 </dd>
354 <dt>attribute double m44</dt>
355 <dd>
356 <p>
357 The value of the element in column 4, row 4 of the matrix.
358 </p>
359 </dd>
360 </dl>
361 </section>
363 <section>
364 <h3>Immutable transformation methods</h3>
366 <p>
367 The following methods do not modify the current matrix and return new <a>Matrix</a> object.
368 </p>
370 <dl title='partial interface Matrix' class='idl'>
371 <dt>// Immutable transform methods</dt>
372 <dd></dd>
373 <dt>Matrix translate()</dt>
374 <dd>
375 <dl class='parameters'>
376 <dt>double tx</dt>
377 <dd>Translation value along the x-axis.</dd>
378 <dt>double ty</dt>
379 <dd>Translation value along the y-axis.</dd>
380 <dt>optional double tz = 0</dt>
381 <dd>Optional translation value along the z-axis.</dd>
382 </dl>
383 Post-multiplies a translation transformation on the current matrix and returns the resulting matrix. The current matrix is not modified.
384 </dd>
385 <dt>Matrix scale()</dt>
386 <dd>
387 <dl class='parameters'>
388 <dt>double scale</dt>
389 <dd>Multiplier for a uniform scale transformation.</dd>
390 <dt>optional double originX = 0</dt>
391 <dd>Transformation origin on the x-axis.</dd>
392 <dt>optional double originY = 0</dt>
393 <dd>Transformation origin on the y-axis.</dd>
394 </dl>
395 Post-multiplies a uniform 2D scale transformation (<code>m11 = m22 = scale</code>) on the current matrix with the given origin and returns the resulting matrix. The current matrix is not modified.
396 </dd>
397 <dt>Matrix scale3d()</dt>
398 <dd>
399 <dl class='parameters'>
400 <dt>double scale</dt>
401 <dd>Multiplier for a uniform scale transformation.</dd>
402 <dt>optional double originX = 0</dt>
403 <dd>Transformation origin on the x-axis.</dd>
404 <dt>optional double originY = 0</dt>
405 <dd>Transformation origin on the y-axis.</dd>
406 <dt>optional double originZ = 0</dt>
407 <dd>Transformation origin on the z-axis.</dd>
408 </dl>
409 Post-multiplies a uniform scale transformation (<code>m11 = m22 = m33 = scale</code>) on the current matrix with the given origin and returns the resulting matrix. The current matrix is not modified.
410 </dd>
411 <dt>Matrix scaleNonUniform()</dt>
412 <dd>
413 <dl class='parameters'>
414 <dt>double scaleX</dt>
415 <dd>Multiplier for a non-uniform scale along the x-axis.</dd>
416 <dt>optional double scaleY = 1</dt>
417 <dd>Multiplier for a non-uniform scale along the y-axis.</dd>
418 <dt>optional double scaleZ = 1</dt>
419 <dd>Multiplier for a non-uniform scale along the z-axis.</dd>
420 <dt>optional double originX = 0</dt>
421 <dd>Transformation origin on the x-axis.</dd>
422 <dt>optional double originY = 0</dt>
423 <dd>Transformation origin on the y-axis.</dd>
424 <dt>optional double originZ = 0</dt>
425 <dd>Transformation origin on the z-axis.</dd>
426 </dl>
427 Post-multiplies a non-uniform scale transformation on the current matrix with the given origin and returns the resulting matrix. The current matrix is not modified.
428 </dd>
429 <dt>Matrix rotate()</dt>
430 <dd>
431 <dl class='parameters'>
432 <dt>double angle</dt>
433 <dd>Rotation angle in degrees.</dd>
434 <dt>optional double originX = 0</dt>
435 <dd>Transformation origin on the x-axis.</dd>
436 <dt>optional double originY = 0</dt>
437 <dd>Transformation origin on the y-axis.</dd>
438 </dl>
439 Post-multiplies a rotation transformation on the current matrix with the given origin and returns the resulting matrix. The current matrix is not modified.
440 </dd>
441 <dt>Matrix rotateFromVector(double x, double y)</dt>
442 <dd>
443 <dl class='parameters'>
444 <dt>double x</dt>
445 <dd>The x coordinate of the vector (x,y). Must not be zero.</dd>
446 <dt>double y</dt>
447 <dd>The y coordinate of the vector (x,y). Must not be zero.</dd>
448 </dl>
449 Post-multiplies a rotation transformation on the current matrix and returns the resulting matrix. The rotation angle is determined by taking (+/-) atan(y/x). The direction of the vector (x, y) determines whether the positive or negative angle value is used. The current matrix is not modified.
450 </dd>
451 <dt>Matrix rotateAxisAngle(double x, double y, double z, double angle)</dt>
452 <dd>
453 <dl class='parameters'>
454 <dt>double x</dt>
455 <dd>The x coordinate of the vector (x,y,z).</dd>
456 <dt>double y</dt>
457 <dd>The y coordinate of the vector (x,y,z).</dd>
458 <dt>double z</dt>
459 <dd>The z coordinate of the vector (x,y,z).</dd>
460 <dt>double angle</dt>
461 <dd>Rotation angle in degrees.</dd>
462 Post-multiplies a rotation transformation on the current matrix and returns the resulting matrix. The rotation of the transform is applied around the given vector. The current matrix is not modified.
463 </dl>
464 </dd>
465 <dt>Matrix skewX()</dt>
466 <dd>
467 <dl class='parameters'>
468 <dt>double sx</dt>
469 <dd>Skew angle along the x-axis in degrees.</dd>
470 </dl>
471 Post-multiplies a skewX transformation on the current matrix and returns the resulting matrix. The current matrix is not modified.
472 </dd>
473 <dt>Matrix skewY()</dt>
474 <dd>
475 <dl class='parameters'>
476 <dt>double sy</dt>
477 <dd>Skew angle along the y-axis in degrees.</dd>
478 </dl>
479 Post-multiplies a skewX transformation on the current matrix and returns the resulting matrix.
480 </dd>
481 <dt>Matrix multiply()</dt>
482 <dd>
483 <dl class='parameters'>
484 <dt>Matrix other</dt>
485 <dd>Other matrix for multiplication</dd>
486 </dl>
487 Performs matrix multiplication. This matrix is post-multiplied by the other matrix, returning the resulting new matrix. The current matrix is not modified.
488 </dd>
489 <dt>Matrix flipX()</dt>
490 <dd>
491 Post-multiplies the transformation <code>Matrix(-1, 0, 0, 1, 0, 0)</code> and returns the resulting matrix. The current matrix is not modified.
492 </dd>
493 <dt>Matrix flipY()</dt>
494 <dd>
495 Post-multiplies the transformation <code>Matrix(1, 0, 0, -1, 0, 0)</code> and returns the resulting matrix. The current matrix is not modified.
496 </dd>
497 <dt>Matrix? inverse()</dt>
498 <dd>
499 Returns the inverted matrix of the current matrix if applicable. Otherwise <code>null</code>. The current matrix is not modified.
500 <dl class='exceptions'>
501 <dt>DOMException of type
502 <code>InvalidModificationError</code></dt>
503 <dd>
504 Raised when the current matrix is singular.
505 </dd>
506 </dl>
507 </dd>
508 </dl>
509 </section>
511 <section>
512 <h3>Mutable transformation methods</h3>
514 <p>
515 The following methods do modify the current matrix. If the <a>Matrix</a> object is immutable, a <var>DOMException</var> with name <code>NoModificationAllowedError</code> must be thrown on calling the operations below.
516 </p>
518 <dl title='partial interface Matrix' class='idl'>
519 <dt>// Mutable transform methods</dt>
520 <dd></dd>
521 <dt>void multiplyBy()</dt>
522 <dd>
523 <dl class='parameters'>
524 <dt>Matrix other</dt>
525 <dd>The matrix that gets post-multiplied.</dd>
526 </dl>
527 The other matrix gets post-multiplied to the current matrix.
528 </dd>
529 <dt>void preMultiplyBy()</dt>
530 <dd>
531 <dl class='parameters'>
532 <dt>Matrix other</dt>
533 <dd>The matrix that gets pre-multiplied.</dd>
534 </dl>
535 The other matrix gets pre-multiplied to the current matrix.
536 </dd>
537 <dt>void translateBy()</dt>
538 <dd>
539 <dl class='parameters'>
540 <dt>double tx</dt>
541 <dd>Translation value along the x-axis.</dd>
542 <dt>double ty</dt>
543 <dd>Translation value along the y-axis.</dd>
544 <dt>optional double tz = 0</dt>
545 <dd>Optional translation value along the z-axis.</dd>
546 </dl>
547 Post-multiplies a translation transformation on the current matrix.
548 </dd>
549 <dt>void scaleBy()</dt>
550 <dd>
551 <dl class='parameters'>
552 <dt>double scale</dt>
553 <dd>Multiplier for a uniform scale transformation.</dd>
554 <dt>optional double originX = 0</dt>
555 <dd>Transformation origin on the x-axis.</dd>
556 <dt>optional double originY = 0</dt>
557 <dd>Transformation origin on the y-axis.</dd>
558 </dl>
559 Post-multiplies a uniform 2D scale transformation (<code>m11 = m22 = scale</code>) on the current matrix with the given origin.
560 </dd>
561 <dt>void scale3dBy()</dt>
562 <dd>
563 <dl class='parameters'>
564 <dt>double scale</dt>
565 <dd>Multiplier for a uniform scale transformation.</dd>
566 <dt>optional double originX = 0</dt>
567 <dd>Transformation origin on the x-axis.</dd>
568 <dt>optional double originY = 0</dt>
569 <dd>Transformation origin on the y-axis.</dd>
570 <dt>optional double originZ = 0</dt>
571 <dd>Transformation origin on the z-axis.</dd>
572 </dl>
573 Post-multiplies a uniform 2D scale transformation (<code>m11 = m22 = m33 = scale</code>) on the current matrix with the given origin.
574 </dd>
575 <dt>void scaleNonUniformBy()</dt>
576 <dd>
577 <dl class='parameters'>
578 <dt>double scaleX</dt>
579 <dd>Multiplier for a non-uniform scale along the x-axis.</dd>
580 <dt>optional double scaleY = 1</dt>
581 <dd>Multiplier for a non-uniform scale along the y-axis.</dd>
582 <dt>optional double scaleZ = 1</dt>
583 <dd>Multiplier for a non-uniform scale along the z-axis.</dd>
584 <dt>optional double originX = 0</dt>
585 <dd>Transformation origin on the x-axis.</dd>
586 <dt>optional double originY = 0</dt>
587 <dd>Transformation origin on the y-axis.</dd>
588 <dt>optional double originZ = 0</dt>
589 <dd>Transformation origin on the z-axis.</dd>
590 </dl>
591 Post-multiplies a non-uniform scale transformation on the current matrix with the given origin.
592 </dd>
593 <dt>void rotateBy()</dt>
594 <dd>
595 <dl class='parameters'>
596 <dt>double angle</dt>
597 <dd>Rotation angle in degrees.</dd>
598 <dt>optional double originX = 0</dt>
599 <dd>Transformation origin on the x-axis.</dd>
600 <dt>optional double originY = 0</dt>
601 <dd>Transformation origin on the y-axis.</dd>
602 </dl>
603 Post-multiplies a rotation transformation on the current matrix with the given origin.
604 </dd>
605 <dt>void rotateFromVectorBy(double x, double y)</dt>
606 <dd>
607 <dl class='parameters'>
608 <dt>double x</dt>
609 <dd>The x coordinate of the vector (x,y). Must not be zero.</dd>
610 <dt>double y</dt>
611 <dd>The y coordinate of the vector (x,y). Must not be zero.</dd>
612 </dl>
613 Post-multiplies a rotation transformation on the current matrix. The rotation angle is determined by taking (+/-) atan(y/x). The direction of the vector (x, y) determines whether the positive or negative angle value is used.
614 </dd>
615 <dt>void rotateAxisAngleBy(double x, double y, double z, double angle)</dt>
616 <dd>
617 <dl class='parameters'>
618 <dt>double x</dt>
619 <dd>The x coordinate of the vector (x,y,z).</dd>
620 <dt>double y</dt>
621 <dd>The y coordinate of the vector (x,y,z).</dd>
622 <dt>double z</dt>
623 <dd>The z coordinate of the vector (x,y,z).</dd>
624 <dt>double angle</dt>
625 <dd>Rotation angle in degrees.</dd>
626 Post-multiplies a rotation transformation on the current matrix. The rotation of the transform is applied around the given vector.
627 </dl>
628 </dd>
629 <dt>void skewXBy()</dt>
630 <dd>
631 <dl class='parameters'>
632 <dt>double sx</dt>
633 <dd>Skew angle along the x-axis in degrees.</dd>
634 </dl>
635 Post-multiplies a skewX transformation on the current matrix.
636 </dd>
637 <dt>void skewYBy()</dt>
638 <dd>
639 <dl class='parameters'>
640 <dt>double sy</dt>
641 <dd>Skew angle along the y-axis in degrees.</dd>
642 </dl>
643 Post-multiplies a skewX transformation on the current matrix.
644 </dd>
645 <dt>void invert()</dt>
646 <dd>
647 Inverts the current matrix.
648 <dl class='exceptions'>
649 <dt>DOMException of type
650 <code>InvalidModificationError</code></dt>
651 <dd>
652 Raised when the current matrix is singular.
653 </dd>
654 </dl>
655 </dd>
656 </dl>
657 </section>
659 <section>
660 <h3>Helper methods</h3>
662 <p>
663 The following helper methods do not modify the <a>Matrix</a> object.
664 </p>
666 <dl title='partial interface Matrix' class='idl'>
667 <dt>// Helper methods</dt>
668 <dd></dd>
669 <dt>boolean is2D()</dt>
670 <dd>
671 Returns <code>true</code> if <code>m13</code>, <code>m14</code>, <code>m23</code>, <code>m24</code>, <code>m31</code>, <code>m32</code>, <code>m34</code>, <code>m43</code> are equal to zero and <code>m33</code>, <code>m44</code> are equal to one.
672 </dd>
673 <dt>double determinant()</dt>
674 <dd>
675 Returns the determinant of the current matrix.
676 </dd>
677 <dt>Point transformPoint()</dt>
678 <dd>
679 <dl class='parameters'>
680 <dt>Point point</dt>
681 <dd>A Point dictionary.</dd>
682 </dl>
683 The point is post-multiplied on the current matrix and returns the resulting point. <code>point</code> is not modified.
684 </dd>
685 <dt>Float32Array toFloat32Array()</dt>
686 <dd>
687 Returns the serialized 16 elements <code>m11</code> to <code>m44</code> of the current matrix in column-major order as Float32Array [[!TYPED-ARRAYS]].
688 </dd>
689 <dt>Float64Array toFloat64Array()</dt>
690 <dd>
691 Returns the serialized 16 elements <code>m11</code> to <code>m44</code> of the current matrix in column-major order as Float64Array [[!TYPED-ARRAYS]].
692 </dd>
693 <dt>DecomposedMatrix decompose()</dt>
694 <dd>
695 Returns the decomposed matrix values of the current matrix as a DecomposedMatrix dictionary. The decomposing follows the algorithm of <a href="#decomposing-the-matrix">Decomposing the Matrix</a>.
696 </dd>
697 <dt>void stringifier()</dt>
698 <dd>
699 Returns a string in the form of a CSS Transforms <code>matrix</code> function if the current matrix is a 2D transform or a CSS Transforms <code>matrix3d</code> else. The syntax is as specified in CSS Transforms [[!CSS3-TRANSFORMS]].
700 <p class='issue'>Should be <code>stringifier;</code>. Bug in old respec tool.</p>
701 <div class='example'>
702 <p>In this example a matrix is created and several methods with 2D transformations are called.</p>
703 <pre><code>var matrix = new Matrix();
704 matrix.scaleBy(2);
705 matrix.translateBy(20,20);</code></pre>
706 <p>The <code>matrix.toString()</code> returns the DOM string:</p>
707 <pre><code>"matrix(2,0,0,2,20,20)"</code></pre>
708 <p>For 3D operations, the <var>stringifier</var> returns DOM string representing a 3D matrix.</p>
709 <pre><code>var matrix = new Matrix();
710 matrix.scale3dBy(2);</code></pre>
711 <p>Calling <code>matrix.toString()</code> after the snippet above returns the DOM string:</p>
712 <pre><code>"matrix3d(2,0,0,0,0,2,0,0,0,0,2,0,0,0,0,1)"</code></pre>
713 </div>
714 </dd>
715 </dl>
716 </section>
717 </section>
719 <section>
720 <h2>Decomposing the Matrix</h2>
722 <p class='issue'>It is unsure if Transformation Matrix should reference the code of CSS3 Transforms
723 or the other way around. Clearly we do not need the code twice.
724 </p>
725 <p>
726 The pseudocode below is based upon the "unmatrix" method in "Graphics Gems II,
727 edited by Jim Arvo", but modified to use Quaternions instead of Euler angles to
728 avoid the problem of Gimbal Locks.
729 </p>
731 <p>
732 The following pseudocode works on a 4x4 homogeneous matrix:
733 </p>
735 <pre>Input: matrix ; a 4x4 matrix
736 Output: translation ; a 3 component vector
737 scale ; a 3 component vector
738 skew ; skew factors XY,XZ,YZ represented as a 3 component vector
739 perspective ; a 4 component vector
740 quaternion ; a 4 component vector
741 Returns false if the matrix cannot be decomposed, true if it can
743 Supporting functions (point is a 3 component vector, matrix is a 4x4 matrix):
744 double determinant(matrix) returns the 4x4 determinant of the matrix
745 matrix inverse(matrix) returns the inverse of the passed matrix
746 matrix transpose(matrix) returns the transpose of the passed matrix
747 point multVecMatrix(point, matrix) multiplies the passed point by the passed matrix
748 and returns the transformed point
749 double length(point) returns the length of the passed vector
750 point normalize(point) normalizes the length of the passed point to 1
751 double dot(point, point) returns the dot product of the passed points
752 double sqrt(double) returns the root square of passed value
753 double max(double y, double x) returns the bigger value of the two passed values
755 Decomposition also makes use of the following function:
756 point combine(point a, point b, double ascl, double bscl)
757 result[0] = (ascl * a[0]) + (bscl * b[0])
758 result[1] = (ascl * a[1]) + (bscl * b[1])
759 result[2] = (ascl * a[2]) + (bscl * b[2])
760 return result
762 // Normalize the matrix.
763 if (matrix[3][3] == 0)
764 return false
766 for (i = 0; i < 4; i++)
767 for (j = 0; j < 4; j++)
768 matrix[i][j] /= matrix[3][3]
770 // perspectiveMatrix is used to solve for perspective, but it also provides
771 // an easy way to test for singularity of the upper 3x3 component.
772 perspectiveMatrix = matrix
774 for (i = 0; i < 3; i++)
775 perspectiveMatrix[i][3] = 0
777 perspectiveMatrix[3][3] = 1
779 if (determinant(perspectiveMatrix) == 0)
780 return false
782 // First, isolate perspective.
783 if (matrix[0][3] != 0 || matrix[1][3] != 0 || matrix[2][3] != 0)
784 // rightHandSide is the right hand side of the equation.
785 rightHandSide[0] = matrix[0][3];
786 rightHandSide[1] = matrix[1][3];
787 rightHandSide[2] = matrix[2][3];
788 rightHandSide[3] = matrix[3][3];
790 // Solve the equation by inverting perspectiveMatrix and multiplying
791 // rightHandSide by the inverse.
792 inversePerspectiveMatrix = inverse(perspectiveMatrix)
793 transposedInversePerspectiveMatrix = transposeMatrix4(inversePerspectiveMatrix)
794 perspective = multVecMatrix(rightHandSide, transposedInversePerspectiveMatrix)
795 else
796 // No perspective.
797 perspective[0] = perspective[1] = perspective[2] = 0
798 perspective[3] = 1
800 // Next take care of translation
801 for (i = 0; i < 3; i++)
802 translate[i] = matrix[3][i]
804 // Now get scale and shear. 'row' is a 3 element array of 3 component vectors
805 for (i = 0; i < 3; i++)
806 row[i][0] = matrix[i][0]
807 row[i][1] = matrix[i][1]
808 row[i][2] = matrix[i][2]
810 // Compute X scale factor and normalize first row.
811 scale[0] = length(row[0])
812 row[0] = normalize(row[0])
814 // Compute XY shear factor and make 2nd row orthogonal to 1st.
815 skew[0] = dot(row[0], row[1])
816 row[1] = combine(row[1], row[0], 1.0, -skew[0])
818 // Now, compute Y scale and normalize 2nd row.
819 scale[1] = length(row[1])
820 row[1] = normalize(row[1])
821 skew[0] /= scale[1];
823 // Compute XZ and YZ shears, orthogonalize 3rd row
824 skew[1] = dot(row[0], row[2])
825 row[2] = combine(row[2], row[0], 1.0, -skew[1])
826 skew[2] = dot(row[1], row[2])
827 row[2] = combine(row[2], row[1], 1.0, -skew[2])
829 // Next, get Z scale and normalize 3rd row.
830 scale[2] = length(row[2])
831 row[2] = normalize(row[2])
832 skew[1] /= scale[2]
833 skew[2] /= scale[2]
835 // At this point, the matrix (in rows) is orthonormal.
836 // Check for a coordinate system flip. If the determinant
837 // is -1, then negate the matrix and the scaling factors.
838 pdum3 = cross(row[1], row[2])
839 if (dot(row[0], pdum3) < 0)
840 for (i = 0; i < 3; i++)
841 scale[i] *= -1;
842 row[i][0] *= -1
843 row[i][1] *= -1
844 row[i][2] *= -1
846 // Now, get the rotations out
847 quaternion[0] = 0.5 * sqrt(max(1 + row[0][0] - row[1][1] - row[2][2], 0))
848 quaternion[1] = 0.5 * sqrt(max(1 - row[0][0] + row[1][1] - row[2][2], 0))
849 quaternion[2] = 0.5 * sqrt(max(1 - row[0][0] - row[1][1] + row[2][2], 0))
850 quaternion[3] = 0.5 * sqrt(max(1 + row[0][0] + row[1][1] + row[2][2], 0))
852 if (row[2][1] > row[1][2])
853 quaternion[0] = -quaternion[0]
854 if (row[0][2] > row[2][0])
855 quaternion[1] = -quaternion[1]
856 if (row[1][0] > row[0][1])
857 quaternion[2] = -quaternion[2]
859 return true</pre>
860 </section>
862 <section>
863 <h2>Recomposing the Matrix</h2>
865 <p class='issue'>
866 Same as for decompose matrix
867 </p>
869 <p>
870 After interpolation the resulting values are used to transform the elements user
871 space. One way to use these values is to recompose them into a 4x4 matrix. This can
872 be done following the pseudo-code below:
873 </p>
875 <pre>Input: translation ; a 3 component vector
876 scale ; a 3 component vector
877 skew ; skew factors XY,XZ,YZ represented as a 3 component vector
878 perspective ; a 4 component vector
879 quaternion ; a 4 component vector
880 Output: matrix ; a 4x4 matrix
882 Supporting functions (matrix is a 4x4 matrix):
883 matrix multiply(matrix a, matrix b) returns the 4x4 matrix product of a * b
885 // apply perspective
886 for (i = 0; i < 4; i++)
887 matrix[i][3] = perspective[i]
889 // apply translation
890 for (i = 0; i < 3; i++)
891 for (j = 0; j < 3; j++)
892 matrix[3][i] += translation[j] * matrix[j][i]
894 // apply rotation
895 x = quaternion[0]
896 y = quaternion[1]
897 z = quaternion[2]
898 w = quaternion[3]
900 // Construct a composite rotation matrix from the quaternion values
901 // rotationMatrix is a identity 4x4 matrix initially
902 rotationMatrix[0][0] = 1 - 2 * (y * y + z * z)
903 rotationMatrix[0][1] = 2 * (x * y - z * w)
904 rotationMatrix[0][2] = 2 * (x * z + y * w)
905 rotationMatrix[1][0] = 2 * (x * y + z * w)
906 rotationMatrix[1][1] = 1 - 2 * (x * x + z * z)
907 rotationMatrix[1][2] = 2 * (y * z - x * w)
908 rotationMatrix[2][0] = 2 * (x * z - y * w)
909 rotationMatrix[2][1] = 2 * (y * z + x * w)
910 rotationMatrix[2][2] = 1 - 2 * (x * x + y * y)
912 matrix = multiply(matrix, rotationMatrix)
914 // apply skew
915 // temp is a identity 4x4 matrix initially
916 if (skew[2])
917 temp[2][1] = skew[2]
918 matrix = multiply(matrix, temp)
920 if (skew[1])
921 temp[2][1] = 0
922 temp[2][0] = skew[1]
923 matrix = multiply(matrix, temp)
925 if (skew[0])
926 temp[2][0] = 0
927 temp[1][0] = skew[0]
928 matrix = multiply(matrix, temp)
930 // apply scale
931 for (i = 0; i < 3; i++)
932 for (j = 0; j < 3; j++)
933 matrix[i][j] *= scale[i]
935 return</pre>
936 </section>
938 <section class='appendix' id="webidl-ref">
939 <h2>Interface summary</h2>
940 </section>
942 <section class='appedix'>
943 <h2>Conformance</h2>
945 <section>
946 <h3 id="conventions">
947 Document conventions</h3>
949 <p>Conformance requirements are expressed with a combination of
950 descriptive assertions and RFC 2119 terminology. The key words “MUST”,
951 “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”,
952 “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this
953 document are to be interpreted as described in RFC 2119.
954 However, for readability, these words do not appear in all uppercase
955 letters in this specification.
957 <p>All of the text of this specification is normative except sections
958 explicitly marked as non-normative, examples, and notes. [[!RFC2119]]</p>
960 <p>Examples in this specification are introduced with the words “for example”
961 or are set apart from the normative text with <code>class="example"</code>,
962 like this:
964 <div class="example">
965 <p>This is an example of an informative example.</p>
966 </div>
968 <p>Informative notes begin with the word “Note” and are set apart from the
969 normative text with <code>class="note"</code>, like this:
971 <p class="note">Note, this is an informative note.</p>
972 </section>
974 <section>
975 <h3 id="conformance-classes">
976 Conformance classes</h3>
978 <p>Conformance to this specification
979 is defined for three conformance classes:
980 <dl>
981 <dt><dfn title="style sheet!!as conformance class">style sheet</dfn>
982 <dd>A <a href="http://www.w3.org/TR/CSS21/conform.html#style-sheet">CSS
983 style sheet</a>.
984 <dt><dfn>renderer</dfn></dt>
985 <dd>A <a href="http://www.w3.org/TR/CSS21/conform.html#user-agent">UA</a>
986 that interprets the semantics of a style sheet and renders
987 documents that use them.
988 <dt><dfn id="authoring-tool">authoring tool</dfn></dt>
989 <dd>A <a href="http://www.w3.org/TR/CSS21/conform.html#user-agent">UA</a>
990 that writes a style sheet.
991 </dl>
993 <p>A style sheet is conformant to this specification
994 if all of its statements that use syntax defined in this module are valid
995 according to the generic CSS grammar and the individual grammars of each
996 feature defined in this module.
998 <p>A renderer is conformant to this specification
999 if, in addition to interpreting the style sheet as defined by the
1000 appropriate specifications, it supports all the features defined
1001 by this specification by parsing them correctly
1002 and rendering the document accordingly. However, the inability of a
1003 UA to correctly render a document due to limitations of the device
1004 does not make the UA non-conformant. (For example, a UA is not
1005 required to render color on a monochrome monitor.)
1007 <p>An authoring tool is conformant to this specification
1008 if it writes style sheets that are syntactically correct according to the
1009 generic CSS grammar and the individual grammars of each feature in
1010 this module, and meet all other conformance requirements of style sheets
1011 as described in this module.
1012 </section>
1014 <section>
1015 <h3 id="partial">
1016 Partial implementations</h3>
1018 <p>So that authors can exploit the forward-compatible parsing rules to
1019 assign fallback values, CSS renderers <strong>must</strong>
1020 treat as invalid (and <a href="http://www.w3.org/TR/CSS21/conform.html#ignore">ignore
1021 as appropriate</a>) any at-rules, properties, property values, keywords,
1022 and other syntactic constructs for which they have no usable level of
1023 support. In particular, user agents <strong>must not</strong> selectively
1024 ignore unsupported component values and honor supported values in a single
1025 multi-value property declaration: if any value is considered invalid
1026 (as unsupported values must be), CSS requires that the entire declaration
1027 be ignored.</p>
1028 </section>
1030 <section>
1031 <h3 id="experimental">
1032 Experimental implementations</h3>
1034 <p>To avoid clashes with future CSS features, the CSS2.1 specification
1035 reserves a <a href="http://www.w3.org/TR/CSS21/syndata.html#vendor-keywords">prefixed
1036 syntax</a> for proprietary and experimental extensions to CSS.
1038 <p>Prior to a specification reaching the Candidate Recommendation stage
1039 in the W3C process, all implementations of a CSS feature are considered
1040 experimental. The CSS Working Group recommends that implementations
1041 use a vendor-prefixed syntax for such features, including those in
1042 W3C Working Drafts. This avoids incompatibilities with future changes
1043 in the draft.
1044 </p>
1045 </section>
1047 <section>
1048 <h3 id="testing">
1049 Non-experimental implementations</h3>
1051 <p>Once a specification reaches the Candidate Recommendation stage,
1052 non-experimental implementations are possible, and implementors should
1053 release an unprefixed implementation of any CR-level feature they
1054 can demonstrate to be correctly implemented according to spec.
1056 <p>To establish and maintain the interoperability of CSS across
1057 implementations, the CSS Working Group requests that non-experimental
1058 CSS renderers submit an implementation report (and, if necessary, the
1059 testcases used for that implementation report) to the W3C before
1060 releasing an unprefixed implementation of any CSS features. Testcases
1061 submitted to W3C are subject to review and correction by the CSS
1062 Working Group.
1064 <p>Further information on submitting testcases and implementation reports
1065 can be found from on the CSS Working Group's website at
1066 <a href="http://www.w3.org/Style/CSS/Test/">http://www.w3.org/Style/CSS/Test/</a>.
1067 Questions should be directed to the
1068 <a href="http://lists.w3.org/Archives/Public/public-css-testsuite">public-css-testsuite@w3.org</a>
1069 mailing list.
1070 </section>
1071 </section>
1073 <section class='appendix'>
1074 <h2>Acknowledgments</h2>
1075 <p>
1076 Many thanks to Dean Jackson for his initial proposal to make this specification possible.
1077 </p>
1078 </section>
1079 </body>
1080 </html>