include/oox/export/drawingml.hxx | 3 oox/source/drawingml/fillproperties.cxx | 4 - oox/source/export/drawingml.cxx | 109 ++++++++++++++++++++++++++++++- sd/qa/unit/data/odp/repeatBitmapMode.odp |binary sd/qa/unit/export-tests-ooxml2.cxx | 23 ++++++ 5 files changed, 136 insertions(+), 3 deletions(-)
New commits: commit 3f70375cf160841b6140f5f1b2b79af3652897f8 Author: Tibor Nagy <nagy.tib...@nisz.hu> AuthorDate: Fri Nov 18 12:06:59 2022 +0100 Commit: László Németh <nem...@numbertext.org> CommitDate: Thu Nov 24 16:56:38 2022 +0100 tdf#152069 tdf#108356 PPTX export: fix missing tile properties of background image patterns defined by a:tile. Note: factor "3.6" comes from EMU. Change-Id: I5da532ff9ad63fd6c236a58933a31dcd96cf5156 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142913 Tested-by: László Németh <nem...@numbertext.org> Reviewed-by: László Németh <nem...@numbertext.org> diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx index bf2ed44bca70..543fb072921f 100644 --- a/include/oox/export/drawingml.hxx +++ b/include/oox/export/drawingml.hxx @@ -275,6 +275,9 @@ public: void WriteXGraphicStretch(css::uno::Reference<css::beans::XPropertySet> const & rXPropSet, css::uno::Reference<css::graphic::XGraphic> const & rxGraphic); + void WriteXGraphicTile(css::uno::Reference<css::beans::XPropertySet> const& rXPropSet, + css::uno::Reference<css::graphic::XGraphic> const& rxGraphic); + void WriteLinespacing(const css::style::LineSpacing& rLineSpacing, float fFirstCharHeight); OUString WriteXGraphicBlip(css::uno::Reference<css::beans::XPropertySet> const & rXPropSet, diff --git a/oox/source/drawingml/fillproperties.cxx b/oox/source/drawingml/fillproperties.cxx index 7933a79f5dba..75da3836b6f5 100644 --- a/oox/source/drawingml/fillproperties.cxx +++ b/oox/source/drawingml/fillproperties.cxx @@ -832,9 +832,9 @@ void FillProperties::pushToPropMap( ShapePropertyMap& rPropMap, rPropMap.setProperty( ShapeProperty::FillBitmapSizeY, nFillBmpSizeY ); // offset of the first bitmap tile (given as EMUs), convert to percent - sal_Int16 nTileOffsetX = getDoubleIntervalValue< sal_Int16 >( maBlipProps.moTileOffsetX.value_or( 0 ) / 3.6 / aOriginalSize.Width, 0, 100 ); + sal_Int16 nTileOffsetX = getDoubleIntervalValue< sal_Int16 >(std::round(maBlipProps.moTileOffsetX.value_or( 0 ) / 3.6 / aOriginalSize.Width), 0, 100 ); rPropMap.setProperty( ShapeProperty::FillBitmapOffsetX, nTileOffsetX ); - sal_Int16 nTileOffsetY = getDoubleIntervalValue< sal_Int16 >( maBlipProps.moTileOffsetY.value_or( 0 ) / 3.6 / aOriginalSize.Height, 0, 100 ); + sal_Int16 nTileOffsetY = getDoubleIntervalValue< sal_Int16 >(std::round(maBlipProps.moTileOffsetY.value_or( 0 ) / 3.6 / aOriginalSize.Height), 0, 100 ); rPropMap.setProperty( ShapeProperty::FillBitmapOffsetY, nTileOffsetY ); } } diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx index 16affd23295b..3dc68b2f3d3b 100644 --- a/oox/source/export/drawingml.cxx +++ b/oox/source/export/drawingml.cxx @@ -100,6 +100,7 @@ #include <com/sun/star/container/XNamed.hpp> #include <com/sun/star/drawing/XDrawPages.hpp> #include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/drawing/RectanglePoint.hpp> #include <comphelper/propertyvalue.hxx> #include <comphelper/random.hxx> @@ -1615,7 +1616,7 @@ void DrawingML::WriteXGraphicBlipMode(uno::Reference<beans::XPropertySet> const switch (eBitmapMode) { case BitmapMode_REPEAT: - mpFS->singleElementNS(XML_a, XML_tile); + WriteXGraphicTile(rXPropSet, rxGraphic); break; case BitmapMode_STRETCH: WriteXGraphicStretch(rXPropSet, rxGraphic); @@ -1838,6 +1839,112 @@ void DrawingML::WriteXGraphicStretch(uno::Reference<beans::XPropertySet> const & mpFS->endElementNS(XML_a, XML_stretch); } +static OUString lclConvertRectanglePointToToken(RectanglePoint eRectanglePoint) +{ + OUString sAlignment; + switch (eRectanglePoint) + { + case RectanglePoint_LEFT_TOP: + sAlignment = "tl"; + break; + case RectanglePoint_MIDDLE_TOP: + sAlignment = "t"; + break; + case RectanglePoint_RIGHT_TOP: + sAlignment = "tr"; + break; + case RectanglePoint_LEFT_MIDDLE: + sAlignment = "l"; + break; + case RectanglePoint_MIDDLE_MIDDLE: + sAlignment = "ctr"; + break; + case RectanglePoint_RIGHT_MIDDLE: + sAlignment = "r"; + break; + case RectanglePoint_LEFT_BOTTOM: + sAlignment = "bl"; + break; + case RectanglePoint_MIDDLE_BOTTOM: + sAlignment = "b"; + break; + case RectanglePoint_RIGHT_BOTTOM: + sAlignment = "br"; + break; + default: + break; + } + return sAlignment; +} + +void DrawingML::WriteXGraphicTile(uno::Reference<beans::XPropertySet> const& rXPropSet, + uno::Reference<graphic::XGraphic> const& rxGraphic) +{ + Graphic aGraphic(rxGraphic); + Size aOriginalSize(aGraphic.GetPrefSize()); + const MapMode& rMapMode = aGraphic.GetPrefMapMode(); + // if the original size is in pixel, convert it to mm100 + if (rMapMode.GetMapUnit() == MapUnit::MapPixel) + aOriginalSize = Application::GetDefaultDevice()->PixelToLogic(aOriginalSize, + MapMode(MapUnit::Map100thMM)); + sal_Int32 nOffsetX = 0; + if (GetProperty(rXPropSet, "FillBitmapPositionOffsetX")) + nOffsetX = (*o3tl::doAccess<sal_Int32>(mAny)) * aOriginalSize.Width() * 3.6; + + sal_Int32 nOffsetY = 0; + if (GetProperty(rXPropSet, "FillBitmapPositionOffsetY")) + nOffsetY = (*o3tl::doAccess<sal_Int32>(mAny)) * aOriginalSize.Height() * 3.6; + + // convert the X size of bitmap to a percentage + sal_Int32 nSizeX = 0; + if (GetProperty(rXPropSet, "FillBitmapSizeX")) + { + mAny >>= nSizeX; + if (nSizeX > 0) + nSizeX = double(nSizeX) / aOriginalSize.Width() * 100000; + else if (nSizeX < 0) + nSizeX *= 1000; + else + nSizeX = 100000; + } + + // convert the Y size of bitmap to a percentage + sal_Int32 nSizeY = 0; + if (GetProperty(rXPropSet, "FillBitmapSizeY")) + { + mAny >>= nSizeY; + if (nSizeY > 0) + nSizeY = double(nSizeY) / aOriginalSize.Height() * 100000; + else if (nSizeY < 0) + nSizeY *= 1000; + else + nSizeY = 100000; + } + + // if the "Scale" setting is checked in the images settings dialog. + if (nSizeX < 0 && nSizeY < 0) + { + Reference<drawing::XDrawPagesSupplier> xDPS(GetFB()->getModel(), UNO_QUERY_THROW); + Reference<drawing::XDrawPages> xDrawPages(xDPS->getDrawPages(), UNO_SET_THROW); + // in this case, the size of the first slide is enough, because all slides are the same size + Reference<XDrawPage> xDrawPage(xDrawPages->getByIndex(0), UNO_QUERY); + css::uno::Reference<css::beans::XPropertySet> mXPagePropSet(xDrawPage, UNO_QUERY); + double nPageWidth, nPageHeight; + mXPagePropSet->getPropertyValue("Width") >>= nPageWidth; + mXPagePropSet->getPropertyValue("Height") >>= nPageHeight; + nSizeX = nPageWidth / aOriginalSize.Width() * std::abs(nSizeX); + nSizeY = nPageHeight / aOriginalSize.Height() * std::abs(nSizeY); + } + + OUString sRectanglePoint; + if (GetProperty(rXPropSet, "FillBitmapRectanglePoint")) + sRectanglePoint = lclConvertRectanglePointToToken(*o3tl::doAccess<RectanglePoint>(mAny)); + + mpFS->singleElementNS(XML_a, XML_tile, XML_tx, OUString::number(nOffsetX), XML_ty, + OUString::number(nOffsetY), XML_sx, OUString::number(nSizeX), XML_sy, + OUString::number(nSizeY), XML_algn, sRectanglePoint); +} + namespace { bool IsTopGroupObj(const uno::Reference<drawing::XShape>& xShape) diff --git a/sd/qa/unit/data/odp/repeatBitmapMode.odp b/sd/qa/unit/data/odp/repeatBitmapMode.odp new file mode 100644 index 000000000000..b3d829930487 Binary files /dev/null and b/sd/qa/unit/data/odp/repeatBitmapMode.odp differ diff --git a/sd/qa/unit/export-tests-ooxml2.cxx b/sd/qa/unit/export-tests-ooxml2.cxx index 57008eefbf8d..4e01e9ed82fd 100644 --- a/sd/qa/unit/export-tests-ooxml2.cxx +++ b/sd/qa/unit/export-tests-ooxml2.cxx @@ -76,6 +76,7 @@ public: { } + void testRepeatBitmapMode(); void testTdf142291(); void testTdf151492(); void testTdf149697(); @@ -147,6 +148,7 @@ public: CPPUNIT_TEST_SUITE(SdOOXMLExportTest2); + CPPUNIT_TEST(testRepeatBitmapMode); CPPUNIT_TEST(testTdf142291); CPPUNIT_TEST(testTdf151492); CPPUNIT_TEST(testTdf149697); @@ -224,6 +226,27 @@ public: } }; +void SdOOXMLExportTest2::testRepeatBitmapMode() +{ + loadFromURL(u"odp/repeatBitmapMode.odp"); + save("Impress Office Open XML"); + + xmlDocUniquePtr pXmlDocContent1 = parseExport("ppt/slides/slide1.xml"); + assertXPath(pXmlDocContent1, "/p:sld/p:cSld/p:bg/p:bgPr/a:blipFill/a:tile", "tx", "1269669"); + assertXPath(pXmlDocContent1, "/p:sld/p:cSld/p:bg/p:bgPr/a:blipFill/a:tile", "ty", "186051"); + assertXPath(pXmlDocContent1, "/p:sld/p:cSld/p:bg/p:bgPr/a:blipFill/a:tile", "sx", "100000"); + assertXPath(pXmlDocContent1, "/p:sld/p:cSld/p:bg/p:bgPr/a:blipFill/a:tile", "sy", "100000"); + assertXPath(pXmlDocContent1, "/p:sld/p:cSld/p:bg/p:bgPr/a:blipFill/a:tile", "algn", "tr"); + + // if the "Scale" setting is checked in the images settings dialog. + xmlDocUniquePtr pXmlDocContent2 = parseExport("ppt/slides/slide2.xml"); + assertXPath(pXmlDocContent2, "/p:sld/p:cSld/p:bg/p:bgPr/a:blipFill/a:tile", "tx", "0"); + assertXPath(pXmlDocContent2, "/p:sld/p:cSld/p:bg/p:bgPr/a:blipFill/a:tile", "ty", "0"); + assertXPath(pXmlDocContent2, "/p:sld/p:cSld/p:bg/p:bgPr/a:blipFill/a:tile", "sx", "682760"); + assertXPath(pXmlDocContent2, "/p:sld/p:cSld/p:bg/p:bgPr/a:blipFill/a:tile", "sy", "639983"); + assertXPath(pXmlDocContent2, "/p:sld/p:cSld/p:bg/p:bgPr/a:blipFill/a:tile", "algn", "ctr"); +} + void SdOOXMLExportTest2::testTdf142291() { loadFromURL(u"pptx/tdt142291.pptx");