sw/qa/core/txtnode/justify.cxx           |   25 ++
 sw/qa/extras/uiwriter/data/tdf149089.odt |binary
 sw/qa/extras/uiwriter/uiwriter7.cxx      |   11 +
 sw/source/core/txtnode/fntcache.cxx      |  265 +++++--------------------------
 sw/source/core/txtnode/justify.cxx       |   27 +++
 sw/source/core/txtnode/justify.hxx       |   10 +
 6 files changed, 120 insertions(+), 218 deletions(-)

New commits:
commit 3e754c07fabd1f74d57f42f273ea46e03dbdc094
Author:     Mark Hung <mark...@gmail.com>
AuthorDate: Sun May 29 15:44:49 2022 +0800
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Jun 8 08:14:25 2022 +0200

    tdf#149089 fix extra mini space in text grid.
    
    1. Create Justify::SnapToGridEdge() to adjust kern array
    under CJK textgrid GRID_LINES_CHARS mode when snap to chars is off.
    This function can handle a) Unicode IVS b) rInf.GetSpace() like
    what CJKJustify() does.  c) rInf.GetKern() value for letter spacing.
    
    Excluded parts comparing to original kern array adjustment:
    a) Kana compression under textgrid mode has been removed. Kana compression
    is used to compress space of punctuation. It doesn't make sense to
    perform that under textgrid node.
    b) Inserting nSpaceAdd for CH_BLANK is removed. I don't know its
    purpose.
    
    2. Use Justify::SnapToGridEdge() in GetTextSize(), GetTextBreak(),
    DrawText(), GetModelPositionForViewPoint() to adjust kern array
    consistently.
    
    Change-Id: I136a92f513fae05af2fb429e747356ba7eedec7f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135086
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sw/qa/core/txtnode/justify.cxx b/sw/qa/core/txtnode/justify.cxx
index 8f8956f5a736..0bdcd01e38d5 100644
--- a/sw/qa/core/txtnode/justify.cxx
+++ b/sw/qa/core/txtnode/justify.cxx
@@ -154,4 +154,29 @@ CPPUNIT_TEST_FIXTURE(SwCoreJustifyTest, testSnapToGridIVS)
     CPPUNIT_ASSERT_EQUAL(aExpected, aActual);
     CPPUNIT_ASSERT_EQUAL(tools::Long(0), nDelta);
 }
