Bug 30731 - Cursor jumps around when moving through some ligatures
Summary: Cursor jumps around when moving through some ligatures
Status: RESOLVED FIXED
Alias: None
Product: LibreOffice
Classification: Unclassified
Component: LibreOffice (show other bugs)
Version:
(earliest affected)
Inherited From OOo
Hardware: All All
: medium minor
Assignee: ⁨خالد حسني⁩
URL:
Whiteboard: target:7.5.0 inReleaseNotes:7.5
Keywords:
: 119347 (view as bug list)
Depends on:
Blocks: Font-Rendering
  Show dependency treegraph
 
Reported: 2010-10-09 07:21 UTC by RGB
Modified: 2022-12-04 14:52 UTC (History)
4 users (show)

See Also:
Crash report or crash signature:


Attachments
Short screencast (97.45 KB, video/mp4)
2016-02-21 10:31 UTC, RGB
Details
Screencast updated to LibO 5.3 (123.56 KB, video/mp4)
2017-03-06 16:59 UTC, RGB
Details
Screencast comparing the cursor movement of ligated with unligated text (704.26 KB, video/quicktime)
2022-08-26 02:29 UTC, ⁨خالد حسني⁩
Details
Screencast of cursor movement with my patches applied (2.22 MB, video/quicktime)
2022-08-30 07:53 UTC, ⁨خالد حسني⁩
Details

Note You need to log in before you can comment on or make changes to this bug.
Description RGB 2010-10-09 07:21:20 UTC
Steps to reproduce the problem:
1- Install Linux Libertine G font from here: http://numbertext.org/linux/
2- Open a Writer document and type the following text

Some text \prime Some text fi more text

3- Modify the paragraph style to use the Linux Libertine G font with "tex mode" enablesd (on the font name box type: Linux Libertine G:texm=1)
"\prime" will change into ' and fi will be replaced with proper typographical ligature.
4- Put the cursor on the end of the paragraph and use the cursor arrows to go to the left one character at a time.

Actual result:
While the cursor behaviour is OK on the fi ligature (and this is an improvement respect OOo 3.2.x), when you arrive to the "prime" the cursor will jump to the right, possible going to the position where the text \prime should be if "tex mode" were not enabled.

This behaviour is confusing because the cursor jump to a text position, but if you press "back space" the text deleted is the one "hidden" by the Graphite replacement, not the one where cursor is shown.
Comment 1 martin_hosken 2011-02-17 19:34:32 UTC
This bug exemplifies a couple of problems.

Bug 34420 addresses most of the needs here. But there is also something wrong with the font. When creating ligatures it is necessary to associate the ligature with all (well the first and last) of the underlying glyphs. Thus a rule (taken from MagyarLinLibertineG) like:

unicode(0x005C) p("a") p("l") p("p") p("h") p("a") > _ _ _ _ _ unicode(0x03B1);

needs to become:

unicode(0x005C) p("a") p("l") p("p") p("h") p("a") > _ _ _ _ _ unicode(0x03B1):(1 6);

This then tells the engine that the whole string \alpha is associated with the one output glyph rather than saying that it is deleting \alph and associating the alpha with the final a only.

Bug 34420 removes the most egregious problems with not specifying appropriately, but doesn't solve everything.

In addition there is the issue that people don't really want to have to right arrow 6 times to get past the alpha, which the current cursor tracking algorithm, which is based on a purely codepoint based (UAX#29) model, requires.
Comment 2 Rainer Bielefeld Retired 2011-10-27 22:33:10 UTC
Modified Version due to report date.

