vcl/qa/cppunit/complextext.cxx |   82 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)

New commits:
commit 70c3803c15d579d5a448e397b4c0988f71e20e2b
Author:     Jonathan Clark <jonat...@libreoffice.org>
AuthorDate: Thu Jun 26 06:33:22 2025 -0600
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Thu Jun 26 22:50:23 2025 +0200

    vcl: Improve test coverage for MultiSalLayout
    
    Added missing unit tests for text layout with fallback runs.
    
    Related: tdf#154104
    Related: tdf#163761
    Change-Id: I489691f7afaa24491ebd0a5660b08b0440ecbc7f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187049
    Tested-by: Jenkins
    Reviewed-by: Jonathan Clark <jonat...@libreoffice.org>
    (cherry picked from commit 1394a23365a793c41fdc799d63d71aaa96510b02)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187069
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/vcl/qa/cppunit/complextext.cxx b/vcl/qa/cppunit/complextext.cxx
index e344c7720bcf..9be428b59128 100644
--- a/vcl/qa/cppunit/complextext.cxx
+++ b/vcl/qa/cppunit/complextext.cxx
@@ -792,4 +792,86 @@ CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testTdf165510)
     }
 }
 
+CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testTdf154104)
+{
+    ScopedVclPtrInstance<VirtualDevice> pOutDev;
+
+    vcl::Font aBaseFont{ u"David Libre"_ustr, u"Regular"_ustr, Size{ 0, 72 } };
+    pOutDev->SetFont(aBaseFont);
+
+    vcl::Font aFallbackFont{ u"Noto Sans Arabic"_ustr, u"Regular"_ustr, Size{ 
0, 72 } };
+    pOutDev->ForceFallbackFont(aFallbackFont);
+
+    pOutDev->SetLayoutMode(vcl::text::ComplexTextLayoutFlags::BiDiRtl
+                           | vcl::text::ComplexTextLayoutFlags::BiDiStrong);
+
+    auto aText = u"\u05D0\u05D0\u05D0\u0644\u0627"_ustr;
+    KernArray aKernArray = { 100, 200, 300, 350, 400 };
+    auto pLayout = pOutDev->ImplLayout(aText, /*nIndex*/ 0, /*nLen*/ 
aText.getLength(),
+                                       /*rLogicPos*/ Point(0, 0), 
/*nLogicWidth*/ 0, aKernArray);
+
+    // Fallback must have happened for this test to be meaningful
+    auto pMultiLayout = dynamic_cast<MultiSalLayout*>(pLayout.get());
+    CPPUNIT_ASSERT(pMultiLayout);
+
+    std::vector<double> aCharX;
+
+    const GlyphItem* pGlyph = nullptr;
+    basegfx::B2DPoint stPos;
+    int nCurrPos = 0;
+    while (pLayout->GetNextGlyph(&pGlyph, stPos, nCurrPos))
+    {
+        aCharX.push_back(stPos.getX());
+    }
+
+    // tdf#154104 caused overlapping glyphs in fallback runs:
+    //                           { -295.0, -195.0, -95.0, -341.0 }
+    std::vector<double> aRefCharX{ -245.0, -145.0, -45.0, -341.0 };
+
+    CPPUNIT_ASSERT_EQUAL(aRefCharX.size(), aCharX.size());
+    for (size_t i = 0; i < aRefCharX.size(); ++i)
+    {
+        CPPUNIT_ASSERT_DOUBLES_EQUAL(aRefCharX.at(i), aCharX.at(i), /*delta*/ 
0.2);
+    }
+}
+
+CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testTdf163761)
+{
+    ScopedVclPtrInstance<VirtualDevice> pOutDev;
+
+    vcl::Font aBaseFont{ u"Noto Sans"_ustr, u"Regular"_ustr, Size{ 0, 72 } };
+    pOutDev->SetFont(aBaseFont);
+
+    vcl::Font aFallbackFont{ u"David Libre"_ustr, u"Regular"_ustr, Size{ 0, 72 
} };
+    pOutDev->ForceFallbackFont(aFallbackFont);
+
+    auto aText = 
u"\u05DC\u0020\u05E0\u05EA\u05D9\u05D1\u05D9\u05BE\u200F\u05E4"_ustr;
+    auto pLayout = pOutDev->ImplLayout(aText, /*nIndex*/ 0, /*nLen*/ 
aText.getLength());
+
+    // Fallback must have happened for this test to be meaningful
+    auto pMultiLayout = dynamic_cast<MultiSalLayout*>(pLayout.get());
+    CPPUNIT_ASSERT(pMultiLayout);
+
+    std::vector<int> aCharIndices;
+
+    const GlyphItem* pGlyph = nullptr;
+    basegfx::B2DPoint stPos;
+    int nCurrPos = 0;
+    while (pLayout->GetNextGlyph(&pGlyph, stPos, nCurrPos))
+    {
+        aCharIndices.push_back(pGlyph->charPos());
+    }
+
+    // tdf#163761 caused failure to remove dropped glyphs from the base layout.
+    // Without the fix, the base layout will contain an errant copy of char 0.
+    //                              { 1, 0, 9, 7, 6, 5, 4, 3, 2, 0 }
+    std::vector<int> aRefCharIndices{ 1, 9, 7, 6, 5, 4, 3, 2, 0 };
+
+    CPPUNIT_ASSERT_EQUAL(aRefCharIndices.size(), aCharIndices.size());
+    for (size_t i = 0; i < aRefCharIndices.size(); ++i)
+    {
+        CPPUNIT_ASSERT_EQUAL(aRefCharIndices.at(i), aCharIndices.at(i));
+    }
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to