include/vcl/outdev.hxx         |    2 
 vcl/source/outdev/textline.cxx |  103 +++++++++++++++++++++++++++++++++++++++--
 2 files changed, 102 insertions(+), 3 deletions(-)

New commits:
commit 0759191e6923945469bc426b2c322ddeade12e09
Author:     merttumer <mert.tu...@collabora.com>
AuthorDate: Wed Jun 16 21:04:33 2021 +0300
Commit:     Mert Tumer <mert.tu...@collabora.com>
CommitDate: Wed Jul 7 08:05:58 2021 +0200

    Cache a static wavy line as bitmap and reuse it
    
    DrawWaveLine is cpu costly so render it as big as
    possible so we can only crop it
    Edit:
    1) Moved the Cache class to textline.cxx file
    as it is local to that
    2) Provided a custom hash method for the unordered_map
    to avoid double hashing the key. Used boost:hash_combine
    for hashing.
    3) changed unordered_map to o3tl::lru_map
    
    Change-Id: I0ab191f7bb72ccd5074c78858de9831c1a462b7b
    Signed-off-by: merttumer <mert.tu...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117362
    Reviewed-by: Michael Meeks <michael.me...@collabora.com>
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117969
    Tested-by: Jenkins

diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx
index ac688f5f2556..eb3c7815450a 100644
--- a/include/vcl/outdev.hxx
+++ b/include/vcl/outdev.hxx
@@ -752,6 +752,8 @@ private:
     SAL_DLLPRIVATE void         ImplDrawPolyPolygonWithB2DPolyPolygon(const 
basegfx::B2DPolyPolygon& rB2DPolyPoly);
     ///@}
 
+    SAL_DLLPRIVATE void         ImplDrawWaveLineBezier(tools::Long nStartX, 
tools::Long nStartY, tools::Long nEndX, tools::Long nEndY, tools::Long 
nWaveHeight, double fOrientation, tools::Long nLineWidth);
+
 
     /** @name Curved shape functions
      */
diff --git a/vcl/source/outdev/textline.cxx b/vcl/source/outdev/textline.cxx
index 046952cf403a..8b22aa8fb847 100644
--- a/vcl/source/outdev/textline.cxx
+++ b/vcl/source/outdev/textline.cxx
@@ -25,6 +25,7 @@
 #include <vcl/outdev.hxx>
 #include <vcl/settings.hxx>
 #include <vcl/virdev.hxx>
+#include <vcl/lazydelete.hxx>
 
 #include <tools/helpers.hxx>
 
@@ -33,10 +34,72 @@
 
 #include <basegfx/matrix/b2dhommatrixtools.hxx>
 #include <basegfx/polygon/WaveLine.hxx>
+#include <boost/functional/hash.hpp>
+#include <o3tl/lru_map.hxx>
 
 #define UNDERLINE_LAST      LINESTYLE_BOLDWAVE
 #define STRIKEOUT_LAST      STRIKEOUT_X
 
+namespace {
+    struct WavyLineCache final
+    {
+        WavyLineCache () : m_aItems( 10 ) {}
+
+        bool find( Color aLineColor, size_t nLineWidth, size_t nWaveHeight, 
size_t nWordWidth, BitmapEx& rOutput )
+        {
+            Key aKey = { nWaveHeight, sal_uInt32(aLineColor) };
+            auto item = m_aItems.find( aKey );
+            if ( item == m_aItems.end() )
+                return false;
+            // needs update
+            if ( item->second.m_aLineWidth != nLineWidth || 
item->second.m_aWordWidth < nWordWidth )
+            {
+                return false;
+            }
+            rOutput = item->second.m_Bitmap;
+            return true;
+        }
+
+        void insert( const BitmapEx& aBitmap, const Color& aLineColor, const 
size_t nLineWidth, const size_t nWaveHeight, const size_t nWordWidth, BitmapEx& 
rOutput )
+        {
+            Key aKey = { nWaveHeight, sal_uInt32(aLineColor) };
+            m_aItems.insert( std::pair< Key, WavyLineCacheItem>( aKey, { 
nLineWidth, nWordWidth, aBitmap } ) );
+            rOutput = aBitmap;
+        }
+
+        private:
+        struct WavyLineCacheItem
+        {
+            size_t m_aLineWidth;
+            size_t m_aWordWidth;
+            BitmapEx m_Bitmap;
+        };
+
+        struct Key
+        {
+            size_t m_aFirst;
+            size_t m_aSecond;
+            bool operator ==( const Key& rOther ) const
+            {
+                return ( m_aFirst == rOther.m_aFirst && m_aSecond == 
rOther.m_aSecond );
+            }
+        };
+
+        struct Hash
+        {
+            size_t operator() ( const Key& rKey ) const
+            {
+                size_t aSeed = 0;
+                boost::hash_combine(aSeed, rKey.m_aFirst);
+                boost::hash_combine(aSeed, rKey.m_aSecond);
+                return aSeed;
+            }
+        };
+
+        o3tl::lru_map< Key, WavyLineCacheItem, Hash > m_aItems;
+    };
+}
+
 void OutputDevice::ImplInitTextLineSize()
 {
     mpFontInstance->mxFontMetric->ImplInitTextLineSize( this );
@@ -1002,6 +1065,43 @@ void OutputDevice::DrawWaveLine(const Point& rStartPos, 
const Point& rEndPos, to
         nLineWidth = 0;
     }
 
+    if ( fOrientation == 0.0 )
+    {
+        static vcl::DeleteOnDeinit< WavyLineCache > snLineCache( new 
WavyLineCache() );
+        if ( !snLineCache.get() )
+            return;
+        WavyLineCache& rLineCache = *snLineCache.get();
+        BitmapEx aWavylinebmp;
+        if ( !rLineCache.find( GetLineColor(), nLineWidth, nWaveHeight, nEndX 
- nStartX, aWavylinebmp ) )
+        {
+            size_t nWordLength = nEndX - nStartX;
+            // start with something big to avoid updating it frequently
+            nWordLength = nWordLength < 1024 ? 1024 : nWordLength;
+            ScopedVclPtrInstance< VirtualDevice > pVirtDev( *this, 
DeviceFormat::DEFAULT,
+                                                           
DeviceFormat::DEFAULT );
+            pVirtDev->SetAntialiasing( AntialiasingFlags::Enable );
+            pVirtDev->SetOutputSizePixel( Size( nWordLength, nWaveHeight * 2 
), false );
+            pVirtDev->SetLineColor( GetLineColor() );
+            pVirtDev->SetBackground( Wallpaper( COL_TRANSPARENT ) );
+            pVirtDev->ImplDrawWaveLineBezier( 0, 0, nWordLength, 0, 
nWaveHeight, fOrientation, nLineWidth );
+            rLineCache.insert( pVirtDev->GetBitmapEx( Point( 0, 0 ), 
pVirtDev->GetOutputSize() ), GetLineColor(), nLineWidth, nWaveHeight, 
nWordLength, aWavylinebmp );
+        }
+        if ( aWavylinebmp.ImplGetBitmapSalBitmap() != nullptr )
+        {
+            Size _size( nEndX - nStartX, aWavylinebmp.GetSizePixel().Height() 
);
+            DrawBitmapEx(Point( rStartPos.X(), rStartPos.Y() ), PixelToLogic( 
_size ), Point(), _size, aWavylinebmp);
+        }
+        return;
+    }
+
+    ImplDrawWaveLineBezier( nStartX, nStartY, nEndX, nEndY, nWaveHeight, 
fOrientation, nLineWidth );
+
+    if( mpAlphaVDev )
+        mpAlphaVDev->DrawWaveLine( rStartPos, rEndPos, nLineWidth );
+}
+
+void OutputDevice::ImplDrawWaveLineBezier(tools::Long nStartX, tools::Long 
nStartY, tools::Long nEndX, tools::Long nEndY, tools::Long nWaveHeight, double 
fOrientation, tools::Long nLineWidth)
+{
     const basegfx::B2DRectangle aWaveLineRectangle(nStartX, nStartY, nEndX, 
nEndY + nWaveHeight);
     const basegfx::B2DPolygon aWaveLinePolygon = 
basegfx::createWaveLinePolygon(aWaveLineRectangle);
     const basegfx::B2DHomMatrix aRotationMatrix = 
basegfx::utils::createRotateAroundPoint(nStartX, nStartY, 
basegfx::deg2rad(-fOrientation));
@@ -1019,9 +1119,6 @@ void OutputDevice::DrawWaveLine(const Point& rStartPos, 
const Point& rEndPos, to
             basegfx::deg2rad(15.0),
             bPixelSnapHairline,
             *this);
-
-    if( mpAlphaVDev )
-        mpAlphaVDev->DrawWaveLine( rStartPos, rEndPos, nLineWidth );
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to