oox/source/vml/vmlshapecontext.cxx                        |    1 
 sw/qa/extras/ooxmlexport/data/tdf126533_noPageBitmap.docx |binary
 sw/qa/extras/ooxmlexport/ooxmlexport21.cxx                |   21 +++++
 writerfilter/source/dmapper/DomainMapper.cxx              |   58 ++++++++++++++
 writerfilter/source/dmapper/DomainMapper_Impl.hxx         |    1 
 writerfilter/source/dmapper/PropertyMap.cxx               |   33 +++++++
 writerfilter/source/ooxml/model.xml                       |    3 
 7 files changed, 115 insertions(+), 2 deletions(-)

New commits:
commit c14574e7ad2d3ec2ada40808be3332fac71e9767
Author:     Justin Luth <justin.l...@collabora.com>
AuthorDate: Sat Feb 3 10:08:56 2024 -0500
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Tue Feb 20 16:54:57 2024 +0100

    tdf#126533 docx import: page background vml fill
    
    This patch imports bitmaps/tiled textures (primarily),
    but also somewhat for gradients
    (because of a gradient2 -> gradient mismatch somewhere)
    and somewhat for patterns
    (because patterns are not well imported in general).
    
    Note that the imported fill likely will NOT match MSO,
    because their background CHANGES BASED ON THE ZOOM LEVEL.
    For example, my primary testing file (A6 landscape)
    has a logo which is only 25% visible in Word 2003 at 100%,
    but shows 90% of the logo at 200%, and many tiles of logos
    when exported as PDF.
    The same is true for gradients etc.
    
    Changing background on zoom is an absolutely bizarre implementation,
    and naturally LO could only accidentally look identical
    (and should never try to do so).
    
    make CppunitTest_sw_ooxmlexport21 \
        CPPUNIT_TEST_NAME=testTdf126533_noPageBitmap
    
    make CppunitTest_sw_ooxmlexport21 \
        CPPUNIT_TEST_NAME=testTdf126533_pageGradient
    
    This is slightly ugly, but I don't know how to make a COPY
    of the XPropertySet UNO junk. All I have is references,
    and dispose deletes everything, even the references.
    
    I took some inspiration from RTF
    which just disposes the shape after grabbing the background color.
    
    Thus, just change the page style known to exist and be used,
    and then simply remove the fill if it isn't needed in the end.
    Any new page styles can just copy the default page style fill.
    
    Change-Id: Id3ea002c685642ff4c289982d0108247a6e9bb8d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162958
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/oox/source/vml/vmlshapecontext.cxx 
b/oox/source/vml/vmlshapecontext.cxx
index e3242368a334..20ce2fa37434 100644
--- a/oox/source/vml/vmlshapecontext.cxx
+++ b/oox/source/vml/vmlshapecontext.cxx
@@ -251,6 +251,7 @@ ContextHandlerRef ShapeContextBase::createShapeContext( 
ContextHandler2Helper co
                 return new ShapeContext( rParent, rShapes.createShape< 
BezierShape >(), rAttribs );
             else
                 return new ShapeContext( rParent, rShapes.createShape< 
ComplexShape >(), rAttribs );
+        case VML_TOKEN(background):
         case VML_TOKEN( rect ):
             return new RectangleShapeContext( rParent, rAttribs, 
rShapes.createShape< RectangleShape >() );
         case VML_TOKEN( roundrect ):
diff --git a/sw/qa/core/data/ooxml/pass/fill.docx 
b/sw/qa/extras/ooxmlexport/data/fill.docx
similarity index 100%
rename from sw/qa/core/data/ooxml/pass/fill.docx
rename to sw/qa/extras/ooxmlexport/data/fill.docx
diff --git a/sw/qa/extras/ooxmlexport/data/tdf126533_noPageBitmap.docx 
b/sw/qa/extras/ooxmlexport/data/tdf126533_noPageBitmap.docx
new file mode 100644
index 000000000000..87dfff296be5
Binary files /dev/null and 
b/sw/qa/extras/ooxmlexport/data/tdf126533_noPageBitmap.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx
index f1d4a5e7121a..e455467a74ef 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx
@@ -11,6 +11,7 @@
 
 #include <com/sun/star/awt/FontSlant.hpp>
 #include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
 #include <com/sun/star/text/XDocumentIndex.hpp>
 #include <com/sun/star/text/XTextTable.hpp>
 #include <com/sun/star/style/LineSpacing.hpp>
@@ -366,6 +367,26 @@ CPPUNIT_TEST_FIXTURE(Test, testPersonalMetaData)
     assertXPath(pCoreDoc, "/cp:coreProperties/cp:revision"_ostr, 0);
 }
 