+
+CPPUNIT_TEST_FIXTURE(SwCoreJustifyTest, testSnapToGridEdge1)
+{
+    CharWidthArray aActual{ 640, 640, 640, 640, 640, 640, 320, 960 };
+    CharWidthArray aExpected{ 840, 840, 840, 840, 840, 840, 440, 1240 };
+    aActual.InvokeWithKernArray([&] { Justify::SnapToGridEdge(aActual.maArray, 
8, 400, 40, 0); });
+    CPPUNIT_ASSERT_EQUAL(aExpected, aActual);
+}
+
+CPPUNIT_TEST_FIXTURE(SwCoreJustifyTest, testSnapToGridEdge2)
+{
+    CharWidthArray aActual{ 640, 640, 640, 640, 640, 640, 320, 640 };
+    CharWidthArray aExpected{ 840, 840, 840, 840, 840, 840, 440, 840 };
+    aActual.InvokeWithKernArray([&] { Justify::SnapToGridEdge(aActual.maArray, 
8, 100, 40, 80); });
+    CPPUNIT_ASSERT_EQUAL(aExpected, aActual);
+}
+
+CPPUNIT_TEST_FIXTURE(SwCoreJustifyTest, testSnapToGridEdgeIVS)
+{
+    CharWidthArray aActual{ 640, 0, 0, 640, 640, 640, 640, 640 };
+    CharWidthArray aExpected{ 840, 0, 0, 840, 840, 840, 840, 840 };
+    aActual.InvokeWithKernArray([&] { Justify::SnapToGridEdge(aActual.maArray, 
8, 400, 40, 0); });
+    CPPUNIT_ASSERT_EQUAL(aExpected, aActual);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/extras/uiwriter/data/tdf149089.odt 
b/sw/qa/extras/uiwriter/data/tdf149089.odt
new file mode 100644
index 000000000000..08cb5a4db594
Binary files /dev/null and b/sw/qa/extras/uiwriter/data/tdf149089.odt differ
diff --git a/sw/qa/extras/uiwriter/uiwriter7.cxx 
b/sw/qa/extras/uiwriter/uiwriter7.cxx
index 0cb70e91076b..8b5a23d1a695 100644
--- a/sw/qa/extras/uiwriter/uiwriter7.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter7.cxx
@@ -2775,6 +2775,17 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest7, testTdf149184)
     xStorable->storeToURL(aTempFile.GetURL(), aStoreProps);
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest7, testTdf149089)
+{
+    createSwDoc(DATA_DIRECTORY, "tdf149089.odt");
+    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+    sal_Int32 nTextPortionWidth = getXPath(pXmlDoc, "(//SwLinePortion)[1]", 
"width").toInt32();
+    sal_Int32 nKernPortionWidth = getXPath(pXmlDoc, "(//SwLinePortion)[2]", 
"width").toInt32();
+    // nKernPortionWidth was about 1/3 of nTextPortionWidth
+    double nRatio = double(nKernPortionWidth) / nTextPortionWidth;
+    CPPUNIT_ASSERT_LESS(0.05, nRatio);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/fntcache.cxx 
b/sw/source/core/txtnode/fntcache.cxx
index 559633126cf8..12613bfd3b7f 100644
--- a/sw/source/core/txtnode/fntcache.cxx
+++ b/sw/source/core/txtnode/fntcache.cxx
@@ -72,24 +72,6 @@ tools::Long SwFntObj::s_nPixWidth;
 MapMode* SwFntObj::s_pPixMap = nullptr;
 static vcl::DeleteOnDeinit< VclPtr<OutputDevice> > s_pFntObjPixOut {};
 
-namespace
-{
-
-tools::Long EvalGridWidthAdd( const SwTextGridItem *const pGrid,
-        const SwDrawTextInfo &rInf, tools::Long nFontWidth )
-{
-    const SwDoc* pDoc = rInf.GetShell()->GetDoc();
-    const sal_uInt16 nGridWidth = GetGridWidth(*pGrid, *pDoc);
-    tools::Long nGridWidthAdd = nGridWidth - nFontWidth;
-
-    while (nGridWidthAdd < 0)
-        nGridWidthAdd += nGridWidth;
-
-    return nGridWidthAdd;
-}
-
-}
-
 void SwFntCache::Flush( )
 {
     if ( pLastFont )
@@ -933,13 +915,13 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
     {
         SwTextGridItem const*const 
pGrid(GetGridItem(rInf.GetFrame()->FindPageFrame()));
 
-        // ASIAN LINE AND CHARACTER GRID MODE: Do we want to snap asian 
characters to the grid?
-        if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && 
pGrid->IsSnapToChars())
+        // ASIAN LINE AND CHARACTER GRID MODE
+        if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() )
         {
             //for textgrid refactor
-            //const sal_uInt16 nGridWidth = pGrid->GetBaseHeight();
             const SwDoc* pDoc = rInf.GetShell()->GetDoc();
-            const sal_uInt16 nGridWidth = GetGridWidth(*pGrid, *pDoc);
+            const tools::Long nGridWidth = GetGridWidth(*pGrid, *pDoc);
+            tools::Long nSpaceAdd = rInf.GetSpace() / SPACING_PRECISION_FACTOR;
 
             // kerning array - gives the absolute position of end of each 
character
             std::vector<sal_Int32> aKernArray;
@@ -949,9 +931,18 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
             else
                 GetTextArray(rInf.GetOut(), rInf, aKernArray);
 
-            tools::Long nDelta
-                = Justify::SnapToGrid(aKernArray, rInf.GetText(), 
sal_Int32(rInf.GetIdx()),
+            tools::Long nDelta = 0;
+
+            if (pGrid->IsSnapToChars())
+            {
+                nDelta = Justify::SnapToGrid(aKernArray, rInf.GetText(), 
sal_Int32(rInf.GetIdx()),
                                       sal_Int32(rInf.GetLen()), nGridWidth, 
false);
+            }
+            else
+            {
+                Justify::SnapToGridEdge(aKernArray, sal_Int32(rInf.GetLen()), 
nGridWidth,
+                        nSpaceAdd, rInf.GetKern());
+            }
 
             if (nDelta)
                 aTextOriginPos.AdjustX(nDelta);
@@ -966,139 +957,6 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
         }
     }
 
-    // For text grid refactor
-    // ASIAN LINE AND CHARACTER GRID MODE START: not snap to characters
-
-    if ( rInf.GetFrame() && rInf.SnapToGrid() && rInf.GetFont() &&
-         SwFontScript::CJK == rInf.GetFont()->GetActual() )
-    {
-        SwTextGridItem const*const 
pGrid(GetGridItem(rInf.GetFrame()->FindPageFrame()));
-
-        // ASIAN LINE AND CHARACTER GRID MODE - do not snap to characters
-        if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && 
!pGrid->IsSnapToChars() )
-        {
-            std::vector<sal_Int32> aKernArray;
-
-            if ( m_pPrinter )
-                GetTextArray(*m_pPrinter, rInf, aKernArray);
-            else
-                GetTextArray(rInf.GetOut(), rInf, aKernArray);
-
-            const tools::Long nGridWidthAdd = EvalGridWidthAdd( pGrid, rInf, 
aKernArray[0] );
-
-            if ( bSwitchH2V )
-                rInf.GetFrame()->SwitchHorizontalToVertical( aTextOriginPos );
-            if ( rInf.GetSpace() || rInf.GetKanaComp())
-            {
-                tools::Long nSpaceAdd = rInf.GetSpace() / 
SPACING_PRECISION_FACTOR;
-                if ( rInf.GetFont() && rInf.GetLen() )
-                {
-                    bool bSpecialJust = false;
-                    const SwScriptInfo* pSI = rInf.GetScriptInfo();
-                    const SwFontScript nActual = rInf.GetFont()->GetActual();
-                    ///Kana Compression
-                    if( SwFontScript::CJK == nActual && rInf.GetKanaComp() &&
-                        pSI && pSI->CountCompChg() &&
-                        lcl_IsMonoSpaceFont( *(rInf.GetpOut()) ) )
-                    {
-                        pSI->Compress( aKernArray.data(), rInf.GetIdx(), 
rInf.GetLen(),
-                            rInf.GetKanaComp(), 
o3tl::narrowing<sal_uInt16>(m_aFont.GetFontSize().Height()), 
lcl_IsFullstopCentered( rInf.GetOut() ) , &aTextOriginPos );
-                        bSpecialJust = true;
-                    }
-                    ///Asian Justification
-                    if ( ( SwFontScript::CJK == nActual || SwFontScript::Latin 
== nActual ) && nSpaceAdd )
-                    {
-                        LanguageType aLang = rInf.GetFont()->GetLanguage( 
SwFontScript::CJK );
-                        if (!MsLangId::isKorean(aLang))
-                        {
-                            tools::Long nSpaceSum = nSpaceAdd;
-                            for (sal_Int32 nI = 0; nI < 
sal_Int32(rInf.GetLen()); ++nI)
-                            {
-                                aKernArray[ nI ] += nSpaceSum;
-                                nSpaceSum += nSpaceAdd;
-                            }
-                            bSpecialJust = true;
-                            nSpaceAdd = 0;
-                        }
-                    }
-                    tools::Long nGridAddSum = nGridWidthAdd;
-                    for (sal_Int32 i = 0; i < sal_Int32(rInf.GetLen()); i++, 
nGridAddSum += nGridWidthAdd )
-                    {
-                        aKernArray[i] += nGridAddSum;
-                    }
-                    tools::Long nKernSum = rInf.GetKern();
-                    if ( bSpecialJust || rInf.GetKern() )
-                    {
-                        for (sal_Int32 i = 0; i < sal_Int32(rInf.GetLen()); 
i++, nKernSum += rInf.GetKern())
-                        {
-                            if (CH_BLANK == 
rInf.GetText()[sal_Int32(rInf.GetIdx())+i])
-                                nKernSum += nSpaceAdd;
-                            aKernArray[i] += nKernSum;
-                        }
-                        ///With through/uderstr. Grouped style requires a 
blank at the end
-                        ///of a text edition special measures:
-                        if( m_bPaintBlank && rInf.GetLen() && (CH_BLANK ==
-                            rInf.GetText()[sal_Int32(rInf.GetIdx() + 
rInf.GetLen()) - 1]))
-                        {
-                            ///If it concerns a singular, underlined space 
acts,
-                            ///we must spend two:
-                            if (TextFrameIndex(1) == rInf.GetLen())
-                            {
-                                aKernArray[0] = rInf.GetWidth() + nSpaceAdd;
-                                rInf.GetOut().DrawTextArray( aTextOriginPos, 
rInf.GetText(),
-                                    aKernArray, sal_Int32(rInf.GetIdx()), 1);
-                            }
-                            else
-                            {
-                                aKernArray[sal_Int32(rInf.GetLen()) - 2] += 
nSpaceAdd;
-                                rInf.GetOut().DrawTextArray( aTextOriginPos, 
rInf.GetText(),
-                                    aKernArray, sal_Int32(rInf.GetIdx()),
-                                    sal_Int32(rInf.GetLen()));
-                            }
-                        }
-                        else
-                        {
-                            rInf.GetOut().DrawTextArray( aTextOriginPos, 
rInf.GetText(),
-                                aKernArray, sal_Int32(rInf.GetIdx()),
-                                sal_Int32(rInf.GetLen()));
-                        }
-                    }
-                    else
-                    {
-                        sal_Int32 i;
-                        tools::Long nSpaceSum = 0;
-                        for (i = 0; i < sal_Int32(rInf.GetLen()); i++)
-                        {
-                            if(CH_BLANK == 
rInf.GetText()[sal_Int32(rInf.GetIdx()) + i])
-                                nSpaceSum += nSpaceAdd + nKernSum;
-
-                            aKernArray[i] += nSpaceSum;
-                        }
-
-                        rInf.GetOut().DrawTextArray(aTextOriginPos,
-                                rInf.GetText(), aKernArray,
-                                sal_Int32(rInf.GetIdx()),
-                                sal_Int32(rInf.GetLen()));
-                    }
-                }
-            }
-            else
-            {
-                //long nKernAdd = rInf.GetKern();
-                tools::Long nKernAdd = 0;
-                tools::Long nGridAddSum = nGridWidthAdd + nKernAdd;
-                for (sal_Int32 i = 0; i < sal_Int32(rInf.GetLen());
-                     i++, nGridAddSum += nGridWidthAdd + nKernAdd)
-                {
-                    aKernArray[i] += nGridAddSum;
-                }
-                rInf.GetOut().DrawTextArray( aTextOriginPos, rInf.GetText(),
-                    aKernArray, sal_Int32(rInf.GetIdx()), 
sal_Int32(rInf.GetLen()));
-            }
-            return;
-        }
-    }
-
     // DIRECT PAINTING WITHOUT SCREEN ADJUSTMENT
 
     if ( bDirectPrint )
