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: */