[Libreoffice-commits] core.git: Branch 'distro/collabora/dcm-6.2' - 5 commits - configure.ac sw/inc sw/source

Luboš Luňák (via logerrit) logerrit at kemper.freedesktop.org
Tue Mar 23 15:04:45 UTC 2021


 configure.ac                        |   11 +-
 sw/inc/swtable.hxx                  |    2 
 sw/source/core/inc/fntcache.hxx     |   23 +----
 sw/source/core/table/swtable.cxx    |   48 +++++-----
 sw/source/core/txtnode/fntcache.cxx |  164 +++++++++++++++++++++++-------------
 sw/source/filter/xml/xmltbli.cxx    |    2 
 6 files changed, 150 insertions(+), 100 deletions(-)

New commits:
commit e5c88ce0b91d105d3dc6ba1366de101c0e04e09a
Author:     Luboš Luňák <l.lunak at collabora.com>
AuthorDate: Tue Mar 23 15:52:31 2021 +0100
Commit:     Luboš Luňák <l.lunak at collabora.com>
CommitDate: Tue Mar 23 15:57:13 2021 +0100

    use --enable-ooenv only if --enable-debug/dbgutil
    
    I'm not sure what the original purpose of the ooenv script was,
    but now it contains only debugging settings such as malloc debugging,
    which has a noticeable overhead (8.2s->10.1s in my random case).
    At least openSUSE appears to not actually package the script, but
    it still doesn't make sense to use this script in non-debug builds.
    
    Change-Id: I4518bb1680a543ed520399c11c83dd6dc5539f71

