editeng/source/editeng/impedit2.cxx | 17 ++++----- editeng/source/items/svxfont.cxx | 66 ++++++++++++++++++++++++++++-------- 2 files changed, 61 insertions(+), 22 deletions(-)
New commits: commit 88aeb649ed33a1a67547419f9b76c2c892dd2ee1 Author: Mark Hung <mark...@gmail.com> AuthorDate: Sun Apr 17 12:56:06 2022 +0800 Commit: Mark Hung <mark...@gmail.com> CommitDate: Wed Apr 20 13:07:31 2022 +0200 tdf#148630 fix text layout and cursor position for IVS+spacing in Impress. This involves: 1. SvxFont::QuickGetTextSize() and SvxFont::GetPhysTxtSize(): insert space only when text array value changes. Same value indicates diffferent characters of the same glyph item (e.x. surrogate pairs, unicode IVS that is made of a base character and a selector. ). 2. ImpEditEngine::GetChar(): fix a logical mistake that tried to increase the index by 1 than checking the value of character position. To advance the index we always need to check the position first. Change-Id: I4e3547413ce361ae7801c957e6d589776ebed114 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133102 Tested-by: Jenkins Reviewed-by: Mark Hung <mark...@gmail.com> diff --git a/editeng/source/editeng/impedit2.cxx b/editeng/source/editeng/impedit2.cxx index 2f44eaf5468a..1471b4f291c1 100644 --- a/editeng/source/editeng/impedit2.cxx +++ b/editeng/source/editeng/impedit2.cxx @@ -4001,16 +4001,17 @@ sal_Int32 ImpEditEngine::GetChar( tools::Long nDiffRight = nTmpPosMax - nXInPortion; OSL_ENSURE( nDiffLeft >= 0, "DiffLeft negative" ); OSL_ENSURE( nDiffRight >= 0, "DiffRight negative" ); - nOffset = ( bSmart && ( nDiffRight < nDiffLeft ) ) ? x+1 : x; - // I18N: If there are character position with the length of 0, - // they belong to the same character, we can not use this position as an index. - // Skip all 0-positions, cheaper than using XBreakIterator: - if ( nOffset < nMax ) + + if (bSmart && nDiffRight < nDiffLeft) { - const tools::Long nX = pLine->GetCharPosArray()[nOffset]; - while ( ( (nOffset+1) < nMax ) && ( pLine->GetCharPosArray()[nOffset+1] == nX ) ) - nOffset++; + // I18N: If there are character position with the length of 0, + // they belong to the same character, we can not use this position as an index. + // Skip all 0-positions, cheaper than using XBreakIterator: + tools::Long nX = pLine->GetCharPosArray()[nTmpCurIndex + x]; + while(x < nMax && pLine->GetCharPosArray()[nTmpCurIndex + x] == nX) + ++x; } + nOffset = x; break; } } diff --git a/editeng/source/items/svxfont.cxx b/editeng/source/items/svxfont.cxx index 4b549d49d711..839240f828df 100644 --- a/editeng/source/items/svxfont.cxx +++ b/editeng/source/items/svxfont.cxx @@ -30,6 +30,15 @@ #include <com/sun/star/i18n/KCharacterType.hpp> #include <editeng/escapementitem.hxx> #include <sal/log.hxx> +#include <limits> + +static tools::Long GetTextArray( const OutputDevice* pOut, const OUString& rStr, std::vector<sal_Int32>* pDXAry, + sal_Int32 nIndex, sal_Int32 nLen ) + +{ + const SalLayoutGlyphs* layoutGlyphs = SalLayoutGlyphsCache::self()->GetLayoutGlyphs(pOut, rStr, nIndex, nLen); + return pOut->GetTextArray( rStr, pDXAry, nIndex, nLen, nullptr, layoutGlyphs); +} SvxFont::SvxFont() { @@ -433,7 +442,21 @@ Size SvxFont::GetPhysTxtSize( const OutputDevice *pOut, const OUString &rTxt, } if( IsKern() && ( nLen > 1 ) ) - aTxtSize.AdjustWidth( ( nLen-1 ) * tools::Long( nKern ) ); + { + std::vector<sal_Int32> aDXArray(nLen); + GetTextArray(pOut, rTxt, &aDXArray, nIdx, nLen); + tools::Long nOldValue = aDXArray[0]; + sal_Int32 nSpaceCount = 0; + for(sal_Int32 i = 1; i < nLen; ++i) + { + if (aDXArray[i] != nOldValue) + { + nOldValue = aDXArray[i]; + ++nSpaceCount; + } + } + aTxtSize.AdjustWidth( nSpaceCount * tools::Long( nKern ) ); + } return aTxtSize; } @@ -453,13 +476,6 @@ Size SvxFont::GetPhysTxtSize( const OutputDevice *pOut ) return aTxtSize; } -static tools::Long GetTextArray( const OutputDevice* pOut, const OUString& rStr, std::vector<sal_Int32>* pDXAry, - sal_Int32 nIndex, sal_Int32 nLen ) -{ - const SalLayoutGlyphs* layoutGlyphs = SalLayoutGlyphsCache::self()->GetLayoutGlyphs(pOut, rStr, nIndex, nLen); - return pOut->GetTextArray( rStr, pDXAry, nIndex, nLen, nullptr, layoutGlyphs); -} - Size SvxFont::QuickGetTextSize( const OutputDevice *pOut, const OUString &rTxt, const sal_Int32 nIdx, const sal_Int32 nLen, std::vector<sal_Int32>* pDXArray ) const { @@ -467,6 +483,15 @@ Size SvxFont::QuickGetTextSize( const OutputDevice *pOut, const OUString &rTxt, return Size( GetTextArray( pOut, rTxt, pDXArray, nIdx, nLen ), pOut->GetTextHeight() ); + std::vector<sal_Int32> aDXArray; + + // We always need pDXArray to count the number of kern spaces + if (!pDXArray && IsKern() && nLen > 1) + { + pDXArray = &aDXArray; + aDXArray.reserve(nLen); + } + Size aTxtSize; aTxtSize.setHeight( pOut->GetTextHeight() ); if ( !IsCaseMap() ) @@ -477,16 +502,29 @@ Size SvxFont::QuickGetTextSize( const OutputDevice *pOut, const OUString &rTxt, if( IsKern() && ( nLen > 1 ) ) { - aTxtSize.AdjustWidth( ( nLen-1 ) * tools::Long( nKern ) ); + tools::Long nOldValue = (*pDXArray)[0]; + tools::Long nSpaceSum = nKern; + (*pDXArray)[0] += nSpaceSum; - if ( pDXArray ) + for ( sal_Int32 i = 1; i < nLen; i++ ) { - for ( sal_Int32 i = 0; i < nLen; i++ ) - (*pDXArray)[i] += ( (i+1) * tools::Long( nKern ) ); - // The last one is a nKern too big: - (*pDXArray)[nLen-1] -= nKern; + if ( (*pDXArray)[i] != nOldValue ) + { + nOldValue = (*pDXArray)[i]; + nSpaceSum += nKern; + } + (*pDXArray)[i] += nSpaceSum; } + + // The last one is a nKern too big: + nOldValue = (*pDXArray)[nLen - 1]; + tools::Long nNewValue = nOldValue - nKern; + for ( sal_Int32 i = nLen - 1; i >= 0 && (*pDXArray)[i] == nOldValue; --i) + (*pDXArray)[i] = nNewValue; + + aTxtSize.AdjustWidth(nSpaceSum - nKern); } + return aTxtSize; }