@@ -1678,7 +1536,7 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf )
          SwFontScript::CJK == rInf.GetFont()->GetActual() )
     {
         SwTextGridItem const*const 
pGrid(GetGridItem(rInf.GetFrame()->FindPageFrame()));
-        if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && 
pGrid->IsSnapToChars() )
+        if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() )
         {
             const SwDoc* pDoc = rInf.GetShell()->GetDoc();
             const sal_uInt16 nGridWidth = GetGridWidth(*pGrid, *pDoc);
@@ -1705,42 +1563,19 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf )
 
             std::vector<sal_Int32> aKernArray;
             GetTextArray(*pOutDev, rInf, aKernArray, sal_Int32(rInf.GetLen()));
-            Justify::SnapToGrid(aKernArray, rInf.GetText(), 
sal_Int32(rInf.GetIdx()),
-                                  sal_Int32(rInf.GetLen()), nGridWidth, true);
-
-            aTextSize.setWidth(aKernArray[sal_Int32(rInf.GetLen()) - 1]);
-            rInf.SetKanaDiff( 0 );
-            return aTextSize;
-        }
-    }
-
-    //for textgrid refactor
-    if ( rInf.GetFrame() && nLn && rInf.SnapToGrid() && rInf.GetFont() &&
-         SwFontScript::CJK == rInf.GetFont()->GetActual() )
-    {
-        SwTextGridItem const*const 
pGrid(GetGridItem(rInf.GetFrame()->FindPageFrame()));
-        if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && 
!pGrid->IsSnapToChars() )
-        {
-            OutputDevice* pOutDev;
-            if ( m_pPrinter )
+            if (pGrid->IsSnapToChars())
             {
-                if( !m_pPrtFont->IsSameInstance( m_pPrinter->GetFont() ) )
-                    m_pPrinter->SetFont(*m_pPrtFont);
-                pOutDev = m_pPrinter;
+                Justify::SnapToGrid(aKernArray, rInf.GetText(), 
sal_Int32(rInf.GetIdx()),
+                                  sal_Int32(rInf.GetLen()), nGridWidth, true);
             }
             else
-                pOutDev = rInf.GetpOut();
-
-            tools::Long nWidth = pOutDev->GetTextWidth(rInf.GetText(),
-                        sal_Int32(rInf.GetIdx()), sal_Int32(nLn));
-            const tools::Long nGridWidthAdd = EvalGridWidthAdd( pGrid, rInf, 
nWidth / sal_Int32(nLn) );
-            aTextSize.setWidth(nWidth);
-            aTextSize.setHeight( pOutDev->GetTextHeight() +
-                                GetFontLeading( rInf.GetShell(), rInf.GetOut() 
) );
-            aTextSize.AdjustWidth(sal_Int32(nLn) * nGridWidthAdd);
-            //if ( rInf.GetKern() && nLn )
-            //    aTextSize.Width() += ( nLn ) * long( rInf.GetKern() );
+            {
+                // use 0 to calculate raw width without rInf.GetSpace().
+                Justify::SnapToGridEdge(aKernArray, sal_Int32(rInf.GetLen()), 
nGridWidth, 0,
+                        rInf.GetKern());
+            }
 
+            aTextSize.setWidth(aKernArray[sal_Int32(rInf.GetLen()) - 1]);
             rInf.SetKanaDiff( 0 );
             return aTextSize;
         }
