editeng/source/editeng/editeng.cxx  |    5 +++++
 editeng/source/editeng/impedit.hxx  |    3 +++
 editeng/source/editeng/impedit2.cxx |    1 +
 editeng/source/editeng/impedit3.cxx |   21 ++++++++++++++++++++-
 include/editeng/editeng.hxx         |    4 ++++
 sc/source/ui/view/output2.cxx       |    5 +++++
 6 files changed, 38 insertions(+), 1 deletion(-)

New commits:
commit e3830b06a9886620ed432a011d2de2abbb7a3a12
Author:     Luboš Luňák <l.lu...@collabora.com>
AuthorDate: Tue Apr 12 18:21:35 2022 +0200
Commit:     Luboš Luňák <l.lu...@collabora.com>
CommitDate: Tue Apr 12 22:16:05 2022 +0200

    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.lu...@collabora.com>

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
 

Reply via email to