diff options
author | Luboš Luňák <l.lunak@collabora.com> | 2022-04-12 18:21:35 +0200 |
---|---|---|
committer | Luboš Luňák <l.lunak@collabora.com> | 2022-04-12 22:16:05 +0200 |
commit | e3830b06a9886620ed432a011d2de2abbb7a3a12 (patch) | |
tree | 7eb233e55e8c13df3f9186d839e3a4a946587e7e | |
parent | efb60b6fb5e11c31fecddf1e0502c1fe4feb7b57 (diff) |
don't FormatDoc() a whole long text if not necessary (tdf#144515)
The testcase has a very long text in a cell that is really high
enough to hold only one line of text, yet EditEngine formats and
wraps the entire string. Which can be expensive because of calling
into text layout to find out width of a text portion, and this
is done repeatedly for the yet-unformatted text, so pretty much
O(N^2). For top-aligned text it's enough to format only as much
as will fit and ignore the rest, so implement that and add
EditEngine::EnableSkipOutsideFormat() to enable the optimization.
Change-Id: Ida87a1843737a368798ba2b3e60eedc99ee0f611
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132932
Tested-by: Jenkins
Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
-rw-r--r-- | editeng/source/editeng/editeng.cxx | 5 | ||||
-rw-r--r-- | editeng/source/editeng/impedit.hxx | 3 | ||||
-rw-r--r-- | editeng/source/editeng/impedit2.cxx | 1 | ||||
-rw-r--r-- | editeng/source/editeng/impedit3.cxx | 21 | ||||
-rw-r--r-- | include/editeng/editeng.hxx | 4 | ||||
-rw-r--r-- | sc/source/ui/view/output2.cxx | 5 |
6 files changed, 38 insertions, 1 deletions
diff --git a/editeng/source/editeng/editeng.cxx b/editeng/source/editeng/editeng.cxx index eb7d1ad5a6fa..237c78264e72 100644 --- a/editeng/source/editeng/editeng.cxx +++ b/editeng/source/editeng/editeng.cxx @@ -2856,6 +2856,11 @@ void EditEngine::DisableAttributeExpanding() { pImpEditEngine->GetEditDoc().DisableAttributeExpanding(); } +void EditEngine::EnableSkipOutsideFormat(bool set) +{ + pImpEditEngine->EnableSkipOutsideFormat(set); +} + void EditEngine::SetLOKSpecialPaperSize(const Size& rSize) { pImpEditEngine->SetLOKSpecialPaperSize(rSize); diff --git a/editeng/source/editeng/impedit.hxx b/editeng/source/editeng/impedit.hxx index 894bb822f676..e66988d60e0c 100644 --- a/editeng/source/editeng/impedit.hxx +++ b/editeng/source/editeng/impedit.hxx @@ -604,6 +604,7 @@ private: bool bFirstWordCapitalization:1; // specifies if auto-correction should capitalize the first word or not bool mbLastTryMerge:1; bool mbReplaceLeadingSingleQuotationMark:1; + bool mbSkipOutsideFormat:1; bool mbNbspRunNext; // can't be a bitfield as it is passed as bool& @@ -1131,6 +1132,8 @@ public: /** Whether last AutoCorrect inserted a NO-BREAK SPACE that may need to be removed again. */ bool IsNbspRunNext() const { return mbNbspRunNext; } + void EnableSkipOutsideFormat(bool set) { mbSkipOutsideFormat = set; } + void Dispose(); void SetLOKSpecialPaperSize(const Size& rSize) { aLOKSpecialPaperSize = rSize; } const Size& GetLOKSpecialPaperSize() const { return aLOKSpecialPaperSize; } diff --git a/editeng/source/editeng/impedit2.cxx b/editeng/source/editeng/impedit2.cxx index 4b7b3490d138..94cc2d479b36 100644 --- a/editeng/source/editeng/impedit2.cxx +++ b/editeng/source/editeng/impedit2.cxx @@ -123,6 +123,7 @@ ImpEditEngine::ImpEditEngine( EditEngine* pEE, SfxItemPool* pItemPool ) : bFirstWordCapitalization(true), mbLastTryMerge(false), mbReplaceLeadingSingleQuotationMark(true), + mbSkipOutsideFormat(false), mbNbspRunNext(false) { aStatus.GetControlWord() = EEControlBits::USECHARATTRIBS | EEControlBits::DOIDLEFORMAT | diff --git a/editeng/source/editeng/impedit3.cxx b/editeng/source/editeng/impedit3.cxx index cdcc05100730..372237ff9c70 100644 --- a/editeng/source/editeng/impedit3.cxx +++ b/editeng/source/editeng/impedit3.cxx @@ -621,10 +621,18 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) return FinishCreateLines( &rParaPortion ); } + sal_Int64 nCurrentPosY = nStartPosY; + // If we're allowed to skip parts outside and this cannot possibly fit in the given height, + // bail out to avoid possibly formatting a lot of text that will not be used. For the first + // paragraph still format at least a bit. + if( mbSkipOutsideFormat && nPara != 0 + && !aStatus.AutoPageHeight() && aPaperSize.Height() < nCurrentPosY ) + { + return false; + } // Initialization... - // Always format for 100%: bool bMapChanged = ImpCheckRefMapMode(); @@ -1607,6 +1615,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) // as nEnd points to the last character! sal_Int32 nEndPortion = pLine->GetEndPortion(); + nCurrentPosY += pLine->GetHeight(); // Next line or maybe a new line... pLine = nullptr; @@ -1617,6 +1626,16 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) nDelFromLine = nLine; break; } + // Stop processing if allowed and this is outside of the paper size height. + // Format at least two lines though, in case something detects whether + // the text has been wrapped or something similar. + if( mbSkipOutsideFormat && nLine > 2 + && !aStatus.AutoPageHeight() && aPaperSize.Height() < nCurrentPosY ) + { + if ( pLine && ( nIndex >= pNode->Len()) ) + nDelFromLine = nLine; + break; + } if ( !pLine ) { if ( nIndex < pNode->Len() ) diff --git a/include/editeng/editeng.hxx b/include/editeng/editeng.hxx index 560f3be1a83a..9bce76b98031 100644 --- a/include/editeng/editeng.hxx +++ b/include/editeng/editeng.hxx @@ -638,6 +638,10 @@ public: // spell check dialog doesn't want that behaviour void DisableAttributeExpanding(); + // Optimization, if set, formatting will be done only for text lines that fit + // in given paper size and exceeding lines will be ignored. + void EnableSkipOutsideFormat(bool set); + void SetLOKSpecialPaperSize(const Size& rSize); const Size& GetLOKSpecialPaperSize() const; diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx index e7bed3f92790..a507e1da8452 100644 --- a/sc/source/ui/view/output2.cxx +++ b/sc/source/ui/view/output2.cxx @@ -2169,6 +2169,7 @@ static void lcl_ClearEdit( EditEngine& rEngine ) // text and attributes if (rPara.Count()) rEngine.SetParaAttribs( 0, SfxItemSet( *rPara.GetPool(), rPara.GetRanges() ) ); + rEngine.EnableSkipOutsideFormat(false); } static bool lcl_SafeIsValue( ScRefCellValue& rCell ) @@ -2920,6 +2921,10 @@ void ScOutputData::DrawEditStandard(DrawEditParam& rParam) rParam.setPatternToEngine(mbUseStyleColor); rParam.setAlignmentToEngine(); + // Don't format unnecessary parts if the text will be drawn from top (Standard will + // act that way if text doesn't fit, see below). + rParam.mpEngine->EnableSkipOutsideFormat(rParam.meVerJust==SvxCellVerJustify::Top + || rParam.meVerJust==SvxCellVerJustify::Standard); // Read content from cell |