After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 715008 - antialiasing gone wrong when the textview is scrollable
antialiasing gone wrong when the textview is scrollable
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: Widget: GtkTextView
3.11.x
Other Linux
: Normal normal
: ---
Assigned To: gtk-bugs
gtk-bugs
: 721063 729126 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2013-11-22 12:26 UTC by Mantas Mikulėnas (grawity)
Modified: 2014-08-22 02:13 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
gedit screenshot (bad) (69.08 KB, image/png)
2013-11-22 12:26 UTC, Mantas Mikulėnas (grawity)
  Details
gedit screenshot (good) (64.08 KB, image/png)
2013-11-22 12:29 UTC, Mantas Mikulėnas (grawity)
  Details
Details enlarged (35.70 KB, image/png)
2013-12-06 09:27 UTC, Alexander Larsson
  Details
PixelCache: Set event window on cairo_t (4.29 KB, patch)
2014-01-09 16:33 UTC, Alexander Larsson
none Details | Review
PixelCache: Refactor pixelcache surface creation (2.78 KB, patch)
2014-01-09 16:33 UTC, Alexander Larsson
none Details | Review
StyleContext: Add gtk_style_context_get_background_is_static() (3.55 KB, patch)
2014-01-09 16:34 UTC, Alexander Larsson
none Details | Review
PixelCache: Add _gtk_pixel_cache_draw_with_bg() (7.71 KB, patch)
2014-01-09 16:34 UTC, Alexander Larsson
none Details | Review
TreeView: Avoid using alpha pixel cache when possible (2.06 KB, patch)
2014-01-09 16:34 UTC, Alexander Larsson
none Details | Review
TextView: Fix AA rendering on pixel cache, re-fixing gedit rendering (5.03 KB, patch)
2014-01-09 16:34 UTC, Alexander Larsson
none Details | Review
TextView: Fix AA rendering on pixel cache, re-fixing gedit rendering (9.16 KB, patch)
2014-01-10 10:57 UTC, Alexander Larsson
none Details | Review

Description Mantas Mikulėnas (grawity) 2013-11-22 12:26:43 UTC
Created attachment 261228 [details]
gedit screenshot (bad)

When the textview widget is scrollable, it starts doing funny things to RGBA-antialiased text, causing very noticeable color fringes.

This affects gedit; the 'description' area in gtk3-demo; some other places too.

comments from #Gtk+ on IRC:

(alex) I think the problem is that it picks a transparent
       background for the offscreen pixmap
(alex) then it composes it again against the white
(alex) I think it essentially does the AA against a black
       background and then applies it on the white, or
       something like that
Comment 1 Mantas Mikulėnas (grawity) 2013-11-22 12:29:57 UTC
Created attachment 261229 [details]
gedit screenshot (good)

gtk3 3.11.2-11-gda86918
cairo 1.12.16-64-g8c73949
freetype2 2.5.0.1-125-gbc25de6
Comment 2 Mantas Mikulėnas (grawity) 2013-12-05 12:01:25 UTC
bisect:

commit 1ac13435b7c14dd9b97ad7a9d292acd51337d66e
Author: Alexander Larsson <alexl@redhat.com>
Date:   Wed Oct 2 15:14:56 2013 +0200

    GtkTextView: Fix regression in GtkSourceView drawing
Comment 3 Alexander Larsson 2013-12-06 08:48:13 UTC
Ugh, yeah, that is the commit that made the pixel cache transparent, which is causing the problem because we do

 // draw text on cache (starting out transparent)
 pixelcache = OVER(transparent, text)
 // draw pixel cache over background
 destination = OVER(background, pixelcache)

Which is not the same as
 destination = OVER(background, text)
that we want.

However, that change was added to fix gedit drawing, so we can't just revert it without breaking gedit in other ways.
Comment 4 Alexander Larsson 2013-12-06 09:27:17 UTC
Created attachment 263641 [details]
Details enlarged
Comment 5 Benjamin Otte (Company) 2013-12-06 12:37:01 UTC
So afaics the problem is that we lose the per-channel alpha information when doing subpixel antialiasing with an intermediate transparency surface.

Example: We have blue text over a white background and the left half of the pixel should be filled. This is the extreme version of what you can see in Alex' comparison for both the "t" glyphs in "content" in the bottommost row.

