diff options
author | Chris Sherlock <chris.sherlock79@gmail.com> | 2023-11-09 18:19:41 +1100 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2023-12-05 04:39:05 +0100 |
commit | 042dc4a9186f526b625817dde50bb2f5a91fd2c6 (patch) | |
tree | dcb3195ade7cae900ffc49bcf0fe80fb5a388c86 /vcl | |
parent | 1a74a87b442857567d20da5dc97bbbc278745afd (diff) |
vcl: add unit tests for a mixture of CJK and latin characters
To influence the fallback fonts chosen, I have introduced a new
OutputDevice function ForceFallbackFont() which injects ("forces") a
font as the first one in the font fallback chain.
Change-Id: I05856cbe829fde0eb140bb48a37795a84d780900
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159221
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/qa/cppunit/complextext.cxx | 37 | ||||
-rw-r--r-- | vcl/source/outdev/font.cxx | 32 | ||||
-rw-r--r-- | vcl/source/outdev/outdev.cxx | 6 |
3 files changed, 69 insertions, 6 deletions
diff --git a/vcl/qa/cppunit/complextext.cxx b/vcl/qa/cppunit/complextext.cxx index 633dc2210e07..d4eb3db67093 100644 --- a/vcl/qa/cppunit/complextext.cxx +++ b/vcl/qa/cppunit/complextext.cxx @@ -491,6 +491,40 @@ CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testTdf153440) #endif } +CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testMixedCJKLatinScript_glyph_advancements) +{ +#if HAVE_MORE_FONTS +#if !defined _WIN32 + OUString aTestScript(u"根据10.1(37BA) Eng"_ustr); + + ScopedVclPtrInstance<VirtualDevice> pOutDev; + // note you can only run this once and it was designed for tdf#107718 + bool bAdded = addFont(pOutDev, u"tdf107718.otf", u"Source Han Sans"); + CPPUNIT_ASSERT_EQUAL(true, bAdded); + + vcl::Font aFont(u"Source Han Sans"_ustr, u"Regular"_ustr, Size(0, 72)); + pOutDev->SetFont( aFont ); + + vcl::Font aFallbackFont("DejaVu Sans", "Book", Size(0, 72)); + pOutDev->ForceFallbackFont(aFallbackFont); + + // absolute character widths AKA text array. + tools::Long nRefTextWidth = 704; + std::vector<sal_Int32> aRefCharWidths = { 72, 144, 190, 236, 259, 305, 333, 379, 425, 474, 523, 551, 567, 612, 658, 704 }; + KernArray aCharWidths; + tools::Long nTextWidth = pOutDev->GetTextArray(aTestScript, &aCharWidths); + + CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths.get_subunit_array()); + CPPUNIT_ASSERT_EQUAL(nRefTextWidth, nTextWidth); + CPPUNIT_ASSERT_EQUAL(sal_Int32(nTextWidth), aCharWidths.back()); + + // text advance width and line height + CPPUNIT_ASSERT_EQUAL(nRefTextWidth, pOutDev->GetTextWidth(aTestScript)); + CPPUNIT_ASSERT_EQUAL(tools::Long(105), pOutDev->GetTextHeight()); +#endif +#endif +} + CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testTdf107718) { #if !defined _WIN32 // TODO: Fails on jenkins but passes locally @@ -498,9 +532,6 @@ CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testTdf107718) ScopedVclPtrInstance<VirtualDevice> pOutDev; - bool bAdded = addFont(pOutDev, u"tdf107718.otf", u"Source Han Sans"); - CPPUNIT_ASSERT_EQUAL(true, bAdded); - OUString aText(u"\u4E16\u1109\u1168\u11BC\u302E"_ustr); for (bool bVertical : { false, true }) { diff --git a/vcl/source/outdev/font.cxx b/vcl/source/outdev/font.cxx index ea0727b294f9..0e37c7613ded 100644 --- a/vcl/source/outdev/font.cxx +++ b/vcl/source/outdev/font.cxx @@ -1020,6 +1020,22 @@ std::unique_ptr<SalLayout> OutputDevice::getFallbackLayout( return pFallback; } +bool OutputDevice::ForceFallbackFont(vcl::Font const& rFallbackFont) +{ + vcl::Font aOldFont = GetFont(); + SetFont(rFallbackFont); + InitFont(); + + mpForcedFallbackInstance = mpFontInstance; + SetFont(aOldFont); + InitFont(); + + if (mpForcedFallbackInstance) + return true; + + return false; +} + std::unique_ptr<SalLayout> OutputDevice::ImplGlyphFallbackLayout( std::unique_ptr<SalLayout> pSalLayout, vcl::text::ImplLayoutArgs& rLayoutArgs, const SalLayoutGlyphs* pGlyphs ) const { @@ -1051,12 +1067,22 @@ std::unique_ptr<SalLayout> OutputDevice::ImplGlyphFallbackLayout( std::unique_pt vcl::font::FontSelectPattern aFontSelData(mpFontInstance->GetFontSelectPattern()); SalLayoutGlyphsImpl* pGlyphsImpl = pGlyphs ? pGlyphs->Impl(1) : nullptr; + bool bHasUsedFallback = false; + // try if fallback fonts support the missing code units for( int nFallbackLevel = 1; nFallbackLevel < MAX_FALLBACK; ++nFallbackLevel ) { rtl::Reference<LogicalFontInstance> pFallbackFont; - if(pGlyphsImpl != nullptr) + if (!bHasUsedFallback && mpForcedFallbackInstance) + { + pFallbackFont = mpForcedFallbackInstance; + bHasUsedFallback = true; + } + else 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 @@ -1067,6 +1093,9 @@ std::unique_ptr<SalLayout> OutputDevice::ImplGlyphFallbackLayout( std::unique_pt if( !pFallbackFont ) break; + SAL_INFO("vcl", "Fallback font (level " << nFallbackLevel << "): family: " << pFallbackFont->GetFontFace()->GetFamilyName() + << ", style: " << pFallbackFont->GetFontFace()->GetStyleName()); + if( nFallbackLevel < MAX_FALLBACK-1) { // ignore fallback font if it is the same as the original font @@ -1255,6 +1284,7 @@ void OutputDevice::ImplReleaseFonts() mbInitFont = true; mpFontInstance.clear(); + mpForcedFallbackInstance.clear(); mpFontFaceCollection.reset(); } diff --git a/vcl/source/outdev/outdev.cxx b/vcl/source/outdev/outdev.cxx index b4c1eac4499e..828a121cca91 100644 --- a/vcl/source/outdev/outdev.cxx +++ b/vcl/source/outdev/outdev.cxx @@ -67,8 +67,9 @@ OutputDevice::OutputDevice(OutDevType eOutDevType) : mpPrevGraphics = nullptr; mpNextGraphics = nullptr; mpMetaFile = nullptr; - mpFontInstance = nullptr; - mpFontFaceCollection = nullptr; + mpFontInstance = nullptr; + mpForcedFallbackInstance = nullptr; + mpFontFaceCollection = nullptr; mpAlphaVDev = nullptr; mpExtOutDevData = nullptr; mnOutOffX = 0; @@ -166,6 +167,7 @@ void OutputDevice::dispose() // release the active font instance mpFontInstance.clear(); + mpForcedFallbackInstance.clear(); // remove cached results of GetDevFontList/GetDevSizeList mpFontFaceCollection.reset(); |