Change GlyphItem::nFallbackLevel to font instance

No need for a real reference, as GlyphItems are bound to their
GenericSalLayout, which holds the valid reference and doesn't
allow font change.

Change-Id: I8e1129ef99f576e43d55f39aee040ceeb635d51d
Reviewed-on: https://gerrit.libreoffice.org/62359
Reviewed-by: Khaled Hosny <khaledhosny@eglug.org>
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
diff --git a/include/vcl/glyphitem.hxx b/include/vcl/glyphitem.hxx
index 39d99bf..306466b 100644
--- a/include/vcl/glyphitem.hxx
+++ b/include/vcl/glyphitem.hxx
@@ -41,10 +41,10 @@ struct VCL_DLLPUBLIC GlyphItem
    sal_GlyphId m_aGlyphId;
    Point m_aLinearPos; // absolute position of non rotated string

    int m_nFallbackLevel;
    LogicalFontInstance* m_pFontInstance;

    GlyphItem(int nCharPos, int nCharCount, sal_GlyphId aGlyphId, const Point& rLinearPos,
              long nFlags, int nOrigWidth, int nXOffset)
              long nFlags, int nOrigWidth, int nXOffset, LogicalFontInstance* pFontInstance)
        : m_nFlags(nFlags)
        , m_nCharPos(nCharPos)
        , m_nCharCount(nCharCount)
@@ -53,7 +53,7 @@ struct VCL_DLLPUBLIC GlyphItem
        , m_nXOffset(nXOffset)
        , m_aGlyphId(aGlyphId)
        , m_aLinearPos(rLinearPos)
        , m_nFallbackLevel(0)
        , m_pFontInstance(pFontInstance)
    {
    }

diff --git a/include/vcl/vcllayout.hxx b/include/vcl/vcllayout.hxx
index 81cb7be..3237973 100644
--- a/include/vcl/vcllayout.hxx
+++ b/include/vcl/vcllayout.hxx
@@ -96,8 +96,9 @@ public:
    virtual bool    IsKashidaPosValid ( int /*nCharPos*/ ) const { return true; } // i60594

    // methods using glyph indexing
    virtual bool    GetNextGlyph(const GlyphItem** pGlyph, Point& rPos, int&,
                                 const PhysicalFontFace** pFallbackFont = nullptr) const = 0;
    virtual bool    GetNextGlyph(const GlyphItem** pGlyph, Point& rPos, int& nStart,
                                 const PhysicalFontFace** pFallbackFont = nullptr,
                                 int* const pFallbackLevel = nullptr) const = 0;
    virtual bool    GetOutline( SalGraphics&, basegfx::B2DPolyPolygonVector& ) const;
    virtual bool    GetBoundRect( SalGraphics&, tools::Rectangle& ) const;

diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx
index ccaa4bd..6b2ca93 100644
--- a/vcl/inc/sallayout.hxx
+++ b/vcl/inc/sallayout.hxx
@@ -130,8 +130,9 @@ public:
    sal_Int32       GetTextBreak(DeviceCoordinate nMaxWidth, DeviceCoordinate nCharExtra, int nFactor) const override;
    DeviceCoordinate FillDXArray(DeviceCoordinate* pDXArray) const override;
    void            GetCaretPositions(int nArraySize, long* pCaretXArray) const override;
    bool            GetNextGlyph(const GlyphItem** pGlyph, Point& rPos, int&,
                                 const PhysicalFontFace** pFallbackFont = nullptr) const override;
    bool            GetNextGlyph(const GlyphItem** pGlyph, Point& rPos, int& nStart,
                                 const PhysicalFontFace** pFallbackFont = nullptr,
                                 int* const pFallbackLevel = nullptr) const override;
    bool            GetOutline(SalGraphics&, basegfx::B2DPolyPolygonVector&) const override;
    bool            IsKashidaPosValid(int nCharPos) const override;

@@ -182,8 +183,9 @@ public:
    // used by display layers
    LogicalFontInstance& GetFont() const { return *mpFont; }

    bool            GetNextGlyph(const GlyphItem** pGlyph, Point& rPos, int&,
                                 const PhysicalFontFace** pFallbackFont = nullptr) const final override;
    bool            GetNextGlyph(const GlyphItem** pGlyph, Point& rPos, int& nStart,
                                 const PhysicalFontFace** pFallbackFont = nullptr,
                                 int* const pFallbackLevel = nullptr) const override;

private:
    // for glyph+font+script fallback