Background: RGBA 0xFFFFFFFF
Foreground: RGBA 0xFF0000FF
alpha mask: 3 channels 0x0080FF

Compositing directly:
     0xFF0000FF
OVER 0xFFFFFFFF
MASK   0x0080FF
RESULT
     0xFFFF80FF

Compositing indirectly:
     0xFF0000FF
OVER 0x00000000
MASK   0x0080FF
RESULT
     0xFF0000FF

     0xFF0000FF
OVER 0xFFFFFFFF
RESULT
     0xFF0000FF

So in the first case we get a pinkish tone 0xFF80FF and in the second case we get blue 0x0000FF.
Comment 6 Alexander Larsson 2013-12-06 12:49:57 UTC
Example without subpixel AA (or rather, using the same value for all alpha channels):

Background: RGBA 0xFFFFFFFF
Foreground: RGBA 0xFF0000FF
alpha mask: 0x80

Compositing directly:
     0xFF0000FF
OVER 0xFFFFFFFF
MASK       0x80
RESULT
     0xFF8080FF

Compositing indirectly:
     0xFF0000FF
OVER 0x00000000
MASK       0x80
RESULT
     0x80000080

     0x80000080
OVER 0xFFFFFFFF
RESULT
     0xFF8080FF
Comment 7 Matthias Clasen 2014-01-05 04:40:47 UTC
*** Bug 721063 has been marked as a duplicate of this bug. ***
Comment 8 Alexander Larsson 2014-01-09 16:33:53 UTC
Created attachment 265854 [details] [review]
PixelCache: Set event window on cairo_t

We set the passed in GdkWindow as the event window on the cairo_t
so that it will return TRUE from gtk_cairo_should_draw_window() only
for that window. It also means we won't be propagating the draw
to children that are in another GdkWindow.

This seems generally right, and will be needed later to allow
GtkTextView to run the entire draw signal handler when drawing the
pixelcache without drawing stuff that was meant for other windows.
Comment 9 Alexander Larsson 2014-01-09 16:33:57 UTC
Created attachment 265855 [details] [review]
PixelCache: Refactor pixelcache surface creation

_gtk_pixel_cache_create_surface_if_needed now returns TRUE if the
cache will be used. Additionally, we avoid painting the cache at all
on draw if its not used due to e.g. drawing on a PDF surface.
Comment 10 Alexander Larsson 2014-01-09 16:34:01 UTC
Created attachment 265856 [details] [review]
StyleContext: Add gtk_style_context_get_background_is_static()

This lets us check for background that are static, i.e look the same
independent of scrolling around on them. For such backgrounds we
need not use alpha in any pixel caches, we can just draw the background
on a opaque pixel cache before drawing the widget. This is an important
optimization.
Comment 11 Alexander Larsson 2014-01-09 16:34:06 UTC
Created attachment 265857 [details] [review]
PixelCache: Add _gtk_pixel_cache_draw_with_bg()

This version has a callback for filling in an opaque
background, which allows us to always use non-alpha surfaces.
If you can guarantee that the background works for this that
is a significant optimization.
Comment 12 Alexander Larsson 2014-01-09 16:34:10 UTC
Created attachment 265858 [details] [review]
TreeView: Avoid using alpha pixel cache when possible

If the style context background is static we can always render
it as a pixel-cache background, so use _gtk_pixel_cache_draw_with_bg()
in that case. This means we avoid using alpha pixel cache in the
"normal" case where the bin_window is transparent but the normal
window is opaque white.
Comment 13 Alexander Larsson 2014-01-09 16:34:15 UTC
Created attachment 265859 [details] [review]
TextView: Fix AA rendering on pixel cache, re-fixing gedit rendering

This changes the text view to only use the pixel cache when the
background is a solid color, and in that case we draw the
widget background first, then re-emit the whole draw signal so
that all drawing goes to the pixelcache, including e.g. things
drawn before chaining up to the draw method of GtkTextView.

This is another fix of bug #708423 where gedit drawing before
chaining up was overdrawn by the pixelcache. The previous fix
of using an alpha pixelcache has worse performance and problems
with rgba AA (bug #715008).
Comment 14 Alexander Larsson 2014-01-09 16:58:51 UTC
Hmm, so i found a different gedit issue with this. If you enable a right margin overlay it will be drawn twice, once on the pixelcache and then once when drawn over the blitted pixelcache.

Anything drawn before the pixelcache will safely be overwritten with opaque paint, but we need to figure out how to disable further drawing.
Comment 15 Alexander Larsson 2014-01-10 10:57:25 UTC
Created attachment 265903 [details] [review]
TextView: Fix AA rendering on pixel cache, re-fixing gedit rendering

This changes the text view to only use the pixel cache when the
background is a solid color, and in that case we draw the
widget background first, then re-run the whole draw vfunc so
that all drawing goes to the pixelcache, including e.g. things
drawn before chaining up to the draw method of GtkTextView.

We draw the pixel cache in a separate after handler in order
to make sure we overdraw all the extra stuff that the
overriding draw vfunc may draw.

This is another fix of bug #708423 where gedit drawing before
chaining up was overdrawn by the pixelcache. The previous fix
of using an alpha pixelcache has worse performance and problems
with rgba AA (bug #715008).
Comment 16 Alexander Larsson 2014-01-10 11:01:48 UTC
New alternative patch trying to fix the remaining gedit issue.
This delays drawing the pixel cache until a separate connect_after signal
handler. It also has to play tricks with get_visible_rect() during drawing the pixel cache to make sourceview draw to the not currently visible part of the cache.

For some reason i can't understand it still doesn't work fully though. gedit
draws the right margin line to the bottom, but the overlay to the right doesn't extend to the bottom.

And, this is starting to get pretty ugly... We should probably look at just fixing sourceview to do this in a cleaner way.
Comment 17 Sébastien Wilmet 2014-04-28 16:48:14 UTC
*** Bug 729126 has been marked as a duplicate of this bug. ***
Comment 18 PJSingh5000 2014-04-30 13:39:44 UTC
Alex, would it make sense to open a bug against sourceview for this issue?
Comment 19 Hugh Malard 2014-05-09 23:06:47 UTC
The text of most programs that this bug affects does not have to be looked at for a very long time (e.g. Synaptic and Update Manager). This is not so for Gedit. I had to switch to another text editor. This is because the corrupted font of Gedit causes my eyes to hurt. Is there perhaps a way to workaround the bug while the bug is being fixed? 

Thank you.
Comment 20 Benjamin Otte (Company) 2014-05-09 23:18:57 UTC
running the application with the env var GTK_DEBUG=no-pixel-cache set should work around the problem.
Comment 21 Hugh Malard 2014-05-13 04:18:26 UTC
Yes adding --gtk-debug=no-pixel-cache when starting Gedit fixes this problem. Thank you Benjamin Otte.
Comment 22 Alexander Larsson 2014-06-19 14:21:34 UTC
I dunno if we need a gtksourview bug or not, but someone needs to update gtksourceview+gtktextview so that we don't have to do the weird workaround with an alpha-based pixelcache.

Personally i think the best approach is to add pre-and post draw() vfuncs to GtkTextView, although it is possible that some of the sourceview features can just be moved to textview (like the highlight bg of current row one).
Comment 23 PJSingh5000 2014-06-19 17:45:06 UTC
FYI, I found that adding "GTK_DEBUG=no-pixel-cache" to your .profile also works, and you don't have to modify individual application launchers (such as gedit.desktop).  I presume the .profile approach would apply this work-around to all applications impacted by this bug.  I do not know if there are any performance penalties of applying this parameter globally, but it is working fine for me.

$ echo -e "\nexport GTK_DEBUG=no-pixel-cache" | tee --append ~/.profile
Comment 24 Sulphur 2014-06-28 20:54:08 UTC
@PJSingh5000 - Thanks for that quicker workaround, though it does not work with all programs (e.g. synaptic). Most seem fine though (gedit, gnome-system-log, update-manager).
Comment 25 Sébastien Wilmet 2014-08-21 17:32:05 UTC
(In reply to comment #22)
> Personally i think the best approach is to add pre-and post draw() vfuncs to
> GtkTextView

Now that it is done, I think this bug is fixed.
Comment 26 PJSingh5000 2014-08-21 17:57:47 UTC
Thank you Sébastien.

I'll test this when the package becomes available as an update for my distro.

So I can keep an eye-out for it, the change was made in libgtk-3-0 ?
Comment 27 Sébastien Wilmet 2014-08-21 18:14:51 UTC
The change is available in GTK+ 3.13.7 (unstable release), and will be available for the 3.14 stable version (in Septembre). You can already test with e.g. Fedora 21, or with jhbuild.