From d141cb7b72d91ebf6c2030cbe3711d288b34a258 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 11 Jun 2024 16:40:42 -0400 Subject: [PATCH 1/7] Fix an oversight This snuck in as part of 098d67f8befdb00d75. --- gdk/gdkvulkancontext.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gdk/gdkvulkancontext.c b/gdk/gdkvulkancontext.c index 6b55e64b78..076a62ac46 100644 --- a/gdk/gdkvulkancontext.c +++ b/gdk/gdkvulkancontext.c @@ -648,7 +648,7 @@ gdk_vulkan_context_begin_frame (GdkDrawContext *draw_context, { if (priv->formats[depth].gdk_format != priv->formats[priv->current_format].gdk_format) { - GdkMemoryFormat old_format = priv->current_format; + GdkMemoryDepth old_format = priv->current_format; GError *error = NULL; priv->current_format = depth; From d71fc41152635d1010117ff4fd6ead33de30a841 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 9 Jun 2024 23:58:32 -0400 Subject: [PATCH 2/7] css: Add support for display-p3 colors A wide-gamut colorspace. --- gtk/gtkcolorutils.c | 61 ++++++++++++++++++++++++++++++++++++++ gtk/gtkcolorutilsprivate.h | 4 +++ gtk/gtkcsscolor.c | 34 +++++++++++++++++++-- gtk/gtkcsscolorprivate.h | 1 + gtk/gtkcsscolorvalue.c | 12 ++++++++ 5 files changed, 110 insertions(+), 2 deletions(-) diff --git a/gtk/gtkcolorutils.c b/gtk/gtkcolorutils.c index f165022225..2c1d6ac797 100644 --- a/gtk/gtkcolorutils.c +++ b/gtk/gtkcolorutils.c @@ -423,3 +423,64 @@ gtk_linear_srgb_to_rgb (float linear_red, float linear_green, float linear_bl *green = apply_gamma (linear_green); *blue = apply_gamma (linear_blue); } + +static void +gtk_linrgb_to_xyz (float r, float g, float b, + float *x, float *y, float *z) +{ + *x = (506752.0 / 1228815.0) * r + (87881.0 / 245763.0) * g + (12673.0 / 70218.0) * b; + *y = (87098.0 / 409605.0) * r + (175762.0 / 245763.0) * g + (12673.0 / 175545.0) * b; + *z = ( 7918.0 / 409605.0) * r + (87881.0 / 737289.0) * g + (1001167.0 / 1053270.0) * b; +} + +static void +gtk_xyz_to_linrgb (float x, float y, float z, + float *r, float *g, float *b) +{ + *r = (12831.0 / 3959.0) * x - (329.0 / 214.0) * y - (1974.0 / 3959.0) * z; + *g = - (851781.0 / 878810.0) * x + (1648619.0 / 878810.0) * y + (36519.0 / 878810.0) * z; + *b = (705.0 / 12673.0) * x - (2585.0 / 12673.0) * y + (705.0 / 667.0) * z; +} + +static void +gtk_lin_p3_to_xyz (float r, float g, float b, + float *x, float *y, float *z) +{ + *x = (608311.0 / 1250200.0) * r + (189793.0 / 714400.0) * g + (198249.0 / 1000160.0) * b; + *y = (35783.0 / 156275.0) * r + (247089.0 / 357200.0) * g + (198249.0 / 2500400.0) * b; + *z = ( 0 / 1) * r + (32229.0 / 714400.0) * g + (5220557.0 / 5000800.0) * b; +} + +static void +gtk_xyz_to_lin_p3 (float x, float y, float z, + float *r, float *g, float *b) +{ + *r = (446124.0 / 178915.0) * x - (333277.0 / 357830.0) * y - (72051.0 / 178915.0) * z; + *g = - (14852.0 / 17905.0) * x + (63121.0 / 35810.0) * y + (423.0 / 17905.0) * z; + *b = (11844.0 / 330415.0) * x - (50337.0 / 660830.0) * y + (316169.0 / 330415.0) * z; +} + +void gtk_rgb_to_p3 (float red, float green, float blue, + float *pr, float *pg, float *pb) +{ + float r, g, b; + float x, y, z; + + gtk_rgb_to_linear_srgb (red, green, blue, &r, &g, &b); + gtk_linrgb_to_xyz (r, g, b, &x, &y, &z); + gtk_xyz_to_lin_p3 (x, y, z, &r, &g, &b); + gtk_linear_srgb_to_rgb (r, g, b, pr, pg, pb); +} + +void +gtk_p3_to_rgb (float pr, float pg, float pb, + float *red, float *green, float *blue) +{ + float r, g, b; + float x, y, z; + + gtk_rgb_to_linear_srgb (pr, pg, pb, &r, &g, &b); + gtk_lin_p3_to_xyz (r, g, b, &x, &y, &z); + gtk_xyz_to_linrgb (x, y, z, &r, &g, &b); + gtk_linear_srgb_to_rgb (r, g, b, red, green, blue); +} diff --git a/gtk/gtkcolorutilsprivate.h b/gtk/gtkcolorutilsprivate.h index 2478559890..3d54ba10c3 100644 --- a/gtk/gtkcolorutilsprivate.h +++ b/gtk/gtkcolorutilsprivate.h @@ -51,5 +51,9 @@ void gtk_rgb_to_linear_srgb (float red, float green, float blue void gtk_linear_srgb_to_rgb (float linear_red, float linear_green, float linear_blue, float *red, float *green, float *blue); +void gtk_rgb_to_p3 (float red, float green, float blue, + float *pr, float *pg, float *pb); +void gtk_p3_to_rgb (float pr, float pg, float pb, + float *red, float *green, float *blue); G_END_DECLS diff --git a/gtk/gtkcsscolor.c b/gtk/gtkcsscolor.c index e260bb1dae..e98690f081 100644 --- a/gtk/gtkcsscolor.c +++ b/gtk/gtkcsscolor.c @@ -35,6 +35,7 @@ gtk_css_color_init (GtkCssColor *color, case GTK_CSS_COLOR_SPACE_SRGB: case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_OKLAB: + case GTK_CSS_COLOR_SPACE_DISPLAY_P3: break; case GTK_CSS_COLOR_SPACE_HSL: @@ -136,6 +137,10 @@ gtk_css_color_print (const GtkCssColor *color, g_string_append (string, "oklch("); break; + case GTK_CSS_COLOR_SPACE_DISPLAY_P3: + g_string_append (string, "color(display-p3 "); + break; + default: g_assert_not_reached (); } @@ -181,6 +186,7 @@ gtk_css_color_space_get_coord_name (GtkCssColorSpace color_space, { case GTK_CSS_COLOR_SPACE_SRGB: case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: + case GTK_CSS_COLOR_SPACE_DISPLAY_P3: switch (coord) { case 0: return "r"; @@ -246,6 +252,7 @@ gtk_css_color_space_get_coord_range (GtkCssColorSpace color_space, *upper = legacy_rgb_scale ? 255 : 1; return; case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: + case GTK_CSS_COLOR_SPACE_DISPLAY_P3: *lower = 0; *upper = 1; return; @@ -287,6 +294,7 @@ color_space_is_polar (GtkCssColorSpace color_space) case GTK_CSS_COLOR_SPACE_SRGB: case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_OKLAB: + case GTK_CSS_COLOR_SPACE_DISPLAY_P3: return FALSE; case GTK_CSS_COLOR_SPACE_HSL: case GTK_CSS_COLOR_SPACE_HWB: @@ -311,6 +319,7 @@ convert_to_rectangular (GtkCssColor *output) case GTK_CSS_COLOR_SPACE_SRGB: case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_OKLAB: + case GTK_CSS_COLOR_SPACE_DISPLAY_P3: break; case GTK_CSS_COLOR_SPACE_HSL: @@ -352,7 +361,8 @@ convert_to_linear (GtkCssColor *output) g_assert (output->color_space == GTK_CSS_COLOR_SPACE_SRGB || output->color_space == GTK_CSS_COLOR_SPACE_SRGB_LINEAR || - output->color_space == GTK_CSS_COLOR_SPACE_OKLAB); + output->color_space == GTK_CSS_COLOR_SPACE_OKLAB || + output->color_space == GTK_CSS_COLOR_SPACE_DISPLAY_P3); if (output->color_space == GTK_CSS_COLOR_SPACE_SRGB) { @@ -363,6 +373,17 @@ convert_to_linear (GtkCssColor *output) v[3] = output->values[3]; gtk_css_color_init (output, GTK_CSS_COLOR_SPACE_SRGB_LINEAR, v); } + else if (output->color_space == GTK_CSS_COLOR_SPACE_DISPLAY_P3) + { + gtk_p3_to_rgb (output->values[0], + output->values[1], + output->values[2], + &v[0], &v[1], &v[2]); + gtk_rgb_to_linear_srgb (v[0], v[1], v[2], + &v[0], &v[1], &v[2]); + v[3] = output->values[3]; + gtk_css_color_init (output, GTK_CSS_COLOR_SPACE_SRGB_LINEAR, v); + } } static void @@ -379,6 +400,7 @@ convert_from_linear (GtkCssColor *output, case GTK_CSS_COLOR_SPACE_SRGB: case GTK_CSS_COLOR_SPACE_HSL: case GTK_CSS_COLOR_SPACE_HWB: + case GTK_CSS_COLOR_SPACE_DISPLAY_P3: gtk_linear_srgb_to_rgb (output->values[0], output->values[1], output->values[2], @@ -408,6 +430,7 @@ convert_from_rectangular (GtkCssColor *output, case GTK_CSS_COLOR_SPACE_SRGB: case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_OKLAB: + case GTK_CSS_COLOR_SPACE_DISPLAY_P3: g_assert (output->color_space == dest); break; @@ -574,6 +597,7 @@ apply_hue_interpolation (GtkCssColor *from, case GTK_CSS_COLOR_SPACE_SRGB: case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_OKLAB: + case GTK_CSS_COLOR_SPACE_DISPLAY_P3: break; case GTK_CSS_COLOR_SPACE_HSL: @@ -606,6 +630,7 @@ normalize_hue (GtkCssColor *color) case GTK_CSS_COLOR_SPACE_SRGB: case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_OKLAB: + case GTK_CSS_COLOR_SPACE_DISPLAY_P3: break; case GTK_CSS_COLOR_SPACE_HSL: @@ -643,6 +668,7 @@ premultiply (GtkCssColor *color) case GTK_CSS_COLOR_SPACE_SRGB: case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_OKLAB: + case GTK_CSS_COLOR_SPACE_DISPLAY_P3: premultiply_component (color, 0); premultiply_component (color, 1); premultiply_component (color, 2); @@ -685,6 +711,7 @@ unpremultiply (GtkCssColor *color) case GTK_CSS_COLOR_SPACE_SRGB: case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_OKLAB: + case GTK_CSS_COLOR_SPACE_DISPLAY_P3: unpremultiply_component (color, 0); unpremultiply_component (color, 1); unpremultiply_component (color, 2); @@ -721,7 +748,7 @@ collect_analogous_missing (const GtkCssColor *color, { -1, -1, -1, -1, -1, 0, -1, -1, 3 }, /* hwb */ { -1, -1, -1, 0, -1, -1, 1, 2, 3 }, /* oklab */ { -1, -1, -1, 0, 1, 2, -1, -1, 3 }, /* oklch */ - + { 0, 1, 2, -1, -1, -1, -1, -1, 3 }, /* display-p3 */ }; int *src = analogous[color->color_space]; @@ -930,6 +957,9 @@ gtk_css_color_interpolation_method_print (GtkCssColorSpace in, case GTK_CSS_COLOR_SPACE_OKLAB: g_string_append (string, "oklab"); break; + case GTK_CSS_COLOR_SPACE_DISPLAY_P3: + g_string_append (string, "display-p3"); + break; default: g_assert_not_reached (); } diff --git a/gtk/gtkcsscolorprivate.h b/gtk/gtkcsscolorprivate.h index 0fa1a518de..127e6043c0 100644 --- a/gtk/gtkcsscolorprivate.h +++ b/gtk/gtkcsscolorprivate.h @@ -31,6 +31,7 @@ typedef enum { GTK_CSS_COLOR_SPACE_HWB, GTK_CSS_COLOR_SPACE_OKLAB, GTK_CSS_COLOR_SPACE_OKLCH, + GTK_CSS_COLOR_SPACE_DISPLAY_P3, } GtkCssColorSpace; typedef struct diff --git a/gtk/gtkcsscolorvalue.c b/gtk/gtkcsscolorvalue.c index c7b29aa7d2..8448f637b4 100644 --- a/gtk/gtkcsscolorvalue.c +++ b/gtk/gtkcsscolorvalue.c @@ -357,6 +357,12 @@ gtk_css_value_color_print (const GtkCssValue *value, g_string_append (string, " srgb-linear"); break; + case GTK_CSS_COLOR_SPACE_DISPLAY_P3: + g_string_append (string, "color(from "); + gtk_css_value_print (value->relative.origin, string); + g_string_append (string, " display-p3"); + break; + case GTK_CSS_COLOR_SPACE_HSL: g_string_append (string, "hsl(from "); gtk_css_value_print (value->relative.origin, string); @@ -1642,6 +1648,12 @@ parse_color_color_channel (GtkCssParser *parser, return 1; } + if (gtk_css_parser_try_ident (parser, "display-p3")) + { + data->ctx.color_space = GTK_CSS_COLOR_SPACE_DISPLAY_P3; + return 1; + } + gtk_css_parser_error_syntax (parser, "Invalid color space in color()"); return 0; From 2d1e9785998842af7ec176529ed2b275aa811f1e Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 10 Jun 2024 00:13:35 -0400 Subject: [PATCH 3/7] css: Add support for xyz colors This is somewhat central, and we have all the pieces to support it, so we might as well add the css syntax for it. --- gtk/gtkcolorutils.c | 16 ++++++------- gtk/gtkcolorutilsprivate.h | 6 +++++ gtk/gtkcsscolor.c | 46 +++++++++++++++++++++++++++++++++++++- gtk/gtkcsscolorprivate.h | 1 + gtk/gtkcsscolorvalue.c | 12 ++++++++++ 5 files changed, 72 insertions(+), 9 deletions(-) diff --git a/gtk/gtkcolorutils.c b/gtk/gtkcolorutils.c index 2c1d6ac797..49023978cd 100644 --- a/gtk/gtkcolorutils.c +++ b/gtk/gtkcolorutils.c @@ -424,18 +424,18 @@ gtk_linear_srgb_to_rgb (float linear_red, float linear_green, float linear_bl *blue = apply_gamma (linear_blue); } -static void -gtk_linrgb_to_xyz (float r, float g, float b, - float *x, float *y, float *z) +void +gtk_linear_srgb_to_xyz (float r, float g, float b, + float *x, float *y, float *z) { *x = (506752.0 / 1228815.0) * r + (87881.0 / 245763.0) * g + (12673.0 / 70218.0) * b; *y = (87098.0 / 409605.0) * r + (175762.0 / 245763.0) * g + (12673.0 / 175545.0) * b; *z = ( 7918.0 / 409605.0) * r + (87881.0 / 737289.0) * g + (1001167.0 / 1053270.0) * b; } -static void -gtk_xyz_to_linrgb (float x, float y, float z, - float *r, float *g, float *b) +void +gtk_xyz_to_linear_srgb (float x, float y, float z, + float *r, float *g, float *b) { *r = (12831.0 / 3959.0) * x - (329.0 / 214.0) * y - (1974.0 / 3959.0) * z; *g = - (851781.0 / 878810.0) * x + (1648619.0 / 878810.0) * y + (36519.0 / 878810.0) * z; @@ -467,7 +467,7 @@ void gtk_rgb_to_p3 (float red, float green, float blue, float x, y, z; gtk_rgb_to_linear_srgb (red, green, blue, &r, &g, &b); - gtk_linrgb_to_xyz (r, g, b, &x, &y, &z); + gtk_linear_srgb_to_xyz (r, g, b, &x, &y, &z); gtk_xyz_to_lin_p3 (x, y, z, &r, &g, &b); gtk_linear_srgb_to_rgb (r, g, b, pr, pg, pb); } @@ -481,6 +481,6 @@ gtk_p3_to_rgb (float pr, float pg, float pb, gtk_rgb_to_linear_srgb (pr, pg, pb, &r, &g, &b); gtk_lin_p3_to_xyz (r, g, b, &x, &y, &z); - gtk_xyz_to_linrgb (x, y, z, &r, &g, &b); + gtk_xyz_to_linear_srgb (x, y, z, &r, &g, &b); gtk_linear_srgb_to_rgb (r, g, b, red, green, blue); } diff --git a/gtk/gtkcolorutilsprivate.h b/gtk/gtkcolorutilsprivate.h index 3d54ba10c3..312b2aa385 100644 --- a/gtk/gtkcolorutilsprivate.h +++ b/gtk/gtkcolorutilsprivate.h @@ -56,4 +56,10 @@ void gtk_rgb_to_p3 (float red, float green, float blue, void gtk_p3_to_rgb (float pr, float pg, float pb, float *red, float *green, float *blue); +void gtk_xyz_to_linear_srgb (float x, float y, float z, + float *r, float *g, float *b); + +void gtk_linear_srgb_to_xyz (float r, float g, float b, + float *x, float *y, float *z); + G_END_DECLS diff --git a/gtk/gtkcsscolor.c b/gtk/gtkcsscolor.c index e98690f081..e7c37aecde 100644 --- a/gtk/gtkcsscolor.c +++ b/gtk/gtkcsscolor.c @@ -36,6 +36,7 @@ gtk_css_color_init (GtkCssColor *color, case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_OKLAB: case GTK_CSS_COLOR_SPACE_DISPLAY_P3: + case GTK_CSS_COLOR_SPACE_XYZ: break; case GTK_CSS_COLOR_SPACE_HSL: @@ -141,6 +142,10 @@ gtk_css_color_print (const GtkCssColor *color, g_string_append (string, "color(display-p3 "); break; + case GTK_CSS_COLOR_SPACE_XYZ: + g_string_append (string, "color(xyz "); + break; + default: g_assert_not_reached (); } @@ -194,6 +199,14 @@ gtk_css_color_space_get_coord_name (GtkCssColorSpace color_space, case 2: return "b"; default: g_assert_not_reached (); } + case GTK_CSS_COLOR_SPACE_XYZ: + switch (coord) + { + case 0: return "x"; + case 1: return "y"; + case 2: return "z"; + default: g_assert_not_reached (); + } case GTK_CSS_COLOR_SPACE_HSL: switch (coord) { @@ -253,6 +266,7 @@ gtk_css_color_space_get_coord_range (GtkCssColorSpace color_space, return; case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_DISPLAY_P3: + case GTK_CSS_COLOR_SPACE_XYZ: *lower = 0; *upper = 1; return; @@ -295,6 +309,7 @@ color_space_is_polar (GtkCssColorSpace color_space) case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_OKLAB: case GTK_CSS_COLOR_SPACE_DISPLAY_P3: + case GTK_CSS_COLOR_SPACE_XYZ: return FALSE; case GTK_CSS_COLOR_SPACE_HSL: case GTK_CSS_COLOR_SPACE_HWB: @@ -320,6 +335,7 @@ convert_to_rectangular (GtkCssColor *output) case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_OKLAB: case GTK_CSS_COLOR_SPACE_DISPLAY_P3: + case GTK_CSS_COLOR_SPACE_XYZ: break; case GTK_CSS_COLOR_SPACE_HSL: @@ -362,7 +378,8 @@ convert_to_linear (GtkCssColor *output) g_assert (output->color_space == GTK_CSS_COLOR_SPACE_SRGB || output->color_space == GTK_CSS_COLOR_SPACE_SRGB_LINEAR || output->color_space == GTK_CSS_COLOR_SPACE_OKLAB || - output->color_space == GTK_CSS_COLOR_SPACE_DISPLAY_P3); + output->color_space == GTK_CSS_COLOR_SPACE_DISPLAY_P3 || + output->color_space == GTK_CSS_COLOR_SPACE_XYZ); if (output->color_space == GTK_CSS_COLOR_SPACE_SRGB) { @@ -384,6 +401,15 @@ convert_to_linear (GtkCssColor *output) v[3] = output->values[3]; gtk_css_color_init (output, GTK_CSS_COLOR_SPACE_SRGB_LINEAR, v); } + else if (output->color_space == GTK_CSS_COLOR_SPACE_XYZ) + { + gtk_xyz_to_linear_srgb (output->values[0], + output->values[1], + output->values[2], + &v[0], &v[1], &v[2]); + v[3] = output->values[3]; + gtk_css_color_init (output, GTK_CSS_COLOR_SPACE_SRGB_LINEAR, v); + } } static void @@ -409,6 +435,15 @@ convert_from_linear (GtkCssColor *output, gtk_css_color_init (output, GTK_CSS_COLOR_SPACE_SRGB, v); break; + case GTK_CSS_COLOR_SPACE_XYZ: + gtk_linear_srgb_to_xyz (output->values[0], + output->values[1], + output->values[2], + &v[0], &v[1], &v[2]); + v[3] = output->values[3]; + gtk_css_color_init (output, GTK_CSS_COLOR_SPACE_XYZ, v); + break; + case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_OKLAB: case GTK_CSS_COLOR_SPACE_OKLCH: @@ -431,6 +466,7 @@ convert_from_rectangular (GtkCssColor *output, case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_OKLAB: case GTK_CSS_COLOR_SPACE_DISPLAY_P3: + case GTK_CSS_COLOR_SPACE_XYZ: g_assert (output->color_space == dest); break; @@ -598,6 +634,7 @@ apply_hue_interpolation (GtkCssColor *from, case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_OKLAB: case GTK_CSS_COLOR_SPACE_DISPLAY_P3: + case GTK_CSS_COLOR_SPACE_XYZ: break; case GTK_CSS_COLOR_SPACE_HSL: @@ -631,6 +668,7 @@ normalize_hue (GtkCssColor *color) case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_OKLAB: case GTK_CSS_COLOR_SPACE_DISPLAY_P3: + case GTK_CSS_COLOR_SPACE_XYZ: break; case GTK_CSS_COLOR_SPACE_HSL: @@ -669,6 +707,7 @@ premultiply (GtkCssColor *color) case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_OKLAB: case GTK_CSS_COLOR_SPACE_DISPLAY_P3: + case GTK_CSS_COLOR_SPACE_XYZ: premultiply_component (color, 0); premultiply_component (color, 1); premultiply_component (color, 2); @@ -712,6 +751,7 @@ unpremultiply (GtkCssColor *color) case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_OKLAB: case GTK_CSS_COLOR_SPACE_DISPLAY_P3: + case GTK_CSS_COLOR_SPACE_XYZ: unpremultiply_component (color, 0); unpremultiply_component (color, 1); unpremultiply_component (color, 2); @@ -749,6 +789,7 @@ collect_analogous_missing (const GtkCssColor *color, { -1, -1, -1, 0, -1, -1, 1, 2, 3 }, /* oklab */ { -1, -1, -1, 0, 1, 2, -1, -1, 3 }, /* oklch */ { 0, 1, 2, -1, -1, -1, -1, -1, 3 }, /* display-p3 */ + { 0, 1, 2, -1, -1, -1, -1, -1, 3 }, /* xyz */ }; int *src = analogous[color->color_space]; @@ -960,6 +1001,9 @@ gtk_css_color_interpolation_method_print (GtkCssColorSpace in, case GTK_CSS_COLOR_SPACE_DISPLAY_P3: g_string_append (string, "display-p3"); break; + case GTK_CSS_COLOR_SPACE_XYZ: + g_string_append (string, "xyz"); + break; default: g_assert_not_reached (); } diff --git a/gtk/gtkcsscolorprivate.h b/gtk/gtkcsscolorprivate.h index 127e6043c0..ad6d5b4f58 100644 --- a/gtk/gtkcsscolorprivate.h +++ b/gtk/gtkcsscolorprivate.h @@ -32,6 +32,7 @@ typedef enum { GTK_CSS_COLOR_SPACE_OKLAB, GTK_CSS_COLOR_SPACE_OKLCH, GTK_CSS_COLOR_SPACE_DISPLAY_P3, + GTK_CSS_COLOR_SPACE_XYZ, } GtkCssColorSpace; typedef struct diff --git a/gtk/gtkcsscolorvalue.c b/gtk/gtkcsscolorvalue.c index 8448f637b4..e16a5e23f2 100644 --- a/gtk/gtkcsscolorvalue.c +++ b/gtk/gtkcsscolorvalue.c @@ -363,6 +363,12 @@ gtk_css_value_color_print (const GtkCssValue *value, g_string_append (string, " display-p3"); break; + case GTK_CSS_COLOR_SPACE_XYZ: + g_string_append (string, "color(from "); + gtk_css_value_print (value->relative.origin, string); + g_string_append (string, " xyz"); + break; + case GTK_CSS_COLOR_SPACE_HSL: g_string_append (string, "hsl(from "); gtk_css_value_print (value->relative.origin, string); @@ -1654,6 +1660,12 @@ parse_color_color_channel (GtkCssParser *parser, return 1; } + if (gtk_css_parser_try_ident (parser, "xyz")) + { + data->ctx.color_space = GTK_CSS_COLOR_SPACE_XYZ; + return 1; + } + gtk_css_parser_error_syntax (parser, "Invalid color space in color()"); return 0; From 8edfa759fbfea3388e4ee5f750c7530b06bbef70 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 10 Jun 2024 00:46:33 -0400 Subject: [PATCH 4/7] css: Add support for rec2020 colors Another extremely wide gamut color space. --- gtk/gtkcolorutils.c | 57 ++++++++++++++++++++++++++++++++++++++ gtk/gtkcolorutilsprivate.h | 6 ++++ gtk/gtkcsscolor.c | 55 ++++++++++++++++++++++++++++++++++-- gtk/gtkcsscolorprivate.h | 1 + gtk/gtkcsscolorvalue.c | 12 ++++++++ 5 files changed, 129 insertions(+), 2 deletions(-) diff --git a/gtk/gtkcolorutils.c b/gtk/gtkcolorutils.c index 49023978cd..35d27bdc32 100644 --- a/gtk/gtkcolorutils.c +++ b/gtk/gtkcolorutils.c @@ -484,3 +484,60 @@ gtk_p3_to_rgb (float pr, float pg, float pb, gtk_xyz_to_linear_srgb (x, y, z, &r, &g, &b); gtk_linear_srgb_to_rgb (r, g, b, red, green, blue); } + +static float +linearize_one (float val) +{ + float alpha = 1.09929682680944 ; + float beta = 0.018053968510807; + + int sign = val < 0 ? -1 : 1; + float abs = fabs (val); + + if (abs < beta * 4.5 ) + return val / 4.5; + else + return sign * powf ((abs + alpha - 1) / alpha, 1.0 / 0.45); +} + +void +gtk_rec2020_to_xyz (float r, float g, float b, + float *x, float *y, float *z) +{ + r = linearize_one (r); + g = linearize_one (g); + b = linearize_one (b); + + *x = (63426534.0 / 99577255.0) * r + (20160776.0 / 139408157.0) * g + (47086771.0 / 278816314.0) * b; + *y = (26158966.0 / 99577255.0) * r + (472592308.0 / 697040785.0) * g + (8267143.0 / 139408157.0) * b; + *z = ( 0 / 1) * r + (19567812.0 / 697040785.0) * g + (295819943.0 / 278816314.0) * b; +} + +static float +delinearize_one (float val) +{ + float alpha = 1.09929682680944; + float beta = 0.018053968510807; + int sign = val < 0 ? -1 : 1; + float abs = fabsf (val); + + if (abs > beta) + return sign * (alpha * powf (abs, 0.45) - (alpha - 1)); + else + return 4.5 * val; +} + +void +gtk_xyz_to_rec2020 (float x, float y, float z, + float *r, float *g, float *b) +{ + float rr, gg, bb; + + rr = (30757411.0 / 17917100.0) * x - (6372589.0 / 17917100.0) * y - (4539589.0 / 17917100.0) * z; + gg = - (19765991.0 / 29648200.0) * x + (47925759.0 / 29648200.0) * y + (467509.0 / 29648200.0) *z; + bb = (792561.0 / 44930125.0) * x - (1921689.0 / 44930125.0) * y + (42328811.0 / 44930125.0) * z; + + *r = delinearize_one (rr); + *g = delinearize_one (gg); + *b = delinearize_one (bb); +} diff --git a/gtk/gtkcolorutilsprivate.h b/gtk/gtkcolorutilsprivate.h index 312b2aa385..12ef6b4255 100644 --- a/gtk/gtkcolorutilsprivate.h +++ b/gtk/gtkcolorutilsprivate.h @@ -62,4 +62,10 @@ void gtk_xyz_to_linear_srgb (float x, float y, float z, void gtk_linear_srgb_to_xyz (float r, float g, float b, float *x, float *y, float *z); +void gtk_rec2020_to_xyz (float r, float g, float b, + float *x, float *y, float *z); + +void gtk_xyz_to_rec2020 (float x, float y, float z, + float *r, float *g, float *b); + G_END_DECLS diff --git a/gtk/gtkcsscolor.c b/gtk/gtkcsscolor.c index e7c37aecde..b6b16c72ec 100644 --- a/gtk/gtkcsscolor.c +++ b/gtk/gtkcsscolor.c @@ -37,6 +37,7 @@ gtk_css_color_init (GtkCssColor *color, case GTK_CSS_COLOR_SPACE_OKLAB: case GTK_CSS_COLOR_SPACE_DISPLAY_P3: case GTK_CSS_COLOR_SPACE_XYZ: + case GTK_CSS_COLOR_SPACE_REC2020: break; case GTK_CSS_COLOR_SPACE_HSL: @@ -146,6 +147,10 @@ gtk_css_color_print (const GtkCssColor *color, g_string_append (string, "color(xyz "); break; + case GTK_CSS_COLOR_SPACE_REC2020: + g_string_append (string, "color(rec2020 "); + break; + default: g_assert_not_reached (); } @@ -192,6 +197,7 @@ gtk_css_color_space_get_coord_name (GtkCssColorSpace color_space, case GTK_CSS_COLOR_SPACE_SRGB: case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_DISPLAY_P3: + case GTK_CSS_COLOR_SPACE_REC2020: switch (coord) { case 0: return "r"; @@ -267,6 +273,7 @@ gtk_css_color_space_get_coord_range (GtkCssColorSpace color_space, case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_DISPLAY_P3: case GTK_CSS_COLOR_SPACE_XYZ: + case GTK_CSS_COLOR_SPACE_REC2020: *lower = 0; *upper = 1; return; @@ -310,6 +317,7 @@ color_space_is_polar (GtkCssColorSpace color_space) case GTK_CSS_COLOR_SPACE_OKLAB: case GTK_CSS_COLOR_SPACE_DISPLAY_P3: case GTK_CSS_COLOR_SPACE_XYZ: + case GTK_CSS_COLOR_SPACE_REC2020: return FALSE; case GTK_CSS_COLOR_SPACE_HSL: case GTK_CSS_COLOR_SPACE_HWB: @@ -336,6 +344,7 @@ convert_to_rectangular (GtkCssColor *output) case GTK_CSS_COLOR_SPACE_OKLAB: case GTK_CSS_COLOR_SPACE_DISPLAY_P3: case GTK_CSS_COLOR_SPACE_XYZ: + case GTK_CSS_COLOR_SPACE_REC2020: break; case GTK_CSS_COLOR_SPACE_HSL: @@ -379,7 +388,8 @@ convert_to_linear (GtkCssColor *output) output->color_space == GTK_CSS_COLOR_SPACE_SRGB_LINEAR || output->color_space == GTK_CSS_COLOR_SPACE_OKLAB || output->color_space == GTK_CSS_COLOR_SPACE_DISPLAY_P3 || - output->color_space == GTK_CSS_COLOR_SPACE_XYZ); + output->color_space == GTK_CSS_COLOR_SPACE_XYZ || + output->color_space == GTK_CSS_COLOR_SPACE_REC2020); if (output->color_space == GTK_CSS_COLOR_SPACE_SRGB) { @@ -410,6 +420,17 @@ convert_to_linear (GtkCssColor *output) v[3] = output->values[3]; gtk_css_color_init (output, GTK_CSS_COLOR_SPACE_SRGB_LINEAR, v); } + else if (output->color_space == GTK_CSS_COLOR_SPACE_REC2020) + { + gtk_rec2020_to_xyz (output->values[0], + output->values[1], + output->values[2], + &v[0], &v[1], &v[2]); + gtk_xyz_to_linear_srgb (v[0], v[1], v[2], + &v[0], &v[1], &v[2]); + v[3] = output->values[3]; + gtk_css_color_init (output, GTK_CSS_COLOR_SPACE_SRGB_LINEAR, v); + } } static void @@ -426,7 +447,6 @@ convert_from_linear (GtkCssColor *output, case GTK_CSS_COLOR_SPACE_SRGB: case GTK_CSS_COLOR_SPACE_HSL: case GTK_CSS_COLOR_SPACE_HWB: - case GTK_CSS_COLOR_SPACE_DISPLAY_P3: gtk_linear_srgb_to_rgb (output->values[0], output->values[1], output->values[2], @@ -435,6 +455,17 @@ convert_from_linear (GtkCssColor *output, gtk_css_color_init (output, GTK_CSS_COLOR_SPACE_SRGB, v); break; + case GTK_CSS_COLOR_SPACE_DISPLAY_P3: + gtk_linear_srgb_to_rgb (output->values[0], + output->values[1], + output->values[2], + &v[0], &v[1], &v[2]); + gtk_rgb_to_p3 (v[0], v[1], v[2], + &v[0], &v[1], &v[2]); + v[3] = output->values[3]; + gtk_css_color_init (output, GTK_CSS_COLOR_SPACE_DISPLAY_P3, v); + break; + case GTK_CSS_COLOR_SPACE_XYZ: gtk_linear_srgb_to_xyz (output->values[0], output->values[1], @@ -444,6 +475,17 @@ convert_from_linear (GtkCssColor *output, gtk_css_color_init (output, GTK_CSS_COLOR_SPACE_XYZ, v); break; + case GTK_CSS_COLOR_SPACE_REC2020: + gtk_linear_srgb_to_xyz (output->values[0], + output->values[1], + output->values[2], + &v[0], &v[1], &v[2]); + gtk_xyz_to_rec2020 (v[0], v[1], v[2], + &v[0], &v[1], &v[2]); + v[3] = output->values[3]; + gtk_css_color_init (output, GTK_CSS_COLOR_SPACE_REC2020, v); + break; + case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_OKLAB: case GTK_CSS_COLOR_SPACE_OKLCH: @@ -467,6 +509,7 @@ convert_from_rectangular (GtkCssColor *output, case GTK_CSS_COLOR_SPACE_OKLAB: case GTK_CSS_COLOR_SPACE_DISPLAY_P3: case GTK_CSS_COLOR_SPACE_XYZ: + case GTK_CSS_COLOR_SPACE_REC2020: g_assert (output->color_space == dest); break; @@ -635,6 +678,7 @@ apply_hue_interpolation (GtkCssColor *from, case GTK_CSS_COLOR_SPACE_OKLAB: case GTK_CSS_COLOR_SPACE_DISPLAY_P3: case GTK_CSS_COLOR_SPACE_XYZ: + case GTK_CSS_COLOR_SPACE_REC2020: break; case GTK_CSS_COLOR_SPACE_HSL: @@ -669,6 +713,7 @@ normalize_hue (GtkCssColor *color) case GTK_CSS_COLOR_SPACE_OKLAB: case GTK_CSS_COLOR_SPACE_DISPLAY_P3: case GTK_CSS_COLOR_SPACE_XYZ: + case GTK_CSS_COLOR_SPACE_REC2020: break; case GTK_CSS_COLOR_SPACE_HSL: @@ -708,6 +753,7 @@ premultiply (GtkCssColor *color) case GTK_CSS_COLOR_SPACE_OKLAB: case GTK_CSS_COLOR_SPACE_DISPLAY_P3: case GTK_CSS_COLOR_SPACE_XYZ: + case GTK_CSS_COLOR_SPACE_REC2020: premultiply_component (color, 0); premultiply_component (color, 1); premultiply_component (color, 2); @@ -752,6 +798,7 @@ unpremultiply (GtkCssColor *color) case GTK_CSS_COLOR_SPACE_OKLAB: case GTK_CSS_COLOR_SPACE_DISPLAY_P3: case GTK_CSS_COLOR_SPACE_XYZ: + case GTK_CSS_COLOR_SPACE_REC2020: unpremultiply_component (color, 0); unpremultiply_component (color, 1); unpremultiply_component (color, 2); @@ -790,6 +837,7 @@ collect_analogous_missing (const GtkCssColor *color, { -1, -1, -1, 0, 1, 2, -1, -1, 3 }, /* oklch */ { 0, 1, 2, -1, -1, -1, -1, -1, 3 }, /* display-p3 */ { 0, 1, 2, -1, -1, -1, -1, -1, 3 }, /* xyz */ + { 0, 1, 2, -1, -1, -1, -1, -1, 3 }, /* rec2020 */ }; int *src = analogous[color->color_space]; @@ -1004,6 +1052,9 @@ gtk_css_color_interpolation_method_print (GtkCssColorSpace in, case GTK_CSS_COLOR_SPACE_XYZ: g_string_append (string, "xyz"); break; + case GTK_CSS_COLOR_SPACE_REC2020: + g_string_append (string, "rec2020"); + break; default: g_assert_not_reached (); } diff --git a/gtk/gtkcsscolorprivate.h b/gtk/gtkcsscolorprivate.h index ad6d5b4f58..b162663c20 100644 --- a/gtk/gtkcsscolorprivate.h +++ b/gtk/gtkcsscolorprivate.h @@ -33,6 +33,7 @@ typedef enum { GTK_CSS_COLOR_SPACE_OKLCH, GTK_CSS_COLOR_SPACE_DISPLAY_P3, GTK_CSS_COLOR_SPACE_XYZ, + GTK_CSS_COLOR_SPACE_REC2020, } GtkCssColorSpace; typedef struct diff --git a/gtk/gtkcsscolorvalue.c b/gtk/gtkcsscolorvalue.c index e16a5e23f2..3f0ded12a2 100644 --- a/gtk/gtkcsscolorvalue.c +++ b/gtk/gtkcsscolorvalue.c @@ -369,6 +369,12 @@ gtk_css_value_color_print (const GtkCssValue *value, g_string_append (string, " xyz"); break; + case GTK_CSS_COLOR_SPACE_REC2020: + g_string_append (string, "color(from "); + gtk_css_value_print (value->relative.origin, string); + g_string_append (string, " rec2020"); + break; + case GTK_CSS_COLOR_SPACE_HSL: g_string_append (string, "hsl(from "); gtk_css_value_print (value->relative.origin, string); @@ -1666,6 +1672,12 @@ parse_color_color_channel (GtkCssParser *parser, return 1; } + if (gtk_css_parser_try_ident (parser, "rec2020")) + { + data->ctx.color_space = GTK_CSS_COLOR_SPACE_REC2020; + return 1; + } + gtk_css_parser_error_syntax (parser, "Invalid color space in color()"); return 0; From 2d1bfc84b989d9d3ce17ad924650202cd63fcab0 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 10 Jun 2024 12:41:09 -0400 Subject: [PATCH 5/7] Expose more colorutils We may want to have a rec2020-linear space available on the gsk level, so expose the conversion functions for it. --- gtk/gtkcolorutils.c | 56 +++++++++++++++++++++++++++----------- gtk/gtkcolorutilsprivate.h | 12 ++++++-- 2 files changed, 50 insertions(+), 18 deletions(-) diff --git a/gtk/gtkcolorutils.c b/gtk/gtkcolorutils.c index 35d27bdc32..7162f40e32 100644 --- a/gtk/gtkcolorutils.c +++ b/gtk/gtkcolorutils.c @@ -485,7 +485,7 @@ gtk_p3_to_rgb (float pr, float pg, float pb, gtk_linear_srgb_to_rgb (r, g, b, red, green, blue); } -static float +static inline float linearize_one (float val) { float alpha = 1.09929682680944 ; @@ -501,19 +501,32 @@ linearize_one (float val) } void -gtk_rec2020_to_xyz (float r, float g, float b, - float *x, float *y, float *z) +gtk_rec2020_to_rec2020_linear (float r, float g , float b, + float *rr, float *gg, float *bb) { - r = linearize_one (r); - g = linearize_one (g); - b = linearize_one (b); + *rr = linearize_one (r); + *gg = linearize_one (g); + *bb = linearize_one (b); +} +void +gtk_rec2020_linear_to_xyz (float r, float g, float b, + float *x, float *y, float *z) +{ *x = (63426534.0 / 99577255.0) * r + (20160776.0 / 139408157.0) * g + (47086771.0 / 278816314.0) * b; *y = (26158966.0 / 99577255.0) * r + (472592308.0 / 697040785.0) * g + (8267143.0 / 139408157.0) * b; *z = ( 0 / 1) * r + (19567812.0 / 697040785.0) * g + (295819943.0 / 278816314.0) * b; } -static float +void +gtk_rec2020_to_xyz (float r, float g, float b, + float *x, float *y, float *z) +{ + gtk_rec2020_to_rec2020_linear (r, g, b, &r, &g, &b); + gtk_rec2020_linear_to_xyz (r, g, b, x, y, z); +} + +static inline float delinearize_one (float val) { float alpha = 1.09929682680944; @@ -527,17 +540,28 @@ delinearize_one (float val) return 4.5 * val; } +void +gtk_rec2020_linear_to_rec2020 (float r, float g, float b, + float *rr, float *gg, float *bb) +{ + *rr = delinearize_one (r); + *gg = delinearize_one (g); + *bb = delinearize_one (b); +} + +void +gtk_xyz_to_rec2020_linear (float x, float y, float z, + float *r, float *g, float *b) +{ + *r = (30757411.0 / 17917100.0) * x - (6372589.0 / 17917100.0) * y - (4539589.0 / 17917100.0) * z; + *g = - (19765991.0 / 29648200.0) * x + (47925759.0 / 29648200.0) * y + (467509.0 / 29648200.0) *z; + *b = (792561.0 / 44930125.0) * x - (1921689.0 / 44930125.0) * y + (42328811.0 / 44930125.0) * z; +} + void gtk_xyz_to_rec2020 (float x, float y, float z, float *r, float *g, float *b) { - float rr, gg, bb; - - rr = (30757411.0 / 17917100.0) * x - (6372589.0 / 17917100.0) * y - (4539589.0 / 17917100.0) * z; - gg = - (19765991.0 / 29648200.0) * x + (47925759.0 / 29648200.0) * y + (467509.0 / 29648200.0) *z; - bb = (792561.0 / 44930125.0) * x - (1921689.0 / 44930125.0) * y + (42328811.0 / 44930125.0) * z; - - *r = delinearize_one (rr); - *g = delinearize_one (gg); - *b = delinearize_one (bb); + gtk_xyz_to_rec2020_linear (x, y, z, r, g, b); + gtk_rec2020_linear_to_rec2020 (*r, *g, *b, r, g, b); } diff --git a/gtk/gtkcolorutilsprivate.h b/gtk/gtkcolorutilsprivate.h index 12ef6b4255..e11eb07716 100644 --- a/gtk/gtkcolorutilsprivate.h +++ b/gtk/gtkcolorutilsprivate.h @@ -58,14 +58,22 @@ void gtk_p3_to_rgb (float pr, float pg, float pb, void gtk_xyz_to_linear_srgb (float x, float y, float z, float *r, float *g, float *b); - void gtk_linear_srgb_to_xyz (float r, float g, float b, float *x, float *y, float *z); void gtk_rec2020_to_xyz (float r, float g, float b, float *x, float *y, float *z); - void gtk_xyz_to_rec2020 (float x, float y, float z, float *r, float *g, float *b); +void gtk_rec2020_to_rec2020_linear (float r, float g , float b, + float *rr, float *gg, float *bb); +void gtk_rec2020_linear_to_rec2020 (float r, float g, float b, + float *rr, float *gg, float *bb); + +void gtk_rec2020_linear_to_xyz (float r, float g, float b, + float *x, float *y, float *z); +void gtk_xyz_to_rec2020_linear (float x, float y, float z, + float *r, float *g, float *b); + G_END_DECLS From 18c2c71cd5cc2ac62c57cb3ad2e269fadbb7f8f0 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 10 Jun 2024 13:17:36 -0400 Subject: [PATCH 6/7] css: Add support for rec2100-pq colors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is our first HDR color space. Yay!! The conversion between rec2020-linear and rec2100-linear assumes that SDR 1,1,1 has a luminance of 203 cd/m². --- gtk/gtkcolorutils.c | 64 ++++++++++++++++++++++++++++++++++++++ gtk/gtkcolorutilsprivate.h | 10 ++++++ gtk/gtkcsscolor.c | 53 ++++++++++++++++++++++++++++++- gtk/gtkcsscolorprivate.h | 1 + gtk/gtkcsscolorvalue.c | 12 +++++++ 5 files changed, 139 insertions(+), 1 deletion(-) diff --git a/gtk/gtkcolorutils.c b/gtk/gtkcolorutils.c index 7162f40e32..e5a8600fa3 100644 --- a/gtk/gtkcolorutils.c +++ b/gtk/gtkcolorutils.c @@ -565,3 +565,67 @@ gtk_xyz_to_rec2020 (float x, float y, float z, gtk_xyz_to_rec2020_linear (x, y, z, r, g, b); gtk_rec2020_linear_to_rec2020 (*r, *g, *b, r, g, b); } + +/* maps [0, 1] to [0, 70] */ +static inline float +pq_to_linear (float v) +{ + float ninv = (1 << 14) / 2610.0; + float minv = (1 << 5) / 2523.0; + float c1 = 3424.0 / (1 << 12); + float c2 = 2413.0 / (1 << 7); + float c3 = 2392.0 / (1 << 7); + + float x = powf (MAX ((powf (v, minv) - c1), 0) / (c2 - (c3 * (powf (v, minv)))), ninv); + return x * 10000 / 203.0; +} + +/* maps [0, 70] to [0, 1] */ +void +gtk_rec2100_pq_to_rec2100_linear (float r, float g, float b, + float *rr, float *gg, float *bb) +{ + *rr = pq_to_linear (r); + *gg = pq_to_linear (g); + *bb = pq_to_linear (b); +} + +static inline float +linear_to_pq (float v) +{ + float x = v * 203.0 / 10000.0; + float n = 2610.0 / (1 << 14); + float m = 2523.0 / (1 << 5); + float c1 = 3424.0 / (1 << 12); + float c2 = 2413.0 / (1 << 7); + float c3 = 2392.0 / (1 << 7); + + return powf (((c1 + (c2 * powf (x, n))) / (1 + (c3 * powf (x, n)))), m); +} + +void +gtk_rec2100_linear_to_rec2100_pq (float r, float g, float b, + float *rr, float *gg, float *bb) +{ + *rr = linear_to_pq (r); + *gg = linear_to_pq (g); + *bb = linear_to_pq (b); +} + +void +gtk_rec2100_linear_to_rec2020_linear (float r, float g, float b, + float *rr, float *gg, float *bb) +{ + *rr = r; + *gg = g; + *bb = b; +} + +void +gtk_rec2020_linear_to_rec2100_linear (float r, float g, float b, + float *rr, float *gg, float *bb) +{ + *rr = r; + *gg = g; + *bb = b; +} diff --git a/gtk/gtkcolorutilsprivate.h b/gtk/gtkcolorutilsprivate.h index e11eb07716..9172e76f0c 100644 --- a/gtk/gtkcolorutilsprivate.h +++ b/gtk/gtkcolorutilsprivate.h @@ -76,4 +76,14 @@ void gtk_rec2020_linear_to_xyz (float r, float g, float b, void gtk_xyz_to_rec2020_linear (float x, float y, float z, float *r, float *g, float *b); +void gtk_rec2100_pq_to_rec2100_linear (float r, float g, float b, + float *rr, float *gg, float *bb); +void gtk_rec2100_linear_to_rec2100_pq (float r, float g, float b, + float *rr, float *gg, float *bb); + +void gtk_rec2100_linear_to_rec2020_linear (float r, float g, float b, + float *rr, float *gg, float *bb); +void gtk_rec2020_linear_to_rec2100_linear (float r, float g, float b, + float *rr, float *gg, float *bb); + G_END_DECLS diff --git a/gtk/gtkcsscolor.c b/gtk/gtkcsscolor.c index b6b16c72ec..b76b1f855a 100644 --- a/gtk/gtkcsscolor.c +++ b/gtk/gtkcsscolor.c @@ -38,6 +38,7 @@ gtk_css_color_init (GtkCssColor *color, case GTK_CSS_COLOR_SPACE_DISPLAY_P3: case GTK_CSS_COLOR_SPACE_XYZ: case GTK_CSS_COLOR_SPACE_REC2020: + case GTK_CSS_COLOR_SPACE_REC2100_PQ: break; case GTK_CSS_COLOR_SPACE_HSL: @@ -151,6 +152,10 @@ gtk_css_color_print (const GtkCssColor *color, g_string_append (string, "color(rec2020 "); break; + case GTK_CSS_COLOR_SPACE_REC2100_PQ: + g_string_append (string, "color(rec2100-pq "); + break; + default: g_assert_not_reached (); } @@ -198,6 +203,7 @@ gtk_css_color_space_get_coord_name (GtkCssColorSpace color_space, case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_DISPLAY_P3: case GTK_CSS_COLOR_SPACE_REC2020: + case GTK_CSS_COLOR_SPACE_REC2100_PQ: switch (coord) { case 0: return "r"; @@ -274,6 +280,7 @@ gtk_css_color_space_get_coord_range (GtkCssColorSpace color_space, case GTK_CSS_COLOR_SPACE_DISPLAY_P3: case GTK_CSS_COLOR_SPACE_XYZ: case GTK_CSS_COLOR_SPACE_REC2020: + case GTK_CSS_COLOR_SPACE_REC2100_PQ: *lower = 0; *upper = 1; return; @@ -318,11 +325,14 @@ color_space_is_polar (GtkCssColorSpace color_space) case GTK_CSS_COLOR_SPACE_DISPLAY_P3: case GTK_CSS_COLOR_SPACE_XYZ: case GTK_CSS_COLOR_SPACE_REC2020: + case GTK_CSS_COLOR_SPACE_REC2100_PQ: return FALSE; + case GTK_CSS_COLOR_SPACE_HSL: case GTK_CSS_COLOR_SPACE_HWB: case GTK_CSS_COLOR_SPACE_OKLCH: return TRUE; + default: g_assert_not_reached (); } @@ -345,6 +355,7 @@ convert_to_rectangular (GtkCssColor *output) case GTK_CSS_COLOR_SPACE_DISPLAY_P3: case GTK_CSS_COLOR_SPACE_XYZ: case GTK_CSS_COLOR_SPACE_REC2020: + case GTK_CSS_COLOR_SPACE_REC2100_PQ: break; case GTK_CSS_COLOR_SPACE_HSL: @@ -389,7 +400,8 @@ convert_to_linear (GtkCssColor *output) output->color_space == GTK_CSS_COLOR_SPACE_OKLAB || output->color_space == GTK_CSS_COLOR_SPACE_DISPLAY_P3 || output->color_space == GTK_CSS_COLOR_SPACE_XYZ || - output->color_space == GTK_CSS_COLOR_SPACE_REC2020); + output->color_space == GTK_CSS_COLOR_SPACE_REC2020 || + output->color_space == GTK_CSS_COLOR_SPACE_REC2100_PQ); if (output->color_space == GTK_CSS_COLOR_SPACE_SRGB) { @@ -431,6 +443,21 @@ convert_to_linear (GtkCssColor *output) v[3] = output->values[3]; gtk_css_color_init (output, GTK_CSS_COLOR_SPACE_SRGB_LINEAR, v); } + else if (output->color_space == GTK_CSS_COLOR_SPACE_REC2100_PQ) + { + gtk_rec2100_pq_to_rec2100_linear (output->values[0], + output->values[1], + output->values[2], + &v[0], &v[1], &v[2]); + gtk_rec2100_linear_to_rec2020_linear (v[0], v[1], v[2], + &v[0], &v[1], &v[2]); + gtk_rec2020_linear_to_xyz (v[0], v[1], v[2], + &v[0], &v[1], &v[2]); + gtk_xyz_to_linear_srgb (v[0], v[1], v[2], + &v[0], &v[1], &v[2]); + v[3] = output->values[3]; + gtk_css_color_init (output, GTK_CSS_COLOR_SPACE_SRGB_LINEAR, v); + } } static void @@ -486,6 +513,21 @@ convert_from_linear (GtkCssColor *output, gtk_css_color_init (output, GTK_CSS_COLOR_SPACE_REC2020, v); break; + case GTK_CSS_COLOR_SPACE_REC2100_PQ: + gtk_linear_srgb_to_xyz (output->values[0], + output->values[1], + output->values[2], + &v[0], &v[1], &v[2]); + gtk_xyz_to_rec2020_linear (v[0], v[1], v[2], + &v[0], &v[1], &v[2]); + gtk_rec2020_linear_to_rec2100_linear (v[0], v[1], v[2], + &v[0], &v[1], &v[2]); + gtk_rec2100_linear_to_rec2100_pq (v[0], v[1], v[2], + &v[0], &v[1], &v[2]); + v[3] = output->values[3]; + gtk_css_color_init (output, GTK_CSS_COLOR_SPACE_REC2100_PQ, v); + break; + case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_OKLAB: case GTK_CSS_COLOR_SPACE_OKLCH: @@ -510,6 +552,7 @@ convert_from_rectangular (GtkCssColor *output, case GTK_CSS_COLOR_SPACE_DISPLAY_P3: case GTK_CSS_COLOR_SPACE_XYZ: case GTK_CSS_COLOR_SPACE_REC2020: + case GTK_CSS_COLOR_SPACE_REC2100_PQ: g_assert (output->color_space == dest); break; @@ -679,6 +722,7 @@ apply_hue_interpolation (GtkCssColor *from, case GTK_CSS_COLOR_SPACE_DISPLAY_P3: case GTK_CSS_COLOR_SPACE_XYZ: case GTK_CSS_COLOR_SPACE_REC2020: + case GTK_CSS_COLOR_SPACE_REC2100_PQ: break; case GTK_CSS_COLOR_SPACE_HSL: @@ -714,6 +758,7 @@ normalize_hue (GtkCssColor *color) case GTK_CSS_COLOR_SPACE_DISPLAY_P3: case GTK_CSS_COLOR_SPACE_XYZ: case GTK_CSS_COLOR_SPACE_REC2020: + case GTK_CSS_COLOR_SPACE_REC2100_PQ: break; case GTK_CSS_COLOR_SPACE_HSL: @@ -754,6 +799,7 @@ premultiply (GtkCssColor *color) case GTK_CSS_COLOR_SPACE_DISPLAY_P3: case GTK_CSS_COLOR_SPACE_XYZ: case GTK_CSS_COLOR_SPACE_REC2020: + case GTK_CSS_COLOR_SPACE_REC2100_PQ: premultiply_component (color, 0); premultiply_component (color, 1); premultiply_component (color, 2); @@ -799,6 +845,7 @@ unpremultiply (GtkCssColor *color) case GTK_CSS_COLOR_SPACE_DISPLAY_P3: case GTK_CSS_COLOR_SPACE_XYZ: case GTK_CSS_COLOR_SPACE_REC2020: + case GTK_CSS_COLOR_SPACE_REC2100_PQ: unpremultiply_component (color, 0); unpremultiply_component (color, 1); unpremultiply_component (color, 2); @@ -838,6 +885,7 @@ collect_analogous_missing (const GtkCssColor *color, { 0, 1, 2, -1, -1, -1, -1, -1, 3 }, /* display-p3 */ { 0, 1, 2, -1, -1, -1, -1, -1, 3 }, /* xyz */ { 0, 1, 2, -1, -1, -1, -1, -1, 3 }, /* rec2020 */ + { 0, 1, 2, -1, -1, -1, -1, -1, 3 }, /* rec2100-pq */ }; int *src = analogous[color->color_space]; @@ -1055,6 +1103,9 @@ gtk_css_color_interpolation_method_print (GtkCssColorSpace in, case GTK_CSS_COLOR_SPACE_REC2020: g_string_append (string, "rec2020"); break; + case GTK_CSS_COLOR_SPACE_REC2100_PQ: + g_string_append (string, "rec2100-pq"); + break; default: g_assert_not_reached (); } diff --git a/gtk/gtkcsscolorprivate.h b/gtk/gtkcsscolorprivate.h index b162663c20..27f16372ff 100644 --- a/gtk/gtkcsscolorprivate.h +++ b/gtk/gtkcsscolorprivate.h @@ -34,6 +34,7 @@ typedef enum { GTK_CSS_COLOR_SPACE_DISPLAY_P3, GTK_CSS_COLOR_SPACE_XYZ, GTK_CSS_COLOR_SPACE_REC2020, + GTK_CSS_COLOR_SPACE_REC2100_PQ, } GtkCssColorSpace; typedef struct diff --git a/gtk/gtkcsscolorvalue.c b/gtk/gtkcsscolorvalue.c index 3f0ded12a2..5f8d830bb4 100644 --- a/gtk/gtkcsscolorvalue.c +++ b/gtk/gtkcsscolorvalue.c @@ -375,6 +375,12 @@ gtk_css_value_color_print (const GtkCssValue *value, g_string_append (string, " rec2020"); break; + case GTK_CSS_COLOR_SPACE_REC2100_PQ: + g_string_append (string, "color(from "); + gtk_css_value_print (value->relative.origin, string); + g_string_append (string, " rec2100-pq"); + break; + case GTK_CSS_COLOR_SPACE_HSL: g_string_append (string, "hsl(from "); gtk_css_value_print (value->relative.origin, string); @@ -1678,6 +1684,12 @@ parse_color_color_channel (GtkCssParser *parser, return 1; } + if (gtk_css_parser_try_ident (parser, "rec2100-pq")) + { + data->ctx.color_space = GTK_CSS_COLOR_SPACE_REC2100_PQ; + return 1; + } + gtk_css_parser_error_syntax (parser, "Invalid color space in color()"); return 0; From f024ee1adf2f7c22a04796177cabca683e84658c Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 11 Jun 2024 16:18:17 -0400 Subject: [PATCH 7/7] Add more tests for css colors --- testsuite/css/color.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/testsuite/css/color.c b/testsuite/css/color.c index daef958c49..8e22982ff5 100644 --- a/testsuite/css/color.c +++ b/testsuite/css/color.c @@ -27,7 +27,7 @@ #include "gtk/gtkcssstylepropertyprivate.h" #include "gtk/gtkcssstaticstyleprivate.h" -#define EPSILON 0.001 +#define EPSILON 0.005 static gboolean color_is_near (const GtkCssColor *color1, @@ -116,8 +116,15 @@ static ColorConversionTest conversion_tests[] = { { "oklch(0.66016 0.15546 134.231)", GTK_CSS_COLOR_SPACE_SRGB, "rgb(40.73% 65.12% 22.35%)" }, { "oklch(72.322% 0.12403 247.996)", GTK_CSS_COLOR_SPACE_SRGB, "rgb(38.29% 67.27% 93.85%)" }, { "oklch(42.1% 48.25% 328.4)", GTK_CSS_COLOR_SPACE_SRGB, "color(srgb 0.501808 0.00257216 0.501403)" }, - /* more random tests */ + /* some self-conversions */ { "oklch(0.392 0.4 none)", GTK_CSS_COLOR_SPACE_OKLCH, "oklch(0.392 0.4 0)" }, + { "color(display-p3 1 1 1)", GTK_CSS_COLOR_SPACE_DISPLAY_P3, "color(display-p3 1 1 1)" }, + { "color(rec2020 1 1 1)", GTK_CSS_COLOR_SPACE_REC2020, "color(rec2020 1 1 1)" }, + { "color(rec2100-pq 0.58 0.58 0.58)", GTK_CSS_COLOR_SPACE_REC2100_PQ, "color(rec2100-pq 0.58 0.58 0.58)" }, + /* more random tests */ + { "color(rec2100-pq 0.58 0.58 0.58)", GTK_CSS_COLOR_SPACE_REC2020, "color(rec2020 1 1 1)" }, + { "color(xyz 0.5 0.7 99%)", GTK_CSS_COLOR_SPACE_DISPLAY_P3, "color(display-p3 0.48 0.93 0.96)" }, + { "hsl(250 100 20)", GTK_CSS_COLOR_SPACE_REC2020, "color(rec2020 0.042 0.008 0.3226)" }, }; static void