This is an automated email from the ASF dual-hosted git repository. jimjag pushed a commit to branch AOO50X in repository https://gitbox.apache.org/repos/asf/openoffice.git
commit 454dc927f66efcf476e75e71b2be6c1d696f6e39 Author: Jim Jagielski <[email protected]> AuthorDate: Wed Nov 4 05:13:39 2026 -0500 xmloff: write Impress table cell fills as style:background-fill in ODF 1.4 --- main/xmloff/source/style/prstylei.cxx | 27 +++++++++++- main/xmloff/source/style/xmlexppr.cxx | 66 ++++++++++++++++++++++++++--- main/xmloff/source/table/XMLTableExport.cxx | 5 ++- 3 files changed, 91 insertions(+), 7 deletions(-) diff --git a/main/xmloff/source/style/prstylei.cxx b/main/xmloff/source/style/prstylei.cxx index 945fa8d001..8d6aede563 100644 --- a/main/xmloff/source/style/prstylei.cxx +++ b/main/xmloff/source/style/prstylei.cxx @@ -174,6 +174,28 @@ namespace { const sal_Char s_aExtGraphicNamespace[] = "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"; +// ODF 1.4: the fill of a table cell style is in a style:background-fill child of its style:table-cell-properties +class XMLTableCellPropsContext : public SvXMLPropertySetContext +{ +public: + XMLTableCellPropsContext( SvXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName, + const Reference< XAttributeList >& xAttrList, std::vector< XMLPropertyState >& rProps, + const UniReference< SvXMLImportPropertyMapper >& rMap ) + : SvXMLPropertySetContext( rImport, nPrfx, rLName, xAttrList, XML_TYPE_PROP_TABLE_CELL, rProps, rMap ) + { + } + + using SvXMLPropertySetContext::CreateChildContext; + virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, + const Reference< XAttributeList >& xAttrList ) + { + if( XML_NAMESPACE_STYLE == nPrefix && IsXMLToken( rLocalName, XML_BACKGROUND_FILL ) ) + return new SvXMLPropertySetContext( GetImport(), nPrefix, rLocalName, xAttrList, + XML_TYPE_PROP_GRAPHIC, mrProperties, mxMapper ); + return SvXMLPropertySetContext::CreateChildContext( nPrefix, rLocalName, xAttrList ); + } +}; + // Keeps the fill only if it is usable and no earlier fill exists; otherwise the fallback attributes apply. class XMLExtParaFillContext : public SvXMLPropertySetContext { @@ -314,7 +336,10 @@ SvXMLImportContext *XMLPropStyleContext::CreateChildContext( UniReference < SvXMLImportPropertyMapper > xImpPrMap = ((SvXMLStylesContext *)&mxStyles)->GetImportPropertyMapper( GetFamily() ); - if( xImpPrMap.is() ) + if( xImpPrMap.is() && nFamily == XML_TYPE_PROP_TABLE_CELL ) + pContext = new XMLTableCellPropsContext( GetImport(), nPrefix, rLocalName, xAttrList, + maProperties, xImpPrMap ); + else if( xImpPrMap.is() ) pContext = new SvXMLPropertySetContext( GetImport(), nPrefix, rLocalName, xAttrList, nFamily, diff --git a/main/xmloff/source/style/xmlexppr.cxx b/main/xmloff/source/style/xmlexppr.cxx index 3a7c76dd29..45e9bd61ca 100644 --- a/main/xmloff/source/style/xmlexppr.cxx +++ b/main/xmloff/source/style/xmlexppr.cxx @@ -104,6 +104,25 @@ static sal_Bool lcl_IsHeaderFooterFill( const UniReference< XMLPropertySetMapper IsXMLToken( rMapper->GetEntryXMLName( nIdx ), XML_REPEAT ) ) ); } +// The shape fill entries of an Impress table cell style; ODF 1.4 writes them in a style:background-fill child +// of style:table-cell-properties. +static sal_Bool lcl_IsTableCellFill( const UniReference< XMLPropertySetMapper >& rMapper, sal_Int32 nIdx ) +{ + return ( rMapper->GetEntryFlags( nIdx ) & XML_TYPE_PROP_MASK ) == XML_TYPE_PROP_GRAPHIC && + rMapper->GetEntryAPIName( nIdx ).matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "Fill" ) ) && + ( rMapper->GetEntryNameSpace( nIdx ) == XML_NAMESPACE_DRAW || + ( rMapper->GetEntryNameSpace( nIdx ) == XML_NAMESPACE_STYLE && + IsXMLToken( rMapper->GetEntryXMLName( nIdx ), XML_REPEAT ) ) ); +} + +static sal_Bool lcl_HasTableCellProperties( const UniReference< XMLPropertySetMapper >& rMapper ) +{ + for( sal_Int32 n = 0; n < rMapper->GetEntryCount(); ++n ) + if( ( rMapper->GetEntryFlags( n ) & XML_TYPE_PROP_MASK ) == XML_TYPE_PROP_TABLE_CELL ) + return sal_True; + return sal_False; +} + /////////////////////////////////////////////////////////////////////////////// // // public methods @@ -871,7 +890,35 @@ void SvXMLExportPropertyMapper::exportXML( sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx, sal_uInt16 nFlags ) const { - sal_uInt16 nPropTypeFlags = 0; + const SvtSaveOptions::ODFDefaultVersion eVersion( SvtSaveOptions().GetODFDefaultVersion() ); + const bool b014 = eVersion == SvtSaveOptions::ODFVER_014 || eVersion == SvtSaveOptions::ODFVER_014_EXT; + + // ODF 1.4: the fill of a table cell style goes into a style:background-fill child of its table-cell-properties + ::std::vector< XMLPropertyState > aCellMainProps, aCellFillProps; + const ::std::vector< XMLPropertyState >* pAllProps = &rProperties; + bool bCellFill = false; + if( b014 && lcl_HasTableCellProperties( maPropMapper ) ) + { + aCellMainProps = rProperties; + aCellFillProps = rProperties; + for( size_t n = 0; n < rProperties.size(); ++n ) + { + const sal_Int32 nIdx = rProperties[n].mnIndex; + if( nIdx == -1 ) + continue; + if( lcl_IsTableCellFill( maPropMapper, nIdx ) ) + { + aCellMainProps[n].mnIndex = -1; + bCellFill = true; + } + else + aCellFillProps[n].mnIndex = -1; + } + if( bCellFill ) + pAllProps = &aCellMainProps; + } + + sal_uInt16 nPropTypeFlags = bCellFill ? ( 1 << GET_PROP_TYPE( XML_TYPE_PROP_TABLE_CELL ) ) : 0; for( sal_uInt16 i=0; i<MAX_PROP_TYPES; ++i ) { sal_uInt16 nPropType = aPropTokens[i].nType; @@ -881,12 +928,21 @@ void SvXMLExportPropertyMapper::exportXML( // ODF 1.4: header and footer fills go into a style:background-fill child ::std::vector< XMLPropertyState > aMainProps, aFillProps; - const ::std::vector< XMLPropertyState >* pMainProps = &rProperties; + const ::std::vector< XMLPropertyState >* pMainProps = pAllProps; SvXMLAttributeList* pFillAttrs = 0; uno::Reference< xml::sax::XAttributeList > xFillAttrs; - const SvtSaveOptions::ODFDefaultVersion eVersion( SvtSaveOptions().GetODFDefaultVersion() ); - if( aPropTokens[i].eToken == XML_HEADER_FOOTER_PROPERTIES && - ( eVersion == SvtSaveOptions::ODFVER_014 || eVersion == SvtSaveOptions::ODFVER_014_EXT ) ) + if( bCellFill && aPropTokens[i].eToken == XML_TABLE_CELL_PROPERTIES ) + { + pFillAttrs = new SvXMLAttributeList; + xFillAttrs = pFillAttrs; + sal_uInt16 nFillTypeFlags = 0; + _exportXML( GET_PROP_TYPE( XML_TYPE_PROP_GRAPHIC ), nFillTypeFlags, *pFillAttrs, aCellFillProps, + rExport.GetMM100UnitConverter(), + rExport.GetNamespaceMap(), + nFlags, 0, + nPropMapStartIdx, nPropMapEndIdx ); + } + else if( aPropTokens[i].eToken == XML_HEADER_FOOTER_PROPERTIES && b014 ) { aMainProps = rProperties; aFillProps = rProperties; diff --git a/main/xmloff/source/table/XMLTableExport.cxx b/main/xmloff/source/table/XMLTableExport.cxx index 29d79d6b4c..ca30a13788 100644 --- a/main/xmloff/source/table/XMLTableExport.cxx +++ b/main/xmloff/source/table/XMLTableExport.cxx @@ -126,6 +126,8 @@ protected: void XMLTableCellExportPropertyMapper::ContextFilter( std::vector< XMLPropertyState >& rProperties, Reference< XPropertySet > rPropSet ) const { const bool bStrict = SvtSaveOptions::IsODFStrict( SvtSaveOptions().GetODFDefaultVersion() ); + // ODF 1.4 keeps the fill, in a style:background-fill child + const bool b014 = SvtSaveOptions().GetODFDefaultVersion() == SvtSaveOptions::ODFVER_014; bool bSolid = false; if( bStrict ) try { @@ -147,7 +149,8 @@ void XMLTableCellExportPropertyMapper::ContextFilter( std::vector< XMLPropertySt if( !bSolid ) aIter->mnIndex = -1; } - else if( bStrict && nPropType == XML_TYPE_PROP_GRAPHIC ) + else if( bStrict && nPropType == XML_TYPE_PROP_GRAPHIC && + !( b014 && maPropMapper->GetEntryAPIName( aIter->mnIndex ).matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "Fill" ) ) ) ) aIter->mnIndex = -1; }