diff --git a/vcl/inc/unx/freetype_glyphcache.hxx b/vcl/inc/unx/freetype_glyphcache.hxx
index 3a6a64f..58cd4eb 100644
--- a/vcl/inc/unx/freetype_glyphcache.hxx
+++ b/vcl/inc/unx/freetype_glyphcache.hxx
@@ -23,6 +23,7 @@
#include <unx/glyphcache.hxx>
#include <PhysicalFontFace.hxx>
#include <fontinstance.hxx>
#include <vcl/glyphitem.hxx>

// FreetypeFontFile has the responsibility that a font file is only mapped once.
// (#86621#) the old directly ft-managed solution caused it to be mapped
@@ -117,6 +118,14 @@ public:
    FreetypeFont* GetFreetypeFont() const { return mpFreetypeFont; }
};

inline FreetypeFont* getFreetypeFontFromGlyph(const GlyphItem& rGlyph)
{
    assert(rGlyph.m_pFontInstance);
    if (!rGlyph.m_pFontInstance)
        return nullptr;
    return static_cast<FreetypeFontInstance*>(rGlyph.m_pFontInstance)->GetFreetypeFont();
}

#endif // INCLUDED_VCL_GENERIC_GLYPHS_GCACH_FTYP_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qt5/Qt5Graphics_Text.cxx b/vcl/qt5/Qt5Graphics_Text.cxx
index 9f63924..79b5c8f 100644
--- a/vcl/qt5/Qt5Graphics_Text.cxx
+++ b/vcl/qt5/Qt5Graphics_Text.cxx
@@ -154,11 +154,7 @@ void Qt5Graphics::GetGlyphWidths(const PhysicalFontFace* /*pPFF*/, bool /*bVerti

bool Qt5Graphics::GetGlyphBoundRect(const GlyphItem& rGlyph, tools::Rectangle& rRect)
{
    const int nLevel = rGlyph.m_nFallbackLevel;
    if (nLevel >= MAX_FALLBACK)
        return false;

    Qt5Font* pFont = m_pTextStyle[nLevel].get();
    Qt5Font* pFont = static_cast<Qt5Font*>(rGlyph.m_pFontInstance);
    if (!pFont)
        return false;

diff --git a/vcl/quartz/salgdi.cxx b/vcl/quartz/salgdi.cxx
index bd7800d..639f54a 100644
--- a/vcl/quartz/salgdi.cxx
+++ b/vcl/quartz/salgdi.cxx
@@ -372,24 +372,12 @@ bool AquaSalGraphics::AddTempDevFont( PhysicalFontCollection*,

bool AquaSalGraphics::GetGlyphOutline(const GlyphItem& rGlyph, basegfx::B2DPolyPolygon& rPolyPoly)
{
    const int nFallbackLevel = rGlyph.m_nFallbackLevel;
    if (nFallbackLevel < MAX_FALLBACK && mpTextStyle[nFallbackLevel])
    {
        const bool bRC = mpTextStyle[nFallbackLevel]->GetGlyphOutline(rGlyph, rPolyPoly);
        return bRC;
    }
    return false;
    return static_cast<CoreTextStyle*>(rGlyph.m_pFontInstance)->GetGlyphOutline(rGlyph, rPolyPoly);
}

bool AquaSalGraphics::GetGlyphBoundRect(const GlyphItem& rGlyph, tools::Rectangle& rRect )
{
    const int nFallbackLevel = rGlyph.m_nFallbackLevel;
    if (nFallbackLevel < MAX_FALLBACK && mpTextStyle[nFallbackLevel])
    {
        const bool bRC = mpTextStyle[nFallbackLevel]->GetGlyphBoundRect(rGlyph, rRect);
        return bRC;
    }
    return false;
    return static_cast<CoreTextStyle*>(rGlyph.m_pFontInstance)->GetGlyphBoundRect(rGlyph, rRect);
}

void AquaSalGraphics::DrawTextLayout(const GenericSalLayout& rLayout)
diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx
index 5ea2f21d..8831d94 100644
--- a/vcl/source/gdi/CommonSalLayout.cxx
+++ b/vcl/source/gdi/CommonSalLayout.cxx
@@ -570,7 +570,7 @@ bool GenericSalLayout::LayoutText(ImplLayoutArgs& rArgs, const SalLayoutGlyphs* 

                Point aNewPos(aCurrPos.X() + nXOffset, aCurrPos.Y() + nYOffset);
                const GlyphItem aGI(nCharPos, nCharCount, nGlyphIndex, aNewPos, nGlyphFlags,
                                    nAdvance, nXOffset);
                                    nAdvance, nXOffset, mpFont.get());
                m_GlyphItems.push_back(aGI);

                aCurrPos.AdjustX(nAdvance );
@@ -767,7 +767,7 @@ void GenericSalLayout::ApplyDXArray(ImplLayoutArgs& rArgs)
            int const nFlags = GlyphItem::IS_IN_CLUSTER | GlyphItem::IS_RTL_GLYPH;
            while (nCopies--)
            {
                GlyphItem aKashida(nCharPos, 0, nKashidaIndex, aPos, nFlags, nKashidaWidth, 0);
                GlyphItem aKashida(nCharPos, 0, nKashidaIndex, aPos, nFlags, nKashidaWidth, 0, mpFont.get());
                pGlyphIter = m_GlyphItems.insert(pGlyphIter, aKashida);
                aPos.AdjustX(nKashidaWidth );
                aPos.AdjustX( -nOverlap );
diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx
index d33c488..3301369 100644
--- a/vcl/source/gdi/sallayout.cxx
+++ b/vcl/source/gdi/sallayout.cxx
@@ -893,7 +893,7 @@ sal_Int32 GenericSalLayout::GetTextBreak( DeviceCoordinate nMaxWidth, DeviceCoor

bool GenericSalLayout::GetNextGlyph(const GlyphItem** pGlyph,
                                    Point& rPos, int& nStart,
                                    const PhysicalFontFace** /*pFallbackFont*/) const
                                    const PhysicalFontFace**, int* const) const
{
    std::vector<GlyphItem>::const_iterator pGlyphIter = m_GlyphItems.begin();
    std::vector<GlyphItem>::const_iterator pGlyphIterEnd = m_GlyphItems.end();
@@ -1503,7 +1503,8 @@ void MultiSalLayout::GetCaretPositions( int nMaxIndex, long* pCaretXArray ) cons

bool MultiSalLayout::GetNextGlyph(const GlyphItem** pGlyph,
                                  Point& rPos, int& nStart,
                                  const PhysicalFontFace** pFallbackFont) const
                                  const PhysicalFontFace** pFallbackFont,
                                  int* const pFallbackLevel) const
{
    // NOTE: nStart is tagged with current font index
    int nLevel = static_cast<unsigned>(nStart) >> GF_FONTSHIFT;
@@ -1517,10 +1518,10 @@ bool MultiSalLayout::GetNextGlyph(const GlyphItem** pGlyph,
        {
            int nFontTag = nLevel << GF_FONTSHIFT;
            nStart |= nFontTag;
            // FIXME: This cast is ugly!
            const_cast<GlyphItem*>(*pGlyph)->m_nFallbackLevel = nLevel;
            if (pFallbackFont)
                *pFallbackFont = pFontFace;
            if (pFallbackLevel)
                *pFallbackLevel = nLevel;
            rPos += maDrawBase;
            rPos += maDrawOffset;
            return true;
diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx
index 5df1082..ce30eb4 100644
--- a/vcl/source/outdev/text.cxx
+++ b/vcl/source/outdev/text.cxx
@@ -2311,14 +2311,12 @@ SystemTextLayoutData OutputDevice::GetSysTextLayoutData(const Point& rStartPt, c
    Point aPos;
    const GlyphItem* pGlyph;
    int nStart = 0;
    while (pLayout->GetNextGlyph(&pGlyph, aPos, nStart))
    SystemGlyphData aSystemGlyph;
    while (pLayout->GetNextGlyph(&pGlyph, aPos, nStart, nullptr, &aSystemGlyph.fallbacklevel))
    {
        SystemGlyphData aSystemGlyph;
        aSystemGlyph.index = pGlyph->m_aGlyphId;
        aSystemGlyph.x = aPos.X();
        aSystemGlyph.y = aPos.Y();
        int nLevel = pGlyph->m_nFallbackLevel;
        aSystemGlyph.fallbacklevel = nLevel < MAX_FALLBACK ? nLevel : 0;
        aSysLayoutData.rGlyphData.push_back(aSystemGlyph);
    }

diff --git a/vcl/unx/generic/gdi/cairotextrender.cxx b/vcl/unx/generic/gdi/cairotextrender.cxx
index b7b8da8..13c8e15 100644
--- a/vcl/unx/generic/gdi/cairotextrender.cxx
+++ b/vcl/unx/generic/gdi/cairotextrender.cxx
@@ -444,11 +444,7 @@ void CairoTextRender::GetFontMetric( ImplFontMetricDataRef& rxFontMetric, int nF

bool CairoTextRender::GetGlyphBoundRect(const GlyphItem& rGlyph, tools::Rectangle& rRect)
{
    const int nLevel = rGlyph.m_nFallbackLevel;
    if( nLevel >= MAX_FALLBACK )
        return false;

    FreetypeFont* pSF = mpFreetypeFont[ nLevel ];
    FreetypeFont* pSF = getFreetypeFontFromGlyph(rGlyph);
    if( !pSF )
        return false;

@@ -475,11 +471,7 @@ bool CairoTextRender::GetGlyphBoundRect(const GlyphItem& rGlyph, tools::Rectangl
bool CairoTextRender::GetGlyphOutline(const GlyphItem& rGlyph,
    basegfx::B2DPolyPolygon& rPolyPoly )
{
    const int nLevel = rGlyph.m_nFallbackLevel;
    if( nLevel >= MAX_FALLBACK )
        return false;

    const FreetypeFont* pSF = mpFreetypeFont[ nLevel ];
    const FreetypeFont* pSF = getFreetypeFontFromGlyph(rGlyph);
    if( !pSF )
        return false;

diff --git a/vcl/unx/generic/print/genpspgraphics.cxx b/vcl/unx/generic/print/genpspgraphics.cxx
index 5350bfc..6762117 100644
--- a/vcl/unx/generic/print/genpspgraphics.cxx
+++ b/vcl/unx/generic/print/genpspgraphics.cxx
@@ -735,11 +735,7 @@ void GenPspGraphics::GetFontMetric(ImplFontMetricDataRef& rxFontMetric, int nFal

bool GenPspGraphics::GetGlyphBoundRect(const GlyphItem& rGlyph, tools::Rectangle& rRect)
{
    const int nLevel = rGlyph.m_nFallbackLevel;
    if( nLevel >= MAX_FALLBACK )
        return false;

    FreetypeFont* pSF = m_pFreetypeFont[ nLevel ];
    FreetypeFont* pSF = getFreetypeFontFromGlyph(rGlyph);
    if( !pSF )
        return false;

@@ -749,11 +745,7 @@ bool GenPspGraphics::GetGlyphBoundRect(const GlyphItem& rGlyph, tools::Rectangle
bool GenPspGraphics::GetGlyphOutline(const GlyphItem& rGlyph,
    basegfx::B2DPolyPolygon& rB2DPolyPoly )
{
    const int nLevel = rGlyph.m_nFallbackLevel;
    if( nLevel >= MAX_FALLBACK )
        return false;

    FreetypeFont* pSF = m_pFreetypeFont[ nLevel ];
    FreetypeFont* pSF = getFreetypeFontFromGlyph(rGlyph);
    if( !pSF )
        return false;

diff --git a/vcl/win/gdi/salfont.cxx b/vcl/win/gdi/salfont.cxx
index 8ee9c60..b5a0efbf 100644
--- a/vcl/win/gdi/salfont.cxx
+++ b/vcl/win/gdi/salfont.cxx
@@ -1328,7 +1328,7 @@ void WinSalGraphics::ClearDevFontCache()

bool WinSalGraphics::GetGlyphBoundRect(const GlyphItem& rGlyph, tools::Rectangle& rRect)
{
    rtl::Reference<WinFontInstance> pFont = mpWinFontEntry[rGlyph.m_nFallbackLevel];
    rtl::Reference<WinFontInstance> pFont = static_cast<WinFontInstance*>(rGlyph.m_pFontInstance);
    assert(pFont.is());

    if (pFont.is() && pFont->GetCachedGlyphBoundRect(rGlyph.m_aGlyphId, rRect))
@@ -1546,7 +1546,7 @@ bool WinSalGraphics::GetGlyphOutline(const GlyphItem& rGlyph,
    // rescaling needed for the tools::PolyPolygon conversion
    if( rB2DPolyPoly.count() )
    {
        rtl::Reference<WinFontInstance> pFont = mpWinFontEntry[rGlyph.m_nFallbackLevel];
        rtl::Reference<WinFontInstance> pFont = static_cast<WinFontInstance*>(rGlyph.m_pFontInstance);
        assert(pFont.is());
        float fFontScale = pFont.is() ? pFont->GetScale() : 1.0;
        const double fFactor(fFontScale/256);