@@ -1845,13 +1680,21 @@ TextFrameIndex 
SwFntObj::GetModelPositionForViewPoint(SwDrawTextInfo &rInf)
          rInf.GetFont() && SwFontScript::CJK == rInf.GetFont()->GetActual() )
     {
         SwTextGridItem const*const 
pGrid(GetGridItem(rInf.GetFrame()->FindPageFrame()));
-        if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && 
pGrid->IsSnapToChars() )
+        if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() )
         {
             const SwDoc* pDoc = rInf.GetShell()->GetDoc();
             const sal_uInt16 nGridWidth = GetGridWidth(*pGrid, *pDoc);
 
-            Justify::SnapToGrid(aKernArray, rInf.GetText(), 
sal_Int32(rInf.GetIdx()),
-                                  sal_Int32(rInf.GetLen()), nGridWidth, true);
+            if (pGrid->IsSnapToChars())
+            {
+                Justify::SnapToGrid(aKernArray, rInf.GetText(), 
sal_Int32(rInf.GetIdx()),
+                                      sal_Int32(rInf.GetLen()), nGridWidth, 
true);
+            }
+            else
+            {
+                Justify::SnapToGridEdge(aKernArray, sal_Int32(rInf.GetLen()), 
nGridWidth,
+                        nSpaceAdd, rInf.GetKern());
+            }
 
             return  TextFrameIndex(Justify::GetModelPosition(aKernArray, 
sal_Int32(rInf.GetLen()),
                         rInf.GetOffset()));
@@ -1925,29 +1768,6 @@ TextFrameIndex 
SwFntObj::GetModelPositionForViewPoint(SwDrawTextInfo &rInf)
     tools::Long nSpaceSum = 0;
     tools::Long nKernSum = 0;
 
-    //for textgrid refactor
-    if ( rInf.GetFrame() && rInf.GetLen() && rInf.SnapToGrid() &&
-         rInf.GetFont() && SwFontScript::CJK == rInf.GetFont()->GetActual() )
-    {
-        SwTextGridItem const*const 
pGrid(GetGridItem(rInf.GetFrame()->FindPageFrame()));
-        if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && 
!pGrid->IsSnapToChars() )
-        {
-
-            const tools::Long nGridWidthAdd = EvalGridWidthAdd( pGrid, rInf, 
aKernArray[0] );
-
-            for (TextFrameIndex j(0); j < rInf.GetLen(); j++)
-            {
-                tools::Long nScr = aKernArray[sal_Int32(j)] + (nSpaceAdd + 
nGridWidthAdd) * (sal_Int32(j) + 1);
-                if( nScr >= rInf.GetOffset())
-                {
-                    nCnt = j;
-                    break;
-                }
-            }
-            return nCnt;
-        }
-    }
-
     sal_Int32 nDone = 0;
     TextFrameIndex nIdx = rInf.GetIdx();
     TextFrameIndex nLastIdx = nIdx;
