sd/inc/sdpage.hxx                  |    2 
 sd/qa/unit/data/TestImage1.png     |binary
 sd/qa/unit/data/TestImage2.png     |binary
 sd/qa/unit/data/TestImage3.png     |binary
 sd/qa/unit/data/TestImage4.png     |binary
 sd/qa/unit/misc-tests.cxx          |  147 +++++++++++++++++++++++++++++++++++++
 sd/source/ui/inc/DrawViewShell.hxx |    4 -
 svx/source/xoutdev/xattr.cxx       |    4 -
 8 files changed, 152 insertions(+), 5 deletions(-)

New commits:
commit c2cc4c4782107da0c1c32d0645b6b295376a83cb
Author:     Tomaž Vajngerl <[email protected]>
AuthorDate: Fri May 23 12:18:28 2025 +0900
Commit:     Tomaž Vajngerl <[email protected]>
CommitDate: Mon May 26 14:03:33 2025 +0200

    tdf#149207 fix image not getting a unique name
    
    Using "background" as the name, CheckNamedItem doesn't correctly
    determine that another XFillBitmapItem exists with an same
    "background" name already, which is then a problem when exporting
    the document and from all "background" images only one will be
    exported.
    
    regression from
      commit ec7ba61a6164c805f5a71b077715b7e1521a2d62
      Author: Noel Grandin <[email protected]>
      Date:   Wed Apr 17 15:19:25 2019 +0200
      simplify SfxPoolItemArray_Impl (tdf#81765 related)
    
    I am not sure why the above commit caused this problem.
    
    Right now, the reason CheckNamedItem doesn't work is because
    with other subsequent changes to the pool infrastructure, the
    new PoolItem is already in the surrogates/NameOrIndex array
    and so it finds itself when scanning the array.
    
    But back then, the new PoolItem should not have been inserted
    yet.
    
    Any way, fix it by making CheckNamedItem exclude itself when
    scanning the surrogates data.
    
    Added a test for uniqueness of names.
    
    Change-Id: I3c04065a4875a21649ad8141243cc39a8d1a5b3c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185719
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <[email protected]>
    (cherry picked from commit cb5a4314c3561179e556107b81830a9949b20517)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185723
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Noel Grandin <[email protected]>

diff --git a/sd/inc/sdpage.hxx b/sd/inc/sdpage.hxx
index 492db5ea56dc..ace5daa0e478 100644
--- a/sd/inc/sdpage.hxx
+++ b/sd/inc/sdpage.hxx
@@ -343,7 +343,7 @@ public:
 
     /** @return the presentation style with the given helpid from this 
masterpage or this
         slides masterpage */
-    SdStyleSheet* getPresentationStyle( sal_uInt32 nHelpId ) const;
+    SD_DLLPUBLIC SdStyleSheet* getPresentationStyle( sal_uInt32 nHelpId ) 
const;
 
     /** removes all empty presentation objects from this slide */
     void RemoveEmptyPresentationObjects();
diff --git a/sd/qa/unit/data/TestImage1.png b/sd/qa/unit/data/TestImage1.png
new file mode 100644
index 000000000000..e698130c6eb3
Binary files /dev/null and b/sd/qa/unit/data/TestImage1.png differ
diff --git a/sd/qa/unit/data/TestImage2.png b/sd/qa/unit/data/TestImage2.png
new file mode 100644
index 000000000000..c89b2d8cc170
Binary files /dev/null and b/sd/qa/unit/data/TestImage2.png differ
diff --git a/sd/qa/unit/data/TestImage3.png b/sd/qa/unit/data/TestImage3.png
new file mode 100644
index 000000000000..0e26be50ef46
Binary files /dev/null and b/sd/qa/unit/data/TestImage3.png differ
diff --git a/sd/qa/unit/data/TestImage4.png b/sd/qa/unit/data/TestImage4.png
new file mode 100644
index 000000000000..4a22e6ea9366
Binary files /dev/null and b/sd/qa/unit/data/TestImage4.png differ
diff --git a/sd/qa/unit/misc-tests.cxx b/sd/qa/unit/misc-tests.cxx
index dc61d3275ed1..f08c7ab31b92 100644
--- a/sd/qa/unit/misc-tests.cxx
+++ b/sd/qa/unit/misc-tests.cxx
@@ -41,10 +41,13 @@
 #include <editeng/outlobj.hxx>
 #include <editeng/editobj.hxx>
 #include <comphelper/base64.hxx>
+#include <comphelper/propertysequence.hxx>
 #include <docmodel/uno/UnoGradientTools.hxx>
 #include <undo/undomanager.hxx>
 #include <GraphicViewShell.hxx>
 #include <sdpage.hxx>
+#include <app.hrc>
+#include <DrawViewShell.hxx>
 #include <LayerTabBar.hxx>
 #include <vcl/event.hxx>
 #include <vcl/keycodes.hxx>
@@ -53,6 +56,8 @@
 #include <svx/view3d.hxx>
 #include <svx/scene3d.hxx>
 #include <svx/sdmetitm.hxx>
+#include <svx/xfillit0.hxx>
+#include <svx/xbtmpit.hxx>
 #include <unomodel.hxx>
 
 using namespace ::com::sun::star;
@@ -90,6 +95,7 @@ public:
     void testTdf164284();
     void testEncodedTableStyles();
     void testTdf157117();
+    void testPageBackgroundImages();
 
     CPPUNIT_TEST_SUITE(SdMiscTest);
     CPPUNIT_TEST(testTdf99396);
@@ -116,6 +122,7 @@ public:
     CPPUNIT_TEST(testTdf164284);
     CPPUNIT_TEST(testEncodedTableStyles);
     CPPUNIT_TEST(testTdf157117);
+    CPPUNIT_TEST(testPageBackgroundImages);
     CPPUNIT_TEST_SUITE_END();
 };
 
