[Libreoffice-commits] core.git: sw/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Mon Sep 3 07:13:53 UTC 2018


 sw/source/core/inc/fntcache.hxx     |   20 ++++++++++++
 sw/source/core/txtnode/fntcache.cxx |   56 +++++++++++++++++++++++++-----------
 2 files changed, 60 insertions(+), 16 deletions(-)

New commits:
commit aeff83240c88435d11590f5e9c6fe9927a508c6a
Author:     Miklos Vajna <vmiklos at collabora.co.uk>
AuthorDate: Fri Aug 31 18:19:12 2018 +0200
Commit:     Miklos Vajna <vmiklos at collabora.co.uk>
CommitDate: Mon Sep 3 09:13:32 2018 +0200

    sw: save more vcl layout calls in SwFntObj
    
    This builds on top of commit 436b829f5b904d76039db0818cff5dedf1ae89f1
    (sw: save one vcl layout call in SwFntObj::DrawText(), 2018-08-16), but
    now layouts are shared not only inside SwFntObj::DrawText(), but also
    between SwFntObj::GetTextSize() and SwFntObj::DrawText().
    
    To get there, create an SwFntObj cache member that stores already
    calculated vcl layouts. SwFntObj already derives from SwCacheObj, so no
    need to explicitly expire this cache member.
    
    Total number of GenericSalLayout::LayoutText() invocations go down from
    8 to 5 with this when pressing a key in Writer.
    
    Change-Id: Ifbe84a5c00025604f9c1331b56074b3dc27864b5
    Reviewed-on: https://gerrit.libreoffice.org/59879
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>

diff --git a/sw/source/core/inc/fntcache.hxx b/sw/source/core/inc/fntcache.hxx
index 9edfd6d0e17b..9bf8024c9f72 100644
--- a/sw/source/core/inc/fntcache.hxx
+++ b/sw/source/core/inc/fntcache.hxx
@@ -20,8 +20,11 @@
 #ifndef INCLUDED_SW_SOURCE_CORE_INC_FNTCACHE_HXX
 #define INCLUDED_SW_SOURCE_CORE_INC_FNTCACHE_HXX
 
+#include <map>
+
 #include <vcl/font.hxx>
 #include <vcl/vclptr.hxx>
+#include <vcl/vcllayout.hxx>
 #include <swtypes.hxx>
 #include "swcache.hxx"
 #include "TextFrameIndex.hxx"
@@ -54,6 +57,20 @@ extern SwFntCache *pFntCache;
 extern SwFntObj *pLastFont;
 extern sal_uInt8 *pMagicNo;
 
