Proposals/Specifying decomposition of scale

From SVG

This proposal is prepared in order to specify decomposition of scale (NOT scale-x or scale-y) in CSS Transforms.

Use Cases

non-scaling Objects

As a part of Vector Effects, SVGWG decided to put a non-scaling Objects function into SVG2. [1]

See a polyfill for non-scaling Objects.

<path vector-effect="non-scaling-size" stroke="red" stroke-width="3" fill="none" transform="matrix(1,0,0,1,150,150)" d="M-50,-50 L50,-50 50,-100 150,0 50,100 50,50 -50,50 -50,-50z M5 0 L0 -5  -5 0 0 5z"/>

Level of detail

SVGWG also determined to standardize a kind of Level Of Detail function which can change contents according to the scale.

See Number19 of SVG2 Requirements Commitments and SVGWG charter's deliverables section

Since this function will turn into a function not only concerning SVG but also Media Queries, I (stakagi) think that I will separately propose the specification for Level of Deatil to FXTF later.

Previous discussion: Zoom feature for media queries

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" viewBox="0 0 100 100">
 <title>Simple SVG + mediaqueries</title>
 <defs>
 <style type="text/css">
   @media (min-scale: 1.5) { <! -- this may be min-zoom: 1.5 -->
     #LowRes  { display: none;   }
     #MedRes  { display: inline; }
     #HighRes { display: none;   }
   }
   @media (min-scale: 2.5) { <! -- this may be min-zoom: 2.5 -->
     #LowRes  { display: none;   }
     #MedRes  { display: none;   }
     #HighRes { display: inline; }
   }
 </style>
 </defs>
 <g id="LowRes" display="inline">
   <! -- Contents for LowRes -->
 </g>
 <g id="MedRes" display="none">
   <! -- Contents for MedRes -->
 </g>
 <g id="HighRes" display="none">
   <! -- Contents for HighRes -->
 </g>
</svg>

The necessity of 'scale' value

The scale value (not scaleX, scaleY, scaleZ) decomposed from the transform matrix is required for each function. And, such scale value is desired to be determined as one scalar value which is always meaningful on all the affine transformation containing skew. It is because almost use cases of non-scaling and level of detail are specific axis independent.

Note

On the non-scaling polyfill, you will look at the strange action by skew, when scaleX and scaleY are chosen as the criteria of scale.

Issues

CSS Transforms has specified decomposition in 21.2.1 Decomposing a 2D matrix and 21.3.1 Decomposing a 3D matrix chapter. However, these chapters specify only the method of decomposing scales for individual axis (scaleX, scaleY and scaleZ).

Proposal

Then, I would like to add the description to specify the decomposition formula of such single unified scalar scale value which does not depend on a specific axis into those chapters.

2D Decomposition

scale = sqrt( abs( scaleX * scaleY * sin( ∠((m11,m12),(m21,m22)) ) ) ) = sqrt( abs( determinant ) )

3D Decomposition

scale = pow( abs( determinant ) , 1/3 )

Note:

Generally determinant is specified as a scale factor on coordinate transformation. (wikipedia:Determinant) However, in the case of 2D, it is a scale factor on the area. And in the case of 3D, it is a scale factor on the volume.

On the other hand, the scale parameter of scale() in CSS transforms is defined as a one-dimensional factor in any case. Then, in order to align a dimension, it is appropriate to assign the cubic root of determinant to the scale in the case of 3D. And it is also appropriate to assign the square root of determinant to the scale in the case of 2D.

Recomposition

When all the axes intersects orthogonally and scales of each axis are equal, the single scale value is equal to scales for each axis. Therefore it is equivalent to the parameter of scale() in the case of having one parameter.

scaleX = scaleY = scaleZ = scale