diff options
author | Regina Henschel <rb.henschel@t-online.de> | 2020-01-02 17:37:32 +0100 |
---|---|---|
committer | Regina Henschel <rb.henschel@t-online.de> | 2020-01-17 18:03:38 +0100 |
commit | bc886f523872d4f9845c188c7d525d72a1a60946 (patch) | |
tree | 8677487eb45e619a9dcbc135c9c934e1a8e201d4 /xmloff | |
parent | 21a5c7f77dea3c880ee1808f5385205f53271338 (diff) |
tdf#98584 Correct import draw:transform values skewY and matrix
Covers tdf#98583 and tdf#98565 too.
TRBaseGeomety (API) uses for skewX the same angle orientation as
written to file. But that results in mathematically wrong matrices.
Change sign where needed.
Vertical shearing is converted and written to file by LO as sequence
rotation * shear horizontal * scale. Same should happen on reading.
Because LO does not write skewY itself, I have used the angle
orientation, that was used in OOo1.1.5 and that is used in
Scribus 1.5.4.
Import generates a transformation matrix from the draw:transform
attribute. That is a mathematically correct matrix. It is applied
to the shape via TRSetBaseGeometry. But that uses a wrong sign in
the shear angle. Therefore conversion of mathematical matrix to
TRBaseGeometry matrix is needed.
The draw:transform attribute can generate a scaling, which needs to
be applied on top of the scaling made from svg:width and svg:height.
Such happens on import of skewY() and might happen with matrix().
SdrPathObject puts scaling form svg:width and svg:height directly
into the coordinates of its points. It had ignored any additional
scaling. I have add a part to detect and apply it.
Change-Id: I7636b9feec432cf403e7c6ef8dbd6a769793d144
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86244
Tested-by: Jenkins
Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
Reviewed-by: Regina Henschel <rb.henschel@t-online.de>
Diffstat (limited to 'xmloff')
-rw-r--r-- | xmloff/source/draw/xexptran.cxx | 10 | ||||
-rw-r--r-- | xmloff/source/draw/ximpshap.cxx | 53 |
2 files changed, 47 insertions, 16 deletions
diff --git a/xmloff/source/draw/xexptran.cxx b/xmloff/source/draw/xexptran.cxx index eb7cb4a634d5..0137166871bc 100644 --- a/xmloff/source/draw/xexptran.cxx +++ b/xmloff/source/draw/xexptran.cxx @@ -510,12 +510,18 @@ void SdXMLImExTransform2D::GetFullTransform(::basegfx::B2DHomMatrix& rFullTrans) } case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX : { - rFullTrans.shearX(tan(static_cast<ImpSdXMLExpTransObj2DSkewX*>(pObj)->mfSkewX)); + // For to get a mathematical correct matrix from already existing documents, + // mirror the value here. ODF spec is unclear about direction. + rFullTrans.shearX(-tan(static_cast<ImpSdXMLExpTransObj2DSkewX*>(pObj)->mfSkewX)); break; } case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY : { - rFullTrans.shearY(tan(static_cast<ImpSdXMLExpTransObj2DSkewY*>(pObj)->mfSkewY)); + // LibreOffice does not write skewY, OOo neither. Such files are foreign documents + // or manually set transformations. OOo had used the value as -tan(value) before + // errors were introduced, Scribus 1.5.4 uses it as -tan(value) too, MS Office does + // not shear at all. ODF spec is unclear about direction. + rFullTrans.shearY(-tan(static_cast<ImpSdXMLExpTransObj2DSkewY*>(pObj)->mfSkewY)); break; } case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX : diff --git a/xmloff/source/draw/ximpshap.cxx b/xmloff/source/draw/ximpshap.cxx index 8bee4b376ba1..3594d1605363 100644 --- a/xmloff/source/draw/ximpshap.cxx +++ b/xmloff/source/draw/ximpshap.cxx @@ -575,21 +575,38 @@ void SdXMLShapeContext::SetTransformation() } // now set transformation for this object - drawing::HomogenMatrix3 aMatrix; - aMatrix.Line1.Column1 = maUsedTransformation.get(0, 0); - aMatrix.Line1.Column2 = maUsedTransformation.get(0, 1); - aMatrix.Line1.Column3 = maUsedTransformation.get(0, 2); + // maUsedTransformtion contains the mathematical correct matrix, which if + // applied to a unit square would generate the transformed shape. But the property + // "Transformation" contains a matrix, which can be used in TRSetBaseGeometry + // and would be created by TRGetBaseGeometry. And those use a mathematically wrong + // sign for the shearing angle. So we need to adapt the matrix here. + basegfx::B2DTuple aScale; + basegfx::B2DTuple aTranslate; + double fRotate; + double fShearX; + maUsedTransformation.decompose(aScale, aTranslate, fRotate, fShearX); + basegfx::B2DHomMatrix aB2DHomMatrix; + aB2DHomMatrix = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix( + aScale, + basegfx::fTools::equalZero(fShearX) ? 0.0 : -fShearX, + basegfx::fTools::equalZero(fRotate) ? 0.0 : fRotate, + aTranslate); + drawing::HomogenMatrix3 aUnoMatrix; - aMatrix.Line2.Column1 = maUsedTransformation.get(1, 0); - aMatrix.Line2.Column2 = maUsedTransformation.get(1, 1); - aMatrix.Line2.Column3 = maUsedTransformation.get(1, 2); + aUnoMatrix.Line1.Column1 = aB2DHomMatrix.get(0, 0); + aUnoMatrix.Line1.Column2 = aB2DHomMatrix.get(0, 1); + aUnoMatrix.Line1.Column3 = aB2DHomMatrix.get(0, 2); - aMatrix.Line3.Column1 = maUsedTransformation.get(2, 0); - aMatrix.Line3.Column2 = maUsedTransformation.get(2, 1); - aMatrix.Line3.Column3 = maUsedTransformation.get(2, 2); + aUnoMatrix.Line2.Column1 = aB2DHomMatrix.get(1, 0); + aUnoMatrix.Line2.Column2 = aB2DHomMatrix.get(1, 1); + aUnoMatrix.Line2.Column3 = aB2DHomMatrix.get(1, 2); - xPropSet->setPropertyValue("Transformation", Any(aMatrix)); + aUnoMatrix.Line3.Column1 = aB2DHomMatrix.get(2, 0); + aUnoMatrix.Line3.Column2 = aB2DHomMatrix.get(2, 1); + aUnoMatrix.Line3.Column3 = aB2DHomMatrix.get(2, 2); + + xPropSet->setPropertyValue("Transformation", Any(aUnoMatrix)); } } } @@ -1093,9 +1110,9 @@ void SdXMLLineShapeContext::StartElement(const uno::Reference< xml::sax::XAttrib xPropSet->setPropertyValue("Geometry", Any(aPolyPoly)); } - // set sizes for transformation - maSize.Width = o3tl::saturating_sub(aBottomRight.X, aTopLeft.X); - maSize.Height = o3tl::saturating_sub(aBottomRight.Y, aTopLeft.Y); + // Size is included in point coordinates + maSize.Width = 1; + maSize.Height = 1; maPosition.X = aTopLeft.X; maPosition.Y = aTopLeft.Y; @@ -1322,6 +1339,10 @@ void SdXMLPolygonShapeContext::StartElement(const uno::Reference< xml::sax::XAtt css::drawing::PointSequenceSequence aPointSequenceSequence; basegfx::utils::B2DPolyPolygonToUnoPointSequenceSequence(basegfx::B2DPolyPolygon(aPolygon), aPointSequenceSequence); xPropSet->setPropertyValue("Geometry", Any(aPointSequenceSequence)); + // Size is now contained in the point coordinates, adapt maSize for + // to use the correct transformation matrix in SetTransformation() + maSize.Width = 1; + maSize.Height = 1; } } } @@ -1471,6 +1492,10 @@ void SdXMLPathShapeContext::StartElement(const uno::Reference< xml::sax::XAttrib } xPropSet->setPropertyValue("Geometry", aAny); + // Size is now contained in the point coordinates, adapt maSize for + // to use the correct transformation matrix in SetTransformation() + maSize.Width = 1; + maSize.Height = 1; } // set pos, size, shear and rotate |