Bug 403868 - Bottom of text lines is sometimes cut off
Summary: Bottom of text lines is sometimes cut off
Status: RESOLVED FIXED
Alias: None
Product: frameworks-ktexteditor
Classification: Frameworks and Libraries
Component: general (show other bugs)
Version: unspecified
Platform: Compiled Sources Linux
: NOR normal
Target Milestone: ---
Assignee: KWrite Developers
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-02-02 17:00 UTC by Thomas Schöps
Modified: 2019-02-25 17:00 UTC (History)
2 users (show)

See Also:
Latest Commit:
Version Fixed In: 5.56


Attachments
Screenshot showing the issue (134.11 KB, image/png)
2019-02-02 17:00 UTC, Thomas Schöps
Details
Screenshot showing another way the bug seems to show up (24.37 KB, image/png)
2019-02-02 17:17 UTC, Thomas Schöps
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas Schöps 2019-02-02 17:00:38 UTC
Created attachment 117788 [details]
Screenshot showing the issue

SUMMARY

In recent versions of KTextEditor-based applications (KWrite, KDevelop), the bottom of text lines is sometimes cut off, to the extent that underscores become invisible. It happens to new text lines that enter the view from the top when scrolling upwards (maybe also in other cases, not sure whether this is the only trigger). When scrolling downwards, everything is fine. The behavior depends on how the scrolling is done:
* When using the mouse wheel (scrolling by 3 lines at once), every 3rd line is cut off
* When dragging the mouse in the minimap, almost every line is cut off
* When scrolling is invoked by the cursor going beyond the top of the view, no line is cut off.

When setting the cursor within some lines affected by the bug, the line with the cursor and the line above it return to normal state.

This seems to be a regression, since old versions of KWrite etc. worked fine. Unfortunately, I don't know when it was introduced.

The attached screenshot demonstrates the bug, showing two versions of KWrite running on the same system. On the left is a current self-compiled version of KWrite after scrolling up within the document with the mouse wheel. Every line contains the same text, including underscores. Look for the missing underscores in every 3rd line (also, the 'g's in 'testing' are cut off, so it does not only affect underscores). On the right is an old version of KWrite (I think it is the distribution-provided version of Kubuntu 14.04), for which the same actions were done, which does not show the bug.


STEPS TO REPRODUCE
1. Using e.g. KWrite, write some text containing underscores that exceeds the view height
2. Starting from the bottom of the document, scroll up by dragging on the minimap
3. Text lines coming into view will be cut off


VERSION
Applies to recent versions of the software, including the current master, I believe.
Comment 1 Thomas Schöps 2019-02-02 17:17:47 UTC
Created attachment 117791 [details]
Screenshot showing another way the bug seems to show up

Another way this bug seems to show up is if doing a multi-line text selection backwards (drag from the end to the start, not the start to the end). Single-line selections don't seem to trigger it. Then, if the multi-line selection is cleared by clicking another point in the document, the blue selection background remains at the bottom of the last line of the selection. See the second attached screenshot.
Comment 2 Dominik Haumann 2019-02-02 22:29:16 UTC
Which Qt version do you use?

The issue with the last line is not fixed. But the selection issue should be fixed with Qt 5.12 (best 5.12.1, since 5.12.0 has severe issues).
Comment 3 Dominik Haumann 2019-02-02 22:33:42 UTC
Duplicate of https://bugs.kde.org/show_bug.cgi?id=403470 ?
Comment 4 Thomas Schöps 2019-02-02 22:39:55 UTC
I am using Qt 5.12.0 (both for compiling and at runtime according to the libraries tab in KWrite's about dialog).

I can reproduce the behavior described in the bugreport you linked as well. Indeed, it seems like this might have the same issue (perhaps not redrawing the full height of text lines?). As I described, it also happens in other cases though, not only for the last line. And these cases seem more severe, as it might e.g. make underscores invisible.
Comment 5 Dominik Haumann 2019-02-02 22:53:02 UTC
Ok, this needs investigation and is bad news ...
Comment 6 Dominik Haumann 2019-02-05 21:29:43 UTC
Background: The rendering pipeline in Kate (KateRenderer) is line based: if a line needs to be drawn, the following happens:
1. We fill the line rect with the background color.
2. We collect range data such as a selection and paint this background data over the background
3. The foreground text is drawn.

The problem of this approach is that many fonts have characters such as _ that are layouted such that they are painted into the next line. However, when the next line is painted, the background fill overpaints these characters again.

In other words: the current painting algo is inherently broken. A proper fix would be to have several layers, and then blit one over the other.

Our hack/workaround in the past was for line N to also again draw text of line N-1 and N+1 with clipping for line N.

This clipping leads to the bug that the very last line misses characters such as _, since there is no line N+1.

Now this bug report tells us we still have issues with overpainting.

If anyone wants ti have a look, the above info may help to understand what's going on in the code, maybe someone finds a good fix?
Comment 7 Thomas Schöps 2019-02-06 00:58:55 UTC
Could it be that the real issue here is that there is a mismatch between the line height used in KTextEditor and the line height used internally in Qt for drawing? I had a look at https://github.com/qt/qtbase/blob/5.12/src/gui/text/qtextlayout.cpp (line 2270 at the moment) where the text height is set as:

qreal height = maxY + fontHeight - minY;

with fontHeight:
qreal fontHeight = font.ascent() + font.descent();

For testing I then replaced the font height setting in KateRenderer::updateFontHeight() to match this with:

m_fontHeight = qMax(1, qCeil(config()->fontMetrics().ascent() + config()->fontMetrics().descent()));

The old resulting value was 14, the new one 15. From some short testing it seems that this makes the related issues disappear (at least for the font that is used on my system by default). I don't have more time to look into this right now though. The Qt code also seems to have a mechanism to adjust the font height according to the glyphs somehow (with maxY and minY).
Comment 8 Christoph Cullmann 2019-02-06 13:52:25 UTC
Hmm, sounds interesting ;=)

I thought I would have once checked that this matches, but it seems that isn't the case.
Comment 9 Christoph Cullmann 2019-02-24 17:32:50 UTC
That height seems to help to avoid overpainting 

https://phabricator.kde.org/D19283
Comment 10 Christoph Cullmann 2019-02-25 17:00:35 UTC
Should be fixed with:

https://phabricator.kde.org/D19283