tdf#142560 handle cached glpyh items in ImplGlyphFallbackLayout

Fallback layout beyond level1 isn't generated because pre-caculated
glyph items does not contain glyph items that needs to fallback, i.e.
when calling ImplLayoutArgs::PrepareFallback. Hence it produce no
maFallbackRuns and maRuns. The patch changes
ImplLayoutArgs::PrepareFallback so that it use pre-caculated glyph
items in the next level to create maRuns to ensure the same fallback
layouts are genrated as layouts generated without pre-caculated glyph
items.

Change-Id: I672f3be6c4915892792b3cb968ad4a325465ccc0
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117105
Tested-by: Jenkins
Reviewed-by: Mark Hung <marklh9@gmail.com>
(cherry picked from commit 10ea27faec115d4cffd6f66cee8f688399e1e0b2)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117570
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx
index 3852442..f6783f3 100644
--- a/vcl/inc/sallayout.hxx
+++ b/vcl/inc/sallayout.hxx
@@ -114,7 +114,7 @@ public:
    // methods used by BiDi and glyph fallback
    bool        NeedFallback() const
                    { return !maFallbackRuns.IsEmpty(); }
    bool        PrepareFallback();
    bool        PrepareFallback(const SalLayoutGlyphsImpl* pGlyphsImpl);

private:
    void        AddRun( int nMinCharPos, int nEndCharPos, bool bRTL );
diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx
index 9f47571..7b8f2c2 100644
--- a/vcl/source/gdi/sallayout.cxx
+++ b/vcl/source/gdi/sallayout.cxx
@@ -486,8 +486,23 @@ void ImplLayoutArgs::AddRun( int nCharPos0, int nCharPos1, bool bRTL )
    maRuns.AddRun( nCharPos0, nCharPos1, bRTL );
}

bool ImplLayoutArgs::PrepareFallback()
bool ImplLayoutArgs::PrepareFallback(const SalLayoutGlyphsImpl* pGlyphsImpl)
{
    // Generate runs with pre-calculated glyph items instead maFallbackRuns.
    if( pGlyphsImpl != nullptr )
    {
        maRuns.Clear();
        maFallbackRuns.Clear();

        for (auto const& aGlyphItem : *pGlyphsImpl)
        {
            for(int i = aGlyphItem.charPos(); i < aGlyphItem.charPos() + aGlyphItem.charCount(); ++i)
                maRuns.AddPos(i, aGlyphItem.IsRTLGlyph());
        }

        return !maRuns.IsEmpty();
    }

    // short circuit if no fallback is needed
    if( maFallbackRuns.IsEmpty() )
    {
diff --git a/vcl/source/outdev/font.cxx b/vcl/source/outdev/font.cxx
index b6c7fcf..6c761ec 100644
--- a/vcl/source/outdev/font.cxx
+++ b/vcl/source/outdev/font.cxx
@@ -1254,7 +1254,7 @@ std::unique_ptr<SalLayout> OutputDevice::ImplGlyphFallbackLayout( std::unique_pt
    // prepare multi level glyph fallback
    std::unique_ptr<MultiSalLayout> pMultiSalLayout;
    ImplLayoutRuns aLayoutRuns = rLayoutArgs.maRuns;
    rLayoutArgs.PrepareFallback();
    rLayoutArgs.PrepareFallback(nullptr);
    rLayoutArgs.mnFlags |= SalLayoutFlags::ForFallback;

    // get list of code units that need glyph fallback
@@ -1267,13 +1267,14 @@ std::unique_ptr<SalLayout> OutputDevice::ImplGlyphFallbackLayout( std::unique_pt
    OUString aMissingCodes = aMissingCodeBuf.makeStringAndClear();

    FontSelectPattern aFontSelData(mpFontInstance->GetFontSelectPattern());
    SalLayoutGlyphsImpl* pGlyphsImpl = pGlyphs ? pGlyphs->Impl(1) : nullptr;

    // try if fallback fonts support the missing code units
    for( int nFallbackLevel = 1; nFallbackLevel < MAX_FALLBACK; ++nFallbackLevel )
    {
        rtl::Reference<LogicalFontInstance> pFallbackFont;
        if(pGlyphs != nullptr && pGlyphs->Impl(nFallbackLevel) != nullptr)
            pFallbackFont = pGlyphs->Impl(nFallbackLevel)->GetFont();
        if(pGlyphsImpl != nullptr)
            pFallbackFont = pGlyphsImpl->GetFont();
        // find a font family suited for glyph fallback
        // GetGlyphFallbackFont() needs a valid FontInstance
        // if the system-specific glyph fallback is active
@@ -1307,8 +1308,11 @@ std::unique_ptr<SalLayout> OutputDevice::ImplGlyphFallbackLayout( std::unique_pt
                pMultiSalLayout->SetIncomplete(true);
        }

        if (pGlyphs != nullptr)
            pGlyphsImpl = pGlyphs->Impl(nFallbackLevel + 1);

        // break when this fallback was sufficient
        if( !rLayoutArgs.PrepareFallback() )
        if( !rLayoutArgs.PrepareFallback(pGlyphsImpl) )
            break;
    }