Bug 463685 - Opaque icons are semi transparent in the middle of a fade transition animation, cause darkened icons when hovering taskbar icons on Plasma Desktop
Summary: Opaque icons are semi transparent in the middle of a fade transition animatio...
Status: RESOLVED FIXED
Alias: None
Product: frameworks-plasma
Classification: Frameworks and Libraries
Component: components (show other bugs)
Version: 5.101.0
Platform: Debian unstable Linux
: NOR minor
Target Milestone: ---
Assignee: Plasma Bugs List
URL:
Keywords: regression
Depends on:
Blocks:
 
Reported: 2023-01-01 01:47 UTC by Alexis Murzeau
Modified: 2023-01-18 21:39 UTC (History)
3 users (show)

See Also:
Latest Commit:
Version Fixed In: 5.103


Attachments
Video of the icon fading between 2 images (first between play/pause, then between normal and active (hovered) states), animation slowed down x5 (135.49 KB, video/mp4)
2023-01-01 01:47 UTC, Alexis Murzeau
Details
Video of the icon fading patched to avoid the darkening. Animation slowed down x5. Patch1. (86.17 KB, video/mp4)
2023-01-01 01:55 UTC, Alexis Murzeau
Details
Patch1: icon fading patched to avoid the darkening. See result in plasma-framework-icon-fading-split-animation-patch1.mp4 (1.57 KB, patch)
2023-01-01 02:12 UTC, Alexis Murzeau
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Alexis Murzeau 2023-01-01 01:47:18 UTC
Created attachment 154935 [details]
Video of the icon fading between 2 images (first between play/pause, then between normal and active (hovered) states), animation slowed down x5

SUMMARY

When using plasma-desktop with icon task manager and using a dark mode theme, when hovering the tasks icons, the animation does this:
 - Start with the existing "normal state" image of the icon
 - Fade to the "active state" highlighted image of the icon by fading the opacity of the existing image from 1.0 to 0.0 and the active image from 0.0 to 1.0 simultaneously
 - End with only the active image opaque and the existing

The issue is that the effect is this:
 - Start the animation
 - Darken the existing image (related to dark background)
 - Lighten the image back to reach the active state image

The darkening looks like icons are flickering when the animation is fast.

The cause of this darkening is that at 50% of the animation time, both the normal state image and the active state image are 50% opaque, which makes the background visible.
As the background is dark when using a dark theme, this make the icons darker.
The QML rendering does this in this order:
- Render the background
- Render the normal state image at 50% opacity (so there are 50% of background color rendered at this step)
- Render the active state image at 50% opacity (so there are 25% of background color rendered at this step)

See video in attachment (plasma-framework-icon-fading.mp4) of this when multimedia player icon changes between play / pause and then when it is hovered by the mouse (which changes the icon between normal and active states).
The animation is slowed down to make the icon darkening more visible.


SOFTWARE/OS VERSIONS

Operating System: Debian GNU/Linux
KDE Plasma Version: 5.26.4
KDE Frameworks Version: 5.101.0
Qt Version: 5.15.7
Kernel Version: 6.0.0-6-amd64 (64-bit)
Graphics Platform: X11
Processors: 12 × AMD Ryzen 5 3600 6-Core Processor
Memory: 15.6 Gio of RAM
Graphics Processor: AMD Radeon RX 580 Series
Manufacturer: Micro-Star International Co., Ltd
Product Name: MS-7B86
System Version: 4.0
Comment 1 Alexis Murzeau 2023-01-01 01:55:47 UTC
Created attachment 154936 [details]
Video of the icon fading patched to avoid the darkening. Animation slowed down x5. Patch1.

I've found the code that manage the fading is in `IconItem::updatePaintNode` in `plasma-framework/src/declarativeimports/core/iconitem.cpp`.

I found that doing this avoid the darkening:
- Split the animation in 2 phases (first between 0% and 50% of the animation value, then between 50% and 100%):
  - First, keep the previous existing image (oldNode->firstChild) opacity 1.0 (100% opaque) and progressevly increase the new image (oldNode->lastChild) opacity from 0.0 to 1.0
  - At the middle of the animation, both the previous and new images are rendered at 100% opacity.
  - Then secondly, progressively decrease the previous image opacity from 1.0 to 0.0

You can see the result in the video in attachment: plasma-framework-icon-fading-split-animation-patch1.mp4
Comment 2 Alexis Murzeau 2023-01-01 02:12:17 UTC
Created attachment 154937 [details]
Patch1: icon fading patched to avoid the darkening. See result in plasma-framework-icon-fading-split-animation-patch1.mp4

Added patch containing the modified code that lead to "Video of the icon fading patched to avoid the darkening. Animation slowed down x5. Patch1. (86.17 KB, video/mp4)".

The resulting animation is still not perfect, as in the middle of the animation, semi-transparent pixels are duplicated (between of 2 images being rendered with 100% opacity) and we can see that the multimedia icon's border are a bit modified.


A visually perfect solution would be to do the rendering in this order using an intermediate image:
- Blend the new image over the old image into an intermediate image with varying opacity for an animated fading
- Render the resulting image as actually done by QtQuick with a fixed 100% opacity

But I think that would require using QPainter and changing the whole QSGNode image at every updatePaintNode call, leading to poor performance I guess.
Comment 3 Nate Graham 2023-01-06 21:47:53 UTC
Nice, since you've got a proposed code change, could you submit it at https://invent.kde.org/frameworks/plasma-framework/-/merge_requests? Patches in bug reports tend to be overlooked. Thanks!
Comment 4 Alexis Murzeau 2023-01-10 18:51:11 UTC
Ok will do that.
I've added bug #432999 to "See also", the previous code before the fix of this bug was probably handling the fading correctly, explaining why the  bug appeared only some time ago.
Comment 5 Arjen Hiemstra 2023-01-17 03:35:57 UTC
Git commit a4bd3879780a02ff653f273a4235e247108729ca by Arjen Hiemstra.
Committed on 16/01/2023 at 16:00.
Pushed by ngraham into branch 'master'.

iconitem: Adjust fade animation to not flicker as much

As it turns out, mix(old texture, new texture, animation value) does
actually result in a different visual from simply blending the two
textures on top of each other, because the old texture first gets
blended with the underlying color. This results in some of the
underlying color bleeding through, which can cause flickering if the two
textures are almost the same. To avoid this, change the animation
slightly so that rather than crossfading, we first fade in the new
texture then fade out the old texture. This doesn't cause a whole lot of
visual difference for two completely different textures, but removes the
flickering when they are very similar.
Related: bug 463061

M  +6    -2    src/declarativeimports/core/iconitem.cpp

https://invent.kde.org/frameworks/plasma-framework/commit/a4bd3879780a02ff653f273a4235e247108729ca
Comment 6 Nate Graham 2023-01-17 03:46:44 UTC
Git commit 3fcd43a6ed03d0aff188dfc190cc464c34302a1f by Nate Graham, on behalf of Arjen Hiemstra.
Committed on 17/01/2023 at 03:44.
Pushed by ngraham into branch 'kf5'.

iconitem: Adjust fade animation to not flicker as much

As it turns out, mix(old texture, new texture, animation value) does
actually result in a different visual from simply blending the two
textures on top of each other, because the old texture first gets
blended with the underlying color. This results in some of the
underlying color bleeding through, which can cause flickering if the two
textures are almost the same. To avoid this, change the animation
slightly so that rather than crossfading, we first fade in the new
texture then fade out the old texture. This doesn't cause a whole lot of
visual difference for two completely different textures, but removes the
flickering when they are very similar.
Related: bug 463061

M  +6    -2    src/declarativeimports/core/iconitem.cpp

https://invent.kde.org/frameworks/plasma-framework/commit/3fcd43a6ed03d0aff188dfc190cc464c34302a1f