tdf#118047: RTF import: better deduplication for header/footer

Here are two related fixes in one patch:

1. By default current style index is 0, not -1. Due to this we
can assume usage of default "Normal" style during deduplication.
Seems there is no difference in case of no style mentioning in
run or mentioning "Normal" one (\s0), so value -1 looks
unnesesary.

2. During header/footer "substreams" processing StyleTableEntires
was not reused in new domain mapper impl instance. So deduplication
did not work well.

2a. To avoid copying of whole StyleTableEntries between instances
it is stored as pointer in domain mapper impl.

Change-Id: Id003d35554e9b43186238920d9a6373452095121
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131899
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
This commit is contained in:
Vasily Melenchuk
2022-03-21 15:58:54 +01:00
committed by Miklos Vajna
parent f8b482f6d6
commit 79b5ff92b1
5 changed files with 46 additions and 18 deletions
+14
View File
@@ -0,0 +1,14 @@
{\rtf1\ansi
{\stylesheet
{\fs72\sa3200 Normal;}
}
\sectd
{
\headerr
Header\par
}
Text\par
}
+15
View File
@@ -1348,6 +1348,21 @@ DECLARE_RTFEXPORT_TEST(testTdf131234, "tdf131234.rtf")
CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE, getProperty<awt::FontSlant>(xRun, "CharPosture"));
}
DECLARE_RTFEXPORT_TEST(testTdf118047, "tdf118047.rtf")
{
uno::Reference<text::XTextRange> xPara = getParagraph(1);
// Ensure that default "Normal" style properties are not applied to text:
// text remains with fontsize 12pt and no huge margin below
CPPUNIT_ASSERT_EQUAL(12.f, getProperty<float>(getRun(xPara, 1), "CharHeight"));
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(1), "ParaBottomMargin"));
// Same for header, it should not derive props from "Normal" style
CPPUNIT_ASSERT_EQUAL(OUString("Header"), parseDump("/root/page[1]/header/txt/text()"));
sal_Int32 nHeight = parseDump("/root/page[1]/header/infos/bounds", "height").toInt32();
CPPUNIT_ASSERT_MESSAGE("Header is too large", 1000 > nHeight);
}
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
@@ -520,12 +520,8 @@ RTFError RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword)
{
m_aStates.top().getParagraphSprms().set(NS_ooxml::LN_CT_PPrBase_pStyle,
new RTFValue(aName));
m_aStates.top().setCurrentStyleIndex(0);
}
else
{
m_aStates.top().setCurrentStyleIndex(-1);
}
m_aStates.top().setCurrentStyleIndex(0);
}
// Need to send paragraph properties again, if there will be any.
m_bNeedPap = true;
+14 -12
View File
@@ -291,6 +291,7 @@ RTFDocumentImpl::RTFDocumentImpl(uno::Reference<uno::XComponentContext> const& x
, m_nCurrentFontIndex(0)
, m_nCurrentEncoding(-1)
, m_nDefaultFontIndex(-1)
, m_pStyleTableEntries(new RTFReferenceTable::Entries_t)
, m_nCurrentStyleIndex(0)
, m_bFormField(false)
, m_bMathNor(false)
@@ -363,6 +364,7 @@ void RTFDocumentImpl::resolveSubstream(std::size_t nPos, Id nId, OUString const&
m_aAuthorInitials.clear();
}
pImpl->m_nDefaultFontIndex = m_nDefaultFontIndex;
pImpl->m_pStyleTableEntries = m_pStyleTableEntries;
pImpl->Strm().Seek(nPos);
SAL_INFO("writerfilter.rtf", "substream start");
Mapper().substream(nId, pImpl);
@@ -497,16 +499,16 @@ RTFDocumentImpl::getProperties(const RTFSprms& rAttributes, RTFSprms const& rSpr
int nStyle = 0;
if (!m_aStates.empty())
nStyle = m_aStates.top().getCurrentStyleIndex();
auto it = m_aStyleTableEntries.find(nStyle);
if (it != m_aStyleTableEntries.end())
auto it = m_pStyleTableEntries->find(nStyle);
if (it != m_pStyleTableEntries->end())
{
// cloneAndDeduplicate() wants to know about only a single "style", so
// let's merge paragraph and character style properties here.
auto itChar = m_aStyleTableEntries.end();
auto itChar = m_pStyleTableEntries->end();
if (!m_aStates.empty())
{
int nCharStyle = m_aStates.top().getCurrentCharacterStyleIndex();
itChar = m_aStyleTableEntries.find(nCharStyle);
itChar = m_pStyleTableEntries->find(nCharStyle);
}
RTFSprms aStyleSprms;
@@ -517,7 +519,7 @@ RTFDocumentImpl::getProperties(const RTFSprms& rAttributes, RTFSprms const& rSpr
RTFReferenceProperties& rProps = *static_cast<RTFReferenceProperties*>(it->second.get());
lcl_copyFlatten(rProps, aStyleAttributes, aStyleSprms);
if (itChar != m_aStyleTableEntries.end())
if (itChar != m_pStyleTableEntries->end())
{
// Found active character style, then update aStyleSprms/Attributes.
if (!nStyleType || nStyleType == NS_ooxml::LN_Value_ST_StyleType_character)
@@ -1402,7 +1404,7 @@ void RTFDocumentImpl::text(OUString& rString)
writerfilter::Reference<Properties>::Pointer_t const pProp(
createStyleProperties());
m_aStyleTableEntries.insert(
m_pStyleTableEntries->insert(
std::make_pair(m_nCurrentStyleIndex, pProp));
}
else
@@ -2091,7 +2093,7 @@ writerfilter::Reference<Properties>::Pointer_t RTFDocumentImpl::createStylePrope
/** 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
stored in m_pStyleTableEntries, 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
@@ -2100,7 +2102,7 @@ writerfilter::Reference<Properties>::Pointer_t RTFDocumentImpl::createStylePrope
RTFReferenceTable::Entries_t RTFDocumentImpl::deduplicateStyleTable()
{
RTFReferenceTable::Entries_t ret;
for (auto const& it : m_aStyleTableEntries)
for (auto const& it : *m_pStyleTableEntries)
{
auto pStyle = it.second;
ret[it.first] = pStyle;
@@ -2116,8 +2118,8 @@ RTFReferenceTable::Entries_t RTFDocumentImpl::deduplicateStyleTable()
if (it.first == nBasedOn)
continue;
auto const itParent(m_aStyleTableEntries.find(nBasedOn)); // definition as read!
if (itParent != m_aStyleTableEntries.end())
auto const itParent(m_pStyleTableEntries->find(nBasedOn)); // definition as read!
if (itParent != m_pStyleTableEntries->end())
{
auto const pStyleType(
static_cast<RTFReferenceProperties&>(*pStyle).getAttributes().find(
@@ -2143,7 +2145,7 @@ RTFReferenceTable::Entries_t RTFDocumentImpl::deduplicateStyleTable()
}
}
}
assert(ret.size() == m_aStyleTableEntries.size());
assert(ret.size() == m_pStyleTableEntries->size());
return ret;
}
@@ -3668,7 +3670,7 @@ RTFParserState::RTFParserState(RTFDocumentImpl* pDocumentImpl)
, m_nHour(0)
, m_nMinute(0)
, m_pCurrentDestinationText(nullptr)
, m_nCurrentStyleIndex(-1)
, m_nCurrentStyleIndex(0)
, m_nCurrentCharacterStyleIndex(-1)
, m_pCurrentBuffer(nullptr)
, m_bInListpicture(false)
@@ -933,7 +933,8 @@ private:
/// Raw default font index, use getFont() on it to get a real one.
int m_nDefaultFontIndex;
RTFReferenceTable::Entries_t m_aStyleTableEntries;
/// To avoid copying entries between DomainMapper instances it is stored as pointer
std::shared_ptr<RTFReferenceTable::Entries_t> m_pStyleTableEntries;
int m_nCurrentStyleIndex;
bool m_bFormField;
/// For the INCLUDEPICTURE field's argument.