shear/skew transformation errors

Friedrich W. H. Kossebau kossebau at kde.org
Thu Apr 5 14:45:42 BST 2012


Hi,

tl;dr There are unclear differences in skew transform handling in ODF and SVG, 
at least loading SVG with skewX/Y is broken. Expert input needed.


I got pointed to the fact that there are problems with loading SVG files with 
shearing transformations, e.g. seen with the coords-trans-03-t from the w3c 
SVG test suite, from
	http://dev.w3.org/SVG/profiles/1.1F2/test/svg/coords-trans-03-t.svg

But after a short look I am still a little puzzled and would like some 
assistance.
For one the docs of QTransform::shear(...) are shitty because they do not tell 
what kind of real value they take. From all code examples I found it seems to 
be "tan(radian value of the angle)", as also is the value in the matrix.
>From the ODF and SVG specs I would have guessed the skewX/skewY attributes 
take the same values with the same semantics. But the SVG attribute values are 
handled with
	tan(DEG2RAD(params[0].toDouble())) 		(SvgUtil.cpp)
and the ODF attribute values with
	tan(-params[0].toDouble())"				(KoShape.cpp)

So the ODF skew values are given in radian values, not degree values, and the 
spec text is wrong about that? And is the angle in ODF clockwise, while it is 
counter-clockwise in SVG (see the "-" for ODF)?

To complicate things more, the code for loading graphic styles does
	tan(params[0].toDouble())					(KoOdfGraphicStyle.cpp)
(and also has an error for mixing up the parameters for skewY).

So what code is wrong, where is LO/OOo code ruling over the spec (and where to 
discuss to fix this, to decrease spoiling of the ODF spec)?

Cheers
Friedrich

PS: Find below an overview of the relevant code/spec parts:


__ODF 1.2 spec, section 19.228 draw:transform___

* skewX(<skew-angle>), specifies a skew transformation by
  <rotate-angle> degrees along the x-axis. 
* skewY(<skew-angle>), specifies a skew transformation by
  <rotate-angle> degrees along the y-axis. 

[[the bad <rotate-angle>s have been reported to odf-comment ml by me]]


__SVG 1.1 spec, section 7.6 The transform attribute___

skewX(<skew-angle>), which specifies a skew transformation along the x-axis.

and referenced from this, section 7.4 Coordinate system transformations__

* A skew transformation along the x-axis is equivalent to [...]
  [1 0 tan(a) 1 0 0], which has the effect of skewing X coordinates
  by angle a.
* A skew transformation along the y-axis is equivalent to [...]
  [1 tan(a) 0 1 0 0], which has the effect of skewing Y coordinates
  by angle a.



SvgUtil.cpp:
        } else if (subtransform[0].toLower() == "skewx") {
            result.shear(tan(DEG2RAD(params[0].toDouble())), 0.0F);
        } else if (subtransform[0].toLower() == "skewy") {
            result.shear(0.0F, tan(DEG2RAD(params[0].toDouble())));

KoShape.cpp:
        } else if (cmd == "skewx") {
            QPointF p = absolutePosition(KoFlake::TopLeftCorner);
            QTransform shearMatrix;
            shearMatrix.translate(p.x(), p.y());
            shearMatrix.shear(tan(-params[0].toDouble()), 0.0F);
            shearMatrix.translate(-p.x(), -p.y());
            matrix = matrix * shearMatrix;
        } else if (cmd == "skewy") {
            QPointF p = absolutePosition(KoFlake::TopLeftCorner);
            QTransform shearMatrix;
            shearMatrix.translate(p.x(), p.y());
            shearMatrix.shear(0.0F, tan(-params[0].toDouble()));
            shearMatrix.translate(-p.x(), -p.y());
            matrix = matrix * shearMatrix;

KoOdfGraphicStyle.cpp:
        } else if (subtransform[0] == "skewx")
            transform.shear(tan(params[0].toDouble()), 0.0F);
        else if (subtransform[0] == "skewy")
            transform.shear(tan(params[0].toDouble()), 0.0F);
[[error! parameters switched in last line]]

qt.gitorious.org/qt/qtsvg/blobs/master/src/svg/qsvghandler.cpp:
        } else if (state == SkewX) {
            if (points.count() != 1)
                goto error;
            const qreal deg2rad = qreal(0.017453292519943295769);
            matrix.shear(qTan(points[0]*deg2rad), 0);
        } else if (state == SkewY) {
            if (points.count() != 1)
                goto error;
            const qreal deg2rad = qreal(0.017453292519943295769);
            matrix.shear(0, qTan(points[0]*deg2rad));




More information about the calligra-devel mailing list