Kaydet (Commit) 73ee631e authored tarafından Paul Trojahn's avatar Paul Trojahn Kaydeden (comit) Tamás Zolnai

tdf#111798 Fix deformed export of flipped custom shapes to pptx

Shapes were deformed because flipping wasn't considered when removing
the rotation. Also WriteShapeTransformation needs information about
flipping to convert the angle correctly.

Change-Id: I7d485e93c00e02b9ec6c73ad6ae2876e5bc6360a
Reviewed-on: https://gerrit.libreoffice.org/41462Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarTamás Zolnai <tamas.zolnai@collabora.com>
üst dffdc0b1
...@@ -189,8 +189,8 @@ public: ...@@ -189,8 +189,8 @@ public:
const OUString& rURL, bool bRelPathToMedia = false , const Graphic *pGraphic=nullptr ); const OUString& rURL, bool bRelPathToMedia = false , const Graphic *pGraphic=nullptr );
void WriteBlipMode( const css::uno::Reference< css::beans::XPropertySet >& rXPropSet, const OUString& rURL ); void WriteBlipMode( const css::uno::Reference< css::beans::XPropertySet >& rXPropSet, const OUString& rURL );
void WriteShapeTransformation( const css::uno::Reference< css::drawing::XShape >& rXShape, void WriteShapeTransformation(const css::uno::Reference< css::drawing::XShape >& rXShape,
sal_Int32 nXmlNamespace, bool bFlipH = false, bool bFlipV = false, bool bSuppressRotation = false ); sal_Int32 nXmlNamespace, bool bFlipH = false, bool bFlipV = false, bool bSuppressRotation = false, bool bSuppressFlipping = false );
void WriteTransformation( const tools::Rectangle& rRectangle, void WriteTransformation( const tools::Rectangle& rRectangle,
sal_Int32 nXmlNamespace, bool bFlipH = false, bool bFlipV = false, sal_Int32 nRotation = 0 ); sal_Int32 nXmlNamespace, bool bFlipH = false, bool bFlipV = false, sal_Int32 nRotation = 0 );
......
...@@ -1157,11 +1157,6 @@ void DrawingML::WriteStretch( const css::uno::Reference< css::beans::XPropertySe ...@@ -1157,11 +1157,6 @@ void DrawingML::WriteStretch( const css::uno::Reference< css::beans::XPropertySe
void DrawingML::WriteTransformation( const tools::Rectangle& rRect, void DrawingML::WriteTransformation( const tools::Rectangle& rRect,
sal_Int32 nXmlNamespace, bool bFlipH, bool bFlipV, sal_Int32 nRotation ) sal_Int32 nXmlNamespace, bool bFlipH, bool bFlipV, sal_Int32 nRotation )
{ {
//OOXML flips shapes before rotating them.
if(bFlipH)
nRotation = nRotation * -1 + 60000*360;
if(bFlipV)
nRotation = nRotation * -1 + 60000*360;
mpFS->startElementNS( nXmlNamespace, XML_xfrm, mpFS->startElementNS( nXmlNamespace, XML_xfrm,
XML_flipH, bFlipH ? "1" : nullptr, XML_flipH, bFlipH ? "1" : nullptr,
...@@ -1183,7 +1178,7 @@ void DrawingML::WriteTransformation( const tools::Rectangle& rRect, ...@@ -1183,7 +1178,7 @@ void DrawingML::WriteTransformation( const tools::Rectangle& rRect,
mpFS->endElementNS( nXmlNamespace, XML_xfrm ); mpFS->endElementNS( nXmlNamespace, XML_xfrm );
} }
void DrawingML::WriteShapeTransformation( const Reference< XShape >& rXShape, sal_Int32 nXmlNamespace, bool bFlipH, bool bFlipV, bool bSuppressRotation ) void DrawingML::WriteShapeTransformation( const Reference< XShape >& rXShape, sal_Int32 nXmlNamespace, bool bFlipH, bool bFlipV, bool bSuppressRotation, bool bSuppressFlipping )
{ {
SAL_INFO("oox.shape", "write shape transformation"); SAL_INFO("oox.shape", "write shape transformation");
...@@ -1220,6 +1215,14 @@ void DrawingML::WriteShapeTransformation( const Reference< XShape >& rXShape, sa ...@@ -1220,6 +1215,14 @@ void DrawingML::WriteShapeTransformation( const Reference< XShape >& rXShape, sa
if (xPropertySetInfo->hasPropertyByName("RotateAngle")) if (xPropertySetInfo->hasPropertyByName("RotateAngle"))
xPropertySet->getPropertyValue("RotateAngle") >>= nRotation; xPropertySet->getPropertyValue("RotateAngle") >>= nRotation;
} }
// OOXML flips shapes before rotating them.
if(bFlipH != bFlipV)
nRotation = nRotation * -1 + 36000;
if(bSuppressFlipping)
bFlipH = bFlipV = false;
WriteTransformation( tools::Rectangle( Point( aPos.X, aPos.Y ), Size( aSize.Width, aSize.Height ) ), nXmlNamespace, bFlipH, bFlipV, OOX_DRAWINGML_EXPORT_ROTATE_CLOCKWISIFY(nRotation) ); WriteTransformation( tools::Rectangle( Point( aPos.X, aPos.Y ), Size( aSize.Width, aSize.Height ) ), nXmlNamespace, bFlipH, bFlipV, OOX_DRAWINGML_EXPORT_ROTATE_CLOCKWISIFY(nRotation) );
} }
......
...@@ -823,7 +823,7 @@ ShapeExport& ShapeExport::WriteCustomShape( const Reference< XShape >& xShape ) ...@@ -823,7 +823,7 @@ ShapeExport& ShapeExport::WriteCustomShape( const Reference< XShape >& xShape )
if (bHasHandles && bCustGeom && pShape) if (bHasHandles && bCustGeom && pShape)
{ {
WriteShapeTransformation( xShape, XML_a ); // do not flip, polypolygon coordinates are flipped already WriteShapeTransformation( xShape, XML_a, bFlipH, bFlipV, false, true );// do not flip, polypolygon coordinates are flipped already
tools::PolyPolygon aPolyPolygon( pShape->GetLineGeometry(true) ); tools::PolyPolygon aPolyPolygon( pShape->GetLineGeometry(true) );
sal_Int32 nRotation = 0; sal_Int32 nRotation = 0;
// The RotateAngle property's value is independent from any flipping, and that's exactly what we need here. // The RotateAngle property's value is independent from any flipping, and that's exactly what we need here.
...@@ -831,8 +831,10 @@ ShapeExport& ShapeExport::WriteCustomShape( const Reference< XShape >& xShape ) ...@@ -831,8 +831,10 @@ ShapeExport& ShapeExport::WriteCustomShape( const Reference< XShape >& xShape )
uno::Reference<beans::XPropertySetInfo> xPropertySetInfo = xPropertySet->getPropertySetInfo(); uno::Reference<beans::XPropertySetInfo> xPropertySetInfo = xPropertySet->getPropertySetInfo();
if (xPropertySetInfo->hasPropertyByName("RotateAngle")) if (xPropertySetInfo->hasPropertyByName("RotateAngle"))
xPropertySet->getPropertyValue("RotateAngle") >>= nRotation; xPropertySet->getPropertyValue("RotateAngle") >>= nRotation;
// Remove rotation
bool bInvertRotation = bFlipH != bFlipV;
if (nRotation != 0) if (nRotation != 0)
aPolyPolygon.Rotate(Point(0,0), static_cast<sal_uInt16>(3600-nRotation/10)); aPolyPolygon.Rotate(Point(0,0), static_cast<sal_uInt16>(bInvertRotation ? nRotation/10 : 3600-nRotation/10));
WritePolyPolygon( aPolyPolygon ); WritePolyPolygon( aPolyPolygon );
} }
else if (bCustGeom) else if (bCustGeom)
......
...@@ -99,6 +99,7 @@ public: ...@@ -99,6 +99,7 @@ public:
void testTdf105739(); void testTdf105739();
void testPageBitmapWithTransparency(); void testPageBitmapWithTransparency();
void testPptmContentType(); void testPptmContentType();
void testTdf111798();
void testPptmVBAStream(); void testPptmVBAStream();
void testTdf111518(); void testTdf111518();
void testTdf100387(); void testTdf100387();
...@@ -128,6 +129,7 @@ public: ...@@ -128,6 +129,7 @@ public:
CPPUNIT_TEST(testTdf105739); CPPUNIT_TEST(testTdf105739);
CPPUNIT_TEST(testPageBitmapWithTransparency); CPPUNIT_TEST(testPageBitmapWithTransparency);
CPPUNIT_TEST(testPptmContentType); CPPUNIT_TEST(testPptmContentType);
CPPUNIT_TEST(testTdf111798);
CPPUNIT_TEST(testPptmVBAStream); CPPUNIT_TEST(testPptmVBAStream);
CPPUNIT_TEST(testTdf111518); CPPUNIT_TEST(testTdf111518);
CPPUNIT_TEST(testTdf100387); CPPUNIT_TEST(testTdf100387);
...@@ -828,6 +830,63 @@ void SdOOXMLExportTest2::testPptmContentType() ...@@ -828,6 +830,63 @@ void SdOOXMLExportTest2::testPptmContentType()
xDocShRef->DoClose(); xDocShRef->DoClose();
} }
void SdOOXMLExportTest2::testTdf111798()
{
sd::DrawDocShellRef xDocShRef = loadURL(m_directories.getURLFromSrc("/sd/qa/unit/data/odp/tdf111798.odp"), ODP);
utl::TempFile tempFile;
xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile);
xDocShRef->DoClose();
xmlDocPtr pXmlDoc = parseExport(tempFile, "ppt/slides/slide1.xml");
const OUString data[][29] =
{
{
"2700000", "2458080", "2414880", "1439640", "1440000",
"moveTo", "0", "3000",
"lnTo[1]", "3000", "3000",
"lnTo[2]", "3000", "4000",
"lnTo[3]", "4000", "2000",
"lnTo[4]", "3000", "0",
"lnTo[5]", "3000", "1000",
"lnTo[6]", "0", "1000",
"lnTo[7]", "0", "3000"
},
{
"2700000", "6778080", "2414880", "1439640", "1440000",
"moveTo", "3000", "0",
"lnTo[1]", "3000", "3000",
"lnTo[2]", "4000", "3000",
"lnTo[3]", "2000", "4000",
"lnTo[4]", "0", "3000",
"lnTo[5]", "1000", "3000",
"lnTo[6]", "1000", "0",
"lnTo[7]", "3000", "0"
}
};
for (size_t nShapeIndex = 0; nShapeIndex < SAL_N_ELEMENTS(data); nShapeIndex++)
{
size_t nDataIndex = 0;
const OString sSpPr = "/p:sld/p:cSld/p:spTree/p:sp[" + OString::number(nShapeIndex + 1) + "]/p:spPr";
const OString sXfrm = sSpPr + "/a:xfrm";
assertXPath(pXmlDoc, sXfrm, "rot", data[nShapeIndex][nDataIndex++]);
const OString sOff = sXfrm + "/a:off";
assertXPath(pXmlDoc, sOff, "x", data[nShapeIndex][nDataIndex++]);
assertXPath(pXmlDoc, sOff, "y", data[nShapeIndex][nDataIndex++]);
const OString sExt = sXfrm + "/a:ext";
assertXPath(pXmlDoc, sExt, "cx", data[nShapeIndex][nDataIndex++]);
assertXPath(pXmlDoc, sExt, "cy", data[nShapeIndex][nDataIndex++]);
while (nDataIndex < SAL_N_ELEMENTS(data[nShapeIndex]))
{
const OString sPt = sSpPr + "/a:custGeom/a:pathLst/a:path/a:" + data[nShapeIndex][nDataIndex++].toUtf8() + "/a:pt";
assertXPath(pXmlDoc, sPt, "x", data[nShapeIndex][nDataIndex++]);
assertXPath(pXmlDoc, sPt, "y", data[nShapeIndex][nDataIndex++]);
}
}
}
void SdOOXMLExportTest2::testPptmVBAStream() void SdOOXMLExportTest2::testPptmVBAStream()
{ {
::sd::DrawDocShellRef xDocShRef = loadURL(m_directories.getURLFromSrc("sd/qa/unit/data/pptm/macro.pptm"), PPTM); ::sd::DrawDocShellRef xDocShRef = loadURL(m_directories.getURLFromSrc("sd/qa/unit/data/pptm/macro.pptm"), PPTM);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment