include/oox/export/drawingml.hxx         |   27 ++++++++-----
 oox/source/export/drawingml.cxx          |   55 ++++++++++++++++------------
 oox/source/export/shapes.cxx             |    6 +--
 sd/qa/unit/data/odp/tdf153107.odp        |binary
 sd/qa/unit/export-tests-ooxml2.cxx       |   60 +++++++++++++++++++++++++++++++
 sd/source/filter/eppt/pptx-epptooxml.cxx |    4 +-
 6 files changed, 112 insertions(+), 40 deletions(-)

New commits:
commit df482562d2532956c197468740e2a02499a89f55
Author:     Tibor Nagy <nagy.tib...@nisz.hu>
AuthorDate: Mon Jan 23 09:33:13 2023 +0100
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Tue Jun 27 14:16:25 2023 +0200

    tdf#153107 OOXML export: fix scale of tile of shape background
    
    Relative scale values were exported as absolute values,
    resulting broken shape background.
    
    Change-Id: Ia38e125862e7f8ceff5d41754340723c3a9eb028
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145996
    Tested-by: László Németh <nem...@numbertext.org>
    Reviewed-by: László Németh <nem...@numbertext.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153576
    Reviewed-by: Jaume Pujantell <jaume.pujant...@collabora.com>
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx
index cdfb31af9c7c..89fb0cab1128 100644
--- a/include/oox/export/drawingml.hxx
+++ b/include/oox/export/drawingml.hxx
@@ -380,16 +380,18 @@ public:
 
     void WriteGrabBagGradientFill( const css::uno::Sequence< 
css::beans::PropertyValue >& aGradientStops, const basegfx::BGradient& 
rGradient);
 
-    void WriteBlipOrNormalFill( const css::uno::Reference< 
css::beans::XPropertySet >& rXPropSet,
-            const OUString& rURLPropName );
-    void WriteBlipFill( const css::uno::Reference< css::beans::XPropertySet >& 
rXPropSet,
-            const OUString& sURLPropName );
-    void WriteBlipFill( const css::uno::Reference< css::beans::XPropertySet >& 
rXPropSet,
-                         const OUString& sURLPropName, sal_Int32 nXmlNamespace 
);
+    void WriteBlipOrNormalFill(const 
css::uno::Reference<css::beans::XPropertySet>& rXPropSet,
+                               const OUString& rURLPropName, const 
css::awt::Size& rSize = {});
+    void WriteBlipFill(const css::uno::Reference<css::beans::XPropertySet>& 
rXPropSet,
+                       const OUString& sURLPropName, const css::awt::Size& 
rSize = {});
+    void WriteBlipFill(const css::uno::Reference<css::beans::XPropertySet>& 
rXPropSet,
+                       const css::awt::Size& rSize, const OUString& 
sURLPropName,
+                       sal_Int32 nXmlNamespace);
 
     void WriteXGraphicBlipFill(css::uno::Reference<css::beans::XPropertySet> 
const & rXPropSet,
                                css::uno::Reference<css::graphic::XGraphic> 
const & rxGraphic,
-                               sal_Int32 nXmlNamespace, bool bWriteMode, bool 
bRelPathToMedia = false);
+                               sal_Int32 nXmlNamespace, bool bWriteMode,
+                               bool bRelPathToMedia = false, css::awt::Size 
const& rSize = {});
 
     void WritePattFill( const css::uno::Reference< css::beans::XPropertySet >& 
rXPropSet );
     void WritePattFill(const css::uno::Reference<css::beans::XPropertySet>& 
rXPropSet,
@@ -408,7 +410,8 @@ public:
                               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);
+                           css::uno::Reference<css::graphic::XGraphic> const& 
rxGraphic,
+                           css::awt::Size const& rSize);
 
     void WriteLinespacing(const css::style::LineSpacing& rLineSpacing, float 
fFirstCharHeight);
 
@@ -418,8 +421,9 @@ public:
 
     void 
WriteImageBrightnessContrastTransparence(css::uno::Reference<css::beans::XPropertySet>
 const & rXPropSet);
 
-    void WriteXGraphicBlipMode(css::uno::Reference<css::beans::XPropertySet> 
const & rXPropSet,
-                               css::uno::Reference<css::graphic::XGraphic> 
const & rxGraphic);
+    void WriteXGraphicBlipMode(css::uno::Reference<css::beans::XPropertySet> 
const& rXPropSet,
+                               css::uno::Reference<css::graphic::XGraphic> 
const& rxGraphic,
+                               css::awt::Size const& rSize);
 
     void WriteShapeTransformation(const css::uno::Reference< 
css::drawing::XShape >& rXShape,
                   sal_Int32 nXmlNamespace, bool bFlipH = false, bool bFlipV = 
false, bool bSuppressRotation = false, bool bSuppressFlipping = false, bool 
bFlippedBeforeRotation = false);
@@ -459,7 +463,8 @@ public:
     void WriteEmptyCustomGeometry();
     void WritePolyPolygon(const css::uno::Reference<css::drawing::XShape>& 
rXShape,
                           const bool bClosed);
-    void WriteFill( const css::uno::Reference< css::beans::XPropertySet >& 
xPropSet );
+    void WriteFill(const css::uno::Reference<css::beans::XPropertySet>& 
xPropSet,
+                   const css::awt::Size& rSize = {});
     void WriteShapeStyle( const css::uno::Reference< css::beans::XPropertySet 
>& rXPropSet );
     void WriteShapeEffects( const css::uno::Reference< 
css::beans::XPropertySet >& rXPropSet );
     void WriteShapeEffect( std::u16string_view sName, const 
css::uno::Sequence< css::beans::PropertyValue >& aEffectProps );
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 6599f6cb1959..f7f67595c025 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -1703,7 +1703,8 @@ OUString 
DrawingML::WriteXGraphicBlip(uno::Reference<beans::XPropertySet> const
 }
 
 void DrawingML::WriteXGraphicBlipMode(uno::Reference<beans::XPropertySet> 
const & rXPropSet,
-                                      uno::Reference<graphic::XGraphic> const 
& rxGraphic)
+                                      uno::Reference<graphic::XGraphic> const 
& rxGraphic,
+                                      css::awt::Size const& rSize)
 {
     BitmapMode eBitmapMode(BitmapMode_NO_REPEAT);
     if (GetProperty(rXPropSet, "FillBitmapMode"))
@@ -1714,7 +1715,7 @@ void 
DrawingML::WriteXGraphicBlipMode(uno::Reference<beans::XPropertySet> const
     switch (eBitmapMode)
     {
     case BitmapMode_REPEAT:
-        WriteXGraphicTile(rXPropSet, rxGraphic);
+        WriteXGraphicTile(rXPropSet, rxGraphic, rSize);
         break;
     case BitmapMode_STRETCH:
         WriteXGraphicStretch(rXPropSet, rxGraphic);
@@ -1724,7 +1725,8 @@ void 
DrawingML::WriteXGraphicBlipMode(uno::Reference<beans::XPropertySet> const
     }
 }
 
-void DrawingML::WriteBlipOrNormalFill( const Reference< XPropertySet >& 
xPropSet, const OUString& rURLPropName )
+void DrawingML::WriteBlipOrNormalFill(const Reference<XPropertySet>& xPropSet,
+                                      const OUString& rURLPropName, const 
awt::Size& rSize)
 {
     // check for blip and otherwise fall back to normal fill
     // we always store normal fill properties but OOXML
@@ -1732,15 +1734,17 @@ void DrawingML::WriteBlipOrNormalFill( const Reference< 
XPropertySet >& xPropSet
     if (GetProperty ( xPropSet, rURLPropName ))
         WriteBlipFill( xPropSet, rURLPropName );
     else
-        WriteFill(xPropSet);
+        WriteFill(xPropSet, rSize);
 }
 
-void DrawingML::WriteBlipFill( const Reference< XPropertySet >& rXPropSet, 
const OUString& sURLPropName )
+void DrawingML::WriteBlipFill(const Reference<XPropertySet>& rXPropSet,
+                              const OUString& sURLPropName, const awt::Size& 
rSize)
 {
-    WriteBlipFill( rXPropSet, sURLPropName, XML_a );
+    WriteBlipFill( rXPropSet, rSize, sURLPropName, XML_a );
 }
 
-void DrawingML::WriteBlipFill( const Reference< XPropertySet >& rXPropSet, 
const OUString& sURLPropName, sal_Int32 nXmlNamespace )
+void DrawingML::WriteBlipFill(const Reference<XPropertySet>& rXPropSet, const 
awt::Size& rSize,
+                              const OUString& sURLPropName, sal_Int32 
nXmlNamespace)
 {
     if ( !GetProperty( rXPropSet, sURLPropName ) )
         return;
@@ -1762,13 +1766,14 @@ void DrawingML::WriteBlipFill( const Reference< 
XPropertySet >& rXPropSet, const
         bool bWriteMode = false;
         if (sURLPropName == "FillBitmap" || sURLPropName == "BackGraphic")
             bWriteMode = true;
-        WriteXGraphicBlipFill(rXPropSet, xGraphic, nXmlNamespace, bWriteMode);
+        WriteXGraphicBlipFill(rXPropSet, xGraphic, nXmlNamespace, bWriteMode, 
false, rSize);
     }
 }
 
 void DrawingML::WriteXGraphicBlipFill(uno::Reference<beans::XPropertySet> 
const & rXPropSet,
                                       uno::Reference<graphic::XGraphic> const 
& rxGraphic,
-                                      sal_Int32 nXmlNamespace, bool 
bWriteMode, bool bRelPathToMedia)
+                                      sal_Int32 nXmlNamespace, bool bWriteMode,
+                                      bool bRelPathToMedia, css::awt::Size 
const& rSize)
 {
     if (!rxGraphic.is() )
         return;
@@ -1785,7 +1790,7 @@ void 
DrawingML::WriteXGraphicBlipFill(uno::Reference<beans::XPropertySet> const
 
     if (bWriteMode)
     {
-        WriteXGraphicBlipMode(rXPropSet, rxGraphic);
+        WriteXGraphicBlipMode(rXPropSet, rxGraphic, rSize);
     }
     else if(GetProperty(rXPropSet, "FillBitmapStretch"))
     {
@@ -1976,7 +1981,8 @@ static OUString 
lclConvertRectanglePointToToken(RectanglePoint eRectanglePoint)
 }
 
 void DrawingML::WriteXGraphicTile(uno::Reference<beans::XPropertySet> const& 
rXPropSet,
-                                  uno::Reference<graphic::XGraphic> const& 
rxGraphic)
+                                  uno::Reference<graphic::XGraphic> const& 
rxGraphic,
+                                  css::awt::Size const& rSize)
 {
     Graphic aGraphic(rxGraphic);
     Size aOriginalSize(aGraphic.GetPrefSize());
@@ -1993,6 +1999,8 @@ void 
DrawingML::WriteXGraphicTile(uno::Reference<beans::XPropertySet> const& rXP
         if (GetProperty(rXPropSet, "FillBitmapPositionOffsetX"))
         {
             sal_Int32 nX = (nSizeX != 0) ? nSizeX : aOriginalSize.Width();
+            if (nX < 0 && rSize.Width > 0)
+                nX = rSize.Width * std::abs(nX) / 100;
             nOffsetX = (*o3tl::doAccess<sal_Int32>(mAny)) * nX * 3.6;
         }
 
@@ -2013,6 +2021,8 @@ void 
DrawingML::WriteXGraphicTile(uno::Reference<beans::XPropertySet> const& rXP
         if (GetProperty(rXPropSet, "FillBitmapPositionOffsetY"))
         {
             sal_Int32 nY = (nSizeY != 0) ? nSizeY : aOriginalSize.Height();
+            if (nY < 0 && rSize.Height > 0)
+                nY = rSize.Height * std::abs(nY) / 100;
             nOffsetY = (*o3tl::doAccess<sal_Int32>(mAny)) * nY * 3.6;
         }
 
@@ -2028,18 +2038,15 @@ void 
DrawingML::WriteXGraphicTile(uno::Reference<beans::XPropertySet> const& rXP
     // 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> xPagePropSet(xDrawPage, 
UNO_QUERY);
-        if (xPagePropSet)
+        if (rSize.Width != 0 && rSize.Height != 0)
+        {
+            nSizeX = rSize.Width / double(aOriginalSize.Width()) * 
std::abs(nSizeX);
+            nSizeY = rSize.Height / double(aOriginalSize.Height()) * 
std::abs(nSizeY);
+        }
+        else
         {
-            double nPageWidth(0.0), nPageHeight(0.0);
-            xPagePropSet->getPropertyValue("Width") >>= nPageWidth;
-            xPagePropSet->getPropertyValue("Height") >>= nPageHeight;
-            nSizeX = nPageWidth / aOriginalSize.Width() * std::abs(nSizeX);
-            nSizeY = nPageHeight / aOriginalSize.Height() * std::abs(nSizeY);
+            nSizeX = std::abs(nSizeX);
+            nSizeY = std::abs(nSizeY);
         }
     }
 
@@ -5145,7 +5152,7 @@ sax_fastparser::FSHelperPtr DrawingML::CreateOutputStream 
(
     return p;
 }
 
-void DrawingML::WriteFill( const Reference< XPropertySet >& xPropSet )
+void DrawingML::WriteFill(const Reference<XPropertySet>& xPropSet, const 
awt::Size& rSize)
 {
     if ( !GetProperty( xPropSet, "FillStyle" ) )
         return;
@@ -5197,7 +5204,7 @@ void DrawingML::WriteFill( const Reference< XPropertySet 
>& xPropSet )
         WriteGradientFill( xPropSet );
         break;
     case FillStyle_BITMAP :
-        WriteBlipFill( xPropSet, "FillBitmap" );
+        WriteBlipFill( xPropSet, "FillBitmap", rSize );
         break;
     case FillStyle_HATCH :
         WritePattFill( xPropSet );
diff --git a/oox/source/export/shapes.cxx b/oox/source/export/shapes.cxx
index 801d4ad9e318..2bf1fe11a6e9 100644
--- a/oox/source/export/shapes.cxx
+++ b/oox/source/export/shapes.cxx
@@ -441,7 +441,7 @@ ShapeExport& ShapeExport::WritePolyPolygonShape( const 
Reference< XShape >& xSha
     Reference< XPropertySet > xProps( xShape, UNO_QUERY );
     if( xProps.is() ) {
         if( bClosed )
-            WriteFill( xProps );
+            WriteFill(xProps, aSize);
         WriteOutline( xProps );
     }
 
@@ -1111,7 +1111,7 @@ ShapeExport& ShapeExport::WriteCustomShape( const 
Reference< XShape >& xShape )
     }
     if( rXPropSet.is() )
     {
-        WriteFill( rXPropSet );
+        WriteFill(rXPropSet, xShape->getSize());
         WriteOutline( rXPropSet );
         WriteShapeEffects( rXPropSet );
 
@@ -2482,7 +2482,7 @@ ShapeExport& ShapeExport::WriteTextShape( const 
Reference< XShape >& xShape )
     uno::Reference<beans::XPropertySet> xPropertySet(xShape, UNO_QUERY);
     if (!IsFontworkShape(xShapeProps)) // Fontwork needs fill and outline in 
run properties instead.
     {
-        WriteBlipOrNormalFill(xPropertySet, "Graphic");
+        WriteBlipOrNormalFill(xPropertySet, "Graphic", xShape->getSize());
         WriteOutline(xPropertySet);
         WriteShapeEffects(xPropertySet);
     }
diff --git a/sd/qa/unit/data/odp/tdf153107.odp 
b/sd/qa/unit/data/odp/tdf153107.odp
new file mode 100644
index 000000000000..c77b65d87fa1
Binary files /dev/null and b/sd/qa/unit/data/odp/tdf153107.odp differ
diff --git a/sd/qa/unit/export-tests-ooxml2.cxx 
b/sd/qa/unit/export-tests-ooxml2.cxx
index be53aebac37d..a777de2b385c 100644
--- a/sd/qa/unit/export-tests-ooxml2.cxx
+++ b/sd/qa/unit/export-tests-ooxml2.cxx
@@ -77,6 +77,7 @@ public:
     }
 
     void testRepeatBitmapMode();
+    void testTdf153107();
     void testTdf142291();
     void testTdf151492();
     void testTdf149697();
@@ -149,6 +150,7 @@ public:
     CPPUNIT_TEST_SUITE(SdOOXMLExportTest2);
 
     CPPUNIT_TEST(testRepeatBitmapMode);
+    CPPUNIT_TEST(testTdf153107);
     CPPUNIT_TEST(testTdf142291);
     CPPUNIT_TEST(testTdf151492);
     CPPUNIT_TEST(testTdf149697);
@@ -247,6 +249,64 @@ void SdOOXMLExportTest2::testRepeatBitmapMode()
     assertXPath(pXmlDocContent2, 
"/p:sld/p:cSld/p:bg/p:bgPr/a:blipFill/a:tile", "algn", "ctr");
 }
 
+void SdOOXMLExportTest2::testTdf153107()
+{
+    createSdImpressDoc("odp/tdf153107.odp");
+    save("Impress Office Open XML");
+
+    // placeholder
+    xmlDocUniquePtr pXmlDocContent1 = parseExport("ppt/slides/slide1.xml");
+    assertXPath(pXmlDocContent1, 
"/p:sld/p:cSld/p:spTree/p:sp[1]/p:spPr/a:blipFill/a:tile", "tx",
+                "1879200");
+    assertXPath(pXmlDocContent1, 
"/p:sld/p:cSld/p:spTree/p:sp[1]/p:spPr/a:blipFill/a:tile", "ty",
+                "83628");
+    assertXPath(pXmlDocContent1, 
"/p:sld/p:cSld/p:spTree/p:sp[1]/p:spPr/a:blipFill/a:tile", "sx",
+                "264773");
+    assertXPath(pXmlDocContent1, 
"/p:sld/p:cSld/p:spTree/p:sp[1]/p:spPr/a:blipFill/a:tile", "sy",
+                "91428");
+    assertXPath(pXmlDocContent1, 
"/p:sld/p:cSld/p:spTree/p:sp[1]/p:spPr/a:blipFill/a:tile", "algn",
+                "ctr");
+
+    // custom shape
+    xmlDocUniquePtr pXmlDocContent2 = parseExport("ppt/slides/slide1.xml");
+    assertXPath(pXmlDocContent2, 
"/p:sld/p:cSld/p:spTree/p:sp[2]/p:spPr/a:blipFill/a:tile", "tx",
+                "198000");
+    assertXPath(pXmlDocContent2, 
"/p:sld/p:cSld/p:spTree/p:sp[2]/p:spPr/a:blipFill/a:tile", "ty",
+                "324000");
+    assertXPath(pXmlDocContent2, 
"/p:sld/p:cSld/p:spTree/p:sp[2]/p:spPr/a:blipFill/a:tile", "sx",
+                "69743");
+    assertXPath(pXmlDocContent2, 
"/p:sld/p:cSld/p:spTree/p:sp[2]/p:spPr/a:blipFill/a:tile", "sy",
+                "78709");
+    assertXPath(pXmlDocContent2, 
"/p:sld/p:cSld/p:spTree/p:sp[2]/p:spPr/a:blipFill/a:tile", "algn",
+                "tl");
+
+    // polygon
+    xmlDocUniquePtr pXmlDocContent3 = parseExport("ppt/slides/slide1.xml");
+    assertXPath(pXmlDocContent3, 
"/p:sld/p:cSld/p:spTree/p:sp[3]/p:spPr/a:blipFill/a:tile", "tx",
+                "2073600");
+    assertXPath(pXmlDocContent3, 
"/p:sld/p:cSld/p:spTree/p:sp[3]/p:spPr/a:blipFill/a:tile", "ty",
+                "221760");
+    assertXPath(pXmlDocContent3, 
"/p:sld/p:cSld/p:spTree/p:sp[3]/p:spPr/a:blipFill/a:tile", "sx",
+                "182602");
+    assertXPath(pXmlDocContent3, 
"/p:sld/p:cSld/p:spTree/p:sp[3]/p:spPr/a:blipFill/a:tile", "sy",
+                "86580");
+    assertXPath(pXmlDocContent3, 
"/p:sld/p:cSld/p:spTree/p:sp[3]/p:spPr/a:blipFill/a:tile", "algn",
+                "ctr");
+
+    // textbox
+    xmlDocUniquePtr pXmlDocContent4 = parseExport("ppt/slides/slide1.xml");
+    assertXPath(pXmlDocContent4, 
"/p:sld/p:cSld/p:spTree/p:sp[4]/p:spPr/a:blipFill/a:tile", "tx",
+                "662400");
+    assertXPath(pXmlDocContent4, 
"/p:sld/p:cSld/p:spTree/p:sp[4]/p:spPr/a:blipFill/a:tile", "ty",
+                "760320");
+    assertXPath(pXmlDocContent4, 
"/p:sld/p:cSld/p:spTree/p:sp[4]/p:spPr/a:blipFill/a:tile", "sx",
+                "202891");
+    assertXPath(pXmlDocContent4, 
"/p:sld/p:cSld/p:spTree/p:sp[4]/p:spPr/a:blipFill/a:tile", "sy",
+                "129870");
+    assertXPath(pXmlDocContent4, 
"/p:sld/p:cSld/p:spTree/p:sp[4]/p:spPr/a:blipFill/a:tile", "algn",
+                "tl");
+}
+
 void SdOOXMLExportTest2::testTdf142291()
 {
     createSdImpressDoc("pptx/tdt142291.pptx");
diff --git a/sd/source/filter/eppt/pptx-epptooxml.cxx 
b/sd/source/filter/eppt/pptx-epptooxml.cxx
index f56a04c04750..00340c03cbd8 100644
--- a/sd/source/filter/eppt/pptx-epptooxml.cxx
+++ b/sd/source/filter/eppt/pptx-epptooxml.cxx
@@ -604,7 +604,7 @@ void PowerPointExport::ImplWriteBackground(const 
FSHelperPtr& pFS, const Referen
 
     PowerPointShapeExport aDML(pFS, &maShapeMap, this);
     aDML.SetBackgroundDark(mbIsBackgroundDark);
-    aDML.WriteFill(rXPropSet);
+    aDML.WriteFill(rXPropSet, maPageSize);
 
     pFS->endElementNS(XML_p, XML_bgPr);
     pFS->endElementNS(XML_p, XML_bg);
@@ -1771,7 +1771,7 @@ ShapeExport& 
PowerPointShapeExport::WritePlaceholderShape(const Reference< XShap
     {
         WriteBlipFill(xProps, "Graphic");
         // Do not forget to export the visible properties.
-        WriteFill( xProps );
+        WriteFill( xProps, xShape->getSize());
         WriteOutline( xProps );
         WriteShapeEffects( xProps );
 

Reply via email to