diff --git a/configure.ac b/configure.ac
index 1182bc1c839c..ea6bee87afe4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1184,8 +1184,8 @@ if test "$enable_compiler_plugins" = debug; then
 fi
 
 libo_FUZZ_ARG_ENABLE(ooenv,
-    AS_HELP_STRING([--disable-ooenv],
-        [Disable ooenv for the instdir installation.]))
+    AS_HELP_STRING([--enable-ooenv],
+        [Enable ooenv for the instdir installation.]))
 
 libo_FUZZ_ARG_ENABLE(libnumbertext,
     AS_HELP_STRING([--disable-libnumbertext],
@@ -4652,6 +4652,13 @@ AC_SUBST(ASSERT_ALWAYS_ABORT)
 # ===================================================================
 if test $_os != "WINNT" -a $_os != "Darwin"; then
     AC_MSG_CHECKING([whether to use ooenv for the instdir installation])
+    if test -z "$enable_ooenv"; then
+        if test -n "$ENABLE_DEBUG$ENABLE_DBGUTIL"; then
+            enable_ooenv=yes
+        else
+            enable_ooenv=no
+        fi
+    fi
     if test "$enable_ooenv" = "no"; then
         AC_MSG_RESULT([no])
     else
commit b3c890ad303f16e514ea30a96ec86dacb82b6e41
Author:     Noel Grandin <noel.grandin at collabora.co.uk>
AuthorDate: Thu Mar 28 13:13:22 2019 +0200
Commit:     Luboš Luňák <l.lunak at collabora.com>
CommitDate: Tue Mar 23 15:57:13 2021 +0100

    tdf#84635 quadratic slowdown on loading large tables
    
    skip the re-registration scan in SwTableBox::ChgFrameFormat, which we
    don't need since we are creating this table for the first time
    
    On my machine,
    loading the  69 page file goes from 40.9s to 30.4s
    loading the 128 page file goes from 79.1s to 45.1s
    
    Change-Id: Id9e48256556e19eca34a892b29beff7eab9f51f1
    Reviewed-on: https://gerrit.libreoffice.org/69885
    Reviewed-by: Noel Grandin <noel.grandin at collabora.co.uk>
    Tested-by: Noel Grandin <noel.grandin at collabora.co.uk>

diff --git a/sw/inc/swtable.hxx b/sw/inc/swtable.hxx
index 21348a36662b..844ab31497e0 100644
--- a/sw/inc/swtable.hxx
+++ b/sw/inc/swtable.hxx
@@ -433,7 +433,7 @@ public:
 
     // Creates its own FrameFormat if more boxes depend on it.
     SwFrameFormat* ClaimFrameFormat();
-    void ChgFrameFormat( SwTableBoxFormat *pNewFormat );
+    void ChgFrameFormat( SwTableBoxFormat *pNewFormat, bool bNeedToReregister = true );
 
     void RemoveFromTable();
     const SwStartNode *GetSttNd() const { return m_pStartNode; }
diff --git a/sw/source/core/table/swtable.cxx b/sw/source/core/table/swtable.cxx
index 93f53065a7ca..82e3259e435e 100644
--- a/sw/source/core/table/swtable.cxx
+++ b/sw/source/core/table/swtable.cxx
@@ -1734,36 +1734,40 @@ SwFrameFormat* SwTableBox::ClaimFrameFormat()
     return pRet;
 }
 
-void SwTableBox::ChgFrameFormat( SwTableBoxFormat* pNewFormat )
+void SwTableBox::ChgFrameFormat( SwTableBoxFormat* pNewFormat, bool bNeedToReregister )
 {
     SwFrameFormat *pOld = GetFrameFormat();
     SwIterator<SwCellFrame,SwFormat> aIter( *pOld );
 
+    // tdf#84635 We set bNeedToReregister=false to avoid a quadratic slowdown on loading large tables,
+    // and since we are creating the table for the first time, no re-registration is necessary.
+
     // First, re-register the Frames.
-    for( SwCellFrame* pCell = aIter.First(); pCell; pCell = aIter.Next() )
-    {
-        if( pCell->GetTabBox() == this )
-        {
-            pCell->RegisterToFormat( *pNewFormat );
-            pCell->InvalidateSize();
-            pCell->InvalidatePrt_();
-            pCell->SetCompletePaint();
-            pCell->SetDerivedVert( false );
-            pCell->CheckDirChange();
-
-            // #i47489#
-            // make sure that the row will be formatted, in order
-            // to have the correct Get(Top|Bottom)MarginForLowers values
-            // set at the row.
-            const SwTabFrame* pTab = pCell->FindTabFrame();
-            if ( pTab && pTab->IsCollapsingBorders() )
+    if (bNeedToReregister)
+        for( SwCellFrame* pCell = aIter.First(); pCell; pCell = aIter.Next() )
+        {
+            if( pCell->GetTabBox() == this )
             {
-                SwFrame* pRow = pCell->GetUpper();
-                pRow->InvalidateSize_();
-                pRow->InvalidatePrt_();
+                pCell->RegisterToFormat( *pNewFormat );
+                pCell->InvalidateSize();
+                pCell->InvalidatePrt_();
+                pCell->SetCompletePaint();
+                pCell->SetDerivedVert( false );
+                pCell->CheckDirChange();
+
+                // #i47489#
+                // make sure that the row will be formatted, in order
+                // to have the correct Get(Top|Bottom)MarginForLowers values
+                // set at the row.
+                const SwTabFrame* pTab = pCell->FindTabFrame();
+                if ( pTab && pTab->IsCollapsingBorders() )
+                {
+                    SwFrame* pRow = pCell->GetUpper();
+                    pRow->InvalidateSize_();
+                    pRow->InvalidatePrt_();
+                }
             }
         }
-    }
 
     // Now, re-register self.
     pNewFormat->Add( this );
diff --git a/sw/source/filter/xml/xmltbli.cxx b/sw/source/filter/xml/xmltbli.cxx
index ed73304a7e5d..6ee095903afc 100644
--- a/sw/source/filter/xml/xmltbli.cxx
+++ b/sw/source/filter/xml/xmltbli.cxx
@@ -1921,7 +1921,7 @@ SwTableBoxFormat* SwXMLTableContext::GetSharedBoxFormat(
     {
         // set the shared format
         pBoxFormat2 = aIter->second;
-        pBox->ChgFrameFormat( pBoxFormat2 );
+        pBox->ChgFrameFormat( pBoxFormat2, /*bNeedToReregister*/false );
         bNew = false;   // copied from an existing format
 
         // claim it, if we are not allowed to share
commit c72de55d0b7a26bb06c4e550b2e4c402ea8676bc
Author:     Luboš Luňák <l.lunak at collabora.com>
AuthorDate: Fri Mar 12 14:08:11 2021 +0100
Commit:     Luboš Luňák <l.lunak at collabora.com>
CommitDate: Tue Mar 23 15:57:13 2021 +0100

    do not disable Writer font caching on zoom mismatch
    
    This code disables font caching for some cases, e.g. when exporting
    to PDF if the zoom is set to anything else than 100%, or also when
    loading a document.
    
    It unfortunately comes from the OOo initial import, so it's
    impossible to find out why it should be needed. SwFntObj instances
    are created only using SwFntAccess ctor, which checks any SwFntObj
    it tries to reuse, so if this some additional factor to consider
    when reusing SwFntObj, then it can be checked there. But when I
    remove the code, I cannot see any breakage. Tests pass, normal
    rendering is fine, document thumbnail is fine, printing is fine,
    PDF export is fine, embedding in a spreadsheet is fine.
    
    We had a look at this with Miklos and concluded that it is not
    needed (until proven otherwise, in which case it'll be also known
    why it would be needed).
    
    Change-Id: I59d375229a265a4353c1da6dd067d892dd4ecfb6
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112589
    Tested-by: Jenkins
    Reviewed-by: Luboš Luňák <l.lunak at collabora.com>

diff --git a/sw/source/core/txtnode/fntcache.cxx b/sw/source/core/txtnode/fntcache.cxx
index 206e95340a0f..7cc9cf35714b 100644
--- a/sw/source/core/txtnode/fntcache.cxx
+++ b/sw/source/core/txtnode/fntcache.cxx
@@ -589,24 +589,6 @@ void SwFntObj::CreateScrFont( const SwViewShell& rSh, const OutputDevice& rOut )
         m_pScrFont = m_pPrtFont;
     }
 
-    // check zoom factor, e.g. because of PrtOle2 during export
-    {
-        // In case the zoom factor of the output device differs from the
-        // one in the ViewOptions, this Font must not be cached,
-        // hence set zoom factor to an invalid value
-        long nTmp;
-        if( pOut->GetMapMode().GetScaleX().IsValid() &&
-            pOut->GetMapMode().GetScaleY().IsValid() &&
-            pOut->GetMapMode().GetScaleX() == pOut->GetMapMode().GetScaleY() )
-        {
-            nTmp = long(100 * pOut->GetMapMode().GetScaleX());
-        }
-        else
-            nTmp = 0;
-        if( nTmp != m_nZoom )
-            m_nZoom = USHRT_MAX - 1;
-    }
-
     m_nScrAscent = static_cast<sal_uInt16>(pOut->GetFontMetric().GetAscent());
     if ( USHRT_MAX == m_nScrHeight )
         m_nScrHeight = static_cast<sal_uInt16>(pOut->GetTextHeight());
commit 5ab9cfe16550ab8d439828d766d36a9a8b611c2b
Author:     Luboš Luňák <l.lunak at collabora.com>
AuthorDate: Thu Mar 11 15:34:41 2021 +0100
Commit:     Luboš Luňák <l.lunak at collabora.com>
CommitDate: Tue Mar 23 15:57:13 2021 +0100

    improve font caching in SwFntObj
    
    The code previously cached only SalGlyphItems, but such caching
    fails if SalLayout::GetGlyphs() does not return valid glyphs,
    which is the case with MultiSalLayout. Worse, it not only fails,
    but layout is once computed for caching, that fails, and is computed
    a second time for actual use.
    
    This improved cache caches the result of GetTextWidth(), which
    itself improves the performance a bit, but it also allows caching
    the value for GetGlyph() not returning valid glyphs. Moreover this
    also caches failures to get valid glyphs from GetGlyphs().
    
    There are quite some calls to GetTextArray(), I didn't cache those,
    but it might be added if needed.
    
    Change-Id: Ia2589fb1b778f4f154c88f65d9906584284239da
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112588
    Tested-by: Jenkins
    Reviewed-by: Luboš Luňák <l.lunak at collabora.com>

diff --git a/sw/source/core/inc/fntcache.hxx b/sw/source/core/inc/fntcache.hxx
index 04cfc4abc219..d8e11701445b 100644
--- a/sw/source/core/inc/fntcache.hxx
+++ b/sw/source/core/inc/fntcache.hxx
@@ -60,19 +60,9 @@ extern SwFntCache *pFntCache;
 extern SwFntObj *pLastFont;
 extern sal_uInt8* mnFontCacheIdCounter;
 
-/**
- * Defines a substring on a given output device, to be used as an std::map<>
- * key.
- */
-struct SwTextGlyphsKey
-{
-    VclPtr<OutputDevice> m_pOutputDevice;
-    OUString m_aText;
-    sal_Int32 m_nIndex;
-    sal_Int32 m_nLength;
-
-};
+struct SwTextGlyphsKey;
 bool operator<(const SwTextGlyphsKey& l, const SwTextGlyphsKey& r);
+struct SwTextGlyphsData;
 
 class SwFntObj : public SwCacheObj
 {
@@ -95,8 +85,8 @@ class SwFntObj : public SwCacheObj
     bool m_bSymbol : 1;
     bool m_bPaintBlank : 1;
 
-    /// Cache of already calculated layout glyphs.
-    std::map<SwTextGlyphsKey, SalLayoutGlyphs> m_aTextGlyphs;
+    /// Cache of already calculated layout glyphs and text widths.
+    std::map<SwTextGlyphsKey, SwTextGlyphsData> m_aTextGlyphs;
 
     static long nPixWidth;
     static MapMode *pPixMap;
@@ -125,7 +115,10 @@ public:
     sal_uInt16   GetZoom() const { return m_nZoom; }
     sal_uInt16   GetPropWidth() const { return m_nPropWidth; }
     bool     IsSymbol() const { return m_bSymbol; }
-    std::map<SwTextGlyphsKey, SalLayoutGlyphs>& GetTextGlyphs() { return m_aTextGlyphs; }
+
+    long GetCachedTextWidth(const SwTextGlyphsKey& key, const vcl::TextLayoutCache* vclCache);
+    SalLayoutGlyphs* GetCachedSalLayoutGlyphs(const SwTextGlyphsKey& key);
+    void ClearCachedTextGlyphs();
 
     void   DrawText( SwDrawTextInfo &rInf );
     /// determine the TextSize (of the printer)
diff --git a/sw/source/core/txtnode/fntcache.cxx b/sw/source/core/txtnode/fntcache.cxx
index 500190bf064c..206e95340a0f 100644
--- a/sw/source/core/txtnode/fntcache.cxx
+++ b/sw/source/core/txtnode/fntcache.cxx
@@ -76,6 +76,28 @@ long SwFntObj::nPixWidth;
 MapMode* SwFntObj::pPixMap = nullptr;
 static vcl::DeleteOnDeinit< VclPtr<OutputDevice> > s_pFntObjPixOut( new VclPtr<OutputDevice> );
 
+/**
+ * Defines a substring on a given output device, to be used as an std::map<>
+ * key.
+ */
+struct SwTextGlyphsKey
+{
+    VclPtr<OutputDevice> m_pOutputDevice;
+    OUString m_aText;
+    sal_Int32 m_nIndex;
+    sal_Int32 m_nLength;
+
+};
+
+/**
+ * Glyphs and text width for the given SwTextGlyphsKey.
+ */
+struct SwTextGlyphsData
+{
+    SalLayoutGlyphs m_aTextGlyphs;
+    long m_nTextWidth = -1; // -1 = not computed yet
+};
+
 namespace
 {
 
@@ -98,36 +120,6 @@ long EvalGridWidthAdd( const SwTextGridItem *const pGrid, const SwDrawTextInfo &
     return nGridWidthAdd;
 }
 
-/**
- * Pre-calculates glyph items for the rendered subset of rKey's text, assuming
- * outdev state does not change between the outdev calls.
- */
-SalLayoutGlyphs* lcl_CreateLayout(SwTextGlyphsKey& rKey, SalLayoutGlyphs& rTextGlyphs)
-{
-    // Use pre-calculated result.
-    if (rTextGlyphs.IsValid())
-        return &rTextGlyphs;
-
-    if (rKey.m_nIndex >= rKey.m_aText.getLength())
-        // Same as in OutputDevice::GetTextArray().
-        return nullptr;
-
-    // Calculate glyph items.
-    std::unique_ptr<SalLayout> pLayout
-        = rKey.m_pOutputDevice->ImplLayout(rKey.m_aText, rKey.m_nIndex, rKey.m_nLength, Point(0, 0), 0,
-                                         nullptr, SalLayoutFlags::GlyphItemsOnly);
-    if (!pLayout)
-        return nullptr;
-
-    const SalLayoutGlyphs* pGlyphs = pLayout->GetGlyphs();
-    if (!pGlyphs)
-        return nullptr;
-
-    // Remember the calculation result.
-    rTextGlyphs = *pGlyphs;
-
-    return &rTextGlyphs;
-}
 }
 
 bool operator<(const SwTextGlyphsKey& l, const SwTextGlyphsKey& r)
@@ -228,6 +220,72 @@ void SwFntObj::CreatePrtFont( const OutputDevice& rPrt )
 
 }
 
+/**
+ * Pre-calculates glyph items for the rendered subset of rKey's text, assuming
+ * outdev state does not change between the outdev calls.
+ */
+static SalLayoutGlyphs* lcl_CreateLayout(const SwTextGlyphsKey& rKey, std::map<SwTextGlyphsKey, SwTextGlyphsData>::iterator it)
+{
+    assert (!it->second.m_aTextGlyphs.IsValid());
+
+    if (rKey.m_nIndex >= rKey.m_aText.getLength())
+        // Same as in OutputDevice::GetTextArray().
+        return nullptr;
+
+    // Calculate glyph items.
+    std::unique_ptr<SalLayout> pLayout
+        = rKey.m_pOutputDevice->ImplLayout(rKey.m_aText, rKey.m_nIndex, rKey.m_nLength, Point(0, 0), 0,
+                                         nullptr, SalLayoutFlags::GlyphItemsOnly);
+    if (!pLayout)
+        return nullptr;
+
+    const SalLayoutGlyphs* pGlyphs = pLayout->GetGlyphs();
+    if (!pGlyphs)
+        return nullptr;
+
+    // Remember the calculation result.
+    it->second.m_aTextGlyphs = *pGlyphs;
+
+    return &it->second.m_aTextGlyphs;
+}
+
+SalLayoutGlyphs* SwFntObj::GetCachedSalLayoutGlyphs(const SwTextGlyphsKey& key)
+{
+    std::map<SwTextGlyphsKey, SwTextGlyphsData>::iterator it = m_aTextGlyphs.find(key);
+    if(it != m_aTextGlyphs.end())
+    {
+        if( it->second.m_aTextGlyphs.IsValid())
+            return &it->second.m_aTextGlyphs;
+        // Do not try to create the layout here. If a cache item exists, it's already
+        // been attempted and the layout was invalid (this happens with MultiSalLayout).
+        // So in that case this is a cached failure.
+        return nullptr;
+    }
+    it = m_aTextGlyphs.emplace( key, SwTextGlyphsData()).first;
+    return lcl_CreateLayout(key, it);
+}
+
+long SwFntObj::GetCachedTextWidth(const SwTextGlyphsKey& key, const vcl::TextLayoutCache* vclCache)
+{
+    std::map<SwTextGlyphsKey, SwTextGlyphsData>::iterator it = m_aTextGlyphs.find(key);
+    if(it != m_aTextGlyphs.end() && it->second.m_nTextWidth >= 0)
+        return it->second.m_nTextWidth;
+    if(it == m_aTextGlyphs.end())
+    {
+        it = m_aTextGlyphs.emplace( key, SwTextGlyphsData()).first;
+        lcl_CreateLayout(key, it);
+    }
+    it->second.m_nTextWidth = key.m_pOutputDevice->GetTextWidth(key.m_aText, key.m_nIndex, key.m_nLength, vclCache,
+        it->second.m_aTextGlyphs.IsValid() ? &it->second.m_aTextGlyphs : nullptr );
+    assert(it->second.m_nTextWidth >= 0);
+    return it->second.m_nTextWidth;
+}
+
+void SwFntObj::ClearCachedTextGlyphs()
+{
+    m_aTextGlyphs.clear();
+}
+
 /*
  *  returns whether we have to adjust the output font to resemble
  *  the formatting font
@@ -1458,7 +1516,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
         // get screen array
         std::unique_ptr<long[]> pScrArray(new long[sal_Int32(rInf.GetLen())]);
         SwTextGlyphsKey aGlyphsKey{ &rInf.GetOut(), rInf.GetText(), sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()) };
-        SalLayoutGlyphs* pGlyphs = lcl_CreateLayout(aGlyphsKey, m_aTextGlyphs[aGlyphsKey]);
+        SalLayoutGlyphs* pGlyphs = GetCachedSalLayoutGlyphs(aGlyphsKey);
         rInf.GetOut().GetTextArray( rInf.GetText(), pScrArray.get(),
                         sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), nullptr, pGlyphs);
 
@@ -1473,7 +1531,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
                     m_pPrinter->SetFont( *m_pPrtFont );
             }
             aGlyphsKey = SwTextGlyphsKey{ m_pPrinter, rInf.GetText(), sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()) };
-            pGlyphs = lcl_CreateLayout(aGlyphsKey, m_aTextGlyphs[aGlyphsKey]);
+            pGlyphs = GetCachedSalLayoutGlyphs(aGlyphsKey);
             m_pPrinter->GetTextArray(rInf.GetText(), pKernArray.get(),
                     sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), nullptr, pGlyphs);
         }
@@ -1818,7 +1876,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
                             : sal_Int32(rInf.GetIdx());
                 aGlyphsKey = SwTextGlyphsKey{ &rInf.GetOut(), *pStr, nTmpIdx, nLen };
                 if (bCacheLayout)
-                    pGlyphs = lcl_CreateLayout(aGlyphsKey, m_aTextGlyphs[aGlyphsKey]);
+                    pGlyphs = GetCachedSalLayoutGlyphs(aGlyphsKey);
                 else
                     pGlyphs = nullptr;
                 rInf.GetOut().DrawTextArray( aTextOriginPos, *pStr, pKernArray.get(),
@@ -2055,10 +2113,7 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf )
         else
         {
             SwTextGlyphsKey aGlyphsKey{ &rInf.GetOut(), rInf.GetText(), sal_Int32(rInf.GetIdx()), sal_Int32(nLn) };
-            SalLayoutGlyphs* pGlyphs = lcl_CreateLayout(aGlyphsKey, m_aTextGlyphs[aGlyphsKey]);
-            aTextSize.setWidth( rInf.GetOut().GetTextWidth( rInf.GetText(),
-                                   sal_Int32(rInf.GetIdx()), sal_Int32(nLn),
-                                                           rInf.GetVclCache(), pGlyphs) );
+            aTextSize.setWidth( GetCachedTextWidth(aGlyphsKey, rInf.GetVclCache()));
             rInf.SetKanaDiff( 0 );
         }
 
@@ -2092,7 +2147,7 @@ TextFrameIndex SwFntObj::GetCursorOfst(SwDrawTextInfo &rInf)
         m_pPrinter->SetLayoutMode( rInf.GetOut().GetLayoutMode() );
         m_pPrinter->SetDigitLanguage( rInf.GetOut().GetDigitLanguage() );
         SwTextGlyphsKey aGlyphsKey{ m_pPrinter, rInf.GetText(), sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()) };
-        SalLayoutGlyphs* pGlyphs = lcl_CreateLayout(aGlyphsKey, m_aTextGlyphs[aGlyphsKey]);
+        SalLayoutGlyphs* pGlyphs = GetCachedSalLayoutGlyphs(aGlyphsKey);
         m_pPrinter->GetTextArray( rInf.GetText(), pKernArray.get(),
                 sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), nullptr, pGlyphs);
     }
@@ -2506,8 +2561,7 @@ TextFrameIndex SwFont::GetTextBreak(SwDrawTextInfo const & rInf, long nTextWidth
             SwFntAccess aFntAccess(m_aSub[m_nActual].m_nFontCacheId, m_aSub[m_nActual].m_nFontIndex,
                                    &m_aSub[m_nActual], rInf.GetShell());
             SwTextGlyphsKey aGlyphsKey{ &rInf.GetOut(), *pTmpText, sal_Int32(nTmpIdx), sal_Int32(nTmpLen) };
-            SalLayoutGlyphs* pGlyphs
-                = lcl_CreateLayout(aGlyphsKey, aFntAccess.Get()->GetTextGlyphs()[aGlyphsKey]);
+            SalLayoutGlyphs* pGlyphs = aFntAccess.Get()->GetCachedSalLayoutGlyphs(aGlyphsKey);
             nTextBreak = TextFrameIndex(rInf.GetOut().GetTextBreak(
                              *pTmpText, nTextWidth,
                              sal_Int32(nTmpIdx), sal_Int32(nTmpLen),
@@ -2699,7 +2753,7 @@ bool SwDrawTextInfo::ApplyAutoColor( vcl::Font* pFont )
 void SwClearFntCacheTextGlyphs()
 {
     for (SwFntObj* pFntObj = pFntCache->First(); pFntObj; pFntObj = SwFntCache::Next(pFntObj))
-        pFntObj->GetTextGlyphs().clear();
+        pFntObj->ClearCachedTextGlyphs();
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 7645b367e51832473f1ed4e19b96dd9b15fb3e1b
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Fri Mar 22 13:51:39 2019 +0100
Commit:     Luboš Luňák <l.lunak at collabora.com>
CommitDate: Mon Mar 22 21:00:57 2021 +0100

    Related: tdf#124109 sw: save one vcl layout call in SwFntObj::DrawText()
    
    Commit 436b829f5b904d76039db0818cff5dedf1ae89f1 (sw: save one vcl layout
    call in SwFntObj::DrawText(), 2018-08-16) did this unconditionally,
    which broke kashida justification. Re-introduce the same mechanism, but
    this time opt out in the kashida case to keep that working.
    
    This means that for Latin scripts we are back to 2 layout calls (instead
    of 3) for each keypress in Writer.
    
    Change-Id: I890f0ab04d1f5dce561f1536d7c8a6d67a639813
    Reviewed-on: https://gerrit.libreoffice.org/69557
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>
    Tested-by: Jenkins

diff --git a/sw/source/core/txtnode/fntcache.cxx b/sw/source/core/txtnode/fntcache.cxx
index 175821ab90ef..500190bf064c 100644
--- a/sw/source/core/txtnode/fntcache.cxx
+++ b/sw/source/core/txtnode/fntcache.cxx
@@ -1487,6 +1487,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
 
         long nSpaceAdd = rInf.GetSpace() / SPACING_PRECISION_FACTOR;
         bool bNoHalfSpace = false;
+        bool bCacheLayout = true;
 
         if ( rInf.GetFont() && rInf.GetLen() )
         {
@@ -1529,7 +1530,12 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
                     if ( pSI && pSI->CountKashida() &&
                          pSI->KashidaJustify( pKernArray.get(), pScrArray.get(), rInf.GetIdx(),
                                               rInf.GetLen(), nSpaceAdd ) != -1 )
+                    {
                         nSpaceAdd = 0;
+                        // Layout can't be reused in this case, it would lead to missing gaps in
+                        // place of kashida.
+                        bCacheLayout = false;
+                    }
                     else
                         bNoHalfSpace = true;
                 }
@@ -1811,8 +1817,12 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
                             ? (rInf.GetIdx() ? 1 : 0)
                             : sal_Int32(rInf.GetIdx());
                 aGlyphsKey = SwTextGlyphsKey{ &rInf.GetOut(), *pStr, nTmpIdx, nLen };
+                if (bCacheLayout)
+                    pGlyphs = lcl_CreateLayout(aGlyphsKey, m_aTextGlyphs[aGlyphsKey]);
+                else
+                    pGlyphs = nullptr;
                 rInf.GetOut().DrawTextArray( aTextOriginPos, *pStr, pKernArray.get(),
-                                             nTmpIdx , nLen );
+                                             nTmpIdx , nLen, SalLayoutFlags::NONE, pGlyphs );
                 if (bBullet)
                 {
                     rInf.GetOut().Push();


More information about the Libreoffice-commits mailing list