summaryrefslogtreecommitdiff
path: root/vcl/source/outdev/text.cxx
diff options
context:
space:
mode:
authorKhaled Hosny <khaled@aliftype.com>2022-08-26 22:20:55 +0200
committerMiklos Vajna <vmiklos@collabora.com>2022-08-31 08:29:49 +0200
commit8cb4db941f91cc234dd18c61f8b1e51f65360d1f (patch)
tree4637ae5e0d509302f7b7a1b12f580a1749e4e36e /vcl/source/outdev/text.cxx
parentd325edf88c8dbcdaf324b8e3585a314c9351cf60 (diff)
tdf#30731: Improve caret travelling in Writer
Previously, when measuring caret position, Writer would measure the width of the substring before the caret (i.e. layout it independent of the text after the caret and measure its width). This is incorrect, though. It assumes cutting the string laying it out would result in the same width as when laid out as part of a bigger string, which is invalid assumption when e.g. cutting inside a ligature or between letters that have different shapes when next to each other, etc. This appears to work when the width of the substring laid out alone is close enough to its width when laid out with the full text. But in cases where is widths are largely different, like the extreme case in the bug report, the caret will be jumping around as it is positioned based on the unligated glyphs not the ligated, rendered glyphs. This change introduces a special mode of measuring text width for caret positioning, that will layout the whole string that return the width of the requested substring. Fields and small caps text are trickier to handle, so old behaviour is retained for them. Now one will probably notice but if they do, it can be dealt with then. This also tries to be conservative and keep other pleases using the existing behaviour which might be desirable (e.g. when measuring text width for line breaking, we want the unligated width), but there might be other places that should use the new behaviour. To handle caret inside ligatures, the grapheme clusters in the ligature are counted and the width of the whole ligature is distributed on them evenly. A further improvement would be using HarfBuzz API to get ligature caret positions for fonts that provide them, which helps when the ligature components have different widths. Change-Id: I02062e2e2e1b1a35c8f84307c0a8f5d743059ab5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138889 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Diffstat (limited to 'vcl/source/outdev/text.cxx')
-rw-r--r--vcl/source/outdev/text.cxx8
1 files changed, 4 insertions, 4 deletions
diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx
index 0cf0283dc5c7..d5969c7a0092 100644
--- a/vcl/source/outdev/text.cxx
+++ b/vcl/source/outdev/text.cxx
@@ -889,7 +889,7 @@ tools::Long OutputDevice::GetTextWidth( const OUString& rStr, sal_Int32 nIndex,
{
tools::Long nWidth = GetTextArray( rStr, nullptr, nIndex,
- nLen, pLayoutCache, pSalLayoutCache );
+ nLen, false, pLayoutCache, pSalLayoutCache );
return nWidth;
}
@@ -956,7 +956,7 @@ void OutputDevice::DrawTextArray( const Point& rStartPt, const OUString& rStr,
}
tools::Long OutputDevice::GetTextArray( const OUString& rStr, std::vector<sal_Int32>* pDXAry,
- sal_Int32 nIndex, sal_Int32 nLen,
+ sal_Int32 nIndex, sal_Int32 nLen, bool bCaret,
vcl::text::TextLayoutCache const*const pLayoutCache,
SalLayoutGlyphs const*const pSalLayoutCache) const
{
@@ -994,7 +994,7 @@ tools::Long OutputDevice::GetTextArray( const OUString& rStr, std::vector<sal_In
xDXPixelArray.reset(new std::vector<DeviceCoordinate>(nLen));
}
std::vector<DeviceCoordinate>* pDXPixelArray = xDXPixelArray.get();
- DeviceCoordinate nWidth = pSalLayout->FillDXArray(pDXPixelArray);
+ DeviceCoordinate nWidth = pSalLayout->FillDXArray(pDXPixelArray, bCaret ? rStr : OUString());
int nWidthFactor = pSalLayout->GetUnitsPerPixel();
// convert virtual char widths to virtual absolute positions
@@ -1039,7 +1039,7 @@ tools::Long OutputDevice::GetTextArray( const OUString& rStr, std::vector<sal_In
#else /* ! VCL_FLOAT_DEVICE_PIXEL */
- tools::Long nWidth = pSalLayout->FillDXArray( pDXAry );
+ tools::Long nWidth = pSalLayout->FillDXArray( pDXAry, bCaret ? rStr : OUString() );
int nWidthFactor = pSalLayout->GetUnitsPerPixel();
// convert virtual char widths to virtual absolute positions