@RGB:
Still a problem for you?
Comment 3 RGB 2011-10-28 17:01:52 UTC
(In reply to comment #2)
> @RGB:
> Still a problem for you?

Yes. Same behavior as described on initial entry with LibO 3.4.2.
Comment 4 Björn Michaelsen 2011-12-23 11:35:38 UTC Comment hidden (noise)
Comment 5 RGB 2011-12-23 16:53:26 UTC
The problem is present on 3.5 beta2.
Comment 6 martin_hosken 2012-01-03 20:19:19 UTC
did you fix the font?
Comment 7 QA Administrators 2014-06-25 17:38:02 UTC Comment hidden (noise)
Comment 8 QA Administrators 2014-10-23 17:32:23 UTC Comment hidden (noise)
Comment 9 Joel Madero 2014-12-15 01:23:38 UTC
I have verified this issue on:
Ubuntu 14.04 x64
LibreOffice 4.3.4.1 release

Changing priority according to flowchart: https://wiki.documentfoundation.org/images/0/06/Prioritizing_Bugs_Flowchart.jpg

Minor - can slow down professional quality work but won't prevent it.
Lowest - seems like this is really a corner case issue and the workaround is pretty straight forward (just push left a few more times).

@RGB - thanks for reporting and for your patience and understanding. Our team is powered by a group of volunteers who are giving thousands of hours at no cost to make LibreOffice better for everyone.
Comment 10 QA Administrators 2016-02-21 08:36:13 UTC Comment hidden (noise)
Comment 11 RGB 2016-02-21 10:11:06 UTC
On 5.1 the behaviour is different, but still not correct. Now, when by pressing the cursor arrow to the left you arrive to the "prime" character, the cursor remains on its position for six strokes before jumping to the other side, which is a bit confusing too. 

Try writing, on the same conditions as before (with textm=1) the following text

Text \prime more text \alpha and final text

and try to move the cursor one position at a time from the right. Now there is a confusing behaviour not only on the prime and alpha characters, but on the word "final" with the cursor remaining for two strokes on the "n" and then jumping the "fi" ligature on one step.

Tested on vanilla LibO 5.1.0.3 (64 bits) under openSUSE 13.2.
Comment 12 RGB 2016-02-21 10:31:47 UTC
Created attachment 122845 [details]
Short screencast

This is a short screencast that show the behaviour on LibO 5.1 (file is a mp4 video)
Comment 13 martin_hosken 2016-02-22 02:43:07 UTC
If my understanding of the internals of libo are correct, the cursor behaviour is not based on font rendering but on Unicode character properties. Thus, although graphite is being used to turn a long string of letters into a single glyph, the cursor movement is based purely on the underlying characters. This would happen whether the font were Graphite or OT based.

The key code seems to be in SwContentNode::GoNext (sw/core/docnode/node.cxx) and uses an ICU break iterator to control the cursor movement.

Basically, this isn't a graphite or graphite integration bug.
Comment 14 QA Administrators 2017-03-06 15:26:40 UTC Comment hidden (noise)
Comment 15 RGB 2017-03-06 16:59:55 UTC
Created attachment 131682 [details]
Screencast updated to LibO 5.3

Still present on 5.3. The behaviour is a bit different than what's shown on the previous screencast (now it's back to the originally reported behaviour), so I updated it.
Comment 16 QA Administrators 2018-05-18 02:33:24 UTC Comment hidden (noise)
Comment 17 RGB 2018-05-18 06:16:59 UTC
Problem still present 6.0.4.2. The behaviour can be seen not only with Graphite fonts, but with OpenType ones too. If you take a font with "alternate fractions", for example, like Sukhumala(1) and set the font as

Sukhumala:afrc

for the text "1/2" you'll see exactly the same behaviour when moving the cursor from right to left towards the fraction.

------
(1) http://www.softerviews.org/Fonts.html#Sukhumala
Comment 18 QA Administrators 2019-05-19 02:50:34 UTC Comment hidden (noise)
Comment 19 RGB 2019-05-19 11:56:46 UTC
Problem still present on 6.2.3.2. Comment 17 is still valid.
Comment 20 martin_hosken 2019-05-20 07:41:59 UTC Comment hidden (no-value)
Comment 21 QA Administrators 2021-05-20 04:34:21 UTC Comment hidden (noise)
Comment 22 RGB 2021-05-20 19:38:34 UTC
Problem still present on 7.1.3.2. Comment 17 is still valid.
Comment 23 ⁨خالد حسني⁩ 2022-08-26 02:29:28 UTC
Created attachment 182033 [details]
Screencast comparing the cursor movement of ligated with unligated text

I believe the problem is that LibreOffice (or writer) is measuring the text width in chunks to determine the cursor position, e.g. in the string “office” for the cursor at “o|ffice” it will measure the width of “o” to position the cursor, and in “of|fice” it will measure the width of “of” and so on. For ligatures where the width of the partial text is close enough to the with of the ligature component, things appear to work, but in the problematic cases here the difference is way off that the cursor appears to be jumping.

See the cursor movement in the attached screencast and compare the cursor position when it jumps with the unligated text below it, the cursor jumps to exactly where the unligated glyph is.
Comment 24 ⁨خالد حسني⁩ 2022-08-26 15:20:40 UTC
(In reply to خالد حسني from comment #23)
> Created attachment 182033 [details]
> Screencast comparing the cursor movement of ligated with unligated text
> 
> I believe the problem is that LibreOffice (or writer) is measuring the text
> width in chunks to determine the cursor position, e.g. in the string
> “office” for the cursor at “o|ffice” it will measure the width of “o” to
> position the cursor, and in “of|fice” it will measure the width of “of” and
> so on. For ligatures where the width of the partial text is close enough to
> the with of the ligature component, things appear to work, but in the
> problematic cases here the difference is way off that the cursor appears to
> be jumping.
> 
> See the cursor movement in the attached screencast and compare the cursor
> position when it jumps with the unligated text below it, the cursor jumps to
> exactly where the unligated glyph is.

I can confirm this is exactly what is happening, and here a quick patch:
diff --git a/sw/source/core/txtnode/fntcache.cxx b/sw/source/core/txtnode/fntcache.cxx
index 146122841e7c..8389c39f54e3 100644
--- a/sw/source/core/txtnode/fntcache.cxx
+++ b/sw/source/core/txtnode/fntcache.cxx
@@ -1608,8 +1608,9 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf )
         if( !GetScrFont()->IsSameInstance( rInf.GetOut().GetFont() ) )
             rInf.GetOut().SetFont( *m_pScrFont );

+        sal_Int32 nLength(rInf.GetText().getLength() - sal_Int32(rInf.GetIdx()));
         GetTextArray(*m_pPrinter, rInf.GetText(), aKernArray,
-                     sal_Int32(rInf.GetIdx()), sal_Int32(nLn));
+                     sal_Int32(rInf.GetIdx()), nLength);
     }
     else
     {

With this patch, the cursor no longer jumps, but it won’t “enter” the ligature either (i.e. it will remain at the end of the ligature for the number of letters in the ligature). We can improve this, but I’m not sure what this code is used also for and this change is certainly wrong in other situations.

Now I need someone who is familiar with these parts of Writer to guide me in untangling all of this.
Comment 25 ⁨خالد حسني⁩ 2022-08-26 21:55:04 UTC
WIP: https://gerrit.libreoffice.org/c/core/+/138889
Comment 26 ⁨خالد حسني⁩ 2022-08-30 07:53:19 UTC
Created attachment 182087 [details]
Screencast of cursor movement with my patches applied

Here is the current status:
1. Ligatures are detected and the width of the glyph is evenly distributed over the number of grapheme clusters that make up the ligature. This works nicely for “real” ligatures, but a bit awkward for Linux Libertine G’s text replacement disguised as ligatures. But we can’t distinguish between the two, and we want this behavior for most ligatures.
2. If the font has OpenType ligature caret information, we will use it for more fine grained caret placement inside the ligature.
Comment 27 Commit Notification 2022-08-31 06:30:19 UTC
Khaled Hosny committed a patch related to this issue.
It has been pushed to "master":

https://git.libreoffice.org/core/commit/8cb4db941f91cc234dd18c61f8b1e51f65360d1f

tdf#30731: Improve caret travelling in Writer

It will be available in 7.5.0.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.
Comment 28 Commit Notification 2022-08-31 06:47:34 UTC
Khaled Hosny committed a patch related to this issue.
It has been pushed to "master":

https://git.libreoffice.org/core/commit/bdbbdc9b931d35f6d7d816512ac5be599295dc80

tdf#30731: Use ligature caret positions from the font

It will be available in 7.5.0.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.
Comment 29 ⁨خالد حسني⁩ 2022-10-02 10:08:09 UTC
*** Bug 119347 has been marked as a duplicate of this bug. ***