editeng/qa/unit/core-test.cxx | 64 ++++++++++++++++++++++++++++++++++++ editeng/source/editeng/impedit3.cxx | 2 + 2 files changed, 66 insertions(+)
New commits: commit 7ff601feca1796b6656e66c7ce2e77edcf0bdd67 Author: Jonathan Clark <jonat...@libreoffice.org> AuthorDate: Wed Sep 4 03:16:06 2024 -0600 Commit: Jonathan Clark <jonat...@libreoffice.org> CommitDate: Wed Sep 4 19:29:51 2024 +0200 tdf#151748 editeng: Fix crash in kashida justification after update Commit 937023bca427f803a9e7085d5090d5d2b17623ed aggravated a bug that would cause editeng to use stale kashida positions after document changes (for example, font changes). This could cause crashes or spurious kashida, and both much more often after the above commit. This change fixes the underlying logic error. Change-Id: Id6465e739740a38ed11c9d9378d30faa51948731 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/172866 Reviewed-by: Jonathan Clark <jonat...@libreoffice.org> Tested-by: Jenkins diff --git a/editeng/qa/unit/core-test.cxx b/editeng/qa/unit/core-test.cxx index 1286c7ade36a..7c6ff42a05b8 100644 --- a/editeng/qa/unit/core-test.cxx +++ b/editeng/qa/unit/core-test.cxx @@ -18,6 +18,7 @@ #include <sfx2/app.hxx> #include <svl/itempool.hxx> +#include <editeng/adjustitem.hxx> #include <editeng/editeng.hxx> #include <editeng/eeitem.hxx> #include <editeng/lspcitem.hxx> @@ -127,6 +128,7 @@ public: void testMoveParagraph(); void testCreateLines(); void testTdf154248MultilineFieldWrapping(); + void testTdf151748StaleKashidaArray(); DECL_STATIC_LINK(Test, CalcFieldValueHdl, EditFieldInfo*, void); @@ -159,6 +161,7 @@ public: CPPUNIT_TEST(testMoveParagraph); CPPUNIT_TEST(testCreateLines); CPPUNIT_TEST(testTdf154248MultilineFieldWrapping); + CPPUNIT_TEST(testTdf151748StaleKashidaArray); CPPUNIT_TEST_SUITE_END(); private: @@ -2239,6 +2242,67 @@ void Test::testTdf154248MultilineFieldWrapping() } } +void Test::testTdf151748StaleKashidaArray() +{ + ScopedVclPtrInstance<VirtualDevice> pVirtualDevice(DeviceFormat::WITHOUT_ALPHA); + + EditEngine aEditEngine(mpItemPool.get()); + aEditEngine.SetRefDevice(pVirtualDevice.get()); + aEditEngine.SetPaperSize(Size(1500, 500)); + aEditEngine.SetDefaultHorizontalTextDirection(EEHorizontalTextDirection::R2L); + aEditEngine.SetText(u"خط تخوردگی و توسط"_ustr); + + CPPUNIT_ASSERT_EQUAL(true, aEditEngine.IsFormatted()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aEditEngine.GetParagraphCount()); + + SfxItemSet aSet{ aEditEngine.GetParaAttribs(0) }; + aSet.Put(SvxAdjustItem{ SvxAdjust::Block, EE_PARA_JUST }); + aEditEngine.SetParaAttribs(0, aSet); + + CPPUNIT_ASSERT_EQUAL(SvxAdjust::Block, aEditEngine.GetParaAttrib(0, EE_PARA_JUST).GetAdjust()); + CPPUNIT_ASSERT_EQUAL(true, aEditEngine.IsFormatted()); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aEditEngine.GetLineCount(0)); + + // Initial state: Check that a kashida array has been created + { + ParaPortionList& rParagraphPortionList = aEditEngine.GetParaPortions(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rParagraphPortionList.Count()); + + EditLineList& rLines = rParagraphPortionList.getRef(0).GetLines(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), rLines.Count()); + EditLine const& rLine = rLines[0]; + + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), rLine.GetStart()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(11), rLine.GetEnd()); + + std::vector<sal_Bool> const& rArray = rLine.GetKashidaArray(); + CPPUNIT_ASSERT_EQUAL(size_t(17), rArray.size()); + } + + // Resize the paper so there is no longer room for kashida + aEditEngine.SetPaperSize(Size(1400, 500)); + + // Follow-up state: Check that the kashida array has been cleared + { + ParaPortionList& rParagraphPortionList = aEditEngine.GetParaPortions(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rParagraphPortionList.Count()); + + EditLineList& rLines = rParagraphPortionList.getRef(0).GetLines(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), rLines.Count()); + EditLine const& rLine = rLines[0]; + + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), rLine.GetStart()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(11), rLine.GetEnd()); + + std::vector<sal_Bool> const& rArray = rLine.GetKashidaArray(); + + // Since there is no room for kashida, the kashida array should be empty. + // Without the bug fix, this will be 17: + CPPUNIT_ASSERT_EQUAL(size_t(0), rArray.size()); + } +} + CPPUNIT_TEST_SUITE_REGISTRATION(Test); } diff --git a/editeng/source/editeng/impedit3.cxx b/editeng/source/editeng/impedit3.cxx index 3cd8ef12eb4d..d7c3111d9e8e 100644 --- a/editeng/source/editeng/impedit3.cxx +++ b/editeng/source/editeng/impedit3.cxx @@ -2378,6 +2378,8 @@ void ImpEditEngine::ImpAdjustBlocks(ParaPortion& rParaPortion, EditLine& rLine, // Mark Kashida positions, so that VCL knows where to insert Kashida and // where to only expand the width. + // The underlying array may be reused across updates. Ensure there is no stale data. + rLine.GetKashidaArray().clear(); if (nKashidas) { rLine.GetKashidaArray().resize(rLine.GetCharPosArray().size(), false);