diff options
author | Attila Szűcs <attila.szucs@collabora.com> | 2024-06-03 22:08:42 +0200 |
---|---|---|
committer | Caolán McNamara <caolan.mcnamara@collabora.com> | 2024-06-06 10:03:14 +0200 |
commit | c30c1d12f283e75fdcc5bb508a79a9d33a431d28 (patch) | |
tree | 38fadb3098cd9516b3871c6340bf77ae2c6c10e3 | |
parent | 734914261347d51dfd4f1140b037c52c86060277 (diff) |
tdf#153008 svx: impl crop for stretched bitmap fill
The ticket had a pptx with a:
<a:blipFill> <a:stretch> <a:fillRect ...>
Impress loaded the fillRect as a crop, but never used.
Implemented a crop in
SdrFillGraphicAttribute::createFillGraphicAttribute
because in the case of stretching, it blindly used the whole picture.
Cropping data was not available there so it is copied
into OffsetPosition, and Size
Change-Id: I195cc40a35dc24c708e7c0e3cdbe40d6e47b8ce5
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168391
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
-rw-r--r-- | drawinglayer/source/attribute/sdrfillgraphicattribute.cxx | 13 | ||||
-rw-r--r-- | svx/qa/unit/data/tdf153008_crop_stretched_bitmap.pptx | bin | 0 -> 37834 bytes | |||
-rw-r--r-- | svx/qa/unit/svdraw.cxx | 68 | ||||
-rw-r--r-- | svx/source/customshapes/EnhancedCustomShape2d.cxx | 27 |
4 files changed, 105 insertions, 3 deletions
diff --git a/drawinglayer/source/attribute/sdrfillgraphicattribute.cxx b/drawinglayer/source/attribute/sdrfillgraphicattribute.cxx index b78f3e322c38..0acf4ba44be2 100644 --- a/drawinglayer/source/attribute/sdrfillgraphicattribute.cxx +++ b/drawinglayer/source/attribute/sdrfillgraphicattribute.cxx @@ -286,6 +286,19 @@ namespace drawinglayer::attribute aBitmapSize.setX(aBitmapSize.getX() / fRangeWidth); aBitmapSize.setY(aBitmapSize.getY() / fRangeHeight); } + else if (mpSdrFillGraphicAttribute->getStretch()) + { + //tdf#153008 We may want to calculate crop. (stretch-fillRect case) + aBitmapTopLeft.setX(getOffsetPosition().getX() * 0.01); + aBitmapTopLeft.setY(getOffsetPosition().getY() * 0.01); + if (getSize().getX() != 0.0 && getSize().getY() != 0.0) + { + const double fRangeWidth(0.0 != rRange.getWidth() ? rRange.getWidth() : 1.0); + const double fRangeHeight(0.0 != rRange.getHeight() ? rRange.getHeight() : 1.0); + aBitmapSize.setX(getSize().getX() / fRangeWidth); + aBitmapSize.setY(getSize().getY() / fRangeHeight); + } + } // get offset in percent const double fOffsetX(std::clamp(getOffset().getX() * 0.01, 0.0, 1.0)); diff --git a/svx/qa/unit/data/tdf153008_crop_stretched_bitmap.pptx b/svx/qa/unit/data/tdf153008_crop_stretched_bitmap.pptx Binary files differnew file mode 100644 index 000000000000..453b81fa006a --- /dev/null +++ b/svx/qa/unit/data/tdf153008_crop_stretched_bitmap.pptx diff --git a/svx/qa/unit/svdraw.cxx b/svx/qa/unit/svdraw.cxx index 83293c52ee3f..5f16baae175d 100644 --- a/svx/qa/unit/svdraw.cxx +++ b/svx/qa/unit/svdraw.cxx @@ -52,16 +52,17 @@ public: } protected: - SdrPage* getFirstDrawPageWithAssert(); + SdrPage* getFirstDrawPageWithAssert(sal_Int32 nPageIndex = 0); }; -SdrPage* SvdrawTest::getFirstDrawPageWithAssert() +SdrPage* SvdrawTest::getFirstDrawPageWithAssert(sal_Int32 nPageIndex /* = 0*/) { uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(mxComponent, uno::UNO_QUERY_THROW); CPPUNIT_ASSERT(xDrawPagesSupplier.is()); uno::Reference<drawing::XDrawPages> xDrawPages(xDrawPagesSupplier->getDrawPages()); - uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPages->getByIndex(0), uno::UNO_QUERY_THROW); + uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPages->getByIndex(nPageIndex), + uno::UNO_QUERY_THROW); CPPUNIT_ASSERT(xDrawPage.is()); auto pDrawPage = dynamic_cast<SvxDrawPage*>(xDrawPage.get()); @@ -465,6 +466,67 @@ CPPUNIT_TEST_FIXTURE(SvdrawTest, testTdf148000_CurvedTextWidth) } } +CPPUNIT_TEST_FIXTURE(SvdrawTest, testTdf153008_CropStretchedBitmapFill) +{ + loadFromFile(u"tdf153008_crop_stretched_bitmap.pptx"); + + SdrPage* pSdrPage = getFirstDrawPageWithAssert(); + + xmlDocUniquePtr pXmlDoc = lcl_dumpAndParseFirstObjectWithAssert(pSdrPage); + + // Load Polygon size + sal_Int16 nPolyHeight = getXPath(pXmlDoc, "//mask/polypolygon"_ostr, "height"_ostr).toInt32(); + sal_Int16 nPolyWidth = getXPath(pXmlDoc, "//mask/polypolygon"_ostr, "width"_ostr).toInt32(); + // polygon position is nearly 0,0 + // Load Bitmap coordinates (from transformation matrix) + sal_Int16 nBmpPosX = getXPath(pXmlDoc, "//bitmap"_ostr, "xy13"_ostr).toInt32(); + sal_Int16 nBmpPosY = getXPath(pXmlDoc, "//bitmap"_ostr, "xy23"_ostr).toInt32(); + sal_Int16 nBmpWidth = getXPath(pXmlDoc, "//bitmap"_ostr, "xy11"_ostr).toInt32(); + sal_Int16 nBmpHeight = getXPath(pXmlDoc, "//bitmap"_ostr, "xy22"_ostr).toInt32(); + + // The Bitmap should start nearly in the middle of the polygon. + // because of rounding errors we tolerate 2% difference + // Before the fix, the bitmap was always stretched to the whole polygon, + // that means they had the same size, and position. + CPPUNIT_ASSERT_DOUBLES_EQUAL(nPolyWidth / 2, nBmpPosX, nPolyWidth / 50); + CPPUNIT_ASSERT_DOUBLES_EQUAL(nPolyHeight / 2, nBmpPosY, nPolyHeight / 50); + // And should have 1/2 width, and 3/8 height of the polygon. + CPPUNIT_ASSERT_DOUBLES_EQUAL(nPolyWidth / 2, nBmpWidth, nPolyWidth / 50); + CPPUNIT_ASSERT_DOUBLES_EQUAL(nPolyHeight * 3 / 8, nBmpHeight, nPolyHeight / 50); +} + +CPPUNIT_TEST_FIXTURE(SvdrawTest, testTdf153008_CropStretchedBitmapFillNegativePosition) +{ + loadFromFile(u"tdf153008_crop_stretched_bitmap.pptx"); + + // get the 2. page + SdrPage* pSdrPage = getFirstDrawPageWithAssert(1); + + xmlDocUniquePtr pXmlDoc = lcl_dumpAndParseFirstObjectWithAssert(pSdrPage); + + // Load Polygon size + sal_Int16 nPolyHeight = getXPath(pXmlDoc, "//mask/polypolygon"_ostr, "height"_ostr).toInt32(); + sal_Int16 nPolyWidth = getXPath(pXmlDoc, "//mask/polypolygon"_ostr, "width"_ostr).toInt32(); + // polygon position is nearly 0,0 + // Load Bitmap coordinates (from transformation matrix) + sal_Int16 nBmpPosX = getXPath(pXmlDoc, "//bitmap"_ostr, "xy13"_ostr).toInt32(); + sal_Int16 nBmpPosY = getXPath(pXmlDoc, "//bitmap"_ostr, "xy23"_ostr).toInt32(); + sal_Int16 nBmpWidth = getXPath(pXmlDoc, "//bitmap"_ostr, "xy11"_ostr).toInt32(); + sal_Int16 nBmpHeight = getXPath(pXmlDoc, "//bitmap"_ostr, "xy22"_ostr).toInt32(); + + // The Bitmap should start before the polygon. + // At x direction it should start left from the polygon with 3/8 polygon width + // At y direction it should start up from the polygon with 3/16 polygon height + // Before the fix, negative numbers overflowed to big positive number, + // so the bitmap was moved to a far away place where it was not visible + // because of rounding errors we tolerate 2% difference + CPPUNIT_ASSERT_DOUBLES_EQUAL(-nPolyWidth * 3 / 8, nBmpPosX, nPolyWidth / 50); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-nPolyHeight * 3 / 16, nBmpPosY, nPolyHeight / 50); + // And should have 3/2 width, and 1/1 height of the polygon. + CPPUNIT_ASSERT_DOUBLES_EQUAL(nPolyWidth * 3 / 2, nBmpWidth, nPolyWidth / 50); + CPPUNIT_ASSERT_DOUBLES_EQUAL(nPolyHeight, nBmpHeight, nPolyHeight / 50); +} + CPPUNIT_TEST_FIXTURE(SvdrawTest, testSurfaceMetal) { loadFromFile(u"tdf140321_metal.odp"); diff --git a/svx/source/customshapes/EnhancedCustomShape2d.cxx b/svx/source/customshapes/EnhancedCustomShape2d.cxx index b8b6d04e4cf4..4c68aa45ded2 100644 --- a/svx/source/customshapes/EnhancedCustomShape2d.cxx +++ b/svx/source/customshapes/EnhancedCustomShape2d.cxx @@ -43,6 +43,10 @@ #include <svx/xbtmpit.hxx> #include <svx/xhatch.hxx> #include <svx/sdshitm.hxx> +#include <svx/xflboxy.hxx> +#include <svx/xflbmsxy.hxx> +#include <svx/sdgcpitm.hxx> +#include <svx/xflbstit.hxx> #include <comphelper/configuration.hxx> #include <com/sun/star/awt/Size.hpp> #include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp> @@ -2626,6 +2630,29 @@ void EnhancedCustomShape2d::CreateSubPath( SfxItemSet aTempSet(*this); aTempSet.Put(makeSdrShadowItem(false)); aTempSet.Put(XLineStyleItem(drawing::LineStyle_NONE)); + + // tdf#153008 If it is a stretched bitmap, with crop, + // then set crop data into PosOffset and BmpSize + // so it can be used at createFillGraphicAttribute to crop the image + if (aTempSet.HasItem(SDRATTR_GRAFCROP) + && aTempSet.HasItem(XATTR_FILLBITMAP) + && aTempSet.HasItem(XATTR_FILLBMP_STRETCH) + && aTempSet.Get(XATTR_FILLBMP_STRETCH).GetValue()) + { + const SdrGrafCropItem& rCrop = aTempSet.Get(SDRATTR_GRAFCROP); + const Size& aBmpSize + = aTempSet.Get(XATTR_FILLBITMAP).GetGraphicObject().GetPrefSize(); + + aTempSet.Put(XFillBmpPosOffsetXItem(rCrop.GetLeft() * 100 / aBmpSize.Width())); + aTempSet.Put(XFillBmpPosOffsetYItem(rCrop.GetTop() * 100 / aBmpSize.Height())); + aTempSet.Put( + XFillBmpSizeXItem((aBmpSize.Width() - rCrop.GetLeft() - rCrop.GetRight()) + * pFill->GetGeoRect().GetWidth() / aBmpSize.Width())); + aTempSet.Put( + XFillBmpSizeYItem((aBmpSize.Height() - rCrop.GetTop() - rCrop.GetBottom()) + * pFill->GetGeoRect().GetHeight() / aBmpSize.Height())); + } + pFill->SetMergedItemSet(aTempSet); rObjectList.push_back(std::pair< rtl::Reference<SdrPathObj>, double >(std::move(pFill), dBrightness)); } |