Opened 5 years ago

Closed 4 years ago

Last modified 4 years ago

#1270 closed defect/bug (fixed)

Alpha in toggle_anouncer OSD is not handled correctly on Linux (gtk)

Reported by: mvglasow (2) Owned by: sleske
Priority: minor Milestone:
Component: graphics/gtk_drawing Version: git master
Severity: normal Keywords:
Cc:

Description

When a custom bitmap is used for toggle_announcer, semitransparent regions of that bitmap will be treated as fully transparent.

Example:

This issue occurs only in the combination of toggle_announcer and Linux. button shows the correct behavior; on Android both OSD types behave correctly.

Attachments (4)

gui_sound_ldpi.png (1.4 KB) - added by mvglasow (2) 5 years ago.
toggle-announcer-old-new.png (26.0 KB) - added by sleske 4 years ago.
With the switch to Cairo (see #66), this problem has been fixed. The attached image shows the old and new (fixed) rendering.
Screen Shot 2015-09-17 at 5.25.26 PM.png (10.9 KB) - added by kazer 4 years ago.
Screen Shot 2015-09-17 at 5.25.38 PM.png (10.7 KB) - added by kazer 4 years ago.

Download all attachments as: .zip

Change History (13)

Changed 5 years ago by mvglasow (2)

comment:1 Changed 5 years ago by sleske

  • Owner changed from mvglasow (2) to sleske

I can confirm the problem on Linux, with graphics gtk_drawing_area. I'll try to have a look...

comment:2 Changed 5 years ago by sleske

As far as I can tell, this is a problem with the "overlay" feature that some OSD controls use. The toggle_announcer seems to use it for drawing. If I enable use_overlay=1 for an OSD button, it also has trouble rendering transparency in a PNG (though the problem looks different). So I'll continue in that direction.

I also posted a related question to the forum: Why do some OSD items use an "overlay" for drawing?

comment:3 Changed 5 years ago by sleske

Took me a while, but I think I now understand the problem.

Short version

When drawing using the "overlay" feature, everything goes via an intermediate buffer (a GdkPixmap). This buffer does not support semi-transparency, thus discarding the semi-transparency.

Long version

OSD items are drawn using the "overlay" feature. This means that the drawing code creates a new "struct graphics" by calling "graphics_overlay_new" before drawing an OSD element, then uses this for drawing.

When graphics_overlay_new is called, the gtk_drawing_area graphics backend creates a separate buffer for drawing into, namely a GdkPixmap. Later, when the window is drawn, all these GdkPixmaps (one per overlay) are drawn into the window.

This is what causes the rendering problems with transparency:

GdkPixmap does not support transparency (aka alpha channel). The OSD code works around this by setting the GdkPixmap to a uniform background color before drawing into it (by calling osd_fill_with_bgcolor()). Later, when drawing the overlay to the window (in graphics_gtk_drawing_area.c:overlay_draw()), the GdkPixmap is copied to a GdkPixbuf, which does support transparency. During copying, the color of each pixel is checked, and if is the background color, the pixel is made (semi-)transparent.

This produces the semi-transparent rectangle around OSD elements like the compass, but it also discards any semi-transparency from images. Therefore images drawn as part of an OSD element will lose their semi-transparency, as described in this bug report.

Additional notes

  • Interestingly, the same problem was apparently noticed for OSD buttons. OSD buttons, unlike other OSD elements, by default do _not_ use an overlay for drawing - that's why they do not suffer fromt this problem.
  • I believe the reason for having the overlay feature in the first place is that it is the only way to achieve the semi-transparent backgrounds - as GDK otherwise cannot draw semi-transparent rectangles.

comment:4 Changed 5 years ago by sleske

As to possible solutions:

To get proper support for sem-transparent images, the step of drawing to the GdkPixmap has to go (at least when drawing images). I see four options:

  1. Do not use an overlay when drawing toggle_announcer (just like "button" already does).
  2. Add a GdkPixbuf to the overlay structure as a second buffer, to be used instead of the GdkPixmap when drawing images. The drawing code in draw_overlay() would then have to check which buffer this overlay uses, and draw the right one.
  3. Just drop this stupid overlay stuff. This would mean no more semi-transparent backgrounds, and might make other features more difficult, which need to keep map and OSD graphics separate (such as keeping the OSD items visible while dragging the map).
  4. Finally, the big solution: Switch to Cairo.

Evaluation:

  1. would work, but would make the code rather ugly, because different OSDs would use different drawing code. This also increases the risk of bugs.
  2. would also work, and is a bit nicer than 1., but still ugly (two buffers, one of which is always unused).
  3. Would drop useful functionality, so not really an option IMHO.

So, it looks like the best option, at least in the longer term, is to switch to Cairo.

This would also solve some other issues, for example we would get anti-aliased drawing. I'll investigate this, and reopen #66 in the process.

Changed 4 years ago by sleske

With the switch to Cairo (see #66), this problem has been fixed. The attached image shows the old and new (fixed) rendering.

comment:5 Changed 4 years ago by sleske

Old rendering on the left, the new, fixed rendering with Cairo on the right:

With the switch to Cairo (see #66), this problem has been fixed. The attached image shows the old and new (fixed) rendering.

comment:6 Changed 4 years ago by sleske

  • Resolution set to fixed
  • Status changed from new to closed

Changed 4 years ago by kazer

Changed 4 years ago by kazer

comment:7 follow-up: Changed 4 years ago by kazer

Confirmed in the layout QA.

Before :

After:

This issue was not affecting every platform. I was using the exact same code in my car without seeing the issue.

Great work Sebastian!

comment:8 in reply to: ↑ 7 Changed 4 years ago by sleske

Replying to http://wiki.navit-project.org/index.php/user:kazer:

Confirmed in the layout QA.

Yes, the CI builds really help here. Nice job :-).

This issue was not affecting every platform. I was using the exact same code in my car without seeing the issue.

This issue was a problem with the gtk_drawing_area graphics driver. However, it was not platform-dependent - i.e. it should have occured on both Linux and Windows with that driver. If you did not see it, you were probably using a different graphics driver.

comment:9 Changed 4 years ago by kazer

That's really weird, because I'm indeed using <graphics type="gtk_drawing_area"/> :) But the issue is fixed, that's what matters. Thanks sleske!

Note: See TracTickets for help on using tickets.