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");

Reply via email to