From 3d74ddd190a5087e0a54ef7b14d0a43006745ec3 Mon Sep 17 00:00:00 2001 From: Michael Stahl Date: Fri, 5 Apr 2019 19:30:45 +0200 Subject: writerfilter: implement RTF derived styles defaulting It turns out that the situation fixed in commit 1be0a3fa9ebb22b607c54b47739d4467acfed259 also applies to the definition of the styles themselves. To implement the same style import as Word, the style definitions need to be stored twice: once as read from the file, and another time with attributes defaulted and deduplicated vs. the parent style; the second representation is then sent to the domain mapper. To make this easier, add a bool parameter to cloneAndDeduplicate() to disable the implicit pPr dereferencing that happens when creating the hard formatted paragraph properties (this could potentially be cleaned up further if those paragraph properties would use pPr wrapper themselves). Also implement defaulting of line spacing in getDefaultSPRM(). Change-Id: I4810e917697b3af244e5dbdd7f5a45b4767c93fc Reviewed-on: https://gerrit.libreoffice.org/70320 Tested-by: Jenkins Reviewed-by: Miklos Vajna --- writerfilter/source/rtftok/rtfdocumentimpl.cxx | 63 ++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 3 deletions(-) (limited to 'writerfilter/source/rtftok/rtfdocumentimpl.cxx') diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx index c5c549f92a2d..ab8b249b8b50 100644 --- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx +++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx @@ -522,8 +522,9 @@ RTFDocumentImpl::getProperties(const RTFSprms& rAttributes, RTFSprms const& rSpr } // Get rid of direct formatting what is already in the style. - RTFSprms const sprms(aSprms.cloneAndDeduplicate(aStyleSprms, nStyleType)); - RTFSprms const attributes(rAttributes.cloneAndDeduplicate(aStyleAttributes, nStyleType)); + RTFSprms const sprms(aSprms.cloneAndDeduplicate(aStyleSprms, nStyleType, true)); + RTFSprms const attributes( + rAttributes.cloneAndDeduplicate(aStyleAttributes, nStyleType, true)); return new RTFReferenceProperties(attributes, sprms); } @@ -2031,6 +2032,61 @@ writerfilter::Reference::Pointer_t RTFDocumentImpl::createStylePrope return pProps; } +/** 2 different representations of the styles are needed: + + 1) flat content, as read from the input file: + stored in m_aStyleTableEntries, used as reference input for + deduplication both here and for hard formatting in getProperties() + + 2) real content, with proper override of sprms/attributes where it differs + from parent style; this is produced here and sent to domain mapper + */ +RTFReferenceTable::Entries_t RTFDocumentImpl::deduplicateStyleTable() +{ + RTFReferenceTable::Entries_t ret; + for (auto const& it : m_aStyleTableEntries) + { + auto pStyle = it.second; + // ugly downcasts here, but can't easily replace the members with + // RTFReferenceProperties because dmapper wants SvRef anyway + RTFValue::Pointer_t const pBasedOn( + static_cast(*pStyle).getSprms().find( + NS_ooxml::LN_CT_Style_basedOn)); + if (pBasedOn) + { + int const nBasedOn(pBasedOn->getInt()); + auto const itParent(m_aStyleTableEntries.find(nBasedOn)); // definition as read! + if (itParent != m_aStyleTableEntries.end()) + { + auto const pStyleType( + static_cast(*pStyle).getAttributes().find( + NS_ooxml::LN_CT_Style_type)); + assert(pStyleType); + int const nStyleType(pStyleType->getInt()); + RTFSprms const sprms( + static_cast(*pStyle).getSprms().cloneAndDeduplicate( + static_cast(*itParent->second).getSprms(), + nStyleType)); + RTFSprms const attributes( + static_cast(*pStyle) + .getAttributes() + .cloneAndDeduplicate( + static_cast(*itParent->second).getAttributes(), + nStyleType)); + + pStyle = new RTFReferenceProperties(attributes, sprms); + } + else + { + SAL_WARN("writerfilter.rtf", "parent style not found: " << nBasedOn); + } + } + ret[it.first] = pStyle; + } + assert(ret.size() == m_aStyleTableEntries.size()); + return ret; +} + void RTFDocumentImpl::resetSprms() { m_aStates.top().aTableSprms.clear(); @@ -2094,8 +2150,9 @@ RTFError RTFDocumentImpl::popState() break; case Destination::STYLESHEET: { + RTFReferenceTable::Entries_t const pStyleTableDeduplicated(deduplicateStyleTable()); writerfilter::Reference::Pointer_t const pTable( - new RTFReferenceTable(m_aStyleTableEntries)); + new RTFReferenceTable(pStyleTableDeduplicated)); Mapper().table(NS_ooxml::LN_STYLESHEET, pTable); } break; -- cgit v1.2.3