+/**
+ * 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;
+
+};
+bool operator<(const SwTextGlyphsKey& l, const SwTextGlyphsKey& r);
+
 class SwFntObj : public SwCacheObj
 {
     friend class SwFntAccess;
@@ -75,6 +92,9 @@ class SwFntObj : public SwCacheObj
     bool m_bSymbol : 1;
     bool m_bPaintBlank : 1;
 
+    /// Cache of already calculated layout glyphs.
+    std::map<SwTextGlyphsKey, SalLayoutGlyphs> m_aTextGlyphs;
+
     static long nPixWidth;
     static MapMode *pPixMap;
 
diff --git a/sw/source/core/txtnode/fntcache.cxx b/sw/source/core/txtnode/fntcache.cxx
index 49b1224501ed..2845d223db86 100644
--- a/sw/source/core/txtnode/fntcache.cxx
+++ b/sw/source/core/txtnode/fntcache.cxx
@@ -98,23 +98,23 @@ long EvalGridWidthAdd( const SwTextGridItem *const pGrid, const SwDrawTextInfo &
 }
 
 /**
- * Pre-calculates glyph items for the rendered subset of rInf's text, assuming
+ * 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(SwDrawTextInfo& rInf, const OUString& rText, sal_Int32 nIdx,
-                                  sal_Int32 nLen, SalLayoutGlyphs& rTextGlyphs)
+SalLayoutGlyphs* lcl_CreateLayout(SwTextGlyphsKey& rKey, SalLayoutGlyphs& rTextGlyphs)
 {
-    // Not the string we want to pre-calculate.
-    if (rText != rInf.GetText() || nIdx != rInf.GetIdx() || nLen != rInf.GetLen())
-        return nullptr;
-
     // Use pre-calculated result.
     if (!rTextGlyphs.empty())
         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 = rInf.GetOut().ImplLayout(
-        rText, nIdx, nLen, Point(0, 0), 0, nullptr, SalLayoutFlags::GlyphItemsOnly);
+    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;
 
@@ -129,6 +129,27 @@ SalLayoutGlyphs* lcl_CreateLayout(SwDrawTextInfo& rInf, const OUString& rText, s
 }
 }
 
+bool operator<(const SwTextGlyphsKey& l, const SwTextGlyphsKey& r)
+{
+    if (l.m_pOutputDevice.get() < r.m_pOutputDevice.get())
+        return true;
+    if (l.m_pOutputDevice.get() > r.m_pOutputDevice.get())
+        return false;
+    if (l.m_aText < r.m_aText)
+        return true;
+    if (l.m_aText > r.m_aText)
+        return false;
+    if (l.m_nIndex < r.m_nIndex)
+        return true;
+    if (l.m_nIndex > r.m_nIndex)
+        return false;
+    if (l.m_nLength < r.m_nLength)
+        return true;
+    if (l.m_nLength > r.m_nLength)
+        return false;
+    return false;
+};
+
 void SwFntCache::Flush( )
 {
     if ( pLastFont )
@@ -810,8 +831,6 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
 
     vcl::Font* pTmpFont = bUseScrFont ? m_pScrFont : m_pPrtFont;
 
-    SalLayoutGlyphs aTextGlyphs;
-
     //  bDirectPrint and bUseScrFont should have these values:
 
     //  Outdev / RefDef  | Printer | VirtPrinter | Window
@@ -1426,8 +1445,8 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
 
         // get screen array
         std::unique_ptr<long[]> pScrArray(new long[sal_Int32(rInf.GetLen())]);
-        SalLayoutGlyphs* pGlyphs = lcl_CreateLayout(rInf, rInf.GetText(), sal_Int32(rInf.GetIdx()),
-                                                    sal_Int32(rInf.GetLen()), aTextGlyphs);
+        SwTextGlyphsKey aGlyphsKey{ &rInf.GetOut(), rInf.GetText(), rInf.GetIdx(), rInf.GetLen() };
+        SalLayoutGlyphs* pGlyphs = lcl_CreateLayout(aGlyphsKey, m_aTextGlyphs[aGlyphsKey]);
         rInf.GetOut().GetTextArray( rInf.GetText(), pScrArray.get(),
                         sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), nullptr, pGlyphs);
 
@@ -1441,8 +1460,10 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
                 if( !m_pPrtFont->IsSameInstance( m_pPrinter->GetFont() ) )
                     m_pPrinter->SetFont( *m_pPrtFont );
             }
+            aGlyphsKey = SwTextGlyphsKey{ m_pPrinter, rInf.GetText(), rInf.GetIdx(), rInf.GetLen() };
+            pGlyphs = lcl_CreateLayout(aGlyphsKey, m_aTextGlyphs[aGlyphsKey]);
             m_pPrinter->GetTextArray(rInf.GetText(), pKernArray.get(),
-                    sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()));
+                    sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), nullptr, pGlyphs);
         }
         else
         {
@@ -1778,7 +1799,8 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
                 sal_Int32 nTmpIdx = bBullet
                             ? (rInf.GetIdx() ? 1 : 0)
                             : sal_Int32(rInf.GetIdx());
-                pGlyphs = lcl_CreateLayout(rInf, *pStr, nTmpIdx, nLen, aTextGlyphs);
+                aGlyphsKey = SwTextGlyphsKey{ &rInf.GetOut(), *pStr, nTmpIdx, nLen };
+                pGlyphs = lcl_CreateLayout(aGlyphsKey, m_aTextGlyphs[aGlyphsKey]);
                 rInf.GetOut().DrawTextArray( aTextOriginPos, *pStr, pKernArray.get(),
                                              nTmpIdx , nLen, SalLayoutFlags::NONE, nullptr, pGlyphs );
                 if (bBullet)
@@ -2012,9 +2034,11 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf )
         }
         else
         {
+            SwTextGlyphsKey aGlyphsKey{ &rInf.GetOut(), rInf.GetText(), rInf.GetIdx(), 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()) );
+                                                           rInf.GetVclCache(), pGlyphs) );
             rInf.SetKanaDiff( 0 );
         }
 


More information about the Libreoffice-commits mailing list