From 14b212dd77799f16d538636a2fb1acc9cb850d8c Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Tue, 26 Apr 2016 09:33:56 +0200 Subject: tdf#90097 RTF import: handle fRelFlipV property for line shapes Can be extended later in every direction: fFlipV, fRelFlipH, non-line shapes. See oox::drawingml::Shape::createAndInsert() on why the convertMm100ToTwip() conversion is necessary. Change-Id: Ifee401dd8dd392c2c9ff85cc871ca0169fcf930b Reviewed-on: https://gerrit.libreoffice.org/24385 Reviewed-by: Miklos Vajna Tested-by: Jenkins (cherry picked from commit 6046062719f30849cd97161c6a89d27a0b0d2a20) Reviewed-on: https://gerrit.libreoffice.org/24612 Reviewed-by: Michael Stahl --- sw/qa/extras/rtfimport/data/tdf90097.rtf | 162 ++++++++++++++++++++++++++++ sw/qa/extras/rtfimport/rtfimport.cxx | 19 ++++ writerfilter/Library_writerfilter.mk | 1 + writerfilter/source/rtftok/rtfsdrimport.cxx | 31 ++++++ 4 files changed, 213 insertions(+) create mode 100644 sw/qa/extras/rtfimport/data/tdf90097.rtf diff --git a/sw/qa/extras/rtfimport/data/tdf90097.rtf b/sw/qa/extras/rtfimport/data/tdf90097.rtf new file mode 100644 index 000000000000..7764fa14233e --- /dev/null +++ b/sw/qa/extras/rtfimport/data/tdf90097.rtf @@ -0,0 +1,162 @@ +{\rtf1\ansi\ansicpg1250\uc1\deff0\stshfdbch0\stshfloch0\stshfhich0\stshfbi0\deflang1029\deflangfe1029 +{\shpgrp +{\*\shpinst\shpleft1008\shptop0\shpright2880\shpbottom1920\shpfhdr0\shpbxcolumn\shpbxignore\shpbypara\shpbyignore\shpwr3\shpwrk0\shpfblwtxt0\shpz0\shplid1026 +{\sp +{\sn groupLeft} +{\sv 0} +} +{\sp +{\sn groupTop} +{\sv 0} +} +{\sp +{\sn groupRight} +{\sv 1872} +} +{\sp +{\sn groupBottom} +{\sv 1920} +} +{\sp +{\sn fFlipH} +{\sv 0} +} +{\sp +{\sn fFlipV} +{\sv 0} +} +{\sp +{\sn lidRegroup} +{\sv 0} +} +{\sp +{\sn posrelh} +{\sv 2} +} +{\sp +{\sn posrelv} +{\sv 2} +} +{\sp +{\sn fLayoutInCell} +{\sv 0} +} +{\sp +{\sn fLayoutInCell} +{\sv 0} +} +{\shp +{\*\shpinst\shplid1060 +{\sp +{\sn relLeft} +{\sv 393} +} +{\sp +{\sn relTop} +{\sv 201} +} +{\sp +{\sn relRight} +{\sv 755} +} +{\sp +{\sn relBottom} +{\sv 544} +} +{\sp +{\sn fRelFlipH} +{\sv 0} +} +{\sp +{\sn fRelFlipV} +{\sv 1} +} +{\sp +{\sn shapeType} +{\sv 20} +} +{\sp +{\sn shapePath} +{\sv 4} +} +{\sp +{\sn fFilled} +{\sv 0} +} +{\sp +{\sn lineWidth} +{\sv 7400} +} +{\sp +{\sn fLine} +{\sv 1} +} +{\sp +{\sn fLayoutInCell} +{\sv 0} +} +{\sp +{\sn fLayoutInCell} +{\sv 0} +} +} +} +{\shp +{\*\shpinst\shplid1061 +{\sp +{\sn relLeft} +{\sv 755} +} +{\sp +{\sn relTop} +{\sv 201} +} +{\sp +{\sn relRight} +{\sv 1117} +} +{\sp +{\sn relBottom} +{\sv 544} +} +{\sp +{\sn fRelFlipH} +{\sv 0} +} +{\sp +{\sn fRelFlipV} +{\sv 0} +} +{\sp +{\sn shapeType} +{\sv 20} +} +{\sp +{\sn shapePath} +{\sv 4} +} +{\sp +{\sn fFilled} +{\sv 0} +} +{\sp +{\sn lineWidth} +{\sv 7400} +} +{\sp +{\sn fLine} +{\sv 1} +} +{\sp +{\sn fLayoutInCell} +{\sv 0} +} +{\sp +{\sn fLayoutInCell} +{\sv 0} +} +} +} +} +} +} diff --git a/sw/qa/extras/rtfimport/rtfimport.cxx b/sw/qa/extras/rtfimport/rtfimport.cxx index 5dfc751c55e5..185fba4eef2a 100644 --- a/sw/qa/extras/rtfimport/rtfimport.cxx +++ b/sw/qa/extras/rtfimport/rtfimport.cxx @@ -2534,6 +2534,25 @@ DECLARE_RTFIMPORT_TEST(testTdf97035, "tdf97035.rtf") CPPUNIT_ASSERT_EQUAL(sal_Int16(2299), getProperty< uno::Sequence >(xTableRows->getByIndex(1), "TableColumnSeparators")[0].Position); } +#ifndef WNT +DECLARE_RTFIMPORT_TEST(testTdf90097, "tdf90097.rtf") +{ + // Get the second child of the group shape. + uno::Reference xGroup(getShape(1), uno::UNO_QUERY); + uno::Reference xShape(xGroup->getByIndex(1), uno::UNO_QUERY); + uno::Sequence< uno::Sequence > aPolyPolySequence; + xShape->getPropertyValue("PolyPolygon") >>= aPolyPolySequence; + uno::Sequence& rPolygon = aPolyPolySequence[0]; + // Vertical flip for the line shape was ignored, so Y coordinates were swapped. + CPPUNIT_ASSERT_EQUAL(static_cast(2819), rPolygon[0].X); + // This was 1619. + CPPUNIT_ASSERT_EQUAL(static_cast(1963), rPolygon[0].Y); + CPPUNIT_ASSERT_EQUAL(static_cast(3181), rPolygon[1].X); + // This was 1962. + CPPUNIT_ASSERT_EQUAL(static_cast(1620), rPolygon[1].Y); +} +#endif + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerfilter/Library_writerfilter.mk b/writerfilter/Library_writerfilter.mk index c81ff5651e05..5ec43d2b0937 100644 --- a/writerfilter/Library_writerfilter.mk +++ b/writerfilter/Library_writerfilter.mk @@ -35,6 +35,7 @@ $(eval $(call gb_Library_add_defs,writerfilter,\ )) $(eval $(call gb_Library_use_libraries,writerfilter,\ + basegfx \ comphelper \ cppu \ cppuhelper \ diff --git a/writerfilter/source/rtftok/rtfsdrimport.cxx b/writerfilter/source/rtftok/rtfsdrimport.cxx index fcc20d4ee421..32846edd7c4b 100644 --- a/writerfilter/source/rtftok/rtfsdrimport.cxx +++ b/writerfilter/source/rtftok/rtfsdrimport.cxx @@ -33,6 +33,7 @@ #include #include #include +#include using namespace com::sun::star; @@ -346,6 +347,7 @@ void RTFSdrImport::resolve(RTFShape& rShape, bool bClose, ShapeOrPict const shap boost::optional oRelativeWidth, oRelativeHeight; sal_Int16 nRelativeWidthRelation = text::RelOrientation::PAGE_FRAME; sal_Int16 nRelativeHeightRelation = text::RelOrientation::PAGE_FRAME; + boost::logic::tribool obRelFlipV(boost::logic::indeterminate); bool bCustom(false); int const nType = initShape(xShape, xPropertySet, bCustom, rShape, bClose, shapeOrPict); @@ -778,6 +780,8 @@ void RTFSdrImport::resolve(RTFShape& rShape, bool bClose, ShapeOrPict const shap while (nCharIndex >= 0); rShape.aWrapPolygonSprms = aPolygonSprms; } + else if (i->first == "fRelFlipV") + obRelFlipV = i->second.toInt32() == 1; else SAL_INFO("writerfilter", "TODO handle shape property '" << i->first << "':'" << i->second << "'"); } @@ -836,6 +840,33 @@ void RTFSdrImport::resolve(RTFShape& rShape, bool bClose, ShapeOrPict const shap } if (!aGeometry.empty() && xPropertySet.is() && !m_bTextFrame) xPropertySet->setPropertyValue("CustomShapeGeometry", uno::Any(comphelper::containerToSequence(aGeometry))); + if (!boost::logic::indeterminate(obRelFlipV) && xPropertySet.is()) + { + if (nType == ESCHER_ShpInst_Line) + { + // Line shape inside group shape: get the polygon sequence and transform it. + uno::Sequence< uno::Sequence > aPolyPolySequence; + if ((xPropertySet->getPropertyValue("PolyPolygon") >>= aPolyPolySequence) && aPolyPolySequence.hasElements()) + { + uno::Sequence& rPolygon = aPolyPolySequence[0]; + basegfx::B2DPolygon aPoly; + for (sal_Int32 i = 0; i < rPolygon.getLength(); ++i) + { + const awt::Point& rPoint = rPolygon[i]; + aPoly.insert(i, basegfx::B2DPoint(rPoint.X, rPoint.Y)); + } + basegfx::B2DHomMatrix aTransformation; + aTransformation.scale(1.0, obRelFlipV ? -1.0 : 1.0); + aPoly.transform(aTransformation); + for (sal_Int32 i = 0; i < rPolygon.getLength(); ++i) + { + basegfx::B2DPoint aPoint(aPoly.getB2DPoint(i)); + rPolygon[i] = awt::Point(static_cast(convertMm100ToTwip(aPoint.getX())), static_cast(convertMm100ToTwip(aPoint.getY()))); + } + xPropertySet->setPropertyValue("PolyPolygon", uno::makeAny(aPolyPolySequence)); + } + } + } // Set position and size if (xShape.is()) -- cgit v1.2.3