tdf#121030 invalidate referenced FontInstances

This sets the FreetypeFont pointer of the FreetypeFontInstances
to nullptr when clearing the cache.
And it changes the interface functions of SalLayoutGlyphs to some
variant different from std::vector.

I don't know if we should prefer the mutable or the const font
instance. With mutable at least one can invalidate the font
instance when checking the IsValid(), so we can get rid of our
referenced font instance.

Change-Id: I6070cfcb3c549dbad3383bd4ec2b05b30645b753
Reviewed-on: https://gerrit.libreoffice.org/62688
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/include/vcl/glyphitem.hxx b/include/vcl/glyphitem.hxx
index 75213a5..8362537 100644
--- a/include/vcl/glyphitem.hxx
+++ b/include/vcl/glyphitem.hxx
@@ -39,8 +39,8 @@

    SalLayoutGlyphsImpl* Impl() const { return m_pImpl; }

    bool empty() const;
    void clear();
    bool IsValid() const;
    void Invalidate();
};

#endif // INCLUDED_VCL_GLYPHITEM_HXX
diff --git a/svtools/source/control/ruler.cxx b/svtools/source/control/ruler.cxx
index 1cb397e..a27fb60 100644
--- a/svtools/source/control/ruler.cxx
+++ b/svtools/source/control/ruler.cxx
@@ -71,7 +71,7 @@
SalLayoutGlyphs* lcl_GetRulerTextGlyphs(vcl::RenderContext& rRenderContext, const OUString& rText,
                                        SalLayoutGlyphs& rTextGlyphs)
{
    if (!rTextGlyphs.empty())
    if (rTextGlyphs.IsValid())
        // Use pre-calculated result.
        return &rTextGlyphs;

diff --git a/sw/source/core/txtnode/fntcache.cxx b/sw/source/core/txtnode/fntcache.cxx
index bf36541..c93e51d 100644
--- a/sw/source/core/txtnode/fntcache.cxx
+++ b/sw/source/core/txtnode/fntcache.cxx
@@ -105,7 +105,7 @@
SalLayoutGlyphs* lcl_CreateLayout(SwTextGlyphsKey& rKey, SalLayoutGlyphs& rTextGlyphs)
{
    // Use pre-calculated result.
    if (!rTextGlyphs.empty())
    if (rTextGlyphs.IsValid())
        return &rTextGlyphs;

    if (rKey.m_nIndex >= rKey.m_aText.getLength())
diff --git a/vcl/inc/impglyphitem.hxx b/vcl/inc/impglyphitem.hxx
index 4c7673e..009be6c 100644
--- a/vcl/inc/impglyphitem.hxx
+++ b/vcl/inc/impglyphitem.hxx
@@ -98,13 +98,15 @@
public:
    virtual ~SalLayoutGlyphsImpl();
    virtual SalLayoutGlyphsImpl* clone(SalLayoutGlyphs&) const = 0;
    virtual bool IsValid() const = 0;
    virtual void Invalidate() = 0;
};

class SalGenericLayoutGlyphsImpl : public SalLayoutGlyphsImpl
{
    friend class GenericSalLayout;

    const rtl::Reference<LogicalFontInstance> m_rFontInstance;
    mutable rtl::Reference<LogicalFontInstance> m_rFontInstance;

    SalGenericLayoutGlyphsImpl(SalLayoutGlyphs& rGlyphs, LogicalFontInstance& rFontInstance)
        : m_rFontInstance(&rFontInstance)
@@ -115,6 +117,8 @@
public:
    SalLayoutGlyphsImpl* clone(SalLayoutGlyphs& rGlyphs) const override;
    LogicalFontInstance& GetFont() const { return *m_rFontInstance; }
    bool IsValid() const override;
    void Invalidate() override;
};

#endif // INCLUDED_VCL_IMPGLYPHITEM_HXX
diff --git a/vcl/source/control/imp_listbox.cxx b/vcl/source/control/imp_listbox.cxx
index 6570fb3..265a958 100644
--- a/vcl/source/control/imp_listbox.cxx
+++ b/vcl/source/control/imp_listbox.cxx
@@ -618,7 +618,7 @@

SalLayoutGlyphs* ImplEntryType::GetTextGlyphs(OutputDevice* pOutputDevice)
{
    if (!maStrGlyphs.empty())
    if (maStrGlyphs.IsValid())
        // Use pre-calculated result.
        return &maStrGlyphs;

diff --git a/vcl/source/gdi/impglyphitem.cxx b/vcl/source/gdi/impglyphitem.cxx
index 8955ea8..d3aa10e 100644
--- a/vcl/source/gdi/impglyphitem.cxx
+++ b/vcl/source/gdi/impglyphitem.cxx
@@ -19,6 +19,10 @@

#include <impglyphitem.hxx>

#if (defined UNX && !defined MACOSX)
#include <unx/freetype_glyphcache.hxx>
#endif

SalLayoutGlyphs::SalLayoutGlyphs()
    : m_pImpl(nullptr)
{
@@ -35,12 +39,12 @@
    return *this;
}

bool SalLayoutGlyphs::empty() const { return !m_pImpl || m_pImpl->empty(); }
bool SalLayoutGlyphs::IsValid() const { return m_pImpl && m_pImpl->IsValid(); }

void SalLayoutGlyphs::clear()
void SalLayoutGlyphs::Invalidate()
{
    if (m_pImpl)
        m_pImpl->clear();
        m_pImpl->Invalidate();
}

SalLayoutGlyphsImpl::~SalLayoutGlyphsImpl() {}
@@ -52,4 +56,27 @@
    return pNew;
}

bool SalGenericLayoutGlyphsImpl::IsValid() const
{
    if (!m_rFontInstance.is())
        return false;
    if (empty())
        return false;
#if (defined UNX && !defined MACOSX)
    const FreetypeFontInstance* pFFI = dynamic_cast<FreetypeFontInstance*>(m_rFontInstance.get());
    if (pFFI && !pFFI->GetFreetypeFont())
    {
        m_rFontInstance.clear();
        return false;
    }
#endif
    return true;
}

void SalGenericLayoutGlyphsImpl::Invalidate()
{
    m_rFontInstance.clear();
    clear();
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx
index 6831950..4cbca56 100644
--- a/vcl/source/gdi/sallayout.cxx
+++ b/vcl/source/gdi/sallayout.cxx
@@ -704,7 +704,7 @@
// the text width is the maximum logical extent of all glyphs
DeviceCoordinate GenericSalLayout::GetTextWidth() const
{
    if( m_GlyphItems.empty() )
    if (!m_GlyphItems.IsValid())
        return 0;

    // initialize the extent
@@ -733,7 +733,7 @@
    if( !nOldWidth || nNewWidth==nOldWidth )
        return;

    if(m_GlyphItems.empty())
    if (!m_GlyphItems.IsValid())
    {
        return;
    }
diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
index eef0138..c67d275 100644
--- a/vcl/source/window/menu.cxx
+++ b/vcl/source/window/menu.cxx
@@ -987,7 +987,7 @@
    {
        pData->aText = rStr;
        // Clear layout for aText.
        pData->aTextGlyphs.clear();
        pData->aTextGlyphs.Invalidate();
        ImplSetMenuItemData( pData );
        // update native menu
        if( ImplGetSalMenu() && pData->pSalMenuItem )
diff --git a/vcl/source/window/menuitemlist.cxx b/vcl/source/window/menuitemlist.cxx
index c0496f1..6212794 100644
--- a/vcl/source/window/menuitemlist.cxx
+++ b/vcl/source/window/menuitemlist.cxx
@@ -41,7 +41,7 @@

SalLayoutGlyphs* MenuItemData::GetTextGlyphs(OutputDevice* pOutputDevice)
{
    if (!aTextGlyphs.empty())
    if (aTextGlyphs.IsValid())
        // Use pre-calculated result.
        return &aTextGlyphs;

diff --git a/vcl/unx/generic/glyphs/glyphcache.cxx b/vcl/unx/generic/glyphs/glyphcache.cxx
index 29e0d1b..b541fe1 100644
--- a/vcl/unx/generic/glyphs/glyphcache.cxx
+++ b/vcl/unx/generic/glyphs/glyphcache.cxx
@@ -46,6 +46,8 @@

void GlyphCache::ClearFontCache()
{
    for (auto &aFontPair : maFontList)
        static_cast<FreetypeFontInstance*>(aFontPair.first.get())->SetFreetypeFont(nullptr);
    maFontList.clear();
    mpCurrentGCFont = nullptr;
    m_aFontInfoList.clear();