@@ -1092,6 +1099,146 @@ void SdMiscTest::testTdf157117()
     CPPUNIT_ASSERT_EQUAL(1, (nPageNum - 1) / 2);
 }
 
+void SdMiscTest::testPageBackgroundImages()
+{
+    // Create empty document
+    createSdDrawDoc();
+
+    auto pXImpressDocument = 
dynamic_cast<SdXImpressDocument*>(mxComponent.get());
+    sd::ViewShell* pViewShell = 
pXImpressDocument->GetDocShell()->GetViewShell();
+    CPPUNIT_ASSERT(pViewShell);
+
+    auto* pDrawViewShell = dynamic_cast<sd::DrawViewShell*>(pViewShell);
+    CPPUNIT_ASSERT(pDrawViewShell);
+
+    SdDrawDocument* pDocument = pXImpressDocument->GetDocShell()->GetDoc();
+    CPPUNIT_ASSERT(pDocument);
+
+    // Check we have 1 Page
+    CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), 
pDocument->GetSdPageCount(PageKind::Standard));
+
+    // Add 3 pages
+    dispatchCommand(mxComponent, u".uno:InsertPage"_ustr, {});
+    dispatchCommand(mxComponent, u".uno:InsertPage"_ustr, {});
+    dispatchCommand(mxComponent, u".uno:InsertPage"_ustr, {});
+
+    // Check we have 4 Pages now
+    CPPUNIT_ASSERT_EQUAL(sal_uInt16(4), 
pDocument->GetSdPageCount(PageKind::Standard));
+
+    // Add a background graphic to page 1
+    {
+        CPPUNIT_ASSERT_EQUAL(true, pDrawViewShell->SwitchPage(0));
+        uno::Sequence<beans::PropertyValue> 
aArgs(comphelper::InitPropertySequence({
+            { "FileName", uno::Any(createFileURL(u"TestImage1.png")) },
+        }));
+
+        dispatchCommand(mxComponent, u".uno:SelectBackground"_ustr, aArgs);
+    }
+
+    // Add a background graphic to page 2
+    {
+        CPPUNIT_ASSERT_EQUAL(true, pDrawViewShell->SwitchPage(1));
+        uno::Sequence<beans::PropertyValue> 
aArgs(comphelper::InitPropertySequence({
+            { "FileName", uno::Any(createFileURL(u"TestImage2.png")) },
+        }));
+
+        dispatchCommand(mxComponent, u".uno:SelectBackground"_ustr, aArgs);
+    }
+
+    // Add a background graphic to page 3
+    {
+        CPPUNIT_ASSERT_EQUAL(true, pDrawViewShell->SwitchPage(2));
+        uno::Sequence<beans::PropertyValue> 
aArgs(comphelper::InitPropertySequence({
+            { "FileName", uno::Any(createFileURL(u"TestImage3.png")) },
+        }));
+
+        dispatchCommand(mxComponent, u".uno:SelectBackground"_ustr, aArgs);
+    }
+
+    // Add a background graphic to page 4
+    {
+        CPPUNIT_ASSERT_EQUAL(true, pDrawViewShell->SwitchPage(3));
+        uno::Sequence<beans::PropertyValue> 
aArgs(comphelper::InitPropertySequence({
+            { "FileName", uno::Any(createFileURL(u"TestImage4.png")) },
+        }));
+
+        dispatchCommand(mxComponent, u".uno:SelectBackground"_ustr, aArgs);
+    }
+
+    // Store graphic names
+    std::unordered_set<OUString> aGraphicNames;
+
+    // Check page 1
+    {
+        CPPUNIT_ASSERT_EQUAL(true, pDrawViewShell->SwitchPage(0));
+        SdPage* pPage = pViewShell->GetActualPage();
+
+        SfxItemSetFixed<XATTR_FILL_FIRST, XATTR_FILL_LAST> 
aMergedAttr(pDocument->GetPool());
+        SdStyleSheet* pStyleSheet = 
pPage->getPresentationStyle(HID_PSEUDOSHEET_BACKGROUND);
+        sd::MergePageBackgroundFilling(pPage, pStyleSheet, false, aMergedAttr);
+
+        // Style should be "BITMAP"
+        CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_BITMAP,
+                             aMergedAttr.Get(XATTR_FILLSTYLE).GetValue());
+        auto aItem = aMergedAttr.Get<XFillBitmapItem>(XATTR_FILLBITMAP);
+        aGraphicNames.insert(aItem.GetName());
+    }
+
+    // Check page 2
+    {
+        CPPUNIT_ASSERT_EQUAL(true, pDrawViewShell->SwitchPage(1));
+        SdPage* pPage = pViewShell->GetActualPage();
+
+        // Style should be "BITMAP"
+        SfxItemSetFixed<XATTR_FILL_FIRST, XATTR_FILL_LAST> 
aMergedAttr(pDocument->GetPool());
+        SdStyleSheet* pStyleSheet = 
pPage->getPresentationStyle(HID_PSEUDOSHEET_BACKGROUND);
+        sd::MergePageBackgroundFilling(pPage, pStyleSheet, false, aMergedAttr);
+
+        CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_BITMAP,
+                             aMergedAttr.Get(XATTR_FILLSTYLE).GetValue());
+        auto aItem = aMergedAttr.Get<XFillBitmapItem>(XATTR_FILLBITMAP);
+        aGraphicNames.insert(aItem.GetName());
+    }
+
+    // Check page 3
+    {
+        CPPUNIT_ASSERT_EQUAL(true, pDrawViewShell->SwitchPage(2));
+        SdPage* pPage = pViewShell->GetActualPage();
+
+        // Style should be "BITMAP"
+        SfxItemSetFixed<XATTR_FILL_FIRST, XATTR_FILL_LAST> 
aMergedAttr(pDocument->GetPool());
+        SdStyleSheet* pStyleSheet = 
pPage->getPresentationStyle(HID_PSEUDOSHEET_BACKGROUND);
+        sd::MergePageBackgroundFilling(pPage, pStyleSheet, false, aMergedAttr);
+
+        CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_BITMAP,
+                             aMergedAttr.Get(XATTR_FILLSTYLE).GetValue());
+        auto aItem = aMergedAttr.Get<XFillBitmapItem>(XATTR_FILLBITMAP);
+        aGraphicNames.insert(aItem.GetName());
+    }
+
+    // Check page 4
+    {
+        CPPUNIT_ASSERT_EQUAL(true, pDrawViewShell->SwitchPage(3));
+        SdPage* pPage = pViewShell->GetActualPage();
+
+        SfxItemSetFixed<XATTR_FILL_FIRST, XATTR_FILL_LAST> 
aMergedAttr(pDocument->GetPool());
+        SdStyleSheet* pStyleSheet = 
pPage->getPresentationStyle(HID_PSEUDOSHEET_BACKGROUND);
+        sd::MergePageBackgroundFilling(pPage, pStyleSheet, false, aMergedAttr);
+
+        // Style should be "BITMAP"
+        CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_BITMAP,
+                             aMergedAttr.Get(XATTR_FILLSTYLE).GetValue());
+        auto aItem = aMergedAttr.Get<XFillBitmapItem>(XATTR_FILLBITMAP);
+        aGraphicNames.insert(aItem.GetName());
+    }
+
+    // Size of graphic names should be 4 - this means each page has a unique 
name
+    CPPUNIT_ASSERT_EQUAL(size_t(4), aGraphicNames.size());
+    // Check none of the graphic names is empty
+    for (OUString const& rName : aGraphicNames)
+        CPPUNIT_ASSERT(!rName.isEmpty());
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SdMiscTest);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sd/source/ui/inc/DrawViewShell.hxx 
b/sd/source/ui/inc/DrawViewShell.hxx
index e2f9296c1ce7..e7022a61ca42 100644
--- a/sd/source/ui/inc/DrawViewShell.hxx
+++ b/sd/source/ui/inc/DrawViewShell.hxx
@@ -513,8 +513,8 @@ private:
     css::uno::Reference<css::presentation::XSlideShow> mxSlideShow;
 };
 
-    /// Merge the background properties together and deposit the result in 
rMergeAttr
-    void MergePageBackgroundFilling(SdPage *pPage, SdStyleSheet *pStyleSheet, 
bool bMasterPage, SfxItemSet& rMergedAttr);
+/// Merge the background properties together and deposit the result in 
rMergeAttr
+SD_DLLPUBLIC void MergePageBackgroundFilling(SdPage *pPage, SdStyleSheet 
*pStyleSheet, bool bMasterPage, SfxItemSet& rMergedAttr);
 
 } // end of namespace sd
 
diff --git a/svx/source/xoutdev/xattr.cxx b/svx/source/xoutdev/xattr.cxx
index b0fbc7bf7043..54d0c1464e0a 100644
--- a/svx/source/xoutdev/xattr.cxx
+++ b/svx/source/xoutdev/xattr.cxx
@@ -153,7 +153,7 @@ OUString NameOrIndex::CheckNamedItem(const sal_uInt16 
nWhich, const SfxItemPool*
             const NameOrIndex *pNameOrIndex = static_cast<const 
NameOrIndex*>(pItem);
 
             // need to check for WhichID, GetItemSurrogatesForItem does buffer 
on type only
-            if( pNameOrIndex->Which() == nWhich && pNameOrIndex->GetName() == 
GetName() )
+            if( pNameOrIndex != this && pNameOrIndex->Which() == nWhich && 
pNameOrIndex->GetName() == GetName() )
             {
                 // if there is already an item with the same name and the same
                 // value it's ok to set it
@@ -242,7 +242,7 @@ OUString NameOrIndex::CheckNamedItem(const sal_uInt16 
nWhich, const SfxItemPool*
                 const NameOrIndex *pNameOrIndex = static_cast<const 
NameOrIndex*>(pItem);
 
                 // need to check for WhichID, GetItemSurrogatesForItem does 
buffer on type only
-                if( pNameOrIndex->Which() == nWhich && 
!pNameOrIndex->GetName().isEmpty() )
+                if( pNameOrIndex != this && pNameOrIndex->Which() == nWhich && 
!pNameOrIndex->GetName().isEmpty() )
                 {
                     if( !bForceNew && pCompareValueFunc( pNameOrIndex, this ) )
                         return pNameOrIndex->GetName();

Reply via email to