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"/>