Commit 9c579023 authored by Vincent Povirk's avatar Vincent Povirk Committed by Alexandre Julliard

gdiplus: Fix blend_colors when alpha channel differs.

When picking a color halfway between 100% white (0xffffffff) and fully transparent (0x00000000), the result was 50% opaque 50% grey (0x80808080) when it should really be 50% opaque white (0x80ffffff). This had a tendency to create grey fringes on things. The fix is to weight the non-alpha components based on how much they contribute to the final alpha value.
parent e95dbb3b
...@@ -521,20 +521,22 @@ static GpStatus alpha_blend_pixels(GpGraphics *graphics, INT dst_x, INT dst_y, ...@@ -521,20 +521,22 @@ static GpStatus alpha_blend_pixels(GpGraphics *graphics, INT dst_x, INT dst_y,
static ARGB blend_colors(ARGB start, ARGB end, REAL position) static ARGB blend_colors(ARGB start, ARGB end, REAL position)
{ {
ARGB result=0; INT start_a, end_a, final_a;
ARGB i; INT pos;
INT a1, a2, a3;
a1 = (start >> 24) & 0xff; pos = gdip_round(position * 0xff);
a2 = (end >> 24) & 0xff;
a3 = (int)(a1*(1.0f - position)+a2*(position)); start_a = ((start >> 24) & 0xff) * (pos ^ 0xff);
end_a = ((end >> 24) & 0xff) * pos;
result |= a3 << 24; final_a = start_a + end_a;
for (i=0xff; i<=0xff0000; i = i << 8) if (final_a < 0xff) return 0;
result |= (int)((start&i)*(1.0f - position)+(end&i)*(position))&i;
return result; return (final_a / 0xff) << 24 |
((((start >> 16) & 0xff) * start_a + (((end >> 16) & 0xff) * end_a)) / final_a) << 16 |
((((start >> 8) & 0xff) * start_a + (((end >> 8) & 0xff) * end_a)) / final_a) << 8 |
(((start & 0xff) * start_a + ((end & 0xff) * end_a)) / final_a);
} }
static ARGB blend_line_gradient(GpLineGradient* brush, REAL position) static ARGB blend_line_gradient(GpLineGradient* brush, REAL position)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment