mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-13 05:50:10 +00:00
gsk: Fix luminance in Cairo and GL renderer
In particular, fix the combination of luminance and alpha. We want to do mask = luminance * alpha and for inverted mask = (1.0 - luminance) * alpha so add a test that makes sure we do that and then fix the code and existing tests to conform to it.
This commit is contained in:
parent
7c58370673
commit
c6eb7fd483
@ -13,6 +13,12 @@ void main() {
|
||||
uniform int u_mode;
|
||||
uniform sampler2D u_mask;
|
||||
|
||||
float
|
||||
luminance (vec3 color)
|
||||
{
|
||||
return dot (vec3 (0.2126, 0.7152, 0.0722), color);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 source = GskTexture(u_source, vUv);
|
||||
vec4 mask = GskTexture(u_mask, vUv);
|
||||
@ -23,9 +29,9 @@ void main() {
|
||||
else if (u_mode == 1)
|
||||
mask_value = 1.0 - mask.a;
|
||||
else if (u_mode == 2)
|
||||
mask_value = (0.2126 * mask.r + 0.7152 * mask.g + 0.0722 * mask.b) * mask.a;
|
||||
mask_value = luminance (mask.rgb);
|
||||
else if (u_mode == 3)
|
||||
mask_value = 1.0 - (0.2126 * mask.r + 0.7152 * mask.g + 0.0722 * mask.b) * mask.a;
|
||||
mask_value = mask.a - luminance (mask.rgb);
|
||||
else
|
||||
mask_value = 0.0;
|
||||
|
||||
|
@ -3702,8 +3702,7 @@ gsk_color_matrix_node_finalize (GskRenderNode *node)
|
||||
static void
|
||||
apply_color_matrix_to_pattern (cairo_pattern_t *pattern,
|
||||
const graphene_matrix_t *color_matrix,
|
||||
const graphene_vec4_t *color_offset,
|
||||
gboolean multiply_alpha)
|
||||
const graphene_vec4_t *color_offset)
|
||||
{
|
||||
cairo_surface_t *surface, *image_surface;
|
||||
guchar *data;
|
||||
@ -3741,13 +3740,6 @@ apply_color_matrix_to_pattern (cairo_pattern_t *pattern,
|
||||
graphene_matrix_transform_vec4 (color_matrix, &pixel, &pixel);
|
||||
}
|
||||
|
||||
if (multiply_alpha)
|
||||
graphene_vec4_init (&pixel,
|
||||
graphene_vec4_get_x (&pixel),
|
||||
graphene_vec4_get_y (&pixel),
|
||||
graphene_vec4_get_z (&pixel),
|
||||
alpha * graphene_vec4_get_w (&pixel));
|
||||
|
||||
graphene_vec4_add (&pixel, color_offset, &pixel);
|
||||
|
||||
alpha = graphene_vec4_get_w (&pixel);
|
||||
@ -3793,7 +3785,7 @@ gsk_color_matrix_node_draw (GskRenderNode *node,
|
||||
|
||||
pattern = cairo_pop_group (cr);
|
||||
|
||||
apply_color_matrix_to_pattern (pattern, &self->color_matrix, &self->color_offset, FALSE);
|
||||
apply_color_matrix_to_pattern (pattern, &self->color_matrix, &self->color_offset);
|
||||
|
||||
cairo_set_source (cr, pattern);
|
||||
cairo_paint (cr);
|
||||
@ -5654,6 +5646,50 @@ gsk_mask_node_finalize (GskRenderNode *node)
|
||||
parent_class->finalize (node);
|
||||
}
|
||||
|
||||
static void
|
||||
apply_luminance_to_pattern (cairo_pattern_t *pattern,
|
||||
gboolean invert_luminance)
|
||||
{
|
||||
cairo_surface_t *surface, *image_surface;
|
||||
guchar *data;
|
||||
gsize x, y, width, height, stride;
|
||||
int red, green, blue, alpha, luminance;
|
||||
guint32* pixel_data;
|
||||
|
||||
cairo_pattern_get_surface (pattern, &surface);
|
||||
image_surface = cairo_surface_map_to_image (surface, NULL);
|
||||
|
||||
data = cairo_image_surface_get_data (image_surface);
|
||||
width = cairo_image_surface_get_width (image_surface);
|
||||
height = cairo_image_surface_get_height (image_surface);
|
||||
stride = cairo_image_surface_get_stride (image_surface);
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
pixel_data = (guint32 *) data;
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
alpha = (pixel_data[x] >> 24) & 0xFF;
|
||||
red = (pixel_data[x] >> 16) & 0xFF;
|
||||
green = (pixel_data[x] >> 8) & 0xFF;
|
||||
blue = (pixel_data[x] >> 0) & 0xFF;
|
||||
|
||||
luminance = 2126 * red + 7152 * green + 722 * blue;
|
||||
if (invert_luminance)
|
||||
luminance = 10000 * alpha - luminance;
|
||||
luminance = (luminance + 5000) / 10000;
|
||||
|
||||
pixel_data[x] = luminance * 0x1010101;
|
||||
}
|
||||
data += stride;
|
||||
}
|
||||
|
||||
cairo_surface_mark_dirty (image_surface);
|
||||
cairo_surface_unmap_image (surface, image_surface);
|
||||
/* https://gitlab.freedesktop.org/cairo/cairo/-/merge_requests/487 */
|
||||
cairo_surface_mark_dirty (surface);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_mask_node_draw (GskRenderNode *node,
|
||||
cairo_t *cr)
|
||||
@ -5676,28 +5712,18 @@ gsk_mask_node_draw (GskRenderNode *node,
|
||||
case GSK_MASK_MODE_ALPHA:
|
||||
break;
|
||||
case GSK_MASK_MODE_INVERTED_ALPHA:
|
||||
graphene_matrix_init_from_float (&color_matrix, (float[]){ 1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, -1 });
|
||||
graphene_vec4_init (&color_offset, 0, 0, 0, 1);
|
||||
apply_color_matrix_to_pattern (mask_pattern, &color_matrix, &color_offset, FALSE);
|
||||
graphene_matrix_init_from_float (&color_matrix, (float[]){ 0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
-1, -1, -1, -1 });
|
||||
graphene_vec4_init (&color_offset, 1, 1, 1, 1);
|
||||
apply_color_matrix_to_pattern (mask_pattern, &color_matrix, &color_offset);
|
||||
break;
|
||||
case GSK_MASK_MODE_LUMINANCE:
|
||||
graphene_matrix_init_from_float (&color_matrix, (float[]){ 1, 0, 0, 0.2126,
|
||||
0, 1, 0, 0.7152,
|
||||
0, 0, 1, 0.0722,
|
||||
0, 0, 0, 0 });
|
||||
graphene_vec4_init (&color_offset, 0, 0, 0, 0);
|
||||
apply_color_matrix_to_pattern (mask_pattern, &color_matrix, &color_offset, TRUE);
|
||||
apply_luminance_to_pattern (mask_pattern, FALSE);
|
||||
break;
|
||||
case GSK_MASK_MODE_INVERTED_LUMINANCE:
|
||||
graphene_matrix_init_from_float (&color_matrix, (float[]){ 1, 0, 0, -0.2126,
|
||||
0, 1, 0, -0.7152,
|
||||
0, 0, 1, -0.0722,
|
||||
0, 0, 0, 0 });
|
||||
graphene_vec4_init (&color_offset, 0, 0, 0, 1);
|
||||
apply_color_matrix_to_pattern (mask_pattern, &color_matrix, &color_offset, TRUE);
|
||||
apply_luminance_to_pattern (mask_pattern, TRUE);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
|
43
testsuite/gsk/compare/mask-modes-with-alpha.node
Normal file
43
testsuite/gsk/compare/mask-modes-with-alpha.node
Normal file
@ -0,0 +1,43 @@
|
||||
mask {
|
||||
source: color {
|
||||
bounds: 0 0 50 50;
|
||||
color: rgb(255,0,0);
|
||||
}
|
||||
mask: color {
|
||||
bounds: 0 0 50 50;
|
||||
color: rgba(204,204,204,0.666667);
|
||||
}
|
||||
}
|
||||
mask {
|
||||
mode: luminance;
|
||||
source: color {
|
||||
bounds: 50 0 50 50;
|
||||
color: rgb(255,0,0);
|
||||
}
|
||||
mask: color {
|
||||
bounds: 50 0 50 50;
|
||||
color: rgba(204,204,204,0.666667);
|
||||
}
|
||||
}
|
||||
mask {
|
||||
mode: inverted-alpha;
|
||||
source: color {
|
||||
bounds: 0 50 50 50;
|
||||
color: rgb(255,0,0);
|
||||
}
|
||||
mask: color {
|
||||
bounds: 0 50 50 50;
|
||||
color: rgba(204,204,204,0.666667);
|
||||
}
|
||||
}
|
||||
mask {
|
||||
mode: inverted-luminance;
|
||||
source: color {
|
||||
bounds: 50 50 50 50;
|
||||
color: rgb(255,0,0);
|
||||
}
|
||||
mask: color {
|
||||
bounds: 50 50 50 50;
|
||||
color: rgba(204,204,204,0.666667);
|
||||
}
|
||||
}
|
BIN
testsuite/gsk/compare/mask-modes-with-alpha.png
Normal file
BIN
testsuite/gsk/compare/mask-modes-with-alpha.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 337 B |
Binary file not shown.
Before Width: | Height: | Size: 255 B After Width: | Height: | Size: 223 B |
@ -66,6 +66,7 @@ compare_render_tests = [
|
||||
'issue-3615',
|
||||
'mask',
|
||||
'mask-modes',
|
||||
'mask-modes-with-alpha',
|
||||
'nested-rounded-clips',
|
||||
'opacity_clip',
|
||||
'opacity-overdraw',
|
||||
|
Loading…
Reference in New Issue
Block a user