diff options
author | Grzegorz Araminowicz <g.araminowicz@gmail.com> | 2017-05-30 11:45:47 +0200 |
---|---|---|
committer | Jan Holesovsky <kendy@collabora.com> | 2017-05-31 15:30:28 +0200 |
commit | 087537dc45bbab3db41fe6d92974cdfde59904cb (patch) | |
tree | d359f2ffc2f850ad0a511739ed9ff984517360a2 | |
parent | 490e9dbade4f9d69cab4b1ec435944c9b4d2f6c2 (diff) |
tdf#76446 GSoC: incorrect rotation of VML shapes
* support poorly documented 'fd' suffix in rotation attribute
* allow non-integer rotation
Change-Id: I3d72f2a708e6585597db09366c00c50038abc9c1
Reviewed-on: https://gerrit.libreoffice.org/38207
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Jan Holesovsky <kendy@collabora.com>
-rw-r--r-- | include/oox/vml/vmlformatting.hxx | 12 | ||||
-rw-r--r-- | oox/source/vml/vmlformatting.cxx | 25 | ||||
-rw-r--r-- | oox/source/vml/vmlshape.cxx | 17 | ||||
-rwxr-xr-x | sw/qa/extras/ooxmlimport/data/tdf76446.docx | bin | 0 -> 10135 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlimport/ooxmlimport.cxx | 7 |
5 files changed, 49 insertions, 12 deletions
diff --git a/include/oox/vml/vmlformatting.hxx b/include/oox/vml/vmlformatting.hxx index efb0e6606887..b07d8b01899a 100644 --- a/include/oox/vml/vmlformatting.hxx +++ b/include/oox/vml/vmlformatting.hxx @@ -75,6 +75,18 @@ namespace ConversionHelper const OUString& rValue, double fDefValue ); + /** Converts the passed VML rotation value to degrees. + See DffPropertyReader::Fix16ToAngle(): in VML, positive rotation + angles are clockwise, we have them as counter-clockwise. + Additionally, VML type is 0..360, our is 0..36000. + + @param rValue The VML rotation value. This is a floating-point value + with optional 'fd' suffix. If the suffix is missing, the floating + point value will be returned unmodified. If the 'fd' suffix is + present, the value will be divided by 65536. + */ + OOX_DLLPUBLIC sal_Int32 decodeRotation( const OUString& rValue ); + /** Converts the passed VML measure string to EMU (English Metric Units). @param rGraphicHelper The graphic helper needed to perform pixel diff --git a/oox/source/vml/vmlformatting.cxx b/oox/source/vml/vmlformatting.cxx index c2e2d139c0d6..6b9d1a9c654d 100644 --- a/oox/source/vml/vmlformatting.cxx +++ b/oox/source/vml/vmlformatting.cxx @@ -34,6 +34,7 @@ #include "oox/helper/graphichelper.hxx" #include <oox/token/properties.hxx> #include <oox/token/tokens.hxx> +#include <svx/svdtrans.hxx> namespace oox { namespace vml { @@ -109,6 +110,30 @@ double ConversionHelper::decodePercent( const OUString& rValue, double fDefValue return fDefValue; } +sal_Int32 ConversionHelper::decodeRotation( const OUString& rValue ) +{ + if( rValue.isEmpty() ) + return 0; + + double fValue = 0.0; + double fRotation = 0.0; + sal_Int32 nEndPos = 0; + if( !lclExtractDouble(fValue, nEndPos, rValue) ) + return 0; + + if( nEndPos == rValue.getLength() ) + fRotation = fValue; + else if( (nEndPos + 2 == rValue.getLength()) && (rValue[nEndPos] == 'f') && (rValue[nEndPos+1] == 'd') ) + fRotation = fValue / 65536.0; + else + { + OSL_FAIL("ConversionHelper::decodeRotation - unknown measure unit"); + return 0; + } + + return NormAngle360(fRotation * -100); +} + sal_Int64 ConversionHelper::decodeMeasureToEmu( const GraphicHelper& rGraphicHelper, const OUString& rValue, sal_Int32 nRefValue, bool bPixelX, bool bDefaultAsPixel ) { diff --git a/oox/source/vml/vmlshape.cxx b/oox/source/vml/vmlshape.cxx index 7c78234e511f..f7d6c6908b8f 100644 --- a/oox/source/vml/vmlshape.cxx +++ b/oox/source/vml/vmlshape.cxx @@ -372,7 +372,7 @@ Reference< XShape > ShapeBase::convertAndInsert( const Reference< XShapes >& rxS } if(!(maTypeModel.maRotation).isEmpty()) - aGrabBag.push_back(comphelper::makePropertyValue("mso-rotation-angle", sal_Int32(NormAngle360((maTypeModel.maRotation.toInt32()) * -100)))); + aGrabBag.push_back(comphelper::makePropertyValue("mso-rotation-angle", ConversionHelper::decodeRotation(maTypeModel.maRotation))); propertySet->setPropertyValue("FrameInteropGrabBag", uno::makeAny(comphelper::containerToSequence(aGrabBag))); sal_Int32 backColorTransparency = 0; propertySet->getPropertyValue("BackColorTransparency") @@ -620,20 +620,13 @@ void lcl_SetAnchorType(PropertySet& rPropSet, const ShapeTypeModel& rTypeModel, lcl_setSurround( rPropSet, rTypeModel, rGraphicHelper ); } -void lcl_SetRotation(PropertySet& rPropSet, const sal_Int32 nRotation) -{ - // See DffPropertyReader::Fix16ToAngle(): in VML, positive rotation angles are clockwise, we have them as counter-clockwise. - // Additionally, VML type is 0..360, our is 0..36000. - rPropSet.setAnyProperty(PROP_RotateAngle, makeAny(sal_Int32(NormAngle360(nRotation * -100)))); -} - Reference< XShape > SimpleShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const awt::Rectangle& rShapeRect ) const { awt::Rectangle aShapeRect(rShapeRect); boost::optional<sal_Int32> oRotation; bool bFlipX = false, bFlipY = false; if (!maTypeModel.maRotation.isEmpty()) - oRotation.reset(maTypeModel.maRotation.toInt32()); + oRotation.reset(ConversionHelper::decodeRotation(maTypeModel.maRotation)); if (!maTypeModel.maFlip.isEmpty()) { if (maTypeModel.maFlip == "x") @@ -786,7 +779,7 @@ Reference< XShape > SimpleShape::implConvertAndInsert( const Reference< XShapes { if (oRotation) { - lcl_SetRotation(aPropertySet, *oRotation); + aPropertySet.setAnyProperty(PROP_RotateAngle, makeAny(*oRotation)); uno::Reference<lang::XServiceInfo> xServiceInfo(rxShapes, uno::UNO_QUERY); if (!xServiceInfo->supportsService("com.sun.star.drawing.GroupShape")) { @@ -844,7 +837,7 @@ Reference< XShape > SimpleShape::createPictureObject( const Reference< XShapes > } // fdo#70457: preserve rotation information if ( !maTypeModel.maRotation.isEmpty() ) - lcl_SetRotation( aPropSet, maTypeModel.maRotation.toInt32() ); + aPropSet.setAnyProperty(PROP_RotateAngle, makeAny(ConversionHelper::decodeRotation(maTypeModel.maRotation))); const GraphicHelper& rGraphicHelper = mrDrawing.getFilter().getGraphicHelper(); lcl_SetAnchorType(aPropSet, maTypeModel, rGraphicHelper); @@ -1288,7 +1281,7 @@ Reference< XShape > GroupShape::implConvertAndInsert( const Reference< XShapes > const GraphicHelper& rGraphicHelper = mrDrawing.getFilter().getGraphicHelper(); lcl_SetAnchorType(aPropertySet, maTypeModel, rGraphicHelper); if (!maTypeModel.maRotation.isEmpty()) - lcl_SetRotation(aPropertySet, maTypeModel.maRotation.toInt32()); + aPropertySet.setAnyProperty(PROP_RotateAngle, makeAny(ConversionHelper::decodeRotation(maTypeModel.maRotation))); return xGroupShape; } diff --git a/sw/qa/extras/ooxmlimport/data/tdf76446.docx b/sw/qa/extras/ooxmlimport/data/tdf76446.docx Binary files differnew file mode 100755 index 000000000000..7ba6db35f146 --- /dev/null +++ b/sw/qa/extras/ooxmlimport/data/tdf76446.docx diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx index dee3ad3d3596..ebebedda914b 100644 --- a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx +++ b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx @@ -1280,6 +1280,13 @@ DECLARE_OOXMLIMPORT_TEST(testTdf100072, "tdf100072.docx") CPPUNIT_ASSERT_MESSAGE("Shape line width does not match", abs(nFirstEnd - nSecondEnd) < 10); } +DECLARE_OOXMLIMPORT_TEST(testTdf76446, "tdf76446.docx") +{ + uno::Reference<drawing::XShape> xShape = getShape(1); + sal_Int64 nRot = getProperty<sal_Int64>(xShape, "RotateAngle"); + CPPUNIT_ASSERT_EQUAL(sal_Int64(3128), nRot); +} + // tests should only be added to ooxmlIMPORT *if* they fail round-tripping in ooxmlEXPORT |