Merge branch 'more-css-color-spaces' into 'main'

css: Add more color spaces

See merge request GNOME/gtk!7352
This commit is contained in:
Matthias Clasen 2024-06-11 21:05:06 +00:00
commit 420bd5bc16
7 changed files with 480 additions and 5 deletions

View File

@ -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) 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; GError *error = NULL;
priv->current_format = depth; priv->current_format = depth;

View File

@ -423,3 +423,209 @@ gtk_linear_srgb_to_rgb (float linear_red, float linear_green, float linear_bl
*green = apply_gamma (linear_green); *green = apply_gamma (linear_green);
*blue = apply_gamma (linear_blue); *blue = apply_gamma (linear_blue);
} }
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;
}
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;
*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_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);
}
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_linear_srgb (x, y, z, &r, &g, &b);
gtk_linear_srgb_to_rgb (r, g, b, red, green, blue);
}
static inline 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_rec2020_linear (float r, float g , float b,
float *rr, float *gg, float *bb)
{
*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;
}
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;
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_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)
{
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;
}

View File

@ -51,5 +51,39 @@ 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, void gtk_linear_srgb_to_rgb (float linear_red, float linear_green, float linear_blue,
float *red, float *green, float *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);
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);
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 G_END_DECLS

View File

@ -35,6 +35,10 @@ gtk_css_color_init (GtkCssColor *color,
case GTK_CSS_COLOR_SPACE_SRGB: case GTK_CSS_COLOR_SPACE_SRGB:
case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_SRGB_LINEAR:
case GTK_CSS_COLOR_SPACE_OKLAB: 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:
case GTK_CSS_COLOR_SPACE_REC2100_PQ:
break; break;
case GTK_CSS_COLOR_SPACE_HSL: case GTK_CSS_COLOR_SPACE_HSL:
@ -136,6 +140,22 @@ gtk_css_color_print (const GtkCssColor *color,
g_string_append (string, "oklch("); g_string_append (string, "oklch(");
break; break;
case GTK_CSS_COLOR_SPACE_DISPLAY_P3:
g_string_append (string, "color(display-p3 ");
break;
case GTK_CSS_COLOR_SPACE_XYZ:
g_string_append (string, "color(xyz ");
break;
case GTK_CSS_COLOR_SPACE_REC2020:
g_string_append (string, "color(rec2020 ");
break;
case GTK_CSS_COLOR_SPACE_REC2100_PQ:
g_string_append (string, "color(rec2100-pq ");
break;
default: default:
g_assert_not_reached (); g_assert_not_reached ();
} }
@ -181,6 +201,9 @@ gtk_css_color_space_get_coord_name (GtkCssColorSpace color_space,
{ {
case GTK_CSS_COLOR_SPACE_SRGB: case GTK_CSS_COLOR_SPACE_SRGB:
case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: 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) switch (coord)
{ {
case 0: return "r"; case 0: return "r";
@ -188,6 +211,14 @@ gtk_css_color_space_get_coord_name (GtkCssColorSpace color_space,
case 2: return "b"; case 2: return "b";
default: g_assert_not_reached (); 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: case GTK_CSS_COLOR_SPACE_HSL:
switch (coord) switch (coord)
{ {
@ -246,6 +277,10 @@ gtk_css_color_space_get_coord_range (GtkCssColorSpace color_space,
*upper = legacy_rgb_scale ? 255 : 1; *upper = legacy_rgb_scale ? 255 : 1;
return; return;
case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: 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:
case GTK_CSS_COLOR_SPACE_REC2100_PQ:
*lower = 0; *lower = 0;
*upper = 1; *upper = 1;
return; return;
@ -287,11 +322,17 @@ color_space_is_polar (GtkCssColorSpace color_space)
case GTK_CSS_COLOR_SPACE_SRGB: case GTK_CSS_COLOR_SPACE_SRGB:
case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_SRGB_LINEAR:
case GTK_CSS_COLOR_SPACE_OKLAB: 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:
case GTK_CSS_COLOR_SPACE_REC2100_PQ:
return FALSE; return FALSE;
case GTK_CSS_COLOR_SPACE_HSL: case GTK_CSS_COLOR_SPACE_HSL:
case GTK_CSS_COLOR_SPACE_HWB: case GTK_CSS_COLOR_SPACE_HWB:
case GTK_CSS_COLOR_SPACE_OKLCH: case GTK_CSS_COLOR_SPACE_OKLCH:
return TRUE; return TRUE;
default: default:
g_assert_not_reached (); g_assert_not_reached ();
} }
@ -311,6 +352,10 @@ convert_to_rectangular (GtkCssColor *output)
case GTK_CSS_COLOR_SPACE_SRGB: case GTK_CSS_COLOR_SPACE_SRGB:
case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_SRGB_LINEAR:
case GTK_CSS_COLOR_SPACE_OKLAB: 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:
case GTK_CSS_COLOR_SPACE_REC2100_PQ:
break; break;
case GTK_CSS_COLOR_SPACE_HSL: case GTK_CSS_COLOR_SPACE_HSL:
@ -352,7 +397,11 @@ convert_to_linear (GtkCssColor *output)
g_assert (output->color_space == GTK_CSS_COLOR_SPACE_SRGB || 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_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 ||
output->color_space == GTK_CSS_COLOR_SPACE_XYZ ||
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) if (output->color_space == GTK_CSS_COLOR_SPACE_SRGB)
{ {
@ -363,6 +412,52 @@ convert_to_linear (GtkCssColor *output)
v[3] = output->values[3]; v[3] = output->values[3];
gtk_css_color_init (output, GTK_CSS_COLOR_SPACE_SRGB_LINEAR, v); 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);
}
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);
}
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);
}
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 static void
@ -387,6 +482,52 @@ convert_from_linear (GtkCssColor *output,
gtk_css_color_init (output, GTK_CSS_COLOR_SPACE_SRGB, v); gtk_css_color_init (output, GTK_CSS_COLOR_SPACE_SRGB, v);
break; 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],
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_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_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_SRGB_LINEAR:
case GTK_CSS_COLOR_SPACE_OKLAB: case GTK_CSS_COLOR_SPACE_OKLAB:
case GTK_CSS_COLOR_SPACE_OKLCH: case GTK_CSS_COLOR_SPACE_OKLCH:
@ -408,6 +549,10 @@ convert_from_rectangular (GtkCssColor *output,
case GTK_CSS_COLOR_SPACE_SRGB: case GTK_CSS_COLOR_SPACE_SRGB:
case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_SRGB_LINEAR:
case GTK_CSS_COLOR_SPACE_OKLAB: 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:
case GTK_CSS_COLOR_SPACE_REC2100_PQ:
g_assert (output->color_space == dest); g_assert (output->color_space == dest);
break; break;
@ -574,6 +719,10 @@ apply_hue_interpolation (GtkCssColor *from,
case GTK_CSS_COLOR_SPACE_SRGB: case GTK_CSS_COLOR_SPACE_SRGB:
case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_SRGB_LINEAR:
case GTK_CSS_COLOR_SPACE_OKLAB: 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:
case GTK_CSS_COLOR_SPACE_REC2100_PQ:
break; break;
case GTK_CSS_COLOR_SPACE_HSL: case GTK_CSS_COLOR_SPACE_HSL:
@ -606,6 +755,10 @@ normalize_hue (GtkCssColor *color)
case GTK_CSS_COLOR_SPACE_SRGB: case GTK_CSS_COLOR_SPACE_SRGB:
case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_SRGB_LINEAR:
case GTK_CSS_COLOR_SPACE_OKLAB: 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:
case GTK_CSS_COLOR_SPACE_REC2100_PQ:
break; break;
case GTK_CSS_COLOR_SPACE_HSL: case GTK_CSS_COLOR_SPACE_HSL:
@ -643,6 +796,10 @@ premultiply (GtkCssColor *color)
case GTK_CSS_COLOR_SPACE_SRGB: case GTK_CSS_COLOR_SPACE_SRGB:
case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_SRGB_LINEAR:
case GTK_CSS_COLOR_SPACE_OKLAB: 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:
case GTK_CSS_COLOR_SPACE_REC2100_PQ:
premultiply_component (color, 0); premultiply_component (color, 0);
premultiply_component (color, 1); premultiply_component (color, 1);
premultiply_component (color, 2); premultiply_component (color, 2);
@ -685,6 +842,10 @@ unpremultiply (GtkCssColor *color)
case GTK_CSS_COLOR_SPACE_SRGB: case GTK_CSS_COLOR_SPACE_SRGB:
case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: case GTK_CSS_COLOR_SPACE_SRGB_LINEAR:
case GTK_CSS_COLOR_SPACE_OKLAB: 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:
case GTK_CSS_COLOR_SPACE_REC2100_PQ:
unpremultiply_component (color, 0); unpremultiply_component (color, 0);
unpremultiply_component (color, 1); unpremultiply_component (color, 1);
unpremultiply_component (color, 2); unpremultiply_component (color, 2);
@ -721,7 +882,10 @@ collect_analogous_missing (const GtkCssColor *color,
{ -1, -1, -1, -1, -1, 0, -1, -1, 3 }, /* hwb */ { -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, -1, 1, 2, 3 }, /* oklab */
{ -1, -1, -1, 0, 1, 2, -1, -1, 3 }, /* oklch */ { -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 */
{ 0, 1, 2, -1, -1, -1, -1, -1, 3 }, /* rec2100-pq */
}; };
int *src = analogous[color->color_space]; int *src = analogous[color->color_space];
@ -930,6 +1094,18 @@ gtk_css_color_interpolation_method_print (GtkCssColorSpace in,
case GTK_CSS_COLOR_SPACE_OKLAB: case GTK_CSS_COLOR_SPACE_OKLAB:
g_string_append (string, "oklab"); g_string_append (string, "oklab");
break; break;
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;
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: default:
g_assert_not_reached (); g_assert_not_reached ();
} }

View File

@ -31,6 +31,10 @@ typedef enum {
GTK_CSS_COLOR_SPACE_HWB, GTK_CSS_COLOR_SPACE_HWB,
GTK_CSS_COLOR_SPACE_OKLAB, GTK_CSS_COLOR_SPACE_OKLAB,
GTK_CSS_COLOR_SPACE_OKLCH, GTK_CSS_COLOR_SPACE_OKLCH,
GTK_CSS_COLOR_SPACE_DISPLAY_P3,
GTK_CSS_COLOR_SPACE_XYZ,
GTK_CSS_COLOR_SPACE_REC2020,
GTK_CSS_COLOR_SPACE_REC2100_PQ,
} GtkCssColorSpace; } GtkCssColorSpace;
typedef struct typedef struct

View File

@ -357,6 +357,30 @@ gtk_css_value_color_print (const GtkCssValue *value,
g_string_append (string, " srgb-linear"); g_string_append (string, " srgb-linear");
break; 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_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_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_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: case GTK_CSS_COLOR_SPACE_HSL:
g_string_append (string, "hsl(from "); g_string_append (string, "hsl(from ");
gtk_css_value_print (value->relative.origin, string); gtk_css_value_print (value->relative.origin, string);
@ -1642,6 +1666,30 @@ parse_color_color_channel (GtkCssParser *parser,
return 1; return 1;
} }
if (gtk_css_parser_try_ident (parser, "display-p3"))
{
data->ctx.color_space = GTK_CSS_COLOR_SPACE_DISPLAY_P3;
return 1;
}
if (gtk_css_parser_try_ident (parser, "xyz"))
{
data->ctx.color_space = GTK_CSS_COLOR_SPACE_XYZ;
return 1;
}
if (gtk_css_parser_try_ident (parser, "rec2020"))
{
data->ctx.color_space = GTK_CSS_COLOR_SPACE_REC2020;
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()"); gtk_css_parser_error_syntax (parser, "Invalid color space in color()");
return 0; return 0;

View File

@ -27,7 +27,7 @@
#include "gtk/gtkcssstylepropertyprivate.h" #include "gtk/gtkcssstylepropertyprivate.h"
#include "gtk/gtkcssstaticstyleprivate.h" #include "gtk/gtkcssstaticstyleprivate.h"
#define EPSILON 0.001 #define EPSILON 0.005
static gboolean static gboolean
color_is_near (const GtkCssColor *color1, 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(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(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)" }, { "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)" }, { "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 static void