use just one shared global SalLayoutGlyphsCache

Now the cache should be capable of detecting what needs
to stay the same for having the same result, so it should
be enough to have just one cache that can reuse results
even between callers from different places.

Change-Id: Ibdc0303f5b727d1a1d7be91d61db9465ed95e1c5
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132673
Tested-by: Jenkins
Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
This commit is contained in:
Luboš Luňák 2022-04-07 12:06:27 +02:00
parent 53fe4a26c7
commit 3e58636058
16 changed files with 81 additions and 217 deletions

View File

@ -36,7 +36,6 @@
#include <vcl/idle.hxx>
#include <vcl/commandevent.hxx>
#include <vcl/ptrstyle.hxx>
#include <vcl/glyphitemcache.hxx>
#include <vcl/dndhelp.hxx>
#include <svl/ondemand.hxx>
@ -608,8 +607,6 @@ private:
bool mbNbspRunNext; // can't be a bitfield as it is passed as bool&
SalLayoutGlyphsCache mGlyphsCache;
// Methods...

View File

@ -3439,7 +3439,7 @@ sal_uInt32 ImpEditEngine::CalcLineWidth( ParaPortion* pPortion, EditLine* pLine,
aTmpFont.SetPhysFont(*GetRefDevice());
ImplInitDigitMode(*GetRefDevice(), aTmpFont.GetLanguage());
nWidth += aTmpFont.QuickGetTextSize( GetRefDevice(),
pPortion->GetNode()->GetString(), nPos, rTextPortion.GetLen(), nullptr, &mGlyphsCache ).Width();
pPortion->GetNode()->GetString(), nPos, rTextPortion.GetLen(), nullptr ).Width();
}
}
break;

View File