+DECLARE_OOXMLEXPORT_TEST(testTdf126533_noPageBitmap, 
"tdf126533_noPageBitmap.docx")
+{
+    // given a document with a v:background bitmap, but no w:background 
fillcolor
+    uno::Reference<beans::XPropertySet> 
xPageStyle(getStyles("PageStyles")->getByName("Standard"),
+                                                   uno::UNO_QUERY);
+    // the image (or any fill for that matter) should be ignored.
+    CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_NONE,
+                         getProperty<drawing::FillStyle>(xPageStyle, 
"FillStyle"));
+}
+
+CPPUNIT_TEST_FIXTURE(Test, testTdf126533_pageGradient)
+{
+    // given a document with a gradient page background
+    loadFromFile(u"fill.docx");
+    uno::Reference<beans::XPropertySet> 
xPageStyle(getStyles("PageStyles")->getByName("Standard"),
+                                                   uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_GRADIENT,
+                         getProperty<drawing::FillStyle>(xPageStyle, 
"FillStyle"));
+}
+
 } // end of anonymous namespace
 CPPUNIT_PLUGIN_IMPLEMENT();
 
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx 
b/writerfilter/source/dmapper/DomainMapper.cxx
index 946befddd2f9..f3e15a69afaf 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -32,6 +32,8 @@
 #include <ooxml/resourceids.hxx>
 #include <oox/token/tokens.hxx>
 #include <oox/drawingml/drawingmltypes.hxx>
+
+#include <com/sun/star/awt/Gradient2.hpp>
 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
 #include <com/sun/star/document/XOOXMLDocumentPropertiesImporter.hpp>
 #include <com/sun/star/drawing/FillStyle.hpp>
