summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Luth <justin.luth@collabora.com>2024-02-03 10:08:56 -0500
committerMiklos Vajna <vmiklos@collabora.com>2024-02-20 16:54:57 +0100
commitc14574e7ad2d3ec2ada40808be3332fac71e9767 (patch)
tree2ece091ae92f54604e671c1f7cfb7db153177ffb
parent178d8a38e133aebd4cff1af2d2c49aec60468c92 (diff)
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 <vmiklos@collabora.com>
-rw-r--r--oox/source/vml/vmlshapecontext.cxx1
-rw-r--r--sw/qa/extras/ooxmlexport/data/fill.docx (renamed from sw/qa/core/data/ooxml/pass/fill.docx)bin12619 -> 12619 bytes
-rw-r--r--sw/qa/extras/ooxmlexport/data/tdf126533_noPageBitmap.docxbin0 -> 63691 bytes
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport21.cxx21
-rw-r--r--writerfilter/source/dmapper/DomainMapper.cxx58
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.hxx1
-rw-r--r--writerfilter/source/dmapper/PropertyMap.cxx33
-rw-r--r--writerfilter/source/ooxml/model.xml3
8 files changed, 115 insertions, 2 deletions
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
index b9a4501b2854..b9a4501b2854 100644
--- a/sw/qa/core/data/ooxml/pass/fill.docx
+++ b/sw/qa/extras/ooxmlexport/data/fill.docx
Binary files differ
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
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/tdf126533_noPageBitmap.docx
Binary files 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"/>