sw/qa/extras/ooxmlexport/data/tdf41542_imagePadding.odt |binary sw/qa/extras/ooxmlexport/ooxmlexport3.cxx | 13 ++++ sw/qa/extras/ww8export/data/tdf41542_imagePadding.odt |binary sw/qa/extras/ww8export/ww8export.cxx | 33 ++++++++--- sw/source/filter/ww8/docxattributeoutput.cxx | 35 ++++++++---- sw/source/filter/ww8/docxattributeoutput.hxx | 2 sw/source/filter/ww8/escher.hxx | 2 sw/source/filter/ww8/wrtw8esh.cxx | 45 +++++++++++----- 8 files changed, 95 insertions(+), 35 deletions(-)
New commits: commit 8eff1decd91cbfb10094c25d4cf1d2b434a4da72 Author: Justin Luth <justin_l...@sil.org> Date: Fri Nov 4 21:32:38 2016 +0300 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 <c...@libreoffice.org> Reviewed-by: Justin Luth <justin_l...@sil.org> diff --git a/sw/qa/extras/ooxmlexport/data/tdf41542_imagePadding.odt b/sw/qa/extras/ooxmlexport/data/tdf41542_imagePadding.odt new file mode 100755 index 0000000..019e19f Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf41542_imagePadding.odt differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx index 4d73a7f..f93ace6 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 new file mode 100755 index 0000000..019e19f Binary files /dev/null and b/sw/qa/extras/ww8export/data/tdf41542_imagePadding.odt differ diff --git a/sw/qa/extras/ww8export/ww8export.cxx b/sw/qa/extras/ww8export/ww8export.cxx index 88a703d..d3d8733 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 09e1172..2aea2cc 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 18339f4..7c5149b 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 fa2f30d..873486b 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 d5d0d2d..24c2583 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 _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits