[Libreoffice-commits] core.git: include/vcl vcl/source
merttumer (via logerrit)
logerrit at kemper.freedesktop.org
Wed Jul 7 06:06:32 UTC 2021
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.tumer at collabora.com>
AuthorDate: Wed Jun 16 21:04:33 2021 +0300
Commit: Mert Tumer <mert.tumer at 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.tumer at collabora.com>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117362
Reviewed-by: Michael Meeks <michael.meeks at collabora.com>
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at 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: */
More information about the Libreoffice-commits
mailing list