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;
}