@ -997,7 +997,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY )
// Height needed...
SeekCursor( pNode, nTmpPos+1, aTmpFont );
pPortion->GetSize().setHeight(
aTmpFont.QuickGetTextSize( GetRefDevice(), OUString(), 0, 0, nullptr, &mGlyphsCache ).Height() );
aTmpFont.QuickGetTextSize( GetRefDevice(), OUString(), 0, 0, nullptr ).Height() );
DBG_ASSERT( pPortion->GetSize().Width() >= 0, "Tab incorrectly calculated!" );
@ -1043,7 +1043,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY )
// get size, but also DXArray to allow length information in line breaking below
std::vector<sal_Int32> aTmpDXArray;
pPortion->GetSize() = aTmpFont.QuickGetTextSize(GetRefDevice(),
aFieldValue, 0, aFieldValue.getLength(), &aTmpDXArray, &mGlyphsCache);
aFieldValue, 0, aFieldValue.getLength(), &aTmpDXArray);
// So no scrolling for oversized fields
if ( pPortion->GetSize().Width() > nXWidth )
@ -1148,7 +1148,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY )
if (bContinueLastPortion)
{
Size aSize( aTmpFont.QuickGetTextSize( GetRefDevice(),
rParaPortion.GetNode()->GetString(), nTmpPos, nPortionLen, &aBuf, &mGlyphsCache ));
rParaPortion.GetNode()->GetString(), nTmpPos, nPortionLen, &aBuf ));
pPortion->GetSize().AdjustWidth(aSize.Width() );
if (pPortion->GetSize().Height() < aSize.Height())
pPortion->GetSize().setHeight( aSize.Height() );
@ -1156,7 +1156,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY )
else
{
pPortion->GetSize() = aTmpFont.QuickGetTextSize( GetRefDevice(),
rParaPortion.GetNode()->GetString(), nTmpPos, nPortionLen, &aBuf, &mGlyphsCache );
rParaPortion.GetNode()->GetString(), nTmpPos, nPortionLen, &aBuf );
}
// #i9050# Do Kerning also behind portions...
@ -1225,7 +1225,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY )
{
nW -= rParaPortion.GetTextPortions()[nTmpPortion].GetSize().Width();
nW += aTmpFont.QuickGetTextSize( GetRefDevice(), rParaPortion.GetNode()->GetString(),
nTmpPos, nDecPos, nullptr, &mGlyphsCache ).Width();
nTmpPos, nDecPos, nullptr ).Width();
aCurrentTab.bValid = false;
}
}
@ -2371,7 +2371,7 @@ sal_Int32 ImpEditEngine::SplitTextPortion( ParaPortion* pPortion, sal_Int32 nPos
GetRefDevice()->Push( vcl::PushFlags::TEXTLANGUAGE );
ImplInitDigitMode(*GetRefDevice(), aTmpFont.GetLanguage());
Size aSz = aTmpFont.QuickGetTextSize( GetRefDevice(), pPortion->GetNode()->GetString(),
nTxtPortionStart, pTextPortion->GetLen(), nullptr, &mGlyphsCache );
nTxtPortionStart, pTextPortion->GetLen(), nullptr );
GetRefDevice()->Pop();
pTextPortion->GetExtraInfos()->nOrgWidth = aSz.Width();
}
@ -3301,7 +3301,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po
if ( 0x200B == cChar || 0x2060 == cChar )
{
tools::Long nHalfBlankWidth = aTmpFont.QuickGetTextSize( &rOutDev,
" ", 0, 1, nullptr, &mGlyphsCache ).Width() / 2;
" ", 0, 1, nullptr ).Width() / 2;
const tools::Long nAdvanceX = ( nTmpIdx == nTmpEnd ?
rTextPortion.GetSize().Width() :
@ -3338,13 +3338,13 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po
aTmpFont.SetPhysFont(rOutDev);
const Size aSlashSize = aTmpFont.QuickGetTextSize( &rOutDev,
aSlash, 0, 1, nullptr, &mGlyphsCache );
aSlash, 0, 1, nullptr );
Point aSlashPos( aTmpPos );
const tools::Long nAddX = nHalfBlankWidth - aSlashSize.Width() / 2;
setXDirectionAwareFrom(aSlashPos, aTopLeftRectPos);
adjustXDirectionAware(aSlashPos, nAddX);
aTmpFont.QuickDrawText( &rOutDev, aSlashPos, aSlash, 0, 1, {}, &mGlyphsCache );
aTmpFont.QuickDrawText( &rOutDev, aSlashPos, aSlash, 0, 1, {} );
aTmpFont.SetEscapement( nOldEscapement );
aTmpFont.SetPropr( nOldPropr );
@ -3406,7 +3406,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po
aTmpFont.SetPhysFont(*GetRefDevice());
aTmpFont.QuickGetTextSize( GetRefDevice(), aText, nTextStart, nTextLen,
&aTmpDXArray, &mGlyphsCache );
&aTmpDXArray );
pDXArray = aTmpDXArray;
// add a meta file comment if we record to a metafile
@ -3433,7 +3433,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po
// crash when accessing 0 pointer in pDXArray
aTmpFont.SetPhysFont(*GetRefDevice());
aTmpFont.QuickGetTextSize( GetRefDevice(), aText, 0, aText.getLength(),
&aTmpDXArray, &mGlyphsCache );
&aTmpDXArray );
pDXArray = aTmpDXArray;
}
@ -3634,7 +3634,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po
--nTextLen;
// output directly
aTmpFont.QuickDrawText( &rOutDev, aRealOutPos, aText, nTextStart, nTextLen, pDXArray, &mGlyphsCache );
aTmpFont.QuickDrawText( &rOutDev, aRealOutPos, aText, nTextStart, nTextLen, pDXArray );
if ( bDrawFrame )
{
@ -3725,7 +3725,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po
aTmpFont.SetEscapement( 0 );
aTmpFont.SetPhysFont(rOutDev);
tools::Long nCharWidth = aTmpFont.QuickGetTextSize( &rOutDev,
OUString(rTextPortion.GetExtraValue()), 0, 1, {}, &mGlyphsCache ).Width();
OUString(rTextPortion.GetExtraValue()), 0, 1, {} ).Width();
sal_Int32 nChars = 2;
if( nCharWidth )
nChars = rTextPortion.GetSize().Width() / nCharWidth;
@ -3737,7 +3737,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po
OUStringBuffer aBuf(nChars);
comphelper::string::padToLength(aBuf, nChars, rTextPortion.GetExtraValue());
OUString aText(aBuf.makeStringAndClear());
aTmpFont.QuickDrawText( &rOutDev, aTmpPos, aText, 0, aText.getLength(), {}, &mGlyphsCache );
aTmpFont.QuickDrawText( &rOutDev, aTmpPos, aText, 0, aText.getLength(), {} );
rOutDev.DrawStretchText( aTmpPos, rTextPortion.GetSize().Width(), aText );
if ( bStripOnly )

View File

