summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorChris Sherlock <chris.sherlock79@gmail.com>2023-11-09 18:19:41 +1100
committerTomaž Vajngerl <quikee@gmail.com>2023-12-05 04:39:05 +0100
commit042dc4a9186f526b625817dde50bb2f5a91fd2c6 (patch)
treedcb3195ade7cae900ffc49bcf0fe80fb5a388c86 /vcl
parent1a74a87b442857567d20da5dc97bbbc278745afd (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.cxx37
-rw-r--r--vcl/source/outdev/font.cxx32
-rw-r--r--vcl/source/outdev/outdev.cxx6
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();