@@ -1474,7 +1476,63 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const 
PropertyMapPtr& rContext )
     switch (rSprm.getId())
     {
     case NS_ooxml::LN_background_background:
+    {
+        // if a VML background has been defined, it was imported into a shape 
to hold the properties
+        uno::Reference<drawing::XShape> xFill(m_pImpl->PopPendingShape());
+        if (xFill.is())
+        {
+            assert(!m_pImpl->GetTopContext());
+            assert(m_pImpl->GetIsFirstParagraphInShape());
+            assert(mbWasShapeInPara);
+            assert(m_pImpl->GetIsFirstParagraphInSection());
+            assert(m_pImpl->IsOutsideAParagraph());
+            if (m_pImpl->GetSettingsTable()->GetDisplayBackgroundShape())
+            {
+                // apply the XATTR_FILL attributes to the default page style
+                const uno::Reference<beans::XPropertySet> 
xFillPropertySet(xFill, uno::UNO_QUERY);
+                const uno::Reference<beans::XPropertySetInfo> xFillInfo
+                    = xFillPropertySet->getPropertySetInfo();
+                uno::Reference<beans::XPropertySet> xPS(
+                    m_pImpl->GetPageStyles()->getByName("Standard"), 
uno::UNO_QUERY_THROW);
+                for (const beans::Property& rProp : 
xPS->getPropertySetInfo()->getProperties())
+                {
+                    if (rProp.Name == "FillComplexColor" || rProp.Name == 
"FillGradientName"
+                        || rProp.Name == "FillGradientStepCount"
+                        || rProp.Name == "FillTransparenceGradientName"
+                        || rProp.Name == "FillBitmapURL" || rProp.Name == 
"FillColor2")
+                    {
+                        // silence exceptions for unsupported stuff when 
appling to page style
+                        continue;
+                    }
+                    if (!rProp.Name.startsWith("Fill"))
+                        continue;
+
+                    if (!xFillInfo->hasPropertyByName(rProp.Name))
+                        continue;
+
+                    try
+                    {
+                        const uno::Any aFillValue = 
xFillPropertySet->getPropertyValue(rProp.Name);
+                        xPS->setPropertyValue(rProp.Name, aFillValue);
+                    }
+                    catch (uno::Exception&)
+                    {
+                        DBG_UNHANDLED_EXCEPTION("writerfilter", "Exception 
setting page background fill");
+                    }
+                }
+
+                m_pImpl->m_bCopyStandardPageStyleFill = true;
+            }
+
+            // The background was unhelpfully imported into the text body: 
remove it
+            uno::Reference<lang::XComponent> xComponent(xFill, 
uno::UNO_QUERY_THROW);
+            xComponent->dispose();
+
+            m_pImpl->SetIsFirstParagraphInShape(false);
+            mbWasShapeInPara = false;
+        }
         return;
+    }
     default:
         break;
     }
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index bd6358a6a7e1..9d1a3aaa3b75 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -1149,6 +1149,7 @@ public:
 
     /// Document background color, applied to every page style.
     std::optional<sal_Int32> m_oBackgroundColor;
+    bool m_bCopyStandardPageStyleFill = false;
 
     /// If the current section has a footnote separator.
     bool m_bHasFtnSep;
diff --git a/writerfilter/source/dmapper/PropertyMap.cxx 
b/writerfilter/source/dmapper/PropertyMap.cxx
index 96bec18a14fa..79ee185ad17d 100644
--- a/writerfilter/source/dmapper/PropertyMap.cxx
+++ b/writerfilter/source/dmapper/PropertyMap.cxx
@@ -39,6 +39,7 @@
 #include <com/sun/star/container/XEnumeration.hpp>
 #include <com/sun/star/container/XEnumerationAccess.hpp>
 #include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
 #include <com/sun/star/style/BreakType.hpp>
 #include <com/sun/star/style/PageStyleLayout.hpp>
 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
@@ -1137,7 +1138,37 @@ void 
SectionPropertyMap::HandleMarginsHeaderFooter(DomainMapper_Impl& rDM_Impl)
     Insert( PROP_RIGHT_MARGIN, uno::Any( m_nRightMargin ) );
     Insert(PROP_GUTTER_MARGIN, uno::Any(m_nGutterMargin));
 
-    if ( rDM_Impl.m_oBackgroundColor )
+    // w:background is applied to every page in the document
+    if (!rDM_Impl.m_oBackgroundColor.has_value() && !rDM_Impl.IsRTFImport())
+    {
+        // DOCX has an interesting quirk, where if the fallback background 
color is not defined,
+        // then the fill is not applied either.
+
+        // Disable the imported fill from the default style
+        if (rDM_Impl.m_bCopyStandardPageStyleFill && m_sPageStyleName == 
"Standard")
+        {
+            rDM_Impl.m_bCopyStandardPageStyleFill = false;
+            m_aPageStyle->setPropertyValue("FillStyle", 
uno::Any(drawing::FillStyle_NONE));
+        }
+    }
+    else if (rDM_Impl.m_bCopyStandardPageStyleFill) // complex fill: 
graphics/gradients/patterns
+    {
+        uno::Reference<beans::XPropertySet> xDefaultPageStyle(
+                    rDM_Impl.GetPageStyles()->getByName("Standard"), 
uno::UNO_QUERY_THROW);
+        for (const beans::Property& rProp : 
m_aPageStyle->getPropertySetInfo()->getProperties())
+        {
+            try
+            {
+                const uno::Any aFillValue = 
xDefaultPageStyle->getPropertyValue(rProp.Name);
+                m_aPageStyle->setPropertyValue(rProp.Name, aFillValue);
+            }
+            catch (uno::Exception&)
+            {
+                DBG_UNHANDLED_EXCEPTION("writerfilter", "Exception setting 
page background fill");
+            }
+        }
+    }
+    else if (rDM_Impl.m_oBackgroundColor) // simple, solid color
         Insert( PROP_BACK_COLOR, uno::Any( *rDM_Impl.m_oBackgroundColor ) );
 
     // Check for missing footnote separator only in case there is at least
diff --git a/writerfilter/source/ooxml/model.xml 
b/writerfilter/source/ooxml/model.xml
index 2c174743f990..2f84e72c0615 100644
--- a/writerfilter/source/ooxml/model.xml
+++ b/writerfilter/source/ooxml/model.xml
@@ -17744,12 +17744,13 @@
       <element name="sectPr" tokenid="ooxml:CT_PPr_sectPr"/>
       <element name="pPrChange" tokenid="ooxml:CT_PPr_pPrChange"/>
     </resource>
-    <resource name="CT_Background" resource="Properties">
+    <resource name="CT_Background" resource="Shape">
       <attribute name="color" tokenid="ooxml:CT_Background_color"/>
       <attribute name="themeColor" tokenid="ooxml:CT_Background_themeColor"/>
       <attribute name="themeTint" tokenid="ooxml:CT_Background_themeTint"/>
       <attribute name="themeShade" tokenid="ooxml:CT_Background_themeShade"/>
       <element name="v:background" tokenid="ooxml:CT_Background_v_background"/>
+      <action name="end" action="sendPropertiesWithId" 
sendtokenid="ooxml:background_background"/>
     </resource>
     <resource name="CT_Rel" resource="Properties">
       <attribute name="r:id" tokenid="ooxml:CT_Rel_id"/>

Reply via email to