editeng/qa/unit/core-test.cxx                |   14 +++----
 editeng/source/editeng/impedit3.cxx          |   48 ++++++++++++------------
 include/vcl/outdev.hxx                       |   10 -----
 vcl/qa/cppunit/pdfexport/data/tdf151748.fodt |   53 ++++++++++++---------------
 vcl/qa/cppunit/pdfexport/pdfexport2.cxx      |   16 ++++----
 vcl/source/outdev/font.cxx                   |   47 -----------------------
 6 files changed, 64 insertions(+), 124 deletions(-)

New commits:
commit 3c9fdd9aeb74d76ef7f1c0581582439c8a135532
Author:     Jonathan Clark <jonat...@libreoffice.org>
AuthorDate: Wed Apr 16 05:00:25 2025 -0600
Commit:     Jonathan Clark <jonat...@libreoffice.org>
CommitDate: Wed Apr 16 17:38:33 2025 +0200

    tdf#163618 editeng: Fix excessive overlap in justified Arabic script
    
    Fixes a bug causing editeng to insert kashida glyphs in positions where
    there is not enough space for them. The root cause was failing to
    account for the extra space used by blanks while rejecting candidate
    kashida positions.
    
    Change-Id: I1e22f758af0a88c2070f31cca040570f3a730c08
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184282
    Tested-by: Jenkins
    Reviewed-by: Jonathan Clark <jonat...@libreoffice.org>

diff --git a/editeng/qa/unit/core-test.cxx b/editeng/qa/unit/core-test.cxx
index 029df4439dee..5484593ad9c5 100644
--- a/editeng/qa/unit/core-test.cxx
+++ b/editeng/qa/unit/core-test.cxx
@@ -2251,9 +2251,9 @@ void Test::testTdf151748StaleKashidaArray()
 
     EditEngine aEditEngine(mpItemPool.get());
     aEditEngine.SetRefDevice(pVirtualDevice.get());
-    aEditEngine.SetPaperSize(Size(1500, 500));
+    aEditEngine.SetPaperSize(Size(1600, 500));
     
aEditEngine.SetDefaultHorizontalTextDirection(EEHorizontalTextDirection::R2L);
-    aEditEngine.SetText(u"خط تخوردگی و توسط"_ustr);
+    aEditEngine.SetText(u"خط تخوردگی وتوسسسسط"_ustr);
 
     CPPUNIT_ASSERT_EQUAL(true, aEditEngine.IsFormatted());
     CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aEditEngine.GetParagraphCount());
@@ -2280,7 +2280,7 @@ void Test::testTdf151748StaleKashidaArray()
         CPPUNIT_ASSERT_EQUAL(sal_Int32(11), rLine.GetEnd());
 
         std::vector<sal_Bool> const& rArray = rLine.GetKashidaArray();
-        CPPUNIT_ASSERT_EQUAL(size_t(17), rArray.size());
+        CPPUNIT_ASSERT_EQUAL(size_t(19), rArray.size());
     }
 
     // Resize the paper so there is no longer room for kashida
@@ -2313,9 +2313,9 @@ void Test::testTdf162803StaleKashidaArray()
 
     EditEngine aEditEngine(mpItemPool.get());
     aEditEngine.SetRefDevice(pVirtualDevice.get());
-    aEditEngine.SetPaperSize(Size(1500, 500));
+    aEditEngine.SetPaperSize(Size(1600, 500));
     
aEditEngine.SetDefaultHorizontalTextDirection(EEHorizontalTextDirection::R2L);
-    aEditEngine.SetText(u"خط تخوردگی و توسط"_ustr);
+    aEditEngine.SetText(u"خط تخوردگی وتوسسسسط"_ustr);
 
     CPPUNIT_ASSERT_EQUAL(true, aEditEngine.IsFormatted());
     CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aEditEngine.GetParagraphCount());
@@ -2342,7 +2342,7 @@ void Test::testTdf162803StaleKashidaArray()
         CPPUNIT_ASSERT_EQUAL(sal_Int32(11), rLine.GetEnd());
 
         std::vector<sal_Bool> const& rArray = rLine.GetKashidaArray();
-        CPPUNIT_ASSERT_EQUAL(size_t(17), rArray.size());
+        CPPUNIT_ASSERT_EQUAL(size_t(19), rArray.size());
     }
 
     // Resize the paper so the entire text fits on a single line
@@ -2358,7 +2358,7 @@ void Test::testTdf162803StaleKashidaArray()
         EditLine const& rLine = rLines[0];
 
         CPPUNIT_ASSERT_EQUAL(sal_Int32(0), rLine.GetStart());
-        CPPUNIT_ASSERT_EQUAL(sal_Int32(17), rLine.GetEnd());
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(19), rLine.GetEnd());
 
         std::vector<sal_Bool> const& rArray = rLine.GetKashidaArray();
 
diff --git a/editeng/source/editeng/impedit3.cxx 
b/editeng/source/editeng/impedit3.cxx
index eafcab1673a1..fac82269ce59 100644
--- a/editeng/source/editeng/impedit3.cxx
+++ b/editeng/source/editeng/impedit3.cxx
@@ -2236,10 +2236,6 @@ void ImpEditEngine::ImpAdjustBlocks(ParaPortion& 
rParaPortion, EditLine& rLine,
     // Search blanks or Kashidas...
     std::vector<sal_Int32> aPositions;
 
-    // Kashidas ?
-    ImpFindKashidas(pNode, nFirstChar, nLastChar, aPositions, nRemainingSpace);
-    auto nKashidas = aPositions.size();
-
     sal_uInt16 nLastScript = i18n::ScriptType::LATIN;
     for ( sal_Int32 nChar = nFirstChar; nChar <= nLastChar; nChar++ )
     {
@@ -2269,6 +2265,11 @@ void ImpEditEngine::ImpAdjustBlocks(ParaPortion& 
rParaPortion, EditLine& rLine,
         nLastScript = nScript;
     }
 
+    // Kashidas ?
+    auto nKashidaStart = aPositions.size();
+    ImpFindKashidas(pNode, nFirstChar, nLastChar, aPositions, nRemainingSpace);
+    auto nKashidas = aPositions.size() - nKashidaStart;
+
     if ( aPositions.empty() )
         return;
 
@@ -2313,7 +2314,7 @@ void ImpEditEngine::ImpAdjustBlocks(ParaPortion& 
rParaPortion, EditLine& rLine,
         rLine.GetKashidaArray().resize(rLine.GetCharPosArray().size(), false);
         for (size_t i = 0; i < nKashidas; i++)
         {
-            auto nChar = aPositions[i];
+            auto nChar = aPositions[nKashidaStart + i];
             if ( nChar < nLastChar )
                 rLine.GetKashidaArray()[nChar-nFirstChar] = 1 /*sal_True*/;
         }
@@ -2371,7 +2372,6 @@ void ImpEditEngine::ImpFindKashidas(ContentNode* pNode, 
sal_Int32 nStart, sal_In
     std::vector<bool> aValidPositions;
     std::vector<sal_Int32> aKashidaArray;
     std::vector<sal_Int32> aMinKashidaArray;
-    sal_Int32 nTotalMinKashida = 0U;
 
     // the search has to be performed on a per word base
 
@@ -2403,7 +2403,6 @@ void ImpEditEngine::ImpFindKashidas(ContentNode* pNode, 
sal_Int32 nStart, sal_In
             aTmpFont.SetPhysFont(*GetRefDevice());
 
             auto nMinKashidaWidth = GetRefDevice()->GetMinKashida();
-            nTotalMinKashida += nMinKashidaWidth;
             aMinKashidaArray.push_back(nMinKashidaWidth);
 
             aKashidaArray.push_back(nKashidaPos);
@@ -2413,28 +2412,29 @@ void ImpEditEngine::ImpFindKashidas(ContentNode* pNode, 
sal_Int32 nStart, sal_In
         aWordSel = SelectWord( aWordSel, css::i18n::WordType::DICTIONARY_WORD 
);
     }
 
-    // Greedily reject kashida positions from start-to-end until there is 
enough room.
-    // This will push kashida justification away from the start of the line.
+    // Every kashida and blank in the block will be given the same amount of 
extra space.
+    // Greedily reject kashida positions from start-to-end until there is 
enough room
+    // for all of the remaining kashida. This will push kashida justification 
away from
+    // the start of the line.
     std::reverse(aKashidaArray.begin(), aKashidaArray.end());
     std::reverse(aMinKashidaArray.begin(), aMinKashidaArray.end());
-    while (!aKashidaArray.empty() && nTotalMinKashida > nRemainingSpace)
-    {
-        nTotalMinKashida -= aMinKashidaArray.back();
-        aMinKashidaArray.pop_back();
-        aKashidaArray.pop_back();
-    }
 
-    std::reverse(aKashidaArray.begin(), aKashidaArray.end());
+    auto nGaps = aKashidaArray.size() + rArray.size();
+    auto nGapSize = nGaps ? (nRemainingSpace / nGaps) : 0;
+    for (size_t i = 0; i < aKashidaArray.size(); ++i)
+    {
+        auto nEmRequiredSize = aMinKashidaArray[i];
+        while (aKashidaArray.size() > i && std::cmp_less(nGapSize, 
nEmRequiredSize))
+        {
+            aMinKashidaArray.pop_back();
+            aKashidaArray.pop_back();
 
-    // Validate
-    std::vector<sal_Int32> aDropped;
-    GetRefDevice()->ValidateKashidas(pNode->GetString(), nStart, nEnd - nStart,
-                                     /*nPartIdx=*/nStart, /*nPartLen=*/nEnd - 
nStart, aKashidaArray,
-                                     &aDropped);
+            --nGaps;
+            nGapSize = nGaps ? (nRemainingSpace / nGaps) : 0;
+        }
+    }
 
-    for (auto const& pos : aKashidaArray)
-        if (std::find(aDropped.begin(), aDropped.end(), pos) == aDropped.end())
-             rArray.push_back(pos);
+    std::copy(aKashidaArray.rbegin(), aKashidaArray.rend(), 
std::back_inserter(rArray));
 }
 
 sal_Int32 ImpEditEngine::SplitTextPortion(ParaPortion& rParaPortion, sal_Int32 
nPos, EditLine* pCurLine)
diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx
index da73268f4b69..f156b86ef295 100644
--- a/include/vcl/outdev.hxx
+++ b/include/vcl/outdev.hxx
@@ -1153,16 +1153,6 @@ public:
 
     tools::Long                        GetMinKashida() const;
 
-    // i60594
-    // validate kashida positions against the current font
-    // returns count of invalid kashida positions
-    sal_Int32
-    ValidateKashidas(const OUString& rTxt, sal_Int32 nIdx, sal_Int32 nLen, 
sal_Int32 nPartIdx,
-                     sal_Int32 nPartLen,
-                     std::span<const sal_Int32> pKashidaPos, // suggested 
kashida positions (in)
-                     std::vector<sal_Int32>* pKashidaPosDropped // invalid 
kashida positions (out)
-    ) const;
-
     // tdf#163105: Get map of valid kashida positions for a single word
     void GetWordKashidaPositions(const OUString& rText, std::vector<bool>* 
pOutMap) const;
 
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf151748.fodt 
b/vcl/qa/cppunit/pdfexport/data/tdf151748.fodt
index 93c12a655fff..7851e97ac328 100644
--- a/vcl/qa/cppunit/pdfexport/data/tdf151748.fodt
+++ b/vcl/qa/cppunit/pdfexport/data/tdf151748.fodt
@@ -1,24 +1,23 @@
 <?xml version='1.0' encoding='UTF-8'?>
-<office:document xmlns:css3t="http://www.w3.org/TR/css3-text/"; 
xmlns:grddl="http://www.w3.org/2003/g/data-view#"; 
xmlns:xhtml="http://www.w3.org/1999/xhtml"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"; 
xmlns:xforms="http://www.w3.org/2002/xforms"; 
xmlns:dom="http://www.w3.org/2001/xml-events"; 
xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" 
xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" 
xmlns:math="http://www.w3.org/1998/Math/MathML"; 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:ooo="http://openoffice.org/2004/office"; 
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" 
xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" 
xmlns:ooow="http://openoffice.org/2004/writer"; 
xmlns:xlink="http://www.w3.org/1999/xlink"; 
xmlns:drawooo="http://openoffice.org/2010/draw"; 
xmlns:oooc="http://openoffice.org/2004/calc"; 
xmlns:dc="http://purl.org/dc/elements/1.1/"; xmlns:c
 alcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" 
xmlns:tableooo="http://openoffice.org/2009/table"; 
xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" 
xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" 
xmlns:rpt="http://openoffice.org/2005/report"; 
xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0"
 xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" 
xmlns:officeooo="http://openoffice.org/2009/office"; 
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" 
xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" 
xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" 
xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:
 meta:1.0" 
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
 office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
- <office:meta><meta:initial-creator>Eyal 
Rozenberg</meta:initial-creator><meta:creation-date>2024-08-16T21:34:46.833527525</meta:creation-date><dc:date>2024-08-30T01:36:34.697764958</dc:date><meta:editing-duration>PT9M57S</meta:editing-duration><meta:editing-cycles>6</meta:editing-cycles><meta:generator>LibreOfficeDev/25.2.0.0.alpha0$Linux_X86_64
 
LibreOffice_project/87ae339de7d1f83235a180dc50293f2857ef37a8</meta:generator><meta:document-statistic
 meta:table-count="0" meta:image-count="0" meta:object-count="0" 
meta:page-count="1" meta:paragraph-count="4" meta:word-count="0" 
meta:character-count="0" meta:non-whitespace-character-count="0"/></office:meta>
+<office:document xmlns:css3t="http://www.w3.org/TR/css3-text/"; 
xmlns:grddl="http://www.w3.org/2003/g/data-view#"; 
xmlns:xhtml="http://www.w3.org/1999/xhtml"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"; 
xmlns:xforms="http://www.w3.org/2002/xforms"; 
xmlns:dom="http://www.w3.org/2001/xml-events"; 
xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" 
xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" 
xmlns:math="http://www.w3.org/1998/Math/MathML"; 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:ooo="http://openoffice.org/2004/office"; 
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" 
xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" 
xmlns:ooow="http://openoffice.org/2004/writer"; 
xmlns:xlink="http://www.w3.org/1999/xlink"; 
xmlns:drawooo="http://openoffice.org/2010/draw"; 
xmlns:oooc="http://openoffice.org/2004/calc"; 
xmlns:dc="http://purl.org/dc/elements/1.1/"; xmlns:c
 alcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" 
xmlns:tableooo="http://openoffice.org/2009/table"; 
xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" 
xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" 
xmlns:rpt="http://openoffice.org/2005/report"; 
xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0"
 xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" 
xmlns:officeooo="http://openoffice.org/2009/office"; 
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" 
xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" 
xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" 
xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:
 meta:1.0" 
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
 office:version="1.4" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:meta><meta:initial-creator>Eyal 
Rozenberg</meta:initial-creator><meta:creation-date>2024-08-16T21:34:46.833527525</meta:creation-date><dc:date>2025-04-16T06:58:25.099932475</dc:date><meta:editing-duration>PT12M14S</meta:editing-duration><meta:editing-cycles>10</meta:editing-cycles><meta:generator>LibreOfficeDev/25.8.0.0.alpha0$Linux_X86_64
 
LibreOffice_project/5fbd402f70ef6b71f3c7812fe06e40f003416e8e</meta:generator><meta:document-statistic
 meta:table-count="0" meta:image-count="0" meta:object-count="0" 
meta:page-count="1" meta:paragraph-count="4" meta:word-count="0" 
meta:character-count="0" meta:non-whitespace-character-count="0"/></office:meta>
  <office:font-face-decls>
-  <style:font-face style:name="David CLM1" svg:font-family="'David CLM'" 
style:font-family-generic="system" style:font-pitch="variable"/>
+  <style:font-face style:name="David CLM" svg:font-family="'David CLM'" 
style:font-family-generic="system" style:font-pitch="variable"/>
   <style:font-face style:name="DejaVu Sans" svg:font-family="'DejaVu Sans'" 
style:font-adornments="Book" style:font-family-generic="swiss" 
style:font-pitch="variable"/>
   <style:font-face style:name="Liberation Serif" svg:font-family="'Liberation 
Serif'" style:font-family-generic="roman" style:font-pitch="variable"/>
-  <style:font-face style:name="Noto Sans Arabic" svg:font-family="'Noto Sans 
Arabic'" style:font-adornments="Regular" style:font-family-generic="swiss" 
style:font-pitch="variable"/>
   <style:font-face style:name="Noto Serif CJK SC" svg:font-family="'Noto Serif 
CJK SC'" style:font-family-generic="system" style:font-pitch="variable"/>
  </office:font-face-decls>
  <office:styles>
   <style:default-style style:family="graphic">
    <style:graphic-properties svg:stroke-color="#3465a4" 
draw:fill-color="#729fcf" fo:wrap-option="no-wrap" 
draw:shadow-offset-x="0.1181in" draw:shadow-offset-y="0.1181in" 
draw:start-line-spacing-horizontal="0.1114in" 
draw:start-line-spacing-vertical="0.1114in" 
draw:end-line-spacing-horizontal="0.1114in" 
draw:end-line-spacing-vertical="0.1114in" style:writing-mode="lr-tb" 
style:flow-with-text="false"/>
-   <style:paragraph-properties fo:text-align="end" 
style:text-autospace="ideograph-alpha" style:line-break="strict" 
loext:tab-stop-distance="0in" style:writing-mode="lr-tb" 
style:font-independent-line-spacing="false">
+   <style:paragraph-properties fo:text-align="end" 
style:text-autospace="ideograph-alpha" style:line-break="strict" 
loext:tab-stop-distance="0in" style:font-independent-line-spacing="false">
     <style:tab-stops/>
    </style:paragraph-properties>
-   <style:text-properties style:use-window-font-color="true" 
loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="12pt" 
fo:language="en" fo:country="IL" style:letter-kerning="true" 
style:font-name-asian="Noto Serif CJK SC" style:font-size-asian="10.5pt" 
style:language-asian="zh" style:country-asian="CN" 
style:font-name-complex="David CLM1" style:font-size-complex="12pt" 
style:language-complex="he" style:country-complex="IL"/>
+   <style:text-properties style:use-window-font-color="true" 
loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="12pt" 
fo:language="en" fo:country="IL" style:letter-kerning="true" 
style:font-name-asian="Noto Serif CJK SC" style:font-size-asian="10.5pt" 
style:language-asian="zh" style:country-asian="CN" 
style:font-name-complex="David CLM" style:font-size-complex="12pt" 
style:language-complex="he" style:country-complex="IL"/>
   </style:default-style>
   <style:default-style style:family="paragraph">
-   <style:paragraph-properties fo:text-align="end" 
style:justify-single-word="false" fo:orphans="2" fo:widows="2" 
fo:hyphenation-ladder-count="no-limit" fo:hyphenation-keep="auto" 
loext:hyphenation-keep-type="column" style:text-autospace="ideograph-alpha" 
style:punctuation-wrap="hanging" style:line-break="strict" 
style:tab-stop-distance="0.4925in" style:writing-mode="page"/>
-   <style:text-properties style:use-window-font-color="true" 
loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="12pt" 
fo:language="en" fo:country="IL" style:letter-kerning="true" 
style:font-name-asian="Noto Serif CJK SC" style:font-size-asian="10.5pt" 
style:language-asian="zh" style:country-asian="CN" 
style:font-name-complex="David CLM1" style:font-size-complex="12pt" 
style:language-complex="he" style:country-complex="IL" fo:hyphenate="false" 
fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" 
loext:hyphenation-no-caps="false" loext:hyphenation-no-last-word="false" 
loext:hyphenation-word-char-count="5" loext:hyphenation-zone="no-limit"/>
+   <style:paragraph-properties fo:text-align="end" 
style:justify-single-word="false" fo:orphans="2" fo:widows="2" 
fo:hyphenation-ladder-count="no-limit" fo:hyphenation-keep="auto" 
loext:hyphenation-keep-type="column" loext:hyphenation-keep-line="false" 
style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" 
style:line-break="strict" style:tab-stop-distance="0.4925in" 
style:writing-mode="page"/>
+   <style:text-properties style:use-window-font-color="true" 
loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="12pt" 
fo:language="en" fo:country="IL" style:letter-kerning="true" 
style:font-name-asian="Noto Serif CJK SC" style:font-size-asian="10.5pt" 
style:language-asian="zh" style:country-asian="CN" 
style:font-name-complex="David CLM" style:font-size-complex="12pt" 
style:language-complex="he" style:country-complex="IL" fo:hyphenate="false" 
fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" 
loext:hyphenation-no-caps="false" loext:hyphenation-no-last-word="false" 
loext:hyphenation-word-char-count="5" loext:hyphenation-zone="no-limit"/>
   </style:default-style>
   <style:default-style style:family="table">
    <style:table-properties table:border-model="collapsing"/>
@@ -87,30 +86,28 @@
   <text:linenumbering-configuration text:number-lines="false" 
text:offset="0.1965in" style:num-format="1" text:number-position="left" 
text:increment="5"/>
   </office:styles>
  <office:automatic-styles>
-  <style:style style:name="P1" style:family="paragraph" 
style:parent-style-name="Standard">
-   <style:text-properties/>
-  </style:style>
-  <style:style style:name="P2" style:family="paragraph">
+  <style:style style:name="P1" style:family="paragraph">
    <style:paragraph-properties fo:text-align="justify" 
style:writing-mode="rl-tb"/>
   </style:style>
-  <style:style style:name="P3" style:family="paragraph">
+  <style:style style:name="P2" style:family="paragraph">
    <loext:graphic-properties draw:fill="none" draw:fill-color="#ffffff"/>
    <style:paragraph-properties fo:text-align="justify"/>
-   <style:text-properties style:font-name-complex="Noto Sans Arabic" 
style:language-complex="ar" style:country-complex="SA" 
style:font-style-complex="normal" style:font-weight-complex="normal"/>
-  </style:style>
-  <style:style style:name="P4" style:family="paragraph" 
style:parent-style-name="Standard">
-   <style:text-properties/>
+   <style:text-properties style:font-family-complex="'Noto Sans Arabic'" 
style:font-style-name-complex="Regular" 
style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" 
style:language-complex="ar" style:country-complex="SA" 
style:font-style-complex="normal" style:font-weight-complex="normal"/>
   </style:style>
   <style:style style:name="T1" style:family="text">
-   <style:text-properties style:font-name-complex="Noto Sans Arabic" 
style:language-complex="ar" style:country-complex="SA" 
style:font-style-complex="normal" style:font-weight-complex="normal"/>
+   <style:text-properties style:font-family-complex="'Noto Sans Arabic'" 
style:font-style-name-complex="Regular" 
style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" 
style:language-complex="ar" style:country-complex="SA" 
style:font-style-complex="normal" style:font-weight-complex="normal"/>
   </style:style>
   <style:style style:name="T2" style:family="text">
-   <style:text-properties fo:font-size="26pt" style:font-size-asian="26pt" 
style:font-name-complex="Noto Sans Arabic" style:font-size-complex="26pt" 
style:language-complex="ar" style:country-complex="SA" 
style:font-style-complex="normal" style:font-weight-complex="normal"/>
+   <style:text-properties fo:font-size="26pt" style:font-size-asian="26pt" 
style:font-family-complex="'Noto Sans Arabic'" 
style:font-style-name-complex="Regular" 
style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" 
style:font-size-complex="26pt" style:language-complex="ar" 
style:country-complex="SA" style:font-style-complex="normal" 
style:font-weight-complex="normal"/>
   </style:style>
   <style:style style:name="gr1" style:family="graphic">
    <style:graphic-properties draw:stroke="solid" svg:stroke-color="#000000" 
draw:fill="none" draw:fill-color="#ffffff" fo:min-height="0.7047in" 
loext:decorative="false" style:run-through="foreground" 
style:wrap="run-through" style:number-wrapped-paragraphs="no-limit" 
style:vertical-pos="middle" style:vertical-rel="baseline" 
style:horizontal-pos="from-left" style:horizontal-rel="paragraph" 
draw:wrap-influence-on-position="once-concurrent" loext:allow-overlap="true" 
style:flow-with-text="false"/>
    <style:paragraph-properties style:writing-mode="lr-tb"/>
   </style:style>
+  <style:style style:name="gr2" style:family="graphic">
+   <style:graphic-properties draw:stroke="solid" svg:stroke-color="#000000" 
draw:fill="none" draw:fill-color="#ffffff" fo:min-height="1.1161in" 
loext:decorative="false" style:run-through="foreground" 
style:wrap="run-through" style:number-wrapped-paragraphs="no-limit" 
style:vertical-pos="middle" style:vertical-rel="baseline" 
style:horizontal-pos="from-left" style:horizontal-rel="paragraph" 
draw:wrap-influence-on-position="once-concurrent" loext:allow-overlap="true" 
style:flow-with-text="false"/>
+   <style:paragraph-properties style:writing-mode="lr-tb"/>
+  </style:style>
   <style:page-layout style:name="pm1">
    <style:page-layout-properties fo:page-width="8.2681in" 
fo:page-height="11.6929in" style:num-format="1" 
style:print-orientation="portrait" fo:margin-top="0.7874in" 
fo:margin-bottom="0.7874in" fo:margin-left="0.7874in" 
fo:margin-right="0.7874in" style:writing-mode="rl-tb" 
style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" 
style:layout-grid-base-height="0.278in" style:layout-grid-ruby-height="0.139in" 
style:layout-grid-mode="none" style:layout-grid-ruby-below="false" 
style:layout-grid-print="false" style:layout-grid-display="false" 
style:footnote-max-height="0in" loext:margin-gutter="0in">
     <style:footnote-sep style:width="0.0071in" 
style:distance-before-sep="0.0398in" style:distance-after-sep="0.0398in" 
style:line-style="solid" style:adjustment="right" style:rel-width="25%" 
style:color="#000000"/>
@@ -134,27 +131,27 @@
     <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>
     <text:sequence-decl text:display-outline-level="0" text:name="Figure"/>
    </text:sequence-decls>
-   <text:p text:style-name="P1"><draw:frame text:anchor-type="as-char" 
draw:z-index="0" draw:name="Text Frame 1" draw:style-name="gr1" 
draw:text-style-name="P3" svg:width="0.9606in" svg:height="0.7051in">
+   <text:p text:style-name="Standard"><draw:frame text:anchor-type="as-char" 
draw:z-index="0" draw:name="Text Frame 1" draw:style-name="gr1" 
draw:text-style-name="P2" svg:width="0.865in" svg:height="0.7051in">
      <draw:text-box>
-      <text:p text:style-name="P2"><text:span text:style-name="T1">خط تخوردگی 
و توسط</text:span></text:p>
+      <text:p text:style-name="P1"><text:span text:style-name="T1">خط تخوردگی 
وتوسط</text:span></text:p>
      </draw:text-box>
     </draw:frame></text:p>
-   <text:p text:style-name="P4"><draw:frame text:anchor-type="as-char" 
draw:z-index="1" draw:name="Text Frame 2" draw:style-name="gr1" 
draw:text-style-name="P3" svg:width="1.0394in" svg:height="0.7051in">
+   <text:p text:style-name="Standard"><draw:frame text:anchor-type="as-char" 
draw:z-index="1" draw:name="Text Frame 2" draw:style-name="gr1" 
draw:text-style-name="P2" svg:width="1.0016in" svg:height="0.7051in">
      <draw:text-box>
-      <text:p text:style-name="P2"><text:span text:style-name="T1">خط تخوردگی 
و توسط</text:span></text:p>
+      <text:p text:style-name="P1"><text:span text:style-name="T1">خط تخوردگی 
وتوسط</text:span></text:p>
      </draw:text-box>
     </draw:frame></text:p>
-   <text:p text:style-name="P4"><draw:frame text:anchor-type="as-char" 
draw:z-index="2" draw:name="Text Frame 3" draw:style-name="gr1" 
draw:text-style-name="P3" svg:width="1.2949in" svg:height="0.7051in">
+   <text:p text:style-name="Standard"><draw:frame text:anchor-type="as-char" 
draw:z-index="2" draw:name="Text Frame 3" draw:style-name="gr1" 
draw:text-style-name="P2" svg:width="1.2949in" svg:height="0.7051in">
      <draw:text-box>
-      <text:p text:style-name="P2"><text:span text:style-name="T1">خط تخوردگی 
و توسط</text:span></text:p>
+      <text:p text:style-name="P1"><text:span text:style-name="T1">خط تخوردگی 
وتوسط</text:span></text:p>
      </draw:text-box>
     </draw:frame></text:p>
-   <text:p text:style-name="P4"><draw:frame text:anchor-type="as-char" 
draw:z-index="3" draw:name="Text Frame 4" draw:style-name="gr1" 
draw:text-style-name="P3" svg:width="1.2949in" svg:height="1.1161in">
+   <text:p text:style-name="Standard"><draw:frame text:anchor-type="as-char" 
draw:z-index="3" draw:name="Text Frame 4" draw:style-name="gr2" 
draw:text-style-name="P2" svg:width="1.2949in" svg:height="1.1161in">
      <draw:text-box>
-      <text:p text:style-name="P2"><text:span 
text:style-name="T2">خط</text:span><text:span text:style-name="T1"> تخوردگی و 
توسط</text:span></text:p>
+      <text:p text:style-name="P1"><text:span 
text:style-name="T2">خط</text:span><text:span text:style-name="T1"> تخوردگی 
وتوسط</text:span></text:p>
      </draw:text-box>
     </draw:frame></text:p>
-   <text:p text:style-name="P4"/>
+   <text:p text:style-name="Standard"/>
   </office:text>
  </office:body>
 </office:document>
\ No newline at end of file
diff --git a/vcl/qa/cppunit/pdfexport/pdfexport2.cxx 
b/vcl/qa/cppunit/pdfexport/pdfexport2.cxx
index 514280ac930f..1dc24cb8aeca 100644
--- a/vcl/qa/cppunit/pdfexport/pdfexport2.cxx
+++ b/vcl/qa/cppunit/pdfexport/pdfexport2.cxx
@@ -5677,29 +5677,29 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest2, 
testTdf151748KashidaSpace)
     CPPUNIT_ASSERT_EQUAL(17, nTextObjectCount);
 
     // Box 1: Not enough room for kashida
-    CPPUNIT_ASSERT_EQUAL(u"خط تخوردگی و"_ustr, aText.at(0).trim());
-    CPPUNIT_ASSERT_EQUAL(u"توسط"_ustr, aText.at(1).trim());
+    CPPUNIT_ASSERT_EQUAL(u"خط تخوردگی"_ustr, aText.at(0).trim());
+    CPPUNIT_ASSERT_EQUAL(u"وتوسط"_ustr, aText.at(1).trim());
 
     // Box 2: One kashida toward end
-    CPPUNIT_ASSERT_EQUAL(u"وردگی و"_ustr, aText.at(2).trim());
+    CPPUNIT_ASSERT_EQUAL(u"وردگی"_ustr, aText.at(2).trim());
     CPPUNIT_ASSERT_EQUAL(u""_ustr, aText.at(3).trim()); // Kashida
     CPPUNIT_ASSERT_EQUAL(u"خط تخ"_ustr, aText.at(4).trim());
-    CPPUNIT_ASSERT_EQUAL(u"توسط"_ustr, aText.at(5).trim());
+    CPPUNIT_ASSERT_EQUAL(u"وتوسط"_ustr, aText.at(5).trim());
 
     // Box 3: Two kashida
-    CPPUNIT_ASSERT_EQUAL(u"وردگی و"_ustr, aText.at(6).trim());
+    CPPUNIT_ASSERT_EQUAL(u"وردگی"_ustr, aText.at(6).trim());
     CPPUNIT_ASSERT_EQUAL(u""_ustr, aText.at(7).trim()); // Kashida
     CPPUNIT_ASSERT_EQUAL(u"ط تخ"_ustr, aText.at(8).trim());
     CPPUNIT_ASSERT_EQUAL(u""_ustr, aText.at(9).trim()); // Kashida
     CPPUNIT_ASSERT_EQUAL(u"خ"_ustr, aText.at(10).trim());
-    CPPUNIT_ASSERT_EQUAL(u"توسط"_ustr, aText.at(11).trim());
+    CPPUNIT_ASSERT_EQUAL(u"وتوسط"_ustr, aText.at(11).trim());
 
     // Box 4: One kashida (text size change)
     CPPUNIT_ASSERT_EQUAL(u"خط"_ustr, aText.at(12).trim());
-    CPPUNIT_ASSERT_EQUAL(u"وردگی و"_ustr, aText.at(13).trim());
+    CPPUNIT_ASSERT_EQUAL(u"وردگی"_ustr, aText.at(13).trim());
     CPPUNIT_ASSERT_EQUAL(u""_ustr, aText.at(14).trim()); // Kashida
     CPPUNIT_ASSERT_EQUAL(u"تخ"_ustr, aText.at(15).trim());
-    CPPUNIT_ASSERT_EQUAL(u"توسط"_ustr, aText.at(16).trim());
+    CPPUNIT_ASSERT_EQUAL(u"وتوسط"_ustr, aText.at(16).trim());
 }
 
 // tdf#163105 - Writer kashida justification should expand spaces
diff --git a/vcl/source/outdev/font.cxx b/vcl/source/outdev/font.cxx
index b75a7863bcb2..b3d4022eb53b 100644
--- a/vcl/source/outdev/font.cxx
+++ b/vcl/source/outdev/font.cxx
@@ -1159,53 +1159,6 @@ tools::Long OutputDevice::GetMinKashida() const
     return ImplDevicePixelToLogicWidth(nKashidaWidth);
 }
 
-sal_Int32 OutputDevice::ValidateKashidas(const OUString& rTxt, sal_Int32 nIdx, 
sal_Int32 nLen,
-                                         sal_Int32 nPartIdx, sal_Int32 
nPartLen,
-                                         std::span<const sal_Int32> 
pKashidaPos,
-                                         std::vector<sal_Int32>* 
pKashidaPosDropped) const
-{
-    pKashidaPosDropped->clear();
-
-   // do layout
-    std::unique_ptr<SalLayout> pSalLayout = ImplLayout( rTxt, nIdx, nLen );
-    if( !pSalLayout )
-        return 0;
-
-    auto nEnd = nIdx + nLen;
-    auto nPartEnd = nPartIdx + nPartLen;
-    sal_Int32 nDropped = 0;
-    for (auto nPos : pKashidaPos)
-    {
-        auto nNextPos = nPos + 1;
-
-        // Skip combining marks to find the next character after this position.
-        while (nNextPos < nEnd
-               && u_getIntPropertyValue(rTxt[nNextPos], UCHAR_JOINING_TYPE) == 
U_JT_TRANSPARENT)
-        {
-            nNextPos++;
-        }
-
-        // tdf#124116: We now apply OpenType features across different 
layouts. Positions past the
-        // end of the layout must be validated.
-
-        // Currently, kashidas cannot be inserted if the grapheme cluster 
indicated by nPos is
-        // split across multiple layouts. Reject any such position.
-        if (nNextPos > nPartEnd)
-        {
-            pKashidaPosDropped->push_back(nPos);
-            ++nDropped;
-        }
-
-        // Check the glyph flags from HarfBuzz in all other situations.
-        if (!pSalLayout->IsKashidaPosValid(nPos, nNextPos))
-        {
-            pKashidaPosDropped->push_back(nPos);
-            ++nDropped;
-        }
-    }
-    return nDropped;
-}
-
 // tdf#163105: Get map of valid kashida positions for a single word
 void OutputDevice::GetWordKashidaPositions(const OUString& rText,
                                            std::vector<bool>* pOutMap) const

Reply via email to