summaryrefslogtreecommitdiff
path: root/writerfilter
diff options
context:
space:
mode:
authorLászló Németh <nemeth@numbertext.org>2021-02-17 09:47:43 +0100
committerLászló Németh <nemeth@numbertext.org>2021-02-18 13:30:55 +0100
commit7dd8f8aace536a8e60e87e61ee1d90d61fba15eb (patch)
tree72638bfc11fa2d0ee1c55f214df3a8e027168aaa /writerfilter
parent63d14566ba93b87f23a7ba68f8ea733cf19be101 (diff)
tdf#120351 DOCX import: fix slow endnote import
by parsing endnotes.xml only once instead of parsing again and again for every endnotes. This was a serious performance problem for documents with hundreds of endnotes, where the endnote import took minutes instead of seconds. Note: switch off CHECK_NOTMERGED in a debug build to measure realistic speed-up, e.g. 98 s -> 18 s for a document with thousand of endnotes. Follow-up of commit 9b39ce0e66acfe812e1d50e530dc2ccdef3e1357 "tdf#76260 DOCX import: fix slow footnote import". Change-Id: I88cdc5101c25041f985fdc23739a0dadf24a13e0 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111030 Tested-by: László Németh <nemeth@numbertext.org> Reviewed-by: László Németh <nemeth@numbertext.org>
Diffstat (limited to 'writerfilter')
-rw-r--r--writerfilter/source/dmapper/DomainMapper.cxx24
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.cxx224
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.hxx26
-rw-r--r--writerfilter/source/dmapper/PropertyMap.cxx2
-rw-r--r--writerfilter/source/ooxml/OOXMLDocumentImpl.cxx6
-rw-r--r--writerfilter/source/ooxml/OOXMLFastContextHandler.cxx2
6 files changed, 157 insertions, 127 deletions
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index 4f58670aefb5..a3b04a014ca8 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -3249,7 +3249,9 @@ void DomainMapper::lcl_text(const sal_uInt8 * data_, size_t len)
m_pImpl->SetFieldLocked();
return;
case 0x0c: //page break
- m_pImpl->deferBreak(PAGE_BREAK);
+ // page breaks aren't supported in footnotes and endnotes
+ if (!m_pImpl->IsInFootOrEndnote())
+ m_pImpl->deferBreak(PAGE_BREAK);
return;
case 0x0e: //column break
m_pImpl->deferBreak(COLUMN_BREAK);
@@ -3373,12 +3375,24 @@ void DomainMapper::lcl_utext(const sal_uInt8 * data_, size_t len)
// preload all footnotes in separated footnotes
if (sText[0] == 0x5)
{
- if (m_pImpl->GetFootnoteCount() > -1)
+ if (m_pImpl->IsInFootnote())
{
- m_pImpl->PopFootOrEndnote(/*bIsFootnote=*/true);
- m_pImpl->PushFootOrEndnote(/*bIsFootnote=*/true);
+ if (m_pImpl->GetFootnoteCount() > -1)
+ {
+ m_pImpl->PopFootOrEndnote();
+ m_pImpl->PushFootOrEndnote(/*bIsFootnote=*/true);
+ }
+ m_pImpl->IncrementFootnoteCount();
+ }
+ else
+ {
+ if (m_pImpl->GetEndnoteCount() > -1)
+ {
+ m_pImpl->PopFootOrEndnote();
+ m_pImpl->PushFootOrEndnote(/*bIsFootnote=*/false);
+ }
+ m_pImpl->IncrementEndnoteCount();
}
- m_pImpl->IncrementFootnoteCount();
}
// If the footnote contains a Footnote Reference Mark, it can't be a custom footnote
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index ebfe9d625bd2..d0ddb431c4d7 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -304,10 +304,12 @@ DomainMapper_Impl::DomainMapper_Impl(
m_eInHeaderFooterImport( HeaderFooterImportState::none ),
m_bDiscardHeaderFooter( false ),
m_bInFootOrEndnote(false),
+ m_bInFootnote(false),
m_bHasFootnoteStyle(false),
m_bCheckFootnoteStyle(false),
m_eSkipFootnoteState(SkipFootnoteSeparator::OFF),
m_nFootnotes(-1),
+ m_nEndnotes(-1),
m_bLineNumberingSet( false ),
m_bIsInFootnoteProperties( false ),
m_bIsParaMarkerChange( false ),
@@ -2614,6 +2616,7 @@ void DomainMapper_Impl::PushFootOrEndnote( bool bIsFootnote )
{
SAL_WARN_IF(m_bInFootOrEndnote, "writerfilter.dmapper", "PushFootOrEndnote() is called from another foot or endnote");
m_bInFootOrEndnote = true;
+ m_bInFootnote = bIsFootnote;
m_bCheckFirstFootnoteTab = true;
m_bSaveFirstParagraphInCell = m_bFirstParagraphInCell;
try
@@ -2703,24 +2706,25 @@ void DomainMapper_Impl::CreateRedline(uno::Reference<text::XTextRange> const& xR
pRedlineProperties[1].Value <<= ConversionHelper::ConvertDateStringToDateTime( pRedline->m_sDate );
pRedlineProperties[2].Name = getPropertyName( PROP_REDLINE_REVERT_PROPERTIES );
pRedlineProperties[2].Value <<= pRedline->m_aRevertProperties;
- // TODO: add !IsInFootOrEndnote(), if loading of endnotes is optimized
if (!m_bIsActualParagraphFramed)
{
uno::Reference < text::XRedline > xRedline( xRange, uno::UNO_QUERY_THROW );
xRedline->makeRedline( sType, aRedlineProperties );
}
// store frame and (possible floating) table redline data for restoring them after frame conversion
+ enum StoredRedlines eType;
if (m_bIsActualParagraphFramed || (hasTableManager() && getTableManager().isInTable()))
- {
- aFramedRedlines.push_back( uno::makeAny(xRange) );
- aFramedRedlines.push_back( uno::makeAny(sType) );
- aFramedRedlines.push_back( uno::makeAny(aRedlineProperties) );
- }
+ eType = StoredRedlines::FRAME;
else if (IsInFootOrEndnote())
+ eType = IsInFootnote() ? StoredRedlines::FOOTNOTE : StoredRedlines::ENDNOTE;
+ else
+ eType = StoredRedlines::NONE;
+
+ if (eType != StoredRedlines::NONE)
{
- aFootnoteRedlines.push_back( uno::makeAny(xRange) );
- aFootnoteRedlines.push_back( uno::makeAny(sType) );
- aFootnoteRedlines.push_back( uno::makeAny(aRedlineProperties) );
+ m_aStoredRedlines[eType].push_back( uno::makeAny(xRange) );
+ m_aStoredRedlines[eType].push_back( uno::makeAny(sType) );
+ m_aStoredRedlines[eType].push_back( uno::makeAny(aRedlineProperties) );
}
}
catch( const uno::Exception & )
@@ -2832,23 +2836,101 @@ void DomainMapper_Impl::PushAnnotation()
}
}
+static void lcl_CopyRedlines(
+ uno::Reference< text::XText > const& xSrc,
+ std::deque<css::uno::Any>& rRedlines,
+ std::vector<sal_Int32>& redPos,
+ std::vector<sal_Int32>& redLen,
+ sal_Int32& redIdx)
+{
+ redIdx = -1;
+ for( size_t i = 0; i < rRedlines.size(); i+=3)
+ {
+ uno::Reference< text::XTextRange > xRange;
+ rRedlines[i] >>= xRange;
+
+ // is this a redline of the temporary footnote?
+ uno::Reference<text::XTextCursor> xRangeCursor;
+ try
+ {
+ xRangeCursor = xSrc->createTextCursorByRange( xRange );
+ }
+ catch( const uno::Exception& )
+ {
+ }
+ if (xRangeCursor.is())
+ {
+ redIdx = i;
+ sal_Int32 nLen = xRange->getString().getLength();
+ redLen.push_back(nLen);
+ xRangeCursor->gotoRange(xSrc->getStart(), true);
+ redPos.push_back(xRangeCursor->getString().getLength() - nLen);
+ }
+ else
+ {
+ // we have already found all redlines of the footnote,
+ // skip checking the redlines of the other footnotes
+ if (redIdx > -1)
+ break;
+ // failed createTextCursorByRange(), for example, table inside the frame
+ redLen.push_back(-1);
+ redPos.push_back(-1);
+ }
+ }
+}
+
+static void lcl_PasteRedlines(
+ uno::Reference< text::XText > const& xDest,
+ std::deque<css::uno::Any>& rRedlines,
+ std::vector<sal_Int32>& redPos,
+ std::vector<sal_Int32>& redLen,
+ sal_Int32& redIdx)
+{
+ // create redlines in the copied footnote
+ for( size_t i = 0; redIdx > -1 && i <= sal::static_int_cast<size_t>(redIdx); i+=3)
+ {
+ OUString sType;
+ beans::PropertyValues aRedlineProperties( 3 );
+ // skip failed createTextCursorByRange()
+ if (redPos[i/3] == -1)
+ continue;
+ rRedlines[i+1] >>= sType;
+ rRedlines[i+2] >>= aRedlineProperties;
+ uno::Reference< text::XTextCursor > xCrsr = xDest->getText()->createTextCursor();
+ xCrsr->goRight(redPos[i/3], false);
+ xCrsr->goRight(redLen[i/3], true);
+ uno::Reference < text::XRedline > xRedline( xCrsr, uno::UNO_QUERY_THROW );
+ xRedline->makeRedline( sType, aRedlineProperties );
+ }
+}
-void DomainMapper_Impl::PopFootOrEndnote( bool bIsFootnote )
+void DomainMapper_Impl::PopFootOrEndnote()
{
// content of the footnotes were inserted after the first footnote in temporary footnotes,
// restore the content of the actual footnote by copying its content from the first
// (remaining) temporary footnote and remove the temporary footnote.
// FIXME: add footnote IDs to handle possible differences in footnote serialization
uno::Reference< text::XFootnotesSupplier> xFootnotesSupplier( GetTextDocument(), uno::UNO_QUERY );
- if ( bIsFootnote && GetFootnoteCount() > -1 && xFootnotesSupplier.is() )
+ uno::Reference< text::XEndnotesSupplier> xEndnotesSupplier( GetTextDocument(), uno::UNO_QUERY );
+ if ( IsInFootOrEndnote() && ( ( IsInFootnote() && GetFootnoteCount() > -1 && xFootnotesSupplier.is() ) ||
+ ( !IsInFootnote() && GetEndnoteCount() > -1 && xEndnotesSupplier.is() ) ) )
{
- auto xFootnotes = xFootnotesSupplier->getFootnotes();
uno::Reference< text::XFootnote > xFootnoteFirst, xFootnoteLast;
- xFootnotes->getByIndex(xFootnotes->getCount()-1) >>= xFootnoteLast;
- if ( xFootnotes->getCount() > 1 && xFootnoteLast->getLabel().isEmpty() )
+ auto xFootnotes = xFootnotesSupplier->getFootnotes();
+ auto xEndnotes = xEndnotesSupplier->getEndnotes();
+ if (IsInFootnote())
+ xFootnotes->getByIndex(xFootnotes->getCount()-1) >>= xFootnoteLast;
+ else
+ xEndnotes->getByIndex(xEndnotes->getCount()-1) >>= xFootnoteLast;
+ if ( ( ( IsInFootnote() && xFootnotes->getCount() > 1 ) ||
+ ( !IsInFootnote() && xEndnotes->getCount() > 1 ) ) &&
+ xFootnoteLast->getLabel().isEmpty() )
{
// copy content of the first remaining temporary footnote
- xFootnotes->getByIndex(1) >>= xFootnoteFirst;
+ if ( IsInFootnote() )
+ xFootnotes->getByIndex(1) >>= xFootnoteFirst;
+ else
+ xEndnotes->getByIndex(1) >>= xFootnoteFirst;
uno::Reference< text::XText > xSrc( xFootnoteFirst, uno::UNO_QUERY_THROW );
uno::Reference< text::XText > xDest( xFootnoteLast, uno::UNO_QUERY_THROW );
uno::Reference< text::XTextCopy > xTxt, xTxt2;
@@ -2858,61 +2940,14 @@ void DomainMapper_Impl::PopFootOrEndnote( bool bIsFootnote )
// copy its redlines
std::vector<sal_Int32> redPos, redLen;
- sal_Int32 nFirstRedline = -1;
- for( size_t i = 0; i < aFootnoteRedlines.size(); i+=3)
- {
- uno::Reference< text::XTextRange > xRange;
- aFootnoteRedlines[i] >>= xRange;
-
- // is this a redline of the temporary footnote?
- uno::Reference<text::XTextCursor> xRangeCursor;
- try
- {
- xRangeCursor = xSrc->createTextCursorByRange( xRange );
- }
- catch( const uno::Exception& )
- {
- }
- if (xRangeCursor.is())
- {
- nFirstRedline = i;
- sal_Int32 nLen = xRange->getString().getLength();
- redLen.push_back(nLen);
- xRangeCursor->gotoRange(xSrc->getStart(), true);
- redPos.push_back(xRangeCursor->getString().getLength() - nLen);
- }
- else
- {
- // we have already found all redlines of the footnote,
- // skip checking the redlines of the other footnotes
- if (nFirstRedline > -1)
- break;
- // failed createTextCursorByRange(), for example, table inside the frame
- redLen.push_back(-1);
- redPos.push_back(-1);
- }
- }
-
- // create redlines in the copied footnote
- for( size_t i = 0; nFirstRedline > -1 && i <= sal::static_int_cast<size_t>(nFirstRedline); i+=3)
- {
- OUString sType;
- beans::PropertyValues aRedlineProperties( 3 );
- // skip failed createTextCursorByRange()
- if (redPos[i/3] == -1)
- continue;
- aFootnoteRedlines[i+1] >>= sType;
- aFootnoteRedlines[i+2] >>= aRedlineProperties;
- uno::Reference< text::XTextCursor > xCrsr = xDest->getText()->createTextCursor();
- xCrsr->goRight(redPos[i/3], false);
- xCrsr->goRight(redLen[i/3], true);
- uno::Reference < text::XRedline > xRedline( xCrsr, uno::UNO_QUERY_THROW );
- xRedline->makeRedline( sType, aRedlineProperties );
- }
+ sal_Int32 redIdx;
+ enum StoredRedlines eType = IsInFootnote() ? StoredRedlines::FOOTNOTE : StoredRedlines::ENDNOTE;
+ lcl_CopyRedlines(xSrc, m_aStoredRedlines[eType], redPos, redLen, redIdx);
+ lcl_PasteRedlines(xDest, m_aStoredRedlines[eType], redPos, redLen, redIdx);
// remove processed redlines
- for( size_t i = 0; nFirstRedline > -1 && i <= sal::static_int_cast<size_t>(nFirstRedline) + 2; i++)
- aFootnoteRedlines.pop_front();
+ for( size_t i = 0; redIdx > -1 && i <= sal::static_int_cast<size_t>(redIdx) + 2; i++)
+ m_aStoredRedlines[eType].pop_front();
// remove temporary footnote
xFootnoteFirst->getAnchor()->setString("");
@@ -7055,49 +7090,16 @@ void DomainMapper_Impl::ExecuteFrameConversion()
{
uno::Reference< text::XTextAppendAndConvert > xTextAppendAndConvert( GetTopTextAppend(), uno::UNO_QUERY_THROW );
// convert redline ranges to cursor movement and character length
-
- for( size_t i = 0; i < aFramedRedlines.size(); i+=3)
- {
- uno::Reference< text::XTextRange > xRange;
- aFramedRedlines[i] >>= xRange;
- uno::Reference<text::XTextCursor> xRangeCursor = GetTopTextAppend()->createTextCursorByRange( xRange );
- if (xRangeCursor.is())
- {
- sal_Int32 nLen = xRange->getString().getLength();
- redLen.push_back(nLen);
- xRangeCursor->gotoRange(m_xFrameStartRange, true);
- redPos.push_back(xRangeCursor->getString().getLength() - nLen);
- }
- else
- {
- // failed createTextCursorByRange(), for example, table inside the frame
- redLen.push_back(-1);
- redPos.push_back(-1);
- }
- }
+ sal_Int32 redIdx;
+ lcl_CopyRedlines(GetTopTextAppend(), m_aStoredRedlines[StoredRedlines::FRAME], redPos, redLen, redIdx);
const uno::Reference< text::XTextContent >& xTextContent = xTextAppendAndConvert->convertToTextFrame(
m_xFrameStartRange,
m_xFrameEndRange,
comphelper::containerToSequence(m_aFrameProperties) );
- // create redlines in the previous frame
- for( size_t i = 0; i < aFramedRedlines.size(); i+=3)
- {
- OUString sType;
- beans::PropertyValues aRedlineProperties( 3 );
- // skip failed createTextCursorByRange()
- if (redPos[i/3] == -1)
- continue;
- aFramedRedlines[i+1] >>= sType;
- aFramedRedlines[i+2] >>= aRedlineProperties;
- uno::Reference< text::XTextFrame > xFrame( xTextContent, uno::UNO_QUERY_THROW );
- uno::Reference< text::XTextCursor > xCrsr = xFrame->getText()->createTextCursor();
- xCrsr->goRight(redPos[i/3], false);
- xCrsr->goRight(redLen[i/3], true);
- uno::Reference < text::XRedline > xRedline( xCrsr, uno::UNO_QUERY_THROW );
- xRedline->makeRedline( sType, aRedlineProperties );
- }
+ uno::Reference< text::XText > xDest( xTextContent, uno::UNO_QUERY_THROW );
+ lcl_PasteRedlines(xDest, m_aStoredRedlines[StoredRedlines::FRAME], redPos, redLen, redIdx);
}
catch( const uno::Exception&)
{
@@ -7106,19 +7108,19 @@ void DomainMapper_Impl::ExecuteFrameConversion()
m_bIsActualParagraphFramed = false;
- if (redPos.size() == aFramedRedlines.size()/3)
+ if (redPos.size() == m_aStoredRedlines[StoredRedlines::FRAME].size()/3)
{
- for( sal_Int32 i = aFramedRedlines.size() - 1; i >= 0; --i)
+ for( sal_Int32 i = m_aStoredRedlines[StoredRedlines::FRAME].size() - 1; i >= 0; --i)
{
// keep redlines of floating tables to process them in CloseSectionGroup()
if ( redPos[i/3] != -1 )
{
- aFramedRedlines.erase(aFramedRedlines.begin() + i);
+ m_aStoredRedlines[StoredRedlines::FRAME].erase(m_aStoredRedlines[StoredRedlines::FRAME].begin() + i);
}
}
}
else
- aFramedRedlines.clear();
+ m_aStoredRedlines[StoredRedlines::FRAME].clear();
}
m_xFrameStartRange = nullptr;
m_xFrameEndRange = nullptr;
@@ -7229,7 +7231,7 @@ void DomainMapper_Impl::RemoveTopRedline( )
{
if (m_aRedlines.top().empty())
{
- if (GetFootnoteCount() > -1)
+ if (GetFootnoteCount() > -1 || GetEndnoteCount() > -1)
return;
SAL_WARN("writerfilter.dmapper", "RemoveTopRedline called with empty stack");
throw uno::Exception("RemoveTopRedline failed", nullptr);
@@ -7610,7 +7612,7 @@ void DomainMapper_Impl::substream(Id rName,
break;
case NS_ooxml::LN_footnote:
case NS_ooxml::LN_endnote:
- PopFootOrEndnote( NS_ooxml::LN_footnote == rName );
+ PopFootOrEndnote();
break;
case NS_ooxml::LN_annotation :
PopAnnotation();
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index 8441b4012152..58cf59b0852c 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -125,6 +125,15 @@ enum class SkipFootnoteSeparator
SKIPPING
};
+// type of stored redlines
+enum StoredRedlines
+{
+ FRAME = 0,
+ FOOTNOTE,
+ ENDNOTE,
+ NONE
+};
+
/**
* Storage for state that is relevant outside a header/footer, but not inside it.
*
@@ -520,13 +529,15 @@ private:
} m_eInHeaderFooterImport;
bool m_bDiscardHeaderFooter;
bool m_bInFootOrEndnote;
+ bool m_bInFootnote;
PropertyMapPtr m_pFootnoteContext;
bool m_bHasFootnoteStyle;
bool m_bCheckFootnoteStyle;
/// Skip paragraphs from the <w:separator/> footnote
SkipFootnoteSeparator m_eSkipFootnoteState;
- /// preload footnotes
+ /// preload footnotes and endnotes
sal_Int32 m_nFootnotes;
+ sal_Int32 m_nEndnotes;
bool m_bLineNumberingSet;
bool m_bIsInFootnoteProperties;
@@ -708,6 +719,7 @@ public:
void PopProperties(ContextType eId);
ContextType GetTopContextType() const { return m_aContextStack.top(); }
+ int GetCContext() const { return m_aContextStack.size(); }
const PropertyMapPtr& GetTopContext() const
{
return m_pTopContext;
@@ -792,8 +804,9 @@ public:
bool IsInTOC() const { return m_bStartTOC; }
void PushFootOrEndnote( bool bIsFootnote );
- void PopFootOrEndnote( bool bIsFootnote );
+ void PopFootOrEndnote();
bool IsInFootOrEndnote() const { return m_bInFootOrEndnote; }
+ bool IsInFootnote() const { return m_bInFootnote; }
void StartCustomFootnote(const PropertyMapPtr pContext);
void EndCustomFootnote();
@@ -808,6 +821,8 @@ public:
void SetSkipFootnoteState(SkipFootnoteSeparator eId) { m_eSkipFootnoteState = eId; }
sal_Int32 GetFootnoteCount() const { return m_nFootnotes; }
void IncrementFootnoteCount() { ++m_nFootnotes; }
+ sal_Int32 GetEndnoteCount() const { return m_nEndnotes; }
+ void IncrementEndnoteCount() { ++m_nEndnotes; }
void PushAnnotation();
void PopAnnotation();
@@ -1091,11 +1106,10 @@ public:
/// start/end node.
void ClearPreviousParagraph();
- /// Handle redline text portions in frames:
- /// store their data, and create them after frame creation
+ /// Handle redline text portions in a frame, footnotes and redlines:
+ /// store their data, and create them after frame creation or footnote/endnote copying
bool m_bIsActualParagraphFramed;
- std::vector<css::uno::Any> aFramedRedlines;
- std::deque<css::uno::Any> aFootnoteRedlines;
+ std::deque<css::uno::Any> m_aStoredRedlines[StoredRedlines::NONE];
bool IsParaWithInlineObject() const { return m_bParaWithInlineObject; }
diff --git a/writerfilter/source/dmapper/PropertyMap.cxx b/writerfilter/source/dmapper/PropertyMap.cxx
index 6f8f8d5a9b1e..50af6463fcf1 100644
--- a/writerfilter/source/dmapper/PropertyMap.cxx
+++ b/writerfilter/source/dmapper/PropertyMap.cxx
@@ -1374,7 +1374,7 @@ void SectionPropertyMap::CloseSectionGroup( DomainMapper_Impl& rDM_Impl )
rInfo.m_nBreakType = m_nBreakType;
if ( FloatingTableConversion( rDM_Impl, rInfo ) )
{
- std::vector<css::uno::Any> aFramedRedlines = rDM_Impl.aFramedRedlines;
+ std::deque<css::uno::Any> aFramedRedlines = rDM_Impl.m_aStoredRedlines[StoredRedlines::FRAME];
try
{
// convert redline ranges to cursor movement and character length
diff --git a/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx b/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx
index 938d977d3348..d8b520cb2e1a 100644
--- a/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx
+++ b/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx
@@ -293,8 +293,8 @@ void OOXMLDocumentImpl::resolveEndnote(Stream & rStream,
Id aType,
const sal_Int32 nNoteId)
{
- writerfilter::Reference<Stream>::Pointer_t pStream =
- getXNoteStream(OOXMLStream::ENDNOTES, nNoteId);
+ if (!mpXNoteStream)
+ mpXNoteStream = getXNoteStream(OOXMLStream::ENDNOTES, nNoteId);
Id nId;
switch (aType)
@@ -308,7 +308,7 @@ void OOXMLDocumentImpl::resolveEndnote(Stream & rStream,
break;
}
- resolveFastSubStreamWithId(rStream, pStream, nId);
+ resolveFastSubStreamWithId(rStream, mpXNoteStream, nId);
}
void OOXMLDocumentImpl::resolveComment(Stream & rStream,
diff --git a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
index fe02597775bd..f04391bd95db 100644
--- a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
+++ b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
@@ -166,7 +166,7 @@ void SAL_CALL OOXMLFastContextHandler::startFastElement
mbPreserveSpace = Attribs->getValue(oox::NMSP_xml | oox::XML_space) == "preserve";
mbPreserveSpaceSet = true;
}
- if (Element == W_TOKEN(footnote))
+ if (Element == W_TOKEN(footnote) || Element == W_TOKEN(endnote))
{
// send uFtnSep to sign new footnote content, but skip footnote separators
if (!Attribs->hasAttribute(W_TOKEN(type)) ||