diff options
author | Justin Luth <justin_luth@sil.org> | 2016-11-04 21:32:38 +0300 |
---|---|---|
committer | Justin Luth <justin_luth@sil.org> | 2016-11-07 04:09:41 +0000 |
commit | 8eff1decd91cbfb10094c25d4cf1d2b434a4da72 (patch) | |
tree | bcc51a30d8eaa4acbaff628dabff996c2273779f | |
parent | bc6017d66fcf37db1f632a3ce667f4c3bf9d1d02 (diff) |
tdf#41542 MSWordExport: accommodate image's borderless padding
Honor the padding value even if the border is not visible.
Previously the padding information was just thrown out, and
the image scaled to fill the entire image size.
The unit test for tdf#77454 needed to be tweaked because surprisingly
it has border padding of 1 - which this patch turns into a negative crop.
Change-Id: I866d26e00f27221239d3291404f70fb57ac0896d
Reviewed-on: https://gerrit.libreoffice.org/30578
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Justin Luth <justin_luth@sil.org>
-rwxr-xr-x | sw/qa/extras/ooxmlexport/data/tdf41542_imagePadding.odt | bin | 0 -> 17926 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport3.cxx | 13 | ||||
-rwxr-xr-x | sw/qa/extras/ww8export/data/tdf41542_imagePadding.odt | bin | 0 -> 17926 bytes | |||
-rw-r--r-- | sw/qa/extras/ww8export/ww8export.cxx | 33 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.cxx | 35 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.hxx | 2 | ||||
-rw-r--r-- | sw/source/filter/ww8/escher.hxx | 2 | ||||
-rw-r--r-- | sw/source/filter/ww8/wrtw8esh.cxx | 45 |
8 files changed, 95 insertions, 35 deletions
diff --git a/sw/qa/extras/ooxmlexport/data/tdf41542_imagePadding.odt b/sw/qa/extras/ooxmlexport/data/tdf41542_imagePadding.odt Binary files differnew file mode 100755 index 000000000000..019e19f247e1 --- /dev/null +++ b/sw/qa/extras/ooxmlexport/data/tdf41542_imagePadding.odt diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx index 4d73a7f62ee9..f93ace6ad4c3 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx @@ -771,6 +771,19 @@ DECLARE_OOXMLEXPORT_TEST(testPNGImageCrop, "test_PNG_ImageCrop.docx") #endif } +DECLARE_OOXMLEXPORT_TEST(testTdf41542_imagePadding, "tdf41542_imagePadding.odt") +{ + // borderlessImage - image WITHOUT BORDERS : simulate padding with -crop + text::GraphicCrop crop = getProperty<text::GraphicCrop>(getShape(2), "GraphicCrop"); + CPPUNIT_ASSERT( crop.Left != 0 && crop.Right != 0 ); + CPPUNIT_ASSERT( crop.Left == crop.Top && crop.Right == crop.Bottom && crop.Left == crop.Right); + + // borderedImage - image WITH BORDERS : simulate padding with -crop + crop = getProperty<text::GraphicCrop>(getShape(3), "GraphicCrop"); + CPPUNIT_ASSERT( crop.Left != 0 && crop.Right != 0 ); + CPPUNIT_ASSERT( crop.Left == crop.Top && crop.Right == crop.Bottom && crop.Left == crop.Right); +} + DECLARE_OOXMLEXPORT_TEST(testFootnoteParagraphTag, "testFootnote.docx") { /* In footnotes.xml, the paragraph tag inside <w:footnote w:id="2"> was getting written into document.xml. diff --git a/sw/qa/extras/ww8export/data/tdf41542_imagePadding.odt b/sw/qa/extras/ww8export/data/tdf41542_imagePadding.odt Binary files differnew file mode 100755 index 000000000000..019e19f247e1 --- /dev/null +++ b/sw/qa/extras/ww8export/data/tdf41542_imagePadding.odt diff --git a/sw/qa/extras/ww8export/ww8export.cxx b/sw/qa/extras/ww8export/ww8export.cxx index 88a703d99782..d3d87332f48e 100644 --- a/sw/qa/extras/ww8export/ww8export.cxx +++ b/sw/qa/extras/ww8export/ww8export.cxx @@ -831,26 +831,39 @@ DECLARE_WW8EXPORT_TEST(testCharacterBorder, "charborder.odt") } } +DECLARE_WW8EXPORT_TEST(testTdf41542_imagePadding, "tdf41542_imagePadding.odt") +{ + // borderlessImage - image WITHOUT BORDERS : simulate padding with -crop + text::GraphicCrop crop = getProperty<text::GraphicCrop>(getShape(2), "GraphicCrop"); + CPPUNIT_ASSERT( crop.Left != 0 && crop.Right != 0 ); + CPPUNIT_ASSERT( crop.Left == crop.Top && crop.Right == crop.Bottom && crop.Left == crop.Right ); + + // borderedImage - image WITH BORDERS : simulate padding with -crop + crop = getProperty<text::GraphicCrop>(getShape(3), "GraphicCrop"); + CPPUNIT_ASSERT( crop.Left != 0 && crop.Right != 0 ); + CPPUNIT_ASSERT( crop.Left == crop.Top && crop.Right == crop.Bottom && crop.Left == crop.Right ); +} + DECLARE_WW8EXPORT_TEST(testFdo77454, "fdo77454.doc") { { - // check negative crops round-trip + // check negative crops round-trip (with border/padding of 1) text::GraphicCrop const crop = getProperty<text::GraphicCrop>(getShape(1), "GraphicCrop"); - CPPUNIT_ASSERT_EQUAL(sal_Int32( -439), crop.Left); - CPPUNIT_ASSERT_EQUAL(sal_Int32(-7040), crop.Right); - CPPUNIT_ASSERT_EQUAL(sal_Int32( -220), crop.Top); - CPPUNIT_ASSERT_EQUAL(sal_Int32(-7040), crop.Bottom); + CPPUNIT_ASSERT(abs(sal_Int32( -439) - crop.Left) <= 2); + CPPUNIT_ASSERT(abs(sal_Int32(-7040) - crop.Right) <= 2); + CPPUNIT_ASSERT(abs(sal_Int32( -220) - crop.Top) <= 2); + CPPUNIT_ASSERT(abs(sal_Int32(-7040) - crop.Bottom) <= 2); } { - // check positive crops round-trip + // check positive crops round-trip (with padding of 1) text::GraphicCrop const crop = getProperty<text::GraphicCrop>(getShape(2), "GraphicCrop"); - CPPUNIT_ASSERT_EQUAL(sal_Int32( 326), crop.Left); - CPPUNIT_ASSERT_EQUAL(sal_Int32( 1208), crop.Right); - CPPUNIT_ASSERT(abs(sal_Int32(1635) - crop.Top) <= 2); - CPPUNIT_ASSERT(abs(sal_Int32( 95) - crop.Bottom) <= 2); + CPPUNIT_ASSERT(abs(sal_Int32( 326) - crop.Left) <= 3); + CPPUNIT_ASSERT(abs(sal_Int32(1208) - crop.Right) <= 3); + CPPUNIT_ASSERT(abs(sal_Int32(1635) - crop.Top) <= 3); + CPPUNIT_ASSERT(abs(sal_Int32( 95) - crop.Bottom) <= 3); } } diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 09e117215169..2aea2cc1ee54 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -4123,7 +4123,7 @@ void DocxAttributeOutput::DefaultStyle() /* Writes <a:srcRect> tag back to document.xml if a file conatins a cropped image. * NOTE : Tested on images of type JPEG,EMF/WMF,BMP, PNG and GIF. */ -void DocxAttributeOutput::WriteSrcRect(const SdrObject* pSdrObj ) +void DocxAttributeOutput::WriteSrcRect(const SdrObject* pSdrObj, const SwFrameFormat* pFrameFormat ) { uno::Reference< drawing::XShape > xShape( const_cast<SdrObject*>(pSdrObj)->getUnoShape(), uno::UNO_QUERY ); uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY ); @@ -4134,9 +4134,6 @@ void DocxAttributeOutput::WriteSrcRect(const SdrObject* pSdrObj ) Size aOriginalSize(aGrafObj.GetPrefSize()); - css::text::GraphicCrop aGraphicCropStruct; - xPropSet->getPropertyValue( "GraphicCrop" ) >>= aGraphicCropStruct; - const MapMode aMap100mm( MapUnit::Map100thMM ); const MapMode& rMapMode = aGrafObj.GetPrefMapMode(); if (rMapMode.GetMapUnit() == MapUnit::MapPixel) @@ -4144,15 +4141,33 @@ void DocxAttributeOutput::WriteSrcRect(const SdrObject* pSdrObj ) aOriginalSize = Application::GetDefaultDevice()->PixelToLogic(aOriginalSize, aMap100mm); } - if ( (0 != aGraphicCropStruct.Left) || (0 != aGraphicCropStruct.Top) || (0 != aGraphicCropStruct.Right) || (0 != aGraphicCropStruct.Bottom) ) + css::text::GraphicCrop aGraphicCropStruct; + xPropSet->getPropertyValue( "GraphicCrop" ) >>= aGraphicCropStruct; + sal_Int16 nCropL = aGraphicCropStruct.Left; + sal_Int16 nCropR = aGraphicCropStruct.Right; + sal_Int16 nCropT = aGraphicCropStruct.Top; + sal_Int16 nCropB = aGraphicCropStruct.Bottom; + + // simulate border padding as a negative crop. + const SfxPoolItem* pItem; + if (pFrameFormat && SfxItemState::SET == pFrameFormat->GetItemState(RES_BOX, false, &pItem)) + { + const SvxBoxItem& rBox = *static_cast<const SvxBoxItem*>(pItem); + nCropL -= rBox.GetDistance( SvxBoxItemLine::LEFT ); + nCropR -= rBox.GetDistance( SvxBoxItemLine::RIGHT ); + nCropT -= rBox.GetDistance( SvxBoxItemLine::TOP ); + nCropB -= rBox.GetDistance( SvxBoxItemLine::BOTTOM ); + } + + if ( (0 != nCropL) || (0 != nCropT) || (0 != nCropR) || (0 != nCropB) ) { double widthMultiplier = 100000.0/aOriginalSize.Width(); double heightMultiplier = 100000.0/aOriginalSize.Height(); - double left = aGraphicCropStruct.Left * widthMultiplier; - double right = aGraphicCropStruct.Right * widthMultiplier; - double top = aGraphicCropStruct.Top * heightMultiplier; - double bottom = aGraphicCropStruct.Bottom * heightMultiplier; + double left = nCropL * widthMultiplier; + double right = nCropR * widthMultiplier; + double top = nCropT * heightMultiplier; + double bottom = nCropB * heightMultiplier; m_pSerializer->singleElementNS( XML_a, XML_srcRect, XML_l, I32S(left), @@ -4347,7 +4362,7 @@ void DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode* pGrfNode, const Size m_pSerializer->endElementNS( XML_a, XML_blip ); if (pSdrObj){ - WriteSrcRect(pSdrObj); + WriteSrcRect(pSdrObj, pFrameFormat); } m_pSerializer->startElementNS( XML_a, XML_stretch, diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx index 18339f453514..7c5149be2ff8 100644 --- a/sw/source/filter/ww8/docxattributeoutput.hxx +++ b/sw/source/filter/ww8/docxattributeoutput.hxx @@ -410,7 +410,7 @@ private: /// /// @see WriteOLE2Obj() void FlyFrameGraphic( const SwGrfNode* pGrfNode, const Size& rSize, const SwFlyFrameFormat* pOLEFrameFormat, SwOLENode* pOLENode, const SdrObject* pSdrObj = nullptr); - void WriteSrcRect( const SdrObject* pSdrObj ); + void WriteSrcRect( const SdrObject* pSdrObj, const SwFrameFormat* pFrameFormat ); void WriteOLE2Obj( const SdrObject* pSdrObj, SwOLENode& rNode, const Size& rSize, const SwFlyFrameFormat* pFlyFrameFormat); bool WriteOLEChart( const SdrObject* pSdrObj, const Size& rSize ); bool WriteOLEMath( const SdrObject* pSdrObj, const SwOLENode& rNode, const Size& rSize ); diff --git a/sw/source/filter/ww8/escher.hxx b/sw/source/filter/ww8/escher.hxx index fa2f30dba168..873486be7a29 100644 --- a/sw/source/filter/ww8/escher.hxx +++ b/sw/source/filter/ww8/escher.hxx @@ -103,7 +103,7 @@ protected: void WriteOLEPicture(EscherPropertyContainer &rPropOpt, sal_uInt32 nShapeFlags, const Graphic &rGraphic, const SdrObject &rObj, sal_uInt32 nShapeId, const css::awt::Rectangle* pVisArea ); - static void WriteGrfAttr(const SwNoTextNode& rNd,EscherPropertyContainer& rPropOpt); + static void WriteGrfAttr(const SwNoTextNode& rNd, const SwFrameFormat& rFormat, EscherPropertyContainer& rPropOpt); sal_Int32 DrawModelToEmu(sal_Int32 nVal) const { return BigMulDiv(nVal, mnEmuMul, mnEmuDiv); } diff --git a/sw/source/filter/ww8/wrtw8esh.cxx b/sw/source/filter/ww8/wrtw8esh.cxx index d5d0d2de844f..24c2583314d0 100644 --- a/sw/source/filter/ww8/wrtw8esh.cxx +++ b/sw/source/filter/ww8/wrtw8esh.cxx @@ -1732,7 +1732,7 @@ sal_Int32 SwBasicEscherEx::WriteGrfFlyFrame(const SwFrameFormat& rFormat, sal_uI aPropOpt.AddOpt( ESCHER_Prop_pibFlags, nFlags ); nBorderThick = WriteFlyFrameAttr(rFormat,mso_sptPictureFrame,aPropOpt); - WriteGrfAttr(*pGrfNd, aPropOpt); + WriteGrfAttr(*pGrfNd, rFormat, aPropOpt); aPropOpt.Commit( GetStream() ); @@ -1743,7 +1743,7 @@ sal_Int32 SwBasicEscherEx::WriteGrfFlyFrame(const SwFrameFormat& rFormat, sal_uI return nBorderThick; } -void SwBasicEscherEx::WriteGrfAttr(const SwNoTextNode& rNd, +void SwBasicEscherEx::WriteGrfAttr(const SwNoTextNode& rNd, const SwFrameFormat& rFormat, EscherPropertyContainer& rPropOpt) { const SfxPoolItem* pItem; @@ -1814,20 +1814,39 @@ void SwBasicEscherEx::WriteGrfAttr(const SwNoTextNode& rNd, if (nBrightness != 0) rPropOpt.AddOpt( ESCHER_Prop_pictureBrightness, nBrightness * 327 ); + sal_Int32 nCropL = 0; + sal_Int32 nCropR = 0; + sal_Int32 nCropT = 0; + sal_Int32 nCropB = 0; if (SfxItemState::SET == rNd.GetSwAttrSet().GetItemState(RES_GRFATR_CROPGRF, true, &pItem)) { - const Size aSz( rNd.GetTwipSize() ); - sal_Int32 nVal; - if( 0 != ( nVal = static_cast<const SwCropGrf*>(pItem )->GetLeft() ) ) - rPropOpt.AddOpt( ESCHER_Prop_cropFromLeft, ToFract16( nVal, aSz.Width()) ); - if( 0 != ( nVal = static_cast<const SwCropGrf*>(pItem )->GetRight() ) ) - rPropOpt.AddOpt( ESCHER_Prop_cropFromRight, ToFract16( nVal, aSz.Width())); - if( 0 != ( nVal = static_cast<const SwCropGrf*>(pItem )->GetTop() ) ) - rPropOpt.AddOpt( ESCHER_Prop_cropFromTop, ToFract16( nVal, aSz.Height())); - if( 0 != ( nVal = static_cast<const SwCropGrf*>(pItem )->GetBottom() ) ) - rPropOpt.AddOpt( ESCHER_Prop_cropFromBottom, ToFract16( nVal, aSz.Height())); + const SwCropGrf& rCrop = *static_cast<const SwCropGrf*>(pItem); + nCropL += rCrop.GetLeft(); + nCropR += rCrop.GetRight(); + nCropT += rCrop.GetTop(); + nCropB += rCrop.GetBottom(); } + + // simulate border padding as a negative crop. + if (SfxItemState::SET == rFormat.GetItemState(RES_BOX, false, &pItem)) + { + const SvxBoxItem& rBox = *static_cast<const SvxBoxItem*>(pItem); + nCropL -= rBox.GetDistance( SvxBoxItemLine::LEFT ); + nCropR -= rBox.GetDistance( SvxBoxItemLine::RIGHT ); + nCropT -= rBox.GetDistance( SvxBoxItemLine::TOP ); + nCropB -= rBox.GetDistance( SvxBoxItemLine::BOTTOM ); + } + + const Size aSz( rNd.GetTwipSize() ); + if( 0 != nCropL ) + rPropOpt.AddOpt( ESCHER_Prop_cropFromLeft, ToFract16( nCropL, aSz.Width()) ); + if( 0 != nCropR ) + rPropOpt.AddOpt( ESCHER_Prop_cropFromRight, ToFract16( nCropR, aSz.Width())); + if( 0 != nCropT ) + rPropOpt.AddOpt( ESCHER_Prop_cropFromTop, ToFract16( nCropT, aSz.Height())); + if( 0 != nCropB ) + rPropOpt.AddOpt( ESCHER_Prop_cropFromBottom, ToFract16( nCropB, aSz.Height())); } void SwBasicEscherEx::SetPicId(const SdrObject &, sal_uInt32, @@ -1891,7 +1910,7 @@ sal_Int32 SwBasicEscherEx::WriteOLEFlyFrame(const SwFrameFormat& rFormat, sal_uI rMirror), pGraphic ? *pGraphic : Graphic(), *pSdrObj, nShapeId, bRectIsSet ? &aRect : nullptr ); nBorderThick = WriteFlyFrameAttr(rFormat, mso_sptPictureFrame, aPropOpt); - WriteGrfAttr(rOLENd, aPropOpt); + WriteGrfAttr(rOLENd, rFormat, aPropOpt); aPropOpt.Commit(GetStream()); // store anchor attribute |