@ -454,27 +454,26 @@ Size SvxFont::GetPhysTxtSize( const OutputDevice *pOut )
}
static tools::Long GetTextArray( const OutputDevice* pOut, const OUString& rStr, std::vector<sal_Int32>* pDXAry,
sal_Int32 nIndex, sal_Int32 nLen, SalLayoutGlyphsCache* cache )
sal_Int32 nIndex, sal_Int32 nLen )
{
const SalLayoutGlyphs* layoutGlyphs = cache ? cache->GetLayoutGlyphs(pOut, rStr, nIndex, nLen) : nullptr;
const SalLayoutGlyphs* layoutGlyphs = SalLayoutGlyphsCache::self()->GetLayoutGlyphs(pOut, rStr, nIndex, nLen);
return pOut->GetTextArray( rStr, pDXAry, nIndex, nLen, nullptr, layoutGlyphs);
}
Size SvxFont::QuickGetTextSize( const OutputDevice *pOut, const OUString &rTxt,
const sal_Int32 nIdx, const sal_Int32 nLen, std::vector<sal_Int32>* pDXArray,
SalLayoutGlyphsCache* cache ) const
const sal_Int32 nIdx, const sal_Int32 nLen, std::vector<sal_Int32>* pDXArray ) const
{
if ( !IsCaseMap() && !IsKern() )
return Size( GetTextArray( pOut, rTxt, pDXArray, nIdx, nLen, cache ),
return Size( GetTextArray( pOut, rTxt, pDXArray, nIdx, nLen ),
pOut->GetTextHeight() );
Size aTxtSize;
aTxtSize.setHeight( pOut->GetTextHeight() );
if ( !IsCaseMap() )
aTxtSize.setWidth( GetTextArray( pOut, rTxt, pDXArray, nIdx, nLen, cache ) );
aTxtSize.setWidth( GetTextArray( pOut, rTxt, pDXArray, nIdx, nLen ) );
else
aTxtSize.setWidth( GetTextArray( pOut, CalcCaseMap( rTxt ),
pDXArray, nIdx, nLen, cache ) );
pDXArray, nIdx, nLen ) );
if( IsKern() && ( nLen > 1 ) )
{
@ -510,23 +509,21 @@ Size SvxFont::GetTextSize(const OutputDevice& rOut, const OUString &rTxt,
static void DrawTextArray( OutputDevice* pOut, const Point& rStartPt, const OUString& rStr,
o3tl::span<const sal_Int32> pDXAry,
sal_Int32 nIndex, sal_Int32 nLen,
SalLayoutGlyphsCache* cache )
sal_Int32 nIndex, sal_Int32 nLen )
{
const SalLayoutGlyphs* layoutGlyphs = cache ? cache->GetLayoutGlyphs(pOut, rStr, nIndex, nLen) : nullptr;
const SalLayoutGlyphs* layoutGlyphs = SalLayoutGlyphsCache::self()->GetLayoutGlyphs(pOut, rStr, nIndex, nLen);
pOut->DrawTextArray(rStartPt, rStr, pDXAry, nIndex, nLen, SalLayoutFlags::NONE, layoutGlyphs);
}
void SvxFont::QuickDrawText( OutputDevice *pOut,
const Point &rPos, const OUString &rTxt,
const sal_Int32 nIdx, const sal_Int32 nLen, o3tl::span<const sal_Int32> pDXArray,
SalLayoutGlyphsCache* cache ) const
const sal_Int32 nIdx, const sal_Int32 nLen, o3tl::span<const sal_Int32> pDXArray ) const
{
// Font has to be selected in OutputDevice...
if ( !IsCaseMap() && !IsCapital() && !IsKern() && !IsEsc() )
{
DrawTextArray( pOut, rPos, rTxt, pDXArray, nIdx, nLen, cache );
DrawTextArray( pOut, rPos, rTxt, pDXArray, nIdx, nLen );
return;
}
@ -563,9 +560,9 @@ void SvxFont::QuickDrawText( OutputDevice *pOut,
else
{
if ( !IsCaseMap() )
DrawTextArray( pOut, aPos, rTxt, pDXArray, nIdx, nLen, cache );
DrawTextArray( pOut, aPos, rTxt, pDXArray, nIdx, nLen );
else
DrawTextArray( pOut, aPos, CalcCaseMap( rTxt ), pDXArray, nIdx, nLen, cache );
DrawTextArray( pOut, aPos, CalcCaseMap( rTxt ), pDXArray, nIdx, nLen );
}
}
}

View File

@ -36,8 +36,6 @@ class Printer;
class Point;
namespace tools { class Rectangle; }
class Size;
class SalLayoutGlyphsCache;
class EDITENG_DLLPUBLIC SvxFont : public vcl::Font
{
SvxCaseMap eCaseMap; // Text Markup
@ -97,12 +95,12 @@ public:
const sal_Int32 nIdx = 0, const sal_Int32 nLen = SAL_MAX_INT32) const;
void QuickDrawText( OutputDevice *pOut, const Point &rPos, const OUString &rTxt,
const sal_Int32 nIdx = 0, const sal_Int32 nLen = SAL_MAX_INT32, o3tl::span<const sal_Int32> pDXArray = {},
SalLayoutGlyphsCache* cache = nullptr ) const;
const sal_Int32 nIdx = 0, const sal_Int32 nLen = SAL_MAX_INT32,
o3tl::span<const sal_Int32> pDXArray = {} ) const;
Size QuickGetTextSize( const OutputDevice *pOut, const OUString &rTxt,
const sal_Int32 nIdx, const sal_Int32 nLen, std::vector<sal_Int32>* pDXArray = nullptr,
SalLayoutGlyphsCache* cache = nullptr ) const;
const sal_Int32 nIdx, const sal_Int32 nLen,
std::vector<sal_Int32>* pDXArray = nullptr ) const;
void DrawPrev( OutputDevice* pOut, Printer* pPrinter,
const Point &rPos, const OUString &rTxt,

View File

@ -40,10 +40,6 @@ If something more changes, call clear().
class VCL_DLLPUBLIC SalLayoutGlyphsCache final
{
public:
SalLayoutGlyphsCache(int size = 1000)
: mCachedGlyphs(size)
{
}
const SalLayoutGlyphs*
GetLayoutGlyphs(VclPtr<const OutputDevice> outputDevice, const OUString& text,
const vcl::text::TextLayoutCache* layoutCache = nullptr) const
@ -56,6 +52,12 @@ public:
const vcl::text::TextLayoutCache* layoutCache = nullptr) const;
void clear() { mCachedGlyphs.clear(); }
static SalLayoutGlyphsCache* self();
SalLayoutGlyphsCache(int size) // needs to be public for vcl::DeleteOnDeinit
: mCachedGlyphs(size)
{
}
private:
struct CachedGlyphsKey
{

View File

@ -121,7 +121,6 @@ class ScDrawStringsVars
tools::Long nExpWidth;
ScRefCellValue maLastCell;
mutable SalLayoutGlyphsCache mCachedGlyphs;
sal_uLong nValueFormat;
bool bLineBreak;
bool bRepeat;
@ -189,7 +188,7 @@ public:
// to lay out the text, which is relatively slow, so cache that operation.
const SalLayoutGlyphs* GetLayoutGlyphs(const OUString& rString) const
{
return mCachedGlyphs.GetLayoutGlyphs(pOutput->pFmtDevice, rString);
return SalLayoutGlyphsCache::self()->GetLayoutGlyphs(pOutput->pFmtDevice, rString);
}
private:
@ -307,7 +306,6 @@ void ScDrawStringsVars::SetPattern(
nSignWidth = 0;
nDotWidth = 0;
nExpWidth = 0;
mCachedGlyphs.clear();
pPattern = pNew;
pCondSet = pSet;
@ -462,7 +460,6 @@ void ScDrawStringsVars::SetPatternSimple( const ScPatternAttr* pNew, const SfxIt
nSignWidth = 0;
nDotWidth = 0;
nExpWidth = 0;
mCachedGlyphs.clear();
// Is called, when the font variables do not change (!StringDiffer)

View File

@ -24,7 +24,6 @@
#include <svl/style.hxx>
#include <com/sun/star/frame/XDispatchProvider.hpp>
#include <sfx2/sfxstatuslistener.hxx>
#include <vcl/glyphitemcache.hxx>
class StylesPreviewWindow_Base;
@ -60,7 +59,6 @@ class StyleItemController
SfxStyleFamily m_eStyleFamily;
std::pair<OUString, OUString> m_aStyleName;
SalLayoutGlyphsCache m_GlyphsCache;
public:
StyleItemController(const std::pair<OUString, OUString>& aStyleName);

View File

@ -27,6 +27,7 @@
#include <sfx2/sfxsids.hrc>
#include <sfx2/tplpitem.hxx>
#include <sfx2/viewsh.hxx>
#include <vcl/glyphitemcache.hxx>
#include <vcl/virdev.hxx>
#include <vcl/settings.hxx>
@ -354,7 +355,7 @@ void StyleItemController::DrawHighlight(vcl::RenderContext& rRenderContext, Colo
void StyleItemController::DrawText(vcl::RenderContext& rRenderContext)
{
const SalLayoutGlyphs* layoutGlyphs
= m_GlyphsCache.GetLayoutGlyphs(&rRenderContext, m_aStyleName.second);
= SalLayoutGlyphsCache::self()->GetLayoutGlyphs(&rRenderContext, m_aStyleName.second);
tools::Rectangle aTextRect;
rRenderContext.GetTextBoundRect(aTextRect, m_aStyleName.second, 0, 0, -1, 0, {}, layoutGlyphs);

View File

@ -2886,7 +2886,6 @@ void SwDoc::SetTabCols(SwTable& rTab, const SwTabCols &rNew, const SwTabCols &rO
}
rTab.SetTabCols( rNew, rOld, pStart, bCurRowOnly );
::ClearFEShellTabCols(*this, nullptr);
SwClearFntCacheTextGlyphs();
getIDocumentState().SetModified();
}

View File

@ -53,37 +53,10 @@ public:
void Flush();
};
/// Clears the pre-calculated text glyphs in all SwFntObj instances.
void SwClearFntCacheTextGlyphs();
// Font cache, global variable, created/destroyed in txtinit.cxx
extern SwFntCache *pFntCache;
extern SwFntObj *pLastFont;
/**
* Defines a substring on a given output device, to be used as an std::unordered_map<>
* key.
*/
struct SwTextGlyphsKey
{
VclPtr<const OutputDevice> m_pOutputDevice;
OUString m_aText;
sal_Int32 m_nIndex;
sal_Int32 m_nLength;
size_t mnHashCode;
SwTextGlyphsKey(const OutputDevice* pOutputDevice, const OUString & sText, sal_Int32 nIndex, sal_Int32 nLength);
bool operator==(SwTextGlyphsKey const & rhs) const;
};
struct SwTextGlyphsKeyHash
{
size_t operator()(SwTextGlyphsKey const & rKey) const { return rKey.mnHashCode; }
};
/**
* Glyphs for the given SwTextGlyphsKey.
*/
typedef std::unordered_map<SwTextGlyphsKey, SalLayoutGlyphs, SwTextGlyphsKeyHash> SwTextGlyphsMap;
class SwFntObj final : public SwCacheObj
{
friend class SwFntAccess;
@ -105,15 +78,12 @@ class SwFntObj final : public SwCacheObj
bool m_bSymbol : 1;
bool m_bPaintBlank : 1;
/// Cache of already calculated layout glyphs and text widths.
SwTextGlyphsMap m_aTextGlyphs;
void GetTextArray(const OutputDevice& rOutputDevice, const OUString& rStr,
std::vector<sal_Int32>& rDXAry, sal_Int32 nIndex, sal_Int32 nLen,
bool bCaching, const vcl::text::TextLayoutCache* layoutCache = nullptr);
void GetTextArray(const OutputDevice& rOutputDevice, const SwDrawTextInfo& rInf, std::vector<sal_Int32>& rDXAry,
sal_Int32 nLen);
void GetTextArray(const OutputDevice& rOutputDevice, const SwDrawTextInfo& rInf, std::vector<sal_Int32>& rDXAry);
static void GetTextArray(const OutputDevice& rOutputDevice, const OUString& rStr,
std::vector<sal_Int32>& rDXAry, sal_Int32 nIndex, sal_Int32 nLen,
const vcl::text::TextLayoutCache* layoutCache = nullptr);
static void GetTextArray(const OutputDevice& rOutputDevice, const SwDrawTextInfo& rInf, std::vector<sal_Int32>& rDXAry,
sal_Int32 nLen);
static void GetTextArray(const OutputDevice& rOutputDevice, const SwDrawTextInfo& rInf, std::vector<sal_Int32>& rDXAry);
static tools::Long s_nPixWidth;
static MapMode *s_pPixMap;
@ -143,9 +113,6 @@ public:
sal_uInt16 GetPropWidth() const { return m_nPropWidth; }
bool IsSymbol() const { return m_bSymbol; }
SalLayoutGlyphs* GetCachedSalLayoutGlyphs(const SwTextGlyphsKey& key, const vcl::text::TextLayoutCache* layoutCache);
void ClearCachedTextGlyphs();
void DrawText( SwDrawTextInfo &rInf );
/// determine the TextSize (of the printer)
Size GetTextSize( SwDrawTextInfo &rInf );

View File

@ -2397,9 +2397,6 @@ SwLayIdle::SwLayIdle( SwRootFrame *pRt, SwViewShellImp *pI ) :
m_pRoot->ResetIdleFormat();
SfxObjectShell* pDocShell = m_pImp->GetShell()->GetDoc()->GetDocShell();
pDocShell->Broadcast( SfxEventHint( SfxEventHintId::SwEventLayoutFinished, SwDocShell::GetEventName(STR_SW_EVENT_LAYOUT_FINISHED), pDocShell ) );
// Limit lifetime of the text glyphs cache to a single run of the
// layout.
SwClearFntCacheTextGlyphs();
}
}

View File

@ -26,11 +26,11 @@
#include <vcl/metric.hxx>
#include <vcl/svapp.hxx>
#include <vcl/lazydelete.hxx>
#include <vcl/glyphitemcache.hxx>
#include <com/sun/star/i18n/CharacterIteratorMode.hpp>
#include <com/sun/star/i18n/WordType.hpp>
#include <com/sun/star/i18n/XBreakIterator.hpp>
#include <breakit.hxx>
#include <config_fuzzers.h>
#include <paintfrm.hxx>
#include <viewsh.hxx>
#include <viewopt.hxx>
@ -71,34 +71,6 @@ tools::Long SwFntObj::s_nPixWidth;
MapMode* SwFntObj::s_pPixMap = nullptr;
static vcl::DeleteOnDeinit< VclPtr<OutputDevice> > s_pFntObjPixOut {};
/**
* Defines a substring on a given output device, to be used as an std::unordered_map<>
* key.
*/
SwTextGlyphsKey::SwTextGlyphsKey(const OutputDevice* pOutputDevice, const OUString & sText, sal_Int32 nIndex, sal_Int32 nLength)
: m_pOutputDevice(pOutputDevice), m_aText(sText), m_nIndex(nIndex), m_nLength(nLength)
{
mnHashCode = 0;
o3tl::hash_combine(mnHashCode, pOutputDevice);
o3tl::hash_combine(mnHashCode, m_nIndex);
o3tl::hash_combine(mnHashCode, m_nLength);
if(m_nLength >= 0 && m_nIndex >= 0 && m_nIndex + m_nLength <= m_aText.getLength())
o3tl::hash_combine(mnHashCode, m_aText.getStr() + m_nIndex, m_nLength);
}
bool SwTextGlyphsKey::operator==(SwTextGlyphsKey const & rhs) const
{
bool b = m_pOutputDevice.get() == rhs.m_pOutputDevice.get()
&& m_nIndex == rhs.m_nIndex
&& m_nLength == rhs.m_nLength
&& m_aText.getLength() == rhs.m_aText.getLength();
if (!b)
return false;
if(m_nLength >= 0 && m_nIndex >= 0 && m_nIndex + m_nLength <= m_aText.getLength())
return m_aText.subView(m_nIndex,m_nLength) == rhs.m_aText.subView(m_nIndex, m_nLength);
return m_aText == rhs.m_aText;
}
namespace
{
@ -188,66 +160,6 @@ void SwFntObj::CreatePrtFont( const OutputDevice& rPrt )
}
#if !ENABLE_FUZZERS
const SalLayoutFlags eGlyphItemsOnlyLayout = SalLayoutFlags::GlyphItemsOnly;
#else
// ofz#39150 skip detecting bidi directions
const SalLayoutFlags eGlyphItemsOnlyLayout = SalLayoutFlags::GlyphItemsOnly | SalLayoutFlags::BiDiStrong;
#endif
/**
* 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, SwTextGlyphsMap::iterator it,
const vcl::text::TextLayoutCache* layoutCache)
{
assert (!it->second.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,
{}, eGlyphItemsOnlyLayout, layoutCache);
if (!pLayout)
return nullptr;
// Remember the calculation result.
it->second = pLayout->GetGlyphs();
return &it->second;
}
SalLayoutGlyphs* SwFntObj::GetCachedSalLayoutGlyphs(const SwTextGlyphsKey& key, const vcl::text::TextLayoutCache* layoutCache)
{
SwTextGlyphsMap::iterator it = m_aTextGlyphs.find(key);
if(it != m_aTextGlyphs.end())
{
if( it->second.IsValid())
return &it->second;
// 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.insert_or_assign( it, key, SalLayoutGlyphs());
std::shared_ptr<const vcl::text::TextLayoutCache> tmpLayoutCache;
if( layoutCache == nullptr )
{
tmpLayoutCache = OutputDevice::CreateTextLayoutCache( key.m_aText );
layoutCache = tmpLayoutCache.get();
}
return lcl_CreateLayout(key, it, layoutCache);
}
void SwFntObj::ClearCachedTextGlyphs()
{
m_aTextGlyphs.clear();
}
/*
* returns whether we have to adjust the output font to resemble
* the formatting font
@ -845,33 +757,23 @@ static void lcl_DrawLineForWrongListData(
}
void SwFntObj::GetTextArray(const OutputDevice& rDevice, const OUString& rStr, std::vector<sal_Int32>& rDXAry,
sal_Int32 nIndex, sal_Int32 nLen, bool bCaching, const vcl::text::TextLayoutCache* layoutCache)
sal_Int32 nIndex, sal_Int32 nLen, const vcl::text::TextLayoutCache* layoutCache)
{
SalLayoutGlyphs* pLayoutCache = nullptr;
std::shared_ptr<const vcl::text::TextLayoutCache> tmpLayoutCache;
if (bCaching)
{
SwTextGlyphsKey aGlyphsKey{&rDevice, rStr, nIndex, nLen};
pLayoutCache = GetCachedSalLayoutGlyphs(aGlyphsKey, layoutCache);
if(pLayoutCache == nullptr)
{ // Try to create at least the lower-level cache if possible.
tmpLayoutCache = OutputDevice::CreateTextLayoutCache( rStr );
layoutCache = tmpLayoutCache.get();
}
}
const SalLayoutGlyphs* pLayoutCache = SalLayoutGlyphsCache::self()->GetLayoutGlyphs(&rDevice, rStr, nIndex, nLen,
0, layoutCache);
rDevice.GetTextArray(rStr, &rDXAry, nIndex, nLen, layoutCache, pLayoutCache);
}
void SwFntObj::GetTextArray(const OutputDevice& rOutputDevice, const SwDrawTextInfo& rInf, std::vector<sal_Int32>& rDXAry)
{
return GetTextArray(rOutputDevice, rInf.GetText(), rDXAry, rInf.GetIdx().get(), rInf.GetLen().get(), true, rInf.GetVclCache());
return GetTextArray(rOutputDevice, rInf.GetText(), rDXAry, rInf.GetIdx().get(), rInf.GetLen().get(), rInf.GetVclCache());
}
void SwFntObj::GetTextArray(const OutputDevice& rOutputDevice, const SwDrawTextInfo& rInf, std::vector<sal_Int32>& rDXAry, sal_Int32 nLen)
{
// Substring is fine.
assert( nLen <= rInf.GetLen().get());
return GetTextArray(rOutputDevice, rInf.GetText(), rDXAry, rInf.GetIdx().get(), nLen, true, rInf.GetVclCache());
return GetTextArray(rOutputDevice, rInf.GetText(), rDXAry, rInf.GetIdx().get(), nLen, rInf.GetVclCache());
}
void SwFntObj::DrawText( SwDrawTextInfo &rInf )
@ -1818,8 +1720,8 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
sal_Int32 nTmpIdx = bBullet
? (rInf.GetIdx() ? 1 : 0)
: sal_Int32(rInf.GetIdx());
SwTextGlyphsKey aGlyphsKey{ &rInf.GetOut(), *pStr, nTmpIdx, nLen };
SalLayoutGlyphs* pGlyphs = GetCachedSalLayoutGlyphs(aGlyphsKey, nullptr);
const SalLayoutGlyphs* pGlyphs = SalLayoutGlyphsCache::self()->GetLayoutGlyphs(&rInf.GetOut(),
*pStr, nTmpIdx, nLen);
rInf.GetOut().DrawTextArray( aTextOriginPos, *pStr, aKernArray,
nTmpIdx , nLen, SalLayoutFlags::NONE, pGlyphs );
if (bBullet)
@ -1982,7 +1884,7 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf )
rInf.GetOut().SetFont( *m_pScrFont );
GetTextArray(*m_pPrinter, rInf.GetText(), aKernArray,
sal_Int32(rInf.GetIdx()), sal_Int32(nLn), false);
sal_Int32(rInf.GetIdx()), sal_Int32(nLn));
}
else
{
@ -2449,8 +2351,8 @@ TextFrameIndex SwFont::GetTextBreak(SwDrawTextInfo const & rInf, tools::Long nTe
{
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 = aFntAccess.Get()->GetCachedSalLayoutGlyphs(aGlyphsKey, nullptr);
const SalLayoutGlyphs* pGlyphs = SalLayoutGlyphsCache::self()->GetLayoutGlyphs(&rInf.GetOut(),
*pTmpText, nTmpIdx.get(), nTmpLen.get(), 0, rInf.GetVclCache());
nTextBreak = TextFrameIndex(rInf.GetOut().GetTextBreak(
*pTmpText, nTextWidth,
sal_Int32(nTmpIdx), sal_Int32(nTmpLen),
@ -2645,10 +2547,4 @@ bool SwDrawTextInfo::ApplyAutoColor( vcl::Font* pFont )
return false;
}
void SwClearFntCacheTextGlyphs()
{
for (SwFntObj* pFntObj = pFntCache->First(); pFntObj; pFntObj = SwFntCache::Next(pFntObj))
pFntObj->ClearCachedTextGlyphs();
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@ -53,7 +53,6 @@
#include <comphelper/hash.hxx>
#include <tools/stream.hxx>
#include <vcl/BinaryDataContainer.hxx>
#include <vcl/glyphitemcache.hxx>
#include <vcl/filter/pdfobjectcontainer.hxx>
#include <pdf/ExternalPDFStreams.hxx>
@ -765,8 +764,6 @@ private:
::comphelper::Hash m_DocDigest;
SalLayoutGlyphsCache m_layoutGlyphsCache;
/*
variables for PDF security
i12626

View File

@ -20,8 +20,10 @@
#include <impglyphitem.hxx>
#include <vcl/glyphitemcache.hxx>
#include <vcl/vcllayout.hxx>
#include <vcl/lazydelete.hxx>
#include <tools/stream.hxx>
#include <TextLayoutCache.hxx>
#include <config_fuzzers.h>
SalLayoutGlyphs::SalLayoutGlyphs() {}
@ -95,6 +97,12 @@ bool SalLayoutGlyphsImpl::IsValid() const
return true;
}
SalLayoutGlyphsCache* SalLayoutGlyphsCache::self()
{
static vcl::DeleteOnDeinit<SalLayoutGlyphsCache> cache(1000);
return cache.get();
}
const SalLayoutGlyphs*
SalLayoutGlyphsCache::GetLayoutGlyphs(VclPtr<const OutputDevice> outputDevice, const OUString& text,
sal_Int32 nIndex, sal_Int32 nLen, tools::Long nLogicWidth,
@ -119,9 +127,15 @@ SalLayoutGlyphsCache::GetLayoutGlyphs(VclPtr<const OutputDevice> outputDevice, c
tmpLayoutCache = OutputDevice::CreateTextLayoutCache(text);
layoutCache = tmpLayoutCache.get();
}
std::unique_ptr<SalLayout> layout
= outputDevice->ImplLayout(text, nIndex, nLen, Point(0, 0), nLogicWidth, {},
SalLayoutFlags::GlyphItemsOnly, layoutCache);
#if !ENABLE_FUZZERS
const SalLayoutFlags glyphItemsOnlyLayout = SalLayoutFlags::GlyphItemsOnly;
#else
// ofz#39150 skip detecting bidi directions
const SalLayoutFlags glyphItemsOnlyLayout
= SalLayoutFlags::GlyphItemsOnly | SalLayoutFlags::BiDiStrong;
#endif
std::unique_ptr<SalLayout> layout = outputDevice->ImplLayout(
text, nIndex, nLen, Point(0, 0), nLogicWidth, {}, glyphItemsOnlyLayout, layoutCache);
if (layout)
{
mCachedGlyphs.insert(std::make_pair(key, layout->GetGlyphs()));

View File

@ -61,6 +61,7 @@
#include <vcl/canvastools.hxx>
#include <vcl/cvtgrf.hxx>
#include <vcl/fontcharmap.hxx>
#include <vcl/glyphitemcache.hxx>
#include <vcl/lineinfo.hxx>
#include <vcl/metric.hxx>
#include <vcl/settings.hxx>
@ -6499,7 +6500,8 @@ void PDFWriterImpl::drawText( const Point& rPos, const OUString& rText, sal_Int3
// get a layout from the OutputDevice's SalGraphics
// this also enforces font substitution and sets the font on SalGraphics
const SalLayoutGlyphs* layoutGlyphs = m_layoutGlyphsCache.GetLayoutGlyphs( this, rText, nIndex, nLen );
const SalLayoutGlyphs* layoutGlyphs = SalLayoutGlyphsCache::self()->
GetLayoutGlyphs( this, rText, nIndex, nLen );
std::unique_ptr<SalLayout> pLayout = ImplLayout( rText, nIndex, nLen, rPos,
0, {}, SalLayoutFlags::NONE, nullptr, layoutGlyphs );
if( pLayout )
@ -6516,7 +6518,8 @@ void PDFWriterImpl::drawTextArray( const Point& rPos, const OUString& rText, o3t
// get a layout from the OutputDevice's SalGraphics
// this also enforces font substitution and sets the font on SalGraphics
const SalLayoutGlyphs* layoutGlyphs = m_layoutGlyphsCache.GetLayoutGlyphs( this, rText, nIndex, nLen );
const SalLayoutGlyphs* layoutGlyphs = SalLayoutGlyphsCache::self()->
GetLayoutGlyphs( this, rText, nIndex, nLen );
std::unique_ptr<SalLayout> pLayout = ImplLayout( rText, nIndex, nLen, rPos, 0, pDXArray,
SalLayoutFlags::NONE, nullptr, layoutGlyphs );
if( pLayout )
@ -6533,7 +6536,8 @@ void PDFWriterImpl::drawStretchText( const Point& rPos, sal_uLong nWidth, const
// get a layout from the OutputDevice's SalGraphics
// this also enforces font substitution and sets the font on SalGraphics
const SalLayoutGlyphs* layoutGlyphs = m_layoutGlyphsCache.GetLayoutGlyphs( this, rText, nIndex, nLen, nWidth );
const SalLayoutGlyphs* layoutGlyphs = SalLayoutGlyphsCache::self()->
GetLayoutGlyphs( this, rText, nIndex, nLen, nWidth );
std::unique_ptr<SalLayout> pLayout = ImplLayout( rText, nIndex, nLen, rPos, nWidth,
{}, SalLayoutFlags::NONE, nullptr, layoutGlyphs );
if( pLayout )