svx/source/svdraw/svdotextdecomposition.cxx | 8 ++- sw/source/core/txtnode/fntcache.cxx | 10 ++++ vcl/inc/sallayout.hxx | 1 vcl/source/gdi/sallayout.cxx | 66 +++++++++++++++------------- 4 files changed, 54 insertions(+), 31 deletions(-)
New commits: commit a84bf20b345ba016ab67217f5fd73eebb517dc6b Author: Khaled Hosny <kha...@libreoffice.org> AuthorDate: Mon Jun 12 22:29:11 2023 +0300 Commit: Caolán McNamara <caolan.mcnam...@collabora.com> CommitDate: Fri Jun 23 22:52:56 2023 +0200 tdf#152048: Fix measuring text width with font fallback This is a regression from: commit 43a5400063b17ed4ba4cbb38bdf5da4a991f60e2 Author: Khaled Hosny <kha...@libreoffice.org> Date: Thu May 25 10:59:18 2023 +0300 tdf#152048: Fix underline width for Kashida-justified text It fixed measuring width when there is Kashida justification, but broke it for font fallback, because of the way MultiSalLayout measures the text width takes the maximum of the text widths for all its layouts, but layouts with missing glyphs are now giving wrong text width as they are measuring the width of .notdef (GID 0) glyph. This change makes MultiSalLayout measure the text width by iterating over all its valid glyphs. Change-Id: I8b19e0d44326c6f0afe6e504ab6d90c6fb3575f9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152933 Tested-by: Jenkins Reviewed-by: خالد حسني <kha...@libreoffice.org> (cherry picked from commit 38b5e9bc7d45f52f11bad125a584ad2261383de6) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152920 Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx index 35496750c286..d48edaaf67f2 100644 --- a/vcl/inc/sallayout.hxx +++ b/vcl/inc/sallayout.hxx @@ -62,6 +62,7 @@ class MultiSalLayout final : public SalLayout public: void DrawText(SalGraphics&) const override; sal_Int32 GetTextBreak(DeviceCoordinate nMaxWidth, DeviceCoordinate nCharExtra, int nFactor) const override; + DeviceCoordinate GetTextWidth() const final override; DeviceCoordinate FillDXArray(std::vector<DeviceCoordinate>* pDXArray, const OUString& rStr) const override; void GetCaretPositions(int nArraySize, sal_Int32* pCaretXArray) const override; bool GetNextGlyph(const GlyphItem** pGlyph, DevicePoint& rPos, int& nStart, diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx index 1ed2a37ad71b..3cdd71642b5b 100644 --- a/vcl/source/gdi/sallayout.cxx +++ b/vcl/source/gdi/sallayout.cxx @@ -1009,45 +1009,53 @@ sal_Int32 MultiSalLayout::GetTextBreak( DeviceCoordinate nMaxWidth, DeviceCoordi return -1; } -DeviceCoordinate MultiSalLayout::FillDXArray( std::vector<DeviceCoordinate>* pCharWidths, const OUString& rStr ) const +DeviceCoordinate MultiSalLayout::GetTextWidth() const { - DeviceCoordinate nMaxWidth = 0; + // Measure text width. There might be holes in each SalLayout due to + // missing chars, so we use GetNextGlyph() to get the glyphs across all + // layouts. + int nStart = 0; + DevicePoint aPos; + const GlyphItem* pGlyphItem; - // prepare merging of fallback levels - std::vector<DeviceCoordinate> aTempWidths; - const int nCharCount = mnEndCharPos - mnMinCharPos; - if( pCharWidths ) + DeviceCoordinate nWidth = 0; + while (GetNextGlyph(&pGlyphItem, aPos, nStart)) + nWidth += pGlyphItem->newWidth(); + + return nWidth; +} + +DeviceCoordinate MultiSalLayout::FillDXArray( std::vector<DeviceCoordinate>* pCharWidths, const OUString& rStr ) const +{ + if (pCharWidths) { + // prepare merging of fallback levels + std::vector<DeviceCoordinate> aTempWidths; + const int nCharCount = mnEndCharPos - mnMinCharPos; pCharWidths->clear(); pCharWidths->resize(nCharCount, 0); - } - for( int n = mnLevel; --n >= 0; ) - { - // query every fallback level - DeviceCoordinate nTextWidth = mpLayouts[n]->FillDXArray( &aTempWidths, rStr ); - if( !nTextWidth ) - continue; - // merge results from current level - if( nMaxWidth < nTextWidth ) - nMaxWidth = nTextWidth; - if( !pCharWidths ) - continue; - // calculate virtual char widths using most probable fallback layout - for( int i = 0; i < nCharCount; ++i ) + for (int n = mnLevel; --n >= 0;) { - // #i17359# restriction: - // one char cannot be resolved from different fallbacks - if( (*pCharWidths)[i] != 0 ) - continue; - DeviceCoordinate nCharWidth = aTempWidths[i]; - if( !nCharWidth ) - continue; - (*pCharWidths)[i] = nCharWidth; + // query every fallback level + mpLayouts[n]->FillDXArray(&aTempWidths, rStr); + + // calculate virtual char widths using most probable fallback layout + for (int i = 0; i < nCharCount; ++i) + { + // #i17359# restriction: + // one char cannot be resolved from different fallbacks + if ((*pCharWidths)[i] != 0) + continue; + DeviceCoordinate nCharWidth = aTempWidths[i]; + if (!nCharWidth) + continue; + (*pCharWidths)[i] = nCharWidth; + } } } - return nMaxWidth; + return GetTextWidth(); } void MultiSalLayout::GetCaretPositions( int nMaxIndex, sal_Int32* pCaretXArray ) const commit 04f4aaa36eab4cb7299e567d59b6e5de5c4f5bf6 Author: Khaled Hosny <kha...@libreoffice.org> AuthorDate: Thu Jun 8 16:41:18 2023 +0300 Commit: Caolán McNamara <caolan.mcnam...@collabora.com> CommitDate: Fri Jun 23 22:52:43 2023 +0200 tdf#151968: Fix vertical position of RTL spelling wavy line Second try. This time making sure start > end even for RTL text. This also now works for horizontal, vertical and rotated Arabic text, in Writer and Edit Engine. Change-Id: I6fe1e9dbb9c071287054200a58d4ddddee073311 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152820 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> diff --git a/svx/source/svdraw/svdotextdecomposition.cxx b/svx/source/svdraw/svdotextdecomposition.cxx index e526c44edc68..6d9d5cd9d5f8 100644 --- a/svx/source/svdraw/svdotextdecomposition.cxx +++ b/svx/source/svdraw/svdotextdecomposition.cxx @@ -427,8 +427,12 @@ namespace // full portion width const double fTextWidth(aDXArray[aDXArray.size() - 1]); - fStart = fTextWidth - fStart; - fEnd = fTextWidth - fEnd; + // tdf#151968 + // if start < end, OutputDevice::DrawWaveLine() will + // think it is a rotated line, so we swap fStart and + // fEnd to avoid this. + fStart = fTextWidth - fEnd; + fEnd = fTextWidth - fStart; } // need to take FontScaling out of values; it's already part of diff --git a/sw/source/core/txtnode/fntcache.cxx b/sw/source/core/txtnode/fntcache.cxx index 20ed476398d8..0da5658e1749 100644 --- a/sw/source/core/txtnode/fntcache.cxx +++ b/sw/source/core/txtnode/fntcache.cxx @@ -241,10 +241,20 @@ static void lcl_calcLinePos( const CalcLinePosData &rData, break; } + // tdf#151968 + // if start < end, OutputDevice::DrawWaveLine() will think it is a rotated + // line, so we swap nStart and nEnd to avoid this. + if ( rData.bBidiPor ) + std::swap(rStart, rEnd); + if ( rData.bSwitchL2R ) { rData.rInf.GetFrame()->SwitchLTRtoRTL( rStart ); rData.rInf.GetFrame()->SwitchLTRtoRTL( rEnd ); + + // tdf#151968 + // We need to do this here as well for LTR text in a RTL paragraph. + std::swap(rStart, rEnd); } if ( rData.bSwitchH2V )