move cache for SalLayoutGlyph's from Calc to VCL
For reuse later. Change-Id: I43479148a8312a36e56f267435e77acc8bf9bd35 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131390 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
This commit is contained in:
parent
ef82ccdda9
commit
3e3ef58be1
3 changed files with 114 additions and 49 deletions
69
include/vcl/glyphitemcache.hxx
Normal file
69
include/vcl/glyphitemcache.hxx
Normal file
|
@ -0,0 +1,69 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* This file incorporates work covered by the following license notice:
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed
|
||||
* with this work for additional information regarding copyright
|
||||
* ownership. The ASF licenses this file to you under the Apache
|
||||
* License, Version 2.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_VCL_GLYPHITEMCACHE_HXX
|
||||
#define INCLUDED_VCL_GLYPHITEMCACHE_HXX
|
||||
|
||||
#include <sal/types.h>
|
||||
#include <vcl/dllapi.h>
|
||||
|
||||
#include <o3tl/lru_map.hxx>
|
||||
#include <o3tl/hash_combine.hxx>
|
||||
#include <vcl/glyphitem.hxx>
|
||||
|
||||
/**
|
||||
A cache for SalLayoutGlyphs objects.
|
||||
|
||||
Allows caching for OutputDevice::DrawText() and similar calls. Pass the text and the output device
|
||||
for the call to OutputDevice::ImplLayout(). Items are cached per output device and its font.
|
||||
If something more changes, call clear().
|
||||
*/
|
||||
class VCL_DLLPUBLIC SalLayoutGlyphsCache final
|
||||
{
|
||||
public:
|
||||
SalLayoutGlyphsCache(int size = 1000)
|
||||
: mCachedGlyphs(size)
|
||||
{
|
||||
}
|
||||
const SalLayoutGlyphs* GetLayoutGlyphs(const OUString& text,
|
||||
VclPtr<OutputDevice> outputDevice) const;
|
||||
void clear() { mCachedGlyphs.clear(); }
|
||||
|
||||
private:
|
||||
struct CachedGlyphsKey
|
||||
{
|
||||
OUString text;
|
||||
VclPtr<OutputDevice> outputDevice;
|
||||
size_t hashValue;
|
||||
CachedGlyphsKey(const OUString& t, const VclPtr<OutputDevice>& dev);
|
||||
bool operator==(const CachedGlyphsKey& other) const;
|
||||
};
|
||||
struct CachedGlyphsHash
|
||||
{
|
||||
size_t operator()(const CachedGlyphsKey& key) const { return key.hashValue; }
|
||||
};
|
||||
mutable o3tl::lru_map<CachedGlyphsKey, SalLayoutGlyphs, CachedGlyphsHash> mCachedGlyphs;
|
||||
|
||||
SalLayoutGlyphsCache(const SalLayoutGlyphsCache&) = delete;
|
||||
SalLayoutGlyphsCache& operator=(const SalLayoutGlyphsCache&) = delete;
|
||||
};
|
||||
|
||||
#endif // INCLUDED_VCL_GLYPHITEMCACHE_HXX
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
|
@ -54,6 +54,7 @@
|
|||
#include <vcl/settings.hxx>
|
||||
#include <vcl/glyphitem.hxx>
|
||||
#include <vcl/vcllayout.hxx>
|
||||
#include <vcl/glyphitemcache.hxx>
|
||||
#include <sal/log.hxx>
|
||||
#include <unotools/charclass.hxx>
|
||||
#include <osl/diagnose.h>
|
||||
|
@ -120,19 +121,7 @@ class ScDrawStringsVars
|
|||
tools::Long nExpWidth;
|
||||
|
||||
ScRefCellValue maLastCell;
|
||||
struct CachedGlyphsKey
|
||||
{
|
||||
OUString text;
|
||||
VclPtr<OutputDevice> outputDevice;
|
||||
size_t hashValue;
|
||||
CachedGlyphsKey( const OUString& t, const VclPtr<OutputDevice>& dev );
|
||||
bool operator==( const CachedGlyphsKey& other ) const;
|
||||
};
|
||||
struct CachedGlyphsHash
|
||||
{
|
||||
size_t operator()( const CachedGlyphsKey& key ) const { return key.hashValue; }
|
||||
};
|
||||
mutable o3tl::lru_map<CachedGlyphsKey, SalLayoutGlyphs, CachedGlyphsHash> mCachedGlyphs;
|
||||
mutable SalLayoutGlyphsCache mCachedGlyphs;
|
||||
sal_uLong nValueFormat;
|
||||
bool bLineBreak;
|
||||
bool bRepeat;
|
||||
|
@ -198,7 +187,10 @@ public:
|
|||
|
||||
// ScOutputData::LayoutStrings() usually triggers a number of calls that require
|
||||
// to lay out the text, which is relatively slow, so cache that operation.
|
||||
const SalLayoutGlyphs* GetLayoutGlyphs(const OUString& rString) const;
|
||||
const SalLayoutGlyphs* GetLayoutGlyphs(const OUString& rString) const
|
||||
{
|
||||
return mCachedGlyphs.GetLayoutGlyphs(rString, pOutput->pFmtDevice);
|
||||
}
|
||||
|
||||
private:
|
||||
tools::Long GetMaxDigitWidth(); // in logic units
|
||||
|
@ -225,7 +217,6 @@ ScDrawStringsVars::ScDrawStringsVars(ScOutputData* pData, bool bPTL) :
|
|||
nSignWidth( 0 ),
|
||||
nDotWidth( 0 ),
|
||||
nExpWidth( 0 ),
|
||||
mCachedGlyphs( 1000 ),
|
||||
nValueFormat( 0 ),
|
||||
bLineBreak ( false ),
|
||||
bRepeat ( false ),
|
||||
|
@ -787,40 +778,6 @@ tools::Long ScDrawStringsVars::GetExpWidth()
|
|||
return nExpWidth;
|
||||
}
|
||||
|
||||
inline ScDrawStringsVars::CachedGlyphsKey::CachedGlyphsKey( const OUString& t, const VclPtr<OutputDevice>& d )
|
||||
: text( t )
|
||||
, outputDevice( d )
|
||||
{
|
||||
hashValue = 0;
|
||||
o3tl::hash_combine( hashValue, outputDevice.get());
|
||||
SvMemoryStream stream;
|
||||
WriteFont( stream, outputDevice->GetFont());
|
||||
o3tl::hash_combine( hashValue, static_cast<const char*>(stream.GetData()), stream.GetSize());
|
||||
o3tl::hash_combine( hashValue, text );
|
||||
}
|
||||
|
||||
inline bool ScDrawStringsVars::CachedGlyphsKey::operator==( const CachedGlyphsKey& other ) const
|
||||
{
|
||||
return hashValue == other.hashValue && outputDevice == other.outputDevice && text == other.text;
|
||||
}
|
||||
|
||||
const SalLayoutGlyphs* ScDrawStringsVars::GetLayoutGlyphs(const OUString& rString) const
|
||||
{
|
||||
const CachedGlyphsKey key( rString, pOutput->pFmtDevice );
|
||||
auto it = mCachedGlyphs.find( key );
|
||||
if( it != mCachedGlyphs.end() && it->second.IsValid())
|
||||
return &it->second;
|
||||
std::unique_ptr<SalLayout> layout = pOutput->pFmtDevice->ImplLayout( rString, 0, rString.getLength(),
|
||||
Point( 0, 0 ), 0, {}, SalLayoutFlags::GlyphItemsOnly );
|
||||
if( layout )
|
||||
{
|
||||
mCachedGlyphs.insert( std::make_pair( key, layout->GetGlyphs()));
|
||||
assert(mCachedGlyphs.find( key ) == mCachedGlyphs.begin()); // newly inserted item is first
|
||||
return &mCachedGlyphs.begin()->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
tools::Long ScDrawStringsVars::GetFmtTextWidth( const OUString& rString )
|
||||
{
|
||||
return pOutput->pFmtDevice->GetTextWidth( rString, 0, -1, nullptr, GetLayoutGlyphs( rString ));
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
*/
|
||||
|
||||
#include <impglyphitem.hxx>
|
||||
#include <vcl/glyphitemcache.hxx>
|
||||
#include <vcl/vcllayout.hxx>
|
||||
#include <tools/stream.hxx>
|
||||
|
||||
SalLayoutGlyphs::SalLayoutGlyphs() {}
|
||||
|
||||
|
@ -91,4 +94,40 @@ bool SalLayoutGlyphsImpl::IsValid() const
|
|||
return true;
|
||||
}
|
||||
|
||||
const SalLayoutGlyphs*
|
||||
SalLayoutGlyphsCache::GetLayoutGlyphs(const OUString& text, VclPtr<OutputDevice> outputDevice) const
|
||||
{
|
||||
const CachedGlyphsKey key(text, outputDevice);
|
||||
auto it = mCachedGlyphs.find(key);
|
||||
if (it != mCachedGlyphs.end() && it->second.IsValid())
|
||||
return &it->second;
|
||||
std::unique_ptr<SalLayout> layout = outputDevice->ImplLayout(
|
||||
text, 0, text.getLength(), Point(0, 0), 0, {}, SalLayoutFlags::GlyphItemsOnly);
|
||||
if (layout)
|
||||
{
|
||||
mCachedGlyphs.insert(std::make_pair(key, layout->GetGlyphs()));
|
||||
assert(mCachedGlyphs.find(key) == mCachedGlyphs.begin()); // newly inserted item is first
|
||||
return &mCachedGlyphs.begin()->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SalLayoutGlyphsCache::CachedGlyphsKey::CachedGlyphsKey(const OUString& t,
|
||||
const VclPtr<OutputDevice>& d)
|
||||
: text(t)
|
||||
, outputDevice(d)
|
||||
{
|
||||
hashValue = 0;
|
||||
o3tl::hash_combine(hashValue, outputDevice.get());
|
||||
SvMemoryStream stream;
|
||||
WriteFont(stream, outputDevice->GetFont());
|
||||
o3tl::hash_combine(hashValue, static_cast<const char*>(stream.GetData()), stream.GetSize());
|
||||
o3tl::hash_combine(hashValue, text);
|
||||
}
|
||||
|
||||
inline bool SalLayoutGlyphsCache::CachedGlyphsKey::operator==(const CachedGlyphsKey& other) const
|
||||
{
|
||||
return hashValue == other.hashValue && outputDevice == other.outputDevice && text == other.text;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
|
Loading…
Reference in a new issue