@@ -2133,7 +1953,7 @@ TextFrameIndex SwFont::GetTextBreak(SwDrawTextInfo const 
& rInf, tools::Long nTe
          rInf.GetFont() && SwFontScript::CJK == rInf.GetFont()->GetActual() )
     {
         SwTextGridItem const*const 
pGrid(GetGridItem(rInf.GetFrame()->FindPageFrame()));
-        if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType())
+        if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() )
         {
             const SwDoc* pDoc = rInf.GetShell()->GetDoc();
             const sal_uInt16 nGridWidth = GetGridWidth(*pGrid, *pDoc);
@@ -2142,8 +1962,17 @@ TextFrameIndex SwFont::GetTextBreak(SwDrawTextInfo const 
& rInf, tools::Long nTe
             GetTextArray( rInf.GetOut(), rInf.GetText(), aKernArray,
                     sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()));
 
-            Justify::SnapToGrid(aKernArray, rInf.GetText(), 
sal_Int32(rInf.GetIdx()),
+            if (pGrid->IsSnapToChars())
+            {
+                Justify::SnapToGrid(aKernArray, rInf.GetText(), 
sal_Int32(rInf.GetIdx()),
                                   sal_Int32(rInf.GetLen()), nGridWidth, true);
+            }
+            else
+            {
+                // use 0 to calculate raw width without rInf.GetSpace().
+                Justify::SnapToGridEdge(aKernArray, sal_Int32(rInf.GetLen()), 
nGridWidth,
+                        0, rInf.GetKern());
+            }
 
             while(nTextBreak < rInf.GetLen() && 
aKernArray[sal_Int32(nTextBreak)] <= nTextWidth)
                 ++nTextBreak;
diff --git a/sw/source/core/txtnode/justify.cxx 
b/sw/source/core/txtnode/justify.cxx
index 6a1228d13169..1cbc16c36c0b 100644
--- a/sw/source/core/txtnode/justify.cxx
+++ b/sw/source/core/txtnode/justify.cxx
@@ -202,6 +202,33 @@ tools::Long SnapToGrid(std::vector<sal_Int32>& rKernArray, 
const OUString& rText
 
     return nDelta;
 }
+
+void SnapToGridEdge(std::vector<sal_Int32>& rKernArray, sal_Int32 nLen, 
tools::Long nGridWidth,
+                    tools::Long nSpace, tools::Long nKern)
+{
+    assert(nLen <= sal_Int32(rKernArray.size()));
+
+    tools::Long nCharWidth = rKernArray[0];
+    tools::Long nEdge = lcl_MinGridWidth(nGridWidth, nCharWidth + nKern) + 
nSpace;
+
+    sal_Int32 nLast = 0;
+
+    for (sal_Int32 i = 1; i < nLen; ++i)
+    {
+        if (rKernArray[i] == rKernArray[nLast])
+            continue;
+
+        nCharWidth = rKernArray[i] - rKernArray[nLast];
+        tools::Long nMinWidth = lcl_MinGridWidth(nGridWidth, nCharWidth + 
nKern);
+        while (nLast < i)
+            rKernArray[nLast++] = nEdge;
+
+        nEdge += nMinWidth + nSpace;
+    }
+
+    while (nLast < nLen)
+        rKernArray[nLast++] = nEdge;
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/justify.hxx 
b/sw/source/core/txtnode/justify.hxx
index 25ba4fe78fd3..6ea07adeceb7 100644
--- a/sw/source/core/txtnode/justify.hxx
+++ b/sw/source/core/txtnode/justify.hxx
@@ -50,6 +50,16 @@ SW_DLLPUBLIC void SpaceDistribution(std::vector<sal_Int32>& 
rKernArray, const OU
 SW_DLLPUBLIC tools::Long SnapToGrid(std::vector<sal_Int32>& rKernArray, const 
OUString& rText,
                                     sal_Int32 nStt, sal_Int32 nLen, 
tools::Long nGridWidth,
                                     bool bForceLeft);
+
+/// Snap ideographs to text grids edge ( used when snap to char is off ):
+/// space will be distributed ( in case that alignment is set to justify. ).
+/// @param[in,out] rKernArray text positions from OutDev::GetTextArray().
+/// @param nLen number of elements to process in rKernArray and rText.
+/// @param nGridWidth width of a text grid
+/// @param nSpace amount of space distributed under justify text alignment 
mode.
+/// @param nKern letter spacing.
+SW_DLLPUBLIC void SnapToGridEdge(std::vector<sal_Int32>& rKernArray, sal_Int32 
nLen,
+                                 tools::Long nGridWidth, tools::Long nSpace, 
tools::Long nKern);
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to