Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 408833

Summary: StyledText hides last character of wrapped line
Product: [Eclipse Project] Platform Reporter: Markus Keller <markus.kell.r>
Component: SWTAssignee: Brian de Alwis <bsd>
Status: VERIFIED FIXED QA Contact: Niraj Modi <niraj.modi>
Severity: major    
Priority: P3 CC: bsd, daniel_megert, Lars.Vogel, loskutov, lshanmug, niraj.modi, peter
Version: 4.3   
Target Milestone: 4.6 M4   
Hardware: PC   
OS: Windows 7   
See Also: https://git.eclipse.org/r/53437
https://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/?id=5a79c3e65a59cceee29d76c03249fe0d5f9ed374
https://git.eclipse.org/r/60742
https://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/?id=9e76f3ed668a6862d407d4ac586dcbb28cbaef59
Whiteboard:
Bug Depends on:    
Bug Blocks: 35779, 479980    
Attachments:
Description Flags
Screenshot
none
Sample test program none

Description Markus Keller CLA 2013-05-23 11:56:40 EDT
Created attachment 231388 [details]
Screenshot

I20130522-2000

StyledText completely hides the last character of a line when wrapping with certain fonts and widget widths. Unless the widget is very narrow, the last character of each line should always be rendered entirely (or moved to the next line if there's not enough space). The Text widget behaves as expected.

The screenshot shows a case in the CustomControlExample where the "h" on the first line is completely invisible and the "w" on the second line is truncated. The text is: "Hello_world,_how_do_you_wrap_today?"

Originally seen in the Variables view's detail pane when rendering string
"file:/C:/e/w/runtime-head-CLEAN-2/org.eclipse.jdt.ui/about.html"
with Lucida Console 8, and the "a" after the last slash was completely missing.
Comment 1 Brian de Alwis CLA 2015-08-07 23:24:26 EDT
Created attachment 255722 [details]
Sample test program

I did some digging into this and have a solution.  I've attached the test program I used to reproduce Markus' example above.

The problem is in the win32-specific TextLayout in computeRuns(), specifically around line 335.  This section handles where there is insufficent room on the line to include the next character run, but there is no obvious spot to break the line (i.e., a soft-break/line-break has not been found).  The code needs to decide whether to split the current character run (at the 'o' in Markus' example above) or push the entire run to the next line.

The previous code would only push the run to the next line if there had been a previous run (firstIndice > 0) and that the previous runs fit exactly into the line (lineWidth == wrapWidth).  Otherwise it would split the current run, and include at least one character of the run even if there was only 1 pixel of space.

The fixed code pushes the run to the next line if nothing fits (firstStart == 0) and there a previous run has already been included (lineWidth > 0 && firstIndice > 0).

                        } else  if (start <= 0 && i == lineStart) {
-                               if (lineWidth == wrapWidth && firstIndice > 0) {
+                               if (lineWidth > 0 && firstIndice > 0 && firstStart == 0) {

In my testing, the StyledText examples now behaves as it does on OS X.
Comment 2 Eclipse Genie CLA 2015-08-07 23:25:45 EDT
New Gerrit change created: https://git.eclipse.org/r/53437
Comment 3 Lars Vogel CLA 2015-08-18 06:22:58 EDT
Can this be reviewed for M2? It blocks the popular Bug 35779 in platform UI.
Comment 5 Niraj Modi CLA 2015-08-27 09:58:57 EDT
Thanks for the patch, resolving the bug now.
Comment 6 Niraj Modi CLA 2015-10-19 06:56:36 EDT
Re-opening.. fix for this bug introduced a freeze in TextLayout.computeRuns bug 479980, hence reverted this fix via below git commit:
http://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/?id=b92b665169259a26da4e7566268a748473b777c4
Comment 7 Andrey Loskutov CLA 2015-10-26 14:58:26 EDT
Since this bug blocks most wanted "word wrapping" feature (see bug 35779 comment 234), increasing the priority and targeting to M4. 
Brian, what do you think, would you have time to look at this issue again in M4?
Comment 8 Dani Megert CLA 2015-10-26 15:12:57 EDT
(In reply to Andrey Loskutov from comment #7)
> Since this bug blocks most wanted "word wrapping" feature (see bug 35779
> comment 234), increasing the priority and targeting to M4. 

+1.
Comment 9 Niraj Modi CLA 2015-11-12 02:15:03 EST
(In reply to Andrey Loskutov from comment #7)
> Since this bug blocks most wanted "word wrapping" feature (see bug 35779
> comment 234), increasing the priority and targeting to M4. 
> Brian, what do you think, would you have time to look at this issue again in
> M4?

Hi Brian,
Just a quick check, are you planning this bug for M4 ?
Comment 10 Brian de Alwis CLA 2015-11-12 09:28:17 EST
(In reply to Niraj Modi from comment #9)
> Just a quick check, are you planning this bug for M4 ?

Yes!
Comment 11 Eclipse Genie CLA 2015-11-18 15:05:44 EST
New Gerrit change created: https://git.eclipse.org/r/60742
Comment 12 Brian de Alwis CLA 2015-11-18 15:19:40 EST
Great test case from Markus on bug 479980.  The reasoning behind my fix is correct, but the actual conditions tested weren't quite right.

> The fixed code pushes the run to the next line if nothing fits (firstStart == 0)    and there a previous run has already been included (lineWidth > 0 && firstIndice > 0).

Markus' case is a bit pathological as the StyledText is initially wrapped with a line length of 1 pixel, and it adds a wrapIndent of 15 pixels.  This meant every subsequent line starts with lineWidth == 15, and (wrongly) triggers the push-current-run-to-the-next-line case:

    if (lineWidth > 0 && firstIndice > 0 && firstStart == 0) {

The correct test for this condition is 

    if (firstStart == 0 && firstIndice > lineStart) {

lineStart is the run index for the first run of the current line.  firstIndice is the run index for the last run that could be completely fit into the current line with no wrapping.  If firstIndice == lineStart, then no runs were able to be fit into the current line.

The test of 'firstIndice > 0' is faulty and was present in the original code.  It should be 'firstIndice > lineStart' as 'firstIndice > 0' will true for all lines > 1.

I've revised my patch.
Comment 13 Niraj Modi CLA 2015-11-20 05:22:46 EST
(In reply to Brian de Alwis from comment #12)
> Great test case from Markus on bug 479980.  The reasoning behind my fix is
> correct, but the actual conditions tested weren't quite right.
> 
> > The fixed code pushes the run to the next line if nothing fits (firstStart == 0)    and there a previous run has already been included (lineWidth > 0 && firstIndice > 0).
> 
> Markus' case is a bit pathological as the StyledText is initially wrapped
> with a line length of 1 pixel, and it adds a wrapIndent of 15 pixels.  This
> meant every subsequent line starts with lineWidth == 15, and (wrongly)
> triggers the push-current-run-to-the-next-line case:
> 
>     if (lineWidth > 0 && firstIndice > 0 && firstStart == 0) {
> 
> The correct test for this condition is 
> 
>     if (firstStart == 0 && firstIndice > lineStart) {
> 
> lineStart is the run index for the first run of the current line. 
> firstIndice is the run index for the last run that could be completely fit
> into the current line with no wrapping.  If firstIndice == lineStart, then
> no runs were able to be fit into the current line.
> 
> The test of 'firstIndice > 0' is faulty and was present in the original
> code.  It should be 'firstIndice > lineStart' as 'firstIndice > 0' will true
> for all lines > 1.
> 
> I've revised my patch.

Revised patch looks good, works fine for the scenario in bug 479980 as well.
Will test this further and planning to push it for coming I-Build.
Comment 15 Niraj Modi CLA 2015-11-24 03:22:26 EST
(In reply to Eclipse Genie from comment #14)
> Gerrit change https://git.eclipse.org/r/60742 was merged to [master].
> Commit:
> http://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/
> ?id=9e76f3ed668a6862d407d4ac586dcbb28cbaef59

Thanks for the revised patch Brian, have verified this patch with Eclipse's Wrod-wrap option as well. Resolving this bug now.
Comment 16 Niraj Modi CLA 2015-12-09 03:04:34 EST
Verified the fix in I-Build: I20151207-2000