diff --git a/sw/qa/extras/ooxmlexport/data/table-theme-preservation.docx b/sw/qa/extras/ooxmlexport/data/table-theme-preservation.docx index fe6b9537bfa9..522dac899417 100644 Binary files a/sw/qa/extras/ooxmlexport/data/table-theme-preservation.docx and b/sw/qa/extras/ooxmlexport/data/table-theme-preservation.docx differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx index b68b8722be16..1e1fd6dac6a3 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx @@ -1956,6 +1956,11 @@ DECLARE_OOXMLEXPORT_TEST(testTableThemePreservation, "table-theme-preservation.d // check table style has been preserved assertXPath(pXmlDocument, "/w:document/w:body/w:tbl/w:tblPr/w:tblStyle", "val", "Sombreadoclaro-nfasis1"); + // check table style is not overwritten by other properties + assertXPath(pXmlDocument, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[2]/w:tcPr/w:tcBorders/*", 0); + assertXPath(pXmlDocument, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[3]/w:tcPr/w:tcBorders/*", 0); + // check that one cell attribute present in the original document has been preserved + assertXPath(pXmlDocument, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:tcPr/w:tcBorders/*", 1); } diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 947cd16d1766..1f4c3014c6a3 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -2075,7 +2075,8 @@ void DocxAttributeOutput::ParagraphStyle( sal_uInt16 nStyle ) m_pSerializer->singleElementNS( XML_w, XML_pStyle, FSNS( XML_w, XML_val ), aStyleId.getStr(), FSEND ); } -static void impl_borderLine( FSHelperPtr pSerializer, sal_Int32 elementToken, const SvxBorderLine* pBorderLine, sal_uInt16 nDist, bool bWriteShadow = false ) +static void impl_borderLine( FSHelperPtr pSerializer, sal_Int32 elementToken, const SvxBorderLine* pBorderLine, sal_uInt16 nDist, + bool bWriteShadow = false, const table::BorderLine2* rStyleProps = NULL ) { FastAttributeList* pAttr = pSerializer->createAttrList(); @@ -2141,6 +2142,19 @@ static void impl_borderLine( FSHelperPtr pSerializer, sal_Int32 elementToken, co break; } } + else if( rStyleProps == NULL ) + // no line, and no line set by the style either: + // there is no need to write the property + return; + + // compare the properties with the theme properties before writing them: + // if they are equal, it means that they were style-defined and there is + // no need to write them. + if( rStyleProps != NULL && pBorderLine && !pBorderLine->isEmpty() && + pBorderLine->GetBorderLineStyle() == rStyleProps->LineStyle && + pBorderLine->GetColor() == rStyleProps->Color && + pBorderLine->GetWidth() == MM100_TO_TWIP_UNSIGNED( rStyleProps->LineWidth ) ) + return; pAttr->add( FSNS( XML_w, XML_val ), OString( pVal ) ); @@ -2235,7 +2249,8 @@ static bool boxHasLineLargerThan31(const SvxBoxItem& rBox) ); } -static void impl_borders( FSHelperPtr pSerializer, const SvxBoxItem& rBox, const OutputBorderOptions& rOptions, PageMargins* pageMargins) +static void impl_borders( FSHelperPtr pSerializer, const SvxBoxItem& rBox, const OutputBorderOptions& rOptions, PageMargins* pageMargins, + std::map &rTableStyleConf ) { static const sal_uInt16 aBorders[] = { @@ -2267,6 +2282,9 @@ static void impl_borders( FSHelperPtr pSerializer, const SvxBoxItem& rBox, const for( int i = 0; i < 4; ++i, ++pBrd ) { const SvxBorderLine* pLn = rBox.GetLine( *pBrd ); + const table::BorderLine2 *aStyleProps = NULL; + if( rTableStyleConf.find( *pBrd ) != rTableStyleConf.end() ) + aStyleProps = &rTableStyleConf[ *pBrd ]; if (!tagWritten && rOptions.bWriteTag) { @@ -2326,7 +2344,7 @@ static void impl_borders( FSHelperPtr pSerializer, const SvxBoxItem& rBox, const } } - impl_borderLine( pSerializer, aXmlElements[i], pLn, nDist, bWriteShadow ); + impl_borderLine( pSerializer, aXmlElements[i], pLn, nDist, bWriteShadow, aStyleProps ); // When exporting default borders, we need to export these 2 attr if ( rOptions.bWriteInsideHV) { @@ -2337,9 +2355,19 @@ static void impl_borders( FSHelperPtr pSerializer, const SvxBoxItem& rBox, const } } if (bWriteInsideH) - impl_borderLine( pSerializer, XML_insideH, rBox.GetLine(BOX_LINE_BOTTOM), 0 ); + { + const table::BorderLine2 *aStyleProps = NULL; + if( rTableStyleConf.find( BOX_LINE_BOTTOM ) != rTableStyleConf.end() ) + aStyleProps = &rTableStyleConf[ BOX_LINE_BOTTOM ]; + impl_borderLine( pSerializer, XML_insideH, rBox.GetLine(BOX_LINE_BOTTOM), 0, false, aStyleProps ); + } if (bWriteInsideV) - impl_borderLine( pSerializer, XML_insideV, rBox.GetLine(BOX_LINE_RIGHT), 0 ); + { + const table::BorderLine2 *aStyleProps = NULL; + if( rTableStyleConf.find( BOX_LINE_RIGHT ) != rTableStyleConf.end() ) + aStyleProps = &rTableStyleConf[ BOX_LINE_RIGHT ]; + impl_borderLine( pSerializer, XML_insideV, rBox.GetLine(BOX_LINE_RIGHT), 0, false, aStyleProps ); + } if (tagWritten && rOptions.bWriteTag) { pSerializer->endElementNS( XML_w, rOptions.tag ); } @@ -2450,7 +2478,7 @@ void DocxAttributeOutput::TableCellProperties( ww8::WW8TableNodeInfoInner::Point const SvxBoxItem& rDefaultBox = (*tableFirstCells.rbegin())->getTableBox( )->GetFrmFmt( )->GetBox( ); { // The cell borders - impl_borders( m_pSerializer, rBox, lcl_getTableCellBorderOptions(bEcma), NULL ); + impl_borders( m_pSerializer, rBox, lcl_getTableCellBorderOptions(bEcma), NULL, m_aTableStyleConf ); } TableBackgrounds( pTableTextNodeInfoInner ); @@ -2549,6 +2577,8 @@ void DocxAttributeOutput::EndTable() // Cleans the table helper delete m_pTableWrt, m_pTableWrt = NULL; + + m_aTableStyleConf.clear(); } void DocxAttributeOutput::StartTableRow( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner ) @@ -2678,14 +2708,25 @@ void DocxAttributeOutput::TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t if ( SFX_ITEM_ON == pTblFmt->GetAttrSet().GetItemState( RES_FRMATR_GRABBAG, false, &pI ) ) aGrabBag = dynamic_cast(pI)->GetGrabBag(); - // Write table style property if it exists - std::map::iterator aGrabBagElement = aGrabBag.find("TableStyleName"); - if( aGrabBagElement != aGrabBag.end() ) + // Extract properties from grab bag + std::map::iterator aGrabBagElement; + for( aGrabBagElement = aGrabBag.begin(); aGrabBagElement != aGrabBag.end(); ++aGrabBagElement ) { - OString sStyleName = OUStringToOString( aGrabBagElement->second.get(), RTL_TEXTENCODING_UTF8 ); - m_pSerializer->singleElementNS( XML_w, XML_tblStyle, - FSNS( XML_w, XML_val ), sStyleName.getStr(), - FSEND ); + if( aGrabBagElement->first == "TableStyleName") + { + OString sStyleName = OUStringToOString( aGrabBagElement->second.get(), RTL_TEXTENCODING_UTF8 ); + m_pSerializer->singleElementNS( XML_w, XML_tblStyle, + FSNS( XML_w, XML_val ), sStyleName.getStr(), + FSEND ); + } + else if( aGrabBagElement->first == "TableStyleTopBorder" ) + m_aTableStyleConf[ BOX_LINE_TOP ] = aGrabBagElement->second.get(); + else if( aGrabBagElement->first == "TableStyleBottomBorder" ) + m_aTableStyleConf[ BOX_LINE_BOTTOM ] = aGrabBagElement->second.get(); + else if( aGrabBagElement->first == "TableStyleLeftBorder" ) + m_aTableStyleConf[ BOX_LINE_LEFT ] = aGrabBagElement->second.get(); + else if( aGrabBagElement->first == "TableStyleRightBorder" ) + m_aTableStyleConf[ BOX_LINE_RIGHT ] = aGrabBagElement->second.get(); } // Output the table alignement @@ -2771,7 +2812,7 @@ void DocxAttributeOutput::TableDefaultBorders( ww8::WW8TableNodeInfoInner::Point bool bEcma = GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT; // the defaults of the table are taken from the top-left cell - impl_borders( m_pSerializer, pFrmFmt->GetBox( ), lcl_getTableDefaultBorderOptions(bEcma), NULL ); + impl_borders( m_pSerializer, pFrmFmt->GetBox( ), lcl_getTableDefaultBorderOptions(bEcma), NULL, m_aTableStyleConf ); } void DocxAttributeOutput::TableDefaultCellMargins( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner ) @@ -4623,7 +4664,9 @@ void DocxAttributeOutput::SectionPageBorders( const SwFrmFmt* pFmt, const SwFrmF aOutputBorderOptions.aShadowLocation = pShadowItem->GetLocation(); } - impl_borders( m_pSerializer, rBox, aOutputBorderOptions, &m_pageMargins ); + std::map aEmptyMap; // empty styles map + impl_borders( m_pSerializer, rBox, aOutputBorderOptions, &m_pageMargins, + aEmptyMap ); m_pSerializer->endElementNS( XML_w, XML_pgBorders ); } @@ -6804,7 +6847,9 @@ void DocxAttributeOutput::FormatBox( const SvxBoxItem& rBox ) // Open the paragraph's borders tag m_pSerializer->startElementNS( XML_w, XML_pBdr, FSEND ); - impl_borders( m_pSerializer, rBox, aOutputBorderOptions, &m_pageMargins ); + std::map aEmptyMap; // empty styles map + impl_borders( m_pSerializer, rBox, aOutputBorderOptions, &m_pageMargins, + aEmptyMap ); // Close the paragraph's borders tag m_pSerializer->endElementNS( XML_w, XML_pBdr ); diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx index 8deff4fe8400..ba26fbaa4a2b 100644 --- a/sw/source/filter/ww8/docxattributeoutput.hxx +++ b/sw/source/filter/ww8/docxattributeoutput.hxx @@ -39,6 +39,8 @@ #include #include +#include + #include class SwGrfNode; @@ -868,6 +870,8 @@ private: ::sax_fastparser::FastAttributeList *m_pRunSdtPrTokenChildren; ::sax_fastparser::FastAttributeList *m_pRunSdtPrDataBindingAttrs; + std::map m_aTableStyleConf; + public: DocxAttributeOutput( DocxExport &rExport, ::sax_fastparser::FSHelperPtr pSerializer, oox::drawingml::DrawingML* pDrawingML ); diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx index 7ed56aa38700..08d1919dd345 100644 --- a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx +++ b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx @@ -340,7 +340,7 @@ TableStyleSheetEntry * DomainMapperTableHandler::endTableGetTableStyle(TableInfo PropertyMap::iterator aTableStyleIter = m_aTableProperties->find(META_PROP_TABLE_STYLE_NAME); - uno::Sequence< beans::PropertyValue > aGrabBag( 1 ); + uno::Sequence< beans::PropertyValue > aGrabBag( 5 ); sal_Int32 nGrabBagSize = 0; if(aTableStyleIter != m_aTableProperties->end()) { @@ -366,6 +366,33 @@ TableStyleSheetEntry * DomainMapperTableHandler::endTableGetTableStyle(TableInfo PropertyMapPtr pMergedProperties = lcl_SearchParentStyleSheetAndMergeProperties(pStyleSheet, pStyleSheetTable); + table::BorderLine2 aBorderLine; + TableInfo rStyleInfo; + if (lcl_extractTableBorderProperty(pMergedProperties, PROP_TOP_BORDER, rStyleInfo, aBorderLine)) + { + aGrabBag[1].Name = "TableStyleTopBorder"; + aGrabBag[1].Value = uno::makeAny( aBorderLine ); + nGrabBagSize++; + } + if (lcl_extractTableBorderProperty(pMergedProperties, PROP_BOTTOM_BORDER, rStyleInfo, aBorderLine)) + { + aGrabBag[2].Name = "TableStyleBottomBorder"; + aGrabBag[2].Value = uno::makeAny( aBorderLine ); + nGrabBagSize++; + } + if (lcl_extractTableBorderProperty(pMergedProperties, PROP_LEFT_BORDER, rStyleInfo, aBorderLine)) + { + aGrabBag[3].Name = "TableStyleLeftBorder"; + aGrabBag[3].Value = uno::makeAny( aBorderLine ); + nGrabBagSize++; + } + if (lcl_extractTableBorderProperty(pMergedProperties, PROP_RIGHT_BORDER, rStyleInfo, aBorderLine)) + { + aGrabBag[4].Name = "TableStyleRightBorder"; + aGrabBag[4].Value = uno::makeAny( aBorderLine ); + nGrabBagSize++; + } + #ifdef DEBUG_DMAPPER_TABLE_HANDLER dmapper_logger->startElement("mergedProps"); pMergedProperties->dumpXml( dmapper_logger ); @@ -402,6 +429,7 @@ TableStyleSheetEntry * DomainMapperTableHandler::endTableGetTableStyle(TableInfo if( nGrabBagSize > 0 ) { + aGrabBag.realloc( nGrabBagSize ); m_aTableProperties->Insert( PROP_TABLE_INTEROP_GRAB_BAG, uno::makeAny( aGrabBag ) ); }