diff options
author | Khaled Hosny <khaled@libreoffice.org> | 2023-07-30 07:12:53 +0300 |
---|---|---|
committer | خالد حسني <khaled@libreoffice.org> | 2023-07-30 09:50:11 +0200 |
commit | d4653fa961b1aa1cd4bf568e7d1fe50ae97df484 (patch) | |
tree | a18a52cd123a3782263d2630c50e79169fa07fbe /vcl | |
parent | 49fc6598426fb4552904c66702cddc6534124227 (diff) |
tdf#107612: Include NNBSP and Mongolian characters in the same fallback run
When a Mongolian character is preceded by a Narrow No Break Space
(NNBSP), it is used to trigger special letter forms, but when we do font
fallback NNBSP is always taken from the main font (HarfBuzz synthesises
it when missing from the font, so we almost never use font fallback for
it).
We now check if the start of the fallback run is a Mongolian character
and the previous is NNBSP and extend the fallback run to include it.
Change-Id: I7607dba37ee51ff62bc9e86c3dbc555cd77e8d5d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155060
Tested-by: Jenkins
Reviewed-by: خالد حسني <khaled@libreoffice.org>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/sallayout.hxx | 4 | ||||
-rw-r--r-- | vcl/qa/cppunit/complextext.cxx | 33 | ||||
-rw-r--r-- | vcl/source/gdi/CommonSalLayout.cxx | 15 |
3 files changed, 51 insertions, 1 deletions
diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx index dbe3000f8a83..94f0086b1517 100644 --- a/vcl/inc/sallayout.hxx +++ b/vcl/inc/sallayout.hxx @@ -57,7 +57,7 @@ namespace vcl::text { class TextLayoutCache; } -class MultiSalLayout final : public SalLayout +class VCL_DLLPUBLIC MultiSalLayout final : public SalLayout { public: void DrawText(SalGraphics&) const override; @@ -86,6 +86,8 @@ public: vcl::text::ImplLayoutArgs& rMultiArgs, const double* pMultiDXArray); + SAL_DLLPRIVATE ImplLayoutRuns* GetFallbackRuns() { return maFallbackRuns; } + virtual ~MultiSalLayout() override; private: diff --git a/vcl/qa/cppunit/complextext.cxx b/vcl/qa/cppunit/complextext.cxx index bcb0c9622361..ec6ce0ccd0e2 100644 --- a/vcl/qa/cppunit/complextext.cxx +++ b/vcl/qa/cppunit/complextext.cxx @@ -540,4 +540,37 @@ CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testTdf107718) #endif } +CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testTdf107612) +{ +#if HAVE_MORE_FONTS + vcl::Font aFont(u"DejaVu Sans", u"Book", Size(0, 72)); + + ScopedVclPtrInstance<VirtualDevice> pOutDev; + pOutDev->SetFont(aFont); + + auto pLayout = pOutDev->ImplLayout(u"a\u202F\u1823", 0, -1, Point(0, 0), 0, {}, {}); + + // If font fallback happened, then the returned layout must be a + // MultiSalLayout instance. + auto pMultiLayout = dynamic_cast<MultiSalLayout*>(pLayout.get()); + CPPUNIT_ASSERT(pMultiLayout); + + auto pFallbackRuns = pMultiLayout->GetFallbackRuns(); + CPPUNIT_ASSERT(!pFallbackRuns->IsEmpty()); + + bool bRTL; + int nCharPos = -1; + std::vector<sal_Int32> aFallbacks; + while (pFallbackRuns->GetNextPos(&nCharPos, &bRTL)) + aFallbacks.push_back(nCharPos); + + // Assert that U+202F is included in the fallback run. + // Without the fix this fails with: + // - Expected: { 2 } + // - Actual : { 1, 2 } + std::vector<sal_Int32> aExpctedFallbacks = { 1, 2 }; + CPPUNIT_ASSERT_EQUAL(aFallbacks, aExpctedFallbacks); +#endif +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx index 3a5fdbef0ad0..79f1a0d2c40c 100644 --- a/vcl/source/gdi/CommonSalLayout.cxx +++ b/vcl/source/gdi/CommonSalLayout.cxx @@ -128,6 +128,21 @@ void GenericSalLayout::SetNeedFallback(vcl::text::ImplLayoutArgs& rArgs, sal_Int mxBreak->previousCharacters(rArgs.mrStr, nCharPos, aLocale, i18n::CharacterIteratorMode::SKIPCELL, 1, nDone); + // tdf#107612 + // If the start of the fallback run is Mongolian character and the previous + // character is NNBSP, we want to include the NNBSP in the fallback since + // it has special uses in Mongolian and have to be in the same text run to + // work. + sal_Int32 nTempPos = nGraphemeStartPos; + if (nGraphemeStartPos > 0) + { + auto nCurrChar = rArgs.mrStr.iterateCodePoints(&nTempPos, 0); + auto nPrevChar = rArgs.mrStr.iterateCodePoints(&nTempPos, -1); + if (nPrevChar == 0x202F + && u_getIntPropertyValue(nCurrChar, UCHAR_SCRIPT) == USCRIPT_MONGOLIAN) + nGraphemeStartPos = nTempPos; + } + //stay inside the Layout range (e.g. with tdf124116-1.odt) nGraphemeStartPos = std::max(rArgs.mnMinCharPos, nGraphemeStartPos); nGraphemeEndPos = std::min(rArgs.mnEndCharPos, nGraphemeEndPos); |