W3C home > Mailing lists > Public > www-style@w3.org > November 2012

Re: [css3-transforms] Multiplication order

From: Dirk Schulze <dschulze@adobe.com>
Date: Sun, 11 Nov 2012 09:12:15 -0800
To: Boris Zbarsky <bzbarsky@MIT.EDU>
CC: "www-style@w3.org" <www-style@w3.org>
Message-ID: <9D8E3AF8-4139-43A7-AE0F-090A1FC512A1@adobe.com>

On Nov 11, 2012, at 8:03 AM, Boris Zbarsky <bzbarsky@MIT.EDU> wrote:

> On 11/11/12 12:56 AM, Simon Sapin wrote:
>> Le 11/11/2012 05:13, Rik Cabanier a écrit :
>>> It's always left to right so:
>>> 
>>>    accumulator = accumulator * to_matrix(function)
>> 
>> Thanks for answering. For some reason I settled on the opposite in my code.
> 
> That's because Rik is mostly wrong.  ;)
> 
> This whole thing is bit of a mess and continues to be in spite of 
> repeated requests to fix it up.  :(  See 
> http://lists.w3.org/Archives/Public/www-style/2011May/0633.html and 

This is addressed in the specification. While the introduction indeed speaks about the transformation of elements (as a starting point for people unfamiliar with transformations), the section about "The Transform Rendering Model"[1] explicitly describes that a transformation function modifies the local coordinate space of an element and that this coordinate space is drawn into the coordinate space of it's parent element (which can be transformed as well).

> http://lists.w3.org/Archives/Public/www-style/2011Feb/0531.html for some 
> previous issues that were raised...  Unfortunately, they were only 
> partially addressed. 
> http://dev.w3.org/csswg/css3-transforms/#mathematical-description now 
> defines what matrix each transform function corresponds to, but not how 
> to apply the matrix.  Note that the matrices defined in this section 
> will act as expected if they are treated as matrices acting on column 
> vectors by left-multiplication.

The mathematical description section defines how the transformation function gets "translated" into a 4x4 matrix. Simon correctly pointed to the section "The Transform Rendering Model"[1] that describes how to multiply transformation functions:

""
	• Start with the identity matrix.
	• Translate by the computed X, Y and Z values of ‘transform-origin’
	• Multiply by each of the transform functions in ‘transform’ property from left to right
""

To get the local transformation matrix of the current element you do the following (note local transformation matrices transform the local coordinate space and are not the CTM):

<div class="transform: translateX(20px) scale(2) rotate(45deg)"></div>

LTM = translateX(20px) * scale(2) * rotate(45deg).

"The Transform Function Lists"[2] explicitly describes the equivalence of multiplying transforms on a list of transform functions to mapping different local coordinate spaces.

""
<div style="transform:translate(-10px,-20px) scale(2) rotate(45deg) translate(5px,10px)"/>

is functionally equivalent to:

<div style="transform:translate(-10px,-20px)">
  <div style="transform:scale(2)">
    <div style="transform:rotate(45deg)">
      <div style="transform:translate(5px,10px)">
      </div>
    </div>
  </div>
</div>
""

Even if it is described in "The Transform Rendering Model" already, this section says how to calculate the CTM:

CTM	= div_(level1) * div_(level2) * div_(level3) * div_(level4)
		= LTM_(level1) * LTM_(level2) * LTM_(level3) * LTM_(level4)
		= translate(-10px,-20px) * scale(2) * rotate(45deg) * translate(5px,10px).

> 
> Rik is thinking of this in terms of what seems to be the usual graphics 
> programming convention in which matrices act on row vectors by 
> right-multiplication.  So for _him_ the multiplication puts the new 
> matrix to the right of the accumulator.

That is what the specification says, no?I am a bit confused about your interpretation of his accumulator right now.

Greetings,
Dirk

> 
> If you're thinking of your matrices as acting on column vectors by 
> left-multiplication, then your multiplication will need to put the new 
> matrix to the left of the accumulator.
> 
> These situations are completely equivalent (because just taking the 
> transpose of everything will go between the two of them).  The main 
> places where confusion can arise are the definition of the 
> "transformation matrix" and the actual definition of what matrices 
> matrix() produces.  The latter has been dealt with, but the former has 
> not as you note.
> 
> What I think we should do is define in section 21 that the matrices it 
> defines act on the column vector [x,y,z,1] by left-multiplication.  And 
> then we should clarify section 6 by either describing what the 
> multiplication order for the matrices is is or by saying that the 
> transformations are applied in order from left to right and that the 
> "transformation matrix" is the matrix of the resulting transformation. 
> That avoids the problem, since transformation application, while 
> non-commutative, does not have the issue of "well, but _how_ do I apply 
> the transformation".
> 
>>>    Similar questions arise with nested "transformed" stacking contexts
> 
> See links above.  :(
> 
>>> Is your confusion with preserver-3d or with regular 2d transforms?
>>> In the case of 2d, the outer transform happens first (= to the left)
> 
> See, this is part of the problem.  The way the spec is phrased right 
> now, "first" is "to the _right_".  And the fact that not everyone is on 
> board with that is not helping.  :(
> 
> -Boris
> 

[1] http://dev.w3.org/csswg/css3-transforms/#transform-rendering
[2] http://dev.w3.org/csswg/css3-transforms/#transform-function-lists
[3] http://dev.w3.org/csswg/css3-transforms/#transform-3d-rendering
Received on Sunday, 11 November 2012 17:12:44 GMT

This archive was generated by hypermail 2.3.1 : Tuesday, 26 March 2013 17:21:02 GMT