From 5a85bc691e5865d4a81363e2916a7e505de24f59 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 31 May 2024 15:46:51 -0400 Subject: [PATCH] css: Split off GtkCssColor Break out a GtkCssColor struct. --- gtk/gtkcsscolor.c | 64 +++++ gtk/gtkcsscolorprivate.h | 87 +++++++ gtk/gtkcsscolorvalue.c | 375 ++++++++++++----------------- gtk/meson.build | 1 + testsuite/css/parser/color.ref.css | 4 +- 5 files changed, 304 insertions(+), 227 deletions(-) create mode 100644 gtk/gtkcsscolor.c create mode 100644 gtk/gtkcsscolorprivate.h diff --git a/gtk/gtkcsscolor.c b/gtk/gtkcsscolor.c new file mode 100644 index 0000000000..dfd5d280f3 --- /dev/null +++ b/gtk/gtkcsscolor.c @@ -0,0 +1,64 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2024 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "config.h" + +#include "gtkcsscolorprivate.h" +#include "gtkcolorutilsprivate.h" + +/* {{{ Initialization */ + +void +gtk_css_color_init (GtkCssColor *color, + GtkCssColorSpace color_space, + const float values[4]) +{ + gboolean missing[4] = { 0, }; + + /* look for powerless components */ + switch (color_space) + { + case GTK_CSS_COLOR_SPACE_SRGB: + case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: + case GTK_CSS_COLOR_SPACE_OKLAB: + break; + + case GTK_CSS_COLOR_SPACE_HSL: + if (fabs (values[2]) < 0.001) + missing[0] = 1; + break; + + case GTK_CSS_COLOR_SPACE_HWB: + if (values[1] + values[2] > 99.999) + missing[0] = 1; + break; + + case GTK_CSS_COLOR_SPACE_OKLCH: + if (fabs (values[1]) < 0.001) + missing[2] = 1; + break; + + default: + g_assert_not_reached (); + } + + gtk_css_color_init_with_missing (color, color_space, values, missing); +} + +/* }}} */ + +/* vim:set foldmethod=marker expandtab: */ diff --git a/gtk/gtkcsscolorprivate.h b/gtk/gtkcsscolorprivate.h new file mode 100644 index 0000000000..f8135d8327 --- /dev/null +++ b/gtk/gtkcsscolorprivate.h @@ -0,0 +1,87 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2040 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#pragma once + +#include +#include + +G_BEGIN_DECLS + +typedef enum { + GTK_CSS_COLOR_SPACE_SRGB, + GTK_CSS_COLOR_SPACE_SRGB_LINEAR, + GTK_CSS_COLOR_SPACE_HSL, + GTK_CSS_COLOR_SPACE_HWB, + GTK_CSS_COLOR_SPACE_OKLAB, + GTK_CSS_COLOR_SPACE_OKLCH, +} GtkCssColorSpace; + +typedef struct +{ + GtkCssColorSpace color_space; + float values[4]; + guint missing; +} GtkCssColor; + +static inline gboolean +gtk_css_color_equal (const GtkCssColor *color1, + const GtkCssColor *color2) +{ + return color1->color_space == color2->color_space && + color1->missing == color2->missing && + memcmp (color1->values, color2->values, sizeof (float) * 4) == 0; +} + +static inline gboolean +gtk_css_color_component_missing (const GtkCssColor *color, + guint idx) +{ + return (color->missing & (1 << idx)) != 0; +} + +static inline float +gtk_css_color_get_component (const GtkCssColor *color, + guint idx) +{ + return color->values[idx]; +} + +static inline void +gtk_css_color_init_with_missing (GtkCssColor *color, + GtkCssColorSpace color_space, + const float values[4], + gboolean missing[4]) +{ + color->color_space = color_space; + for (guint i = 0; i < 4; i++) + color->values[i] = missing[i] ? 0 : values[i]; + color->missing = missing[0] | (missing[1] << 1) | (missing[2] << 2) | (missing[3] << 3); +} + +static inline void +gtk_css_color_init_from_color (GtkCssColor *color, + const GtkCssColor *src) +{ + memcpy (color, src, sizeof (GtkCssColor)); +} + +void gtk_css_color_init (GtkCssColor *color, + GtkCssColorSpace color_space, + const float values[4]); + +G_END_DECLS diff --git a/gtk/gtkcsscolorvalue.c b/gtk/gtkcsscolorvalue.c index df92f6b427..c6c6aeb746 100644 --- a/gtk/gtkcsscolorvalue.c +++ b/gtk/gtkcsscolorvalue.c @@ -28,19 +28,14 @@ #include "gdk/gdkhslaprivate.h" #include "gdk/gdkrgbaprivate.h" +#include "gtkcsscolorprivate.h" #include "gtkcolorutilsprivate.h" -typedef enum { - GTK_CSS_COLOR_SPACE_SRGB, - GTK_CSS_COLOR_SPACE_SRGB_LINEAR, -} GtkCssColorSpace; - static GtkCssValue * gtk_css_color_value_new_mix (GtkCssValue *color1, GtkCssValue *color2, double factor); -static GtkCssValue * gtk_css_color_value_new_literal (const GdkRGBA *color, - gboolean missing[4]); +static GtkCssValue * gtk_css_color_value_new_literal (const GdkRGBA *color); typedef enum { COLOR_TYPE_LITERAL, @@ -50,26 +45,19 @@ typedef enum { COLOR_TYPE_ALPHA, COLOR_TYPE_MIX, COLOR_TYPE_CURRENT_COLOR, - COLOR_TYPE_OKLAB, - COLOR_TYPE_OKLCH, } ColorType; struct _GtkCssValue { GTK_CSS_VALUE_BASE + guint serialize_as_rgb: 1; ColorType type; - guint missing; union { char *name; GdkRGBA rgba; - - struct - { - GtkCssColorSpace color_space; - float values[4]; - } color; + GtkCssColor color; struct { @@ -83,16 +71,6 @@ struct _GtkCssValue GtkCssValue *color2; double factor; } mix; - - struct - { - float L, a, b, alpha; - } oklab; - - struct - { - float L, C, H, alpha; - } oklch; }; }; @@ -121,8 +99,6 @@ gtk_css_value_color_free (GtkCssValue *color) case COLOR_TYPE_LITERAL: case COLOR_TYPE_COLOR: case COLOR_TYPE_CURRENT_COLOR: - case COLOR_TYPE_OKLAB: - case COLOR_TYPE_OKLCH: default: break; } @@ -220,13 +196,10 @@ gtk_css_value_color_equal (const GtkCssValue *value1, switch (value1->type) { case COLOR_TYPE_LITERAL: - return gdk_rgba_equal (&value1->rgba, &value2->rgba) && - value1->missing == value2->missing; + return gdk_rgba_equal (&value1->rgba, &value2->rgba); case COLOR_TYPE_COLOR: - return value1->color.color_space == value2->color.color_space && - memcmp (value1->color.values, value2->color.values, sizeof (float) * 4) == 0 && - value1->missing == value2->missing; + return gtk_css_color_equal (&value1->color, &value2->color); case COLOR_TYPE_NAME: return g_str_equal (value1->name, value2->name); @@ -251,20 +224,6 @@ gtk_css_value_color_equal (const GtkCssValue *value1, case COLOR_TYPE_CURRENT_COLOR: return TRUE; - case COLOR_TYPE_OKLAB: - return value1->oklab.L == value2->oklab.L && - value1->oklab.a == value2->oklab.a && - value1->oklab.b == value2->oklab.b && - value1->oklab.alpha == value2->oklab.alpha && - value1->missing == value2->missing; - - case COLOR_TYPE_OKLCH: - return value1->oklch.L == value2->oklch.L && - value1->oklch.C == value2->oklch.C && - value1->oklch.H == value2->oklch.H && - value1->oklch.alpha == value2->oklch.alpha && - value1->missing == value2->missing; - default: g_assert_not_reached (); return FALSE; @@ -281,14 +240,93 @@ gtk_css_value_color_transition (GtkCssValue *start, } static inline void -append_color_component (GString *string, - float value, - gboolean missing) +append_color_component (GString *string, + const GtkCssColor *color, + guint idx) { - if (missing) + if (gtk_css_color_component_missing (color, idx)) g_string_append (string, "none"); else - g_string_append_printf (string, "%g", value); + g_string_append_printf (string, "%g", gtk_css_color_get_component (color, idx)); +} + +static void +convert_to_rgba (const GtkCssValue *value, + GdkRGBA *rgba) +{ + g_assert (value->type == COLOR_TYPE_COLOR); + + switch (value->color.color_space) + { + case GTK_CSS_COLOR_SPACE_SRGB: + rgba->red = CLAMP (value->color.values[0], 0, 1); + rgba->green = CLAMP (value->color.values[1], 0, 1); + rgba->blue = CLAMP (value->color.values[2], 0, 1); + rgba->alpha = CLAMP (value->color.values[3], 0, 1); + break; + + case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: + gtk_linear_srgb_to_rgb (CLAMP (value->color.values[0], 0, 1), + CLAMP (value->color.values[1], 0, 1), + CLAMP (value->color.values[2], 0, 1), + &rgba->red, + &rgba->green, + &rgba->blue); + rgba->alpha = CLAMP (value->color.values[3], 0, 1); + break; + + case GTK_CSS_COLOR_SPACE_HSL: + { + GdkHSLA hsla; + + hsla.hue = value->color.values[0]; + hsla.saturation = CLAMP (value->color.values[1] / 100, 0, 1); + hsla.lightness = CLAMP (value->color.values[2] / 100, 0, 1); + hsla.alpha = CLAMP (value->color.values[3], 0, 1); + + _gdk_rgba_init_from_hsla (rgba, &hsla); + } + break; + + case GTK_CSS_COLOR_SPACE_HWB: + { + float h, w, b; + + h = value->color.values[0]; + w = CLAMP (value->color.values[1] / 100, 0, 1); + b = CLAMP (value->color.values[2] / 100, 0, 1); + + gtk_hwb_to_rgb (h, w, b, &rgba->red, &rgba->green, &rgba->blue); + rgba->alpha = value->color.values[3]; + } + break; + + case GTK_CSS_COLOR_SPACE_OKLAB: + gtk_oklab_to_rgb (CLAMP (value->color.values[0], 0, 1), + value->color.values[1], + value->color.values[2], + &rgba->red, + &rgba->green, + &rgba->blue); + rgba->alpha = value->color.values[3]; + break; + + case GTK_CSS_COLOR_SPACE_OKLCH: + { + float L, C, H, a, b; + + L = CLAMP (value->color.values[0], 0, 1); + C = MAX (value->color.values[1], 0); + H = value->color.values[2]; + gtk_oklch_to_oklab (L, C, H, &L, &a, &b); + gtk_oklab_to_rgb (L, a, b, &rgba->red, &rgba->green, &rgba->blue); + rgba->alpha = value->color.values[3]; + } + break; + + default: + g_assert_not_reached (); + } } static void @@ -308,16 +346,39 @@ gtk_css_value_color_print (const GtkCssValue *value, break; case COLOR_TYPE_COLOR: - g_string_append (string, "color("); - switch (value->color.color_space) { + case GTK_CSS_COLOR_SPACE_HSL: + case GTK_CSS_COLOR_SPACE_HWB: + { +print_rgb: + GdkRGBA rgba; + char *s; + + convert_to_rgba (value, &rgba); + s = gdk_rgba_to_string (&rgba); + g_string_append (string, s); + g_free (s); + } + return; + case GTK_CSS_COLOR_SPACE_SRGB: - g_string_append (string, "srgb"); + if (value->serialize_as_rgb) + goto print_rgb; + + g_string_append (string, "color(srgb "); break; case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: - g_string_append (string, "srgb-linear"); + g_string_append (string, "color(srgb-linear "); + break; + + case GTK_CSS_COLOR_SPACE_OKLAB: + g_string_append (string, "oklab("); + break; + + case GTK_CSS_COLOR_SPACE_OKLCH: + g_string_append (string, "oklch("); break; default: @@ -326,14 +387,16 @@ gtk_css_value_color_print (const GtkCssValue *value, for (guint i = 0; i < 3; i++) { - g_string_append_c (string, ' '); - append_color_component (string, value->color.values[i], value->missing & (1 << i)); + if (i > 0) + g_string_append_c (string, ' '); + append_color_component (string, &value->color, i); } - if ((value->missing & (1 << 3)) != 0 || value->color.values[3] < 0.999) + if (gtk_css_color_component_missing (&value->color, 3) || + gtk_css_color_get_component (&value->color, 3) < 0.999) { g_string_append (string, " / "); - append_color_component (string, value->color.values[3], value->missing & (1 << 3)); + append_color_component (string, &value->color, 3); } g_string_append_c (string, ')'); @@ -377,37 +440,6 @@ gtk_css_value_color_print (const GtkCssValue *value, g_string_append (string, "currentcolor"); break; - case COLOR_TYPE_OKLAB: - g_string_append (string, "oklab("); - append_color_component (string, value->oklab.L, value->missing & (1 << 0)); - g_string_append_c (string, ' '); - append_color_component (string, value->oklab.a, value->missing & (1 << 1)); - g_string_append_c (string, ' '); - append_color_component (string, value->oklab.b, value->missing & (1 << 2)); - - if ((value->missing & (1 << 3)) != 0 || value->oklab.alpha < 0.999) - { - g_string_append (string, " / "); - append_color_component (string, value->oklab.alpha, value->missing & (1 << 3)); - } - g_string_append_c (string, ')'); - break; - - case COLOR_TYPE_OKLCH: - g_string_append (string, "oklch("); - append_color_component (string, value->oklch.L, value->missing & (1 << 0)); - g_string_append_c (string, ' '); - append_color_component (string, value->oklch.C, value->missing & (1 << 1)); - g_string_append_c (string, ' '); - append_color_component (string, value->oklch.H, value->missing & (1 << 2)); - if ((value->missing & (1 << 3)) != 0 || value->oklch.alpha < 0.999) - { - g_string_append (string, " / "); - append_color_component (string, value->oklab.alpha, value->missing & (1 << 3)); - } - g_string_append_c (string, ')'); - break; - default: g_assert_not_reached (); } @@ -495,34 +527,8 @@ gtk_css_color_value_do_resolve (GtkCssValue *color, { GdkRGBA rgba; - switch (color->color.color_space) - { - case GTK_CSS_COLOR_SPACE_SRGB: - rgba.red = CLAMP (color->color.values[0], 0, 1); - rgba.green = CLAMP (color->color.values[1], 0, 1); - rgba.blue = CLAMP (color->color.values[2], 0, 1); - rgba.alpha = color->color.values[3]; - break; - - case GTK_CSS_COLOR_SPACE_SRGB_LINEAR: - gtk_linear_srgb_to_rgb (CLAMP (color->color.values[0], 0, 1), - CLAMP (color->color.values[1], 0, 1), - CLAMP (color->color.values[2], 0, 1), - &rgba.red, &rgba.green, &rgba.blue); - rgba.alpha = color->color.values[3]; - break; - - default: - g_assert_not_reached (); - } - - value = gtk_css_color_value_new_literal (&rgba, - (gboolean []) { - (color->missing & (1 << 0)) != 0, - (color->missing & (1 << 1)) != 0, - (color->missing & (1 << 2)) != 0, - (color->missing & (1 << 3)) != 0, - }); + convert_to_rgba (color, &rgba); + value = gtk_css_color_value_new_literal (&rgba); } break; @@ -557,7 +563,7 @@ gtk_css_color_value_do_resolve (GtkCssValue *color, apply_shade (c, &shade, color->shade.factor); - value = gtk_css_color_value_new_literal (&shade, NULL); + value = gtk_css_color_value_new_literal (&shade); gtk_css_value_unref (val); } break; @@ -575,7 +581,7 @@ gtk_css_color_value_do_resolve (GtkCssValue *color, apply_alpha (c, &alpha, color->alpha.factor); - value = gtk_css_color_value_new_literal (&alpha, NULL); + value = gtk_css_color_value_new_literal (&alpha); gtk_css_value_unref (val); } break; @@ -598,7 +604,7 @@ gtk_css_color_value_do_resolve (GtkCssValue *color, apply_mix (color1, color2, &res, color->mix.factor); - value = gtk_css_color_value_new_literal (&res, NULL); + value = gtk_css_color_value_new_literal (&res); gtk_css_value_unref (val1); gtk_css_value_unref (val2); } @@ -611,32 +617,6 @@ gtk_css_color_value_do_resolve (GtkCssValue *color, value = gtk_css_value_ref (current); break; - case COLOR_TYPE_OKLAB: - { - GdkRGBA rgba; - - gtk_oklab_to_rgb (color->oklab.L, color->oklab.a, color->oklab.b, - &rgba.red, &rgba.green, &rgba.blue); - rgba.alpha = color->oklab.alpha; - - value = gtk_css_color_value_new_literal (&rgba, NULL); - } - break; - - case COLOR_TYPE_OKLCH: - { - float L, a, b; - GdkRGBA rgba; - - gtk_oklch_to_oklab (color->oklch.L, color->oklch.C, color->oklch.H, &L, &a, &b); - gtk_oklab_to_rgb (L, a, b, &rgba.red, &rgba.green, &rgba.blue); - - rgba.alpha = color->oklab.alpha; - - value = gtk_css_color_value_new_literal (&rgba, NULL); - } - break; - default: value = NULL; g_assert_not_reached (); @@ -653,9 +633,9 @@ gtk_css_color_value_resolve (GtkCssValue *color, return gtk_css_color_value_do_resolve (color, provider, current, NULL); } -static GtkCssValue transparent_black_singleton = { >K_CSS_VALUE_COLOR, 1, TRUE, FALSE, COLOR_TYPE_LITERAL, +static GtkCssValue transparent_black_singleton = { >K_CSS_VALUE_COLOR, 1, TRUE, FALSE, FALSE, COLOR_TYPE_LITERAL, .rgba = {0, 0, 0, 0} }; -static GtkCssValue white_singleton = { >K_CSS_VALUE_COLOR, 1, TRUE, FALSE, COLOR_TYPE_LITERAL, +static GtkCssValue white_singleton = { >K_CSS_VALUE_COLOR, 1, TRUE, FALSE, FALSE, COLOR_TYPE_LITERAL, .rgba = {1, 1, 1, 1} }; @@ -672,8 +652,7 @@ gtk_css_color_value_new_white (void) } static GtkCssValue * -gtk_css_color_value_new_literal (const GdkRGBA *color, - gboolean missing[4]) +gtk_css_color_value_new_literal (const GdkRGBA *color) { GtkCssValue *value; @@ -687,8 +666,6 @@ gtk_css_color_value_new_literal (const GdkRGBA *color, value = gtk_css_value_new (GtkCssValue, >K_CSS_VALUE_COLOR); value->type = COLOR_TYPE_LITERAL; - if (missing) - value->missing = missing[0] | (missing[1] << 1) | (missing[2] << 2) | missing[3] << 3; value->is_computed = TRUE; value->rgba = *color; @@ -696,7 +673,8 @@ gtk_css_color_value_new_literal (const GdkRGBA *color, } static GtkCssValue * -gtk_css_value_value_new_color (GtkCssColorSpace color_space, +gtk_css_color_value_new_color (GtkCssColorSpace color_space, + gboolean serialize_as_rgb, float values[4], gboolean missing[4]) { @@ -704,9 +682,9 @@ gtk_css_value_value_new_color (GtkCssColorSpace color_space, value = gtk_css_value_new (GtkCssValue, >K_CSS_VALUE_COLOR); value->type = COLOR_TYPE_COLOR; - value->missing = missing[0] | (missing[1] << 1) | (missing[2] << 2) | missing[3] << 3; value->color.color_space = color_space; - memcpy (value->color.values, values, sizeof (float) * 4); + value->serialize_as_rgb = serialize_as_rgb; + gtk_css_color_init_with_missing (&value->color, color_space, values, missing); return value; } @@ -739,7 +717,7 @@ gtk_css_color_value_new_shade (GtkCssValue *color, apply_shade (&color->rgba, &c, factor); - return gtk_css_color_value_new_literal (&c, (gboolean[]) { 0, 0, 0, 0 }); + return gtk_css_color_value_new_literal (&c); } value = gtk_css_value_new (GtkCssValue, >K_CSS_VALUE_COLOR); @@ -764,7 +742,7 @@ gtk_css_color_value_new_alpha (GtkCssValue *color, apply_alpha (&color->rgba, &c, factor); - return gtk_css_color_value_new_literal (&c, NULL); + return gtk_css_color_value_new_literal (&c); } value = gtk_css_value_new (GtkCssValue, >K_CSS_VALUE_COLOR); @@ -792,7 +770,7 @@ gtk_css_color_value_new_mix (GtkCssValue *color1, apply_mix (&color1->rgba, &color2->rgba, &result, factor); - return gtk_css_color_value_new_literal (&result, NULL); + return gtk_css_color_value_new_literal (&result); } @@ -808,51 +786,11 @@ gtk_css_color_value_new_mix (GtkCssValue *color1, GtkCssValue * gtk_css_color_value_new_current_color (void) { - static GtkCssValue current_color = { >K_CSS_VALUE_COLOR, 1, FALSE, FALSE, COLOR_TYPE_CURRENT_COLOR, }; + static GtkCssValue current_color = { >K_CSS_VALUE_COLOR, 1, FALSE, FALSE, FALSE, COLOR_TYPE_CURRENT_COLOR, }; return gtk_css_value_ref (¤t_color); } -static GtkCssValue * -gtk_css_color_value_new_oklab (float L, - float a, - float b, - float alpha, - gboolean missing[4]) -{ - GtkCssValue *value; - - value = gtk_css_value_new (GtkCssValue, >K_CSS_VALUE_COLOR); - value->type = COLOR_TYPE_OKLAB; - value->missing = missing[0] | (missing[1] << 1) | (missing[2] << 2) | missing[3] << 3; - value->oklab.L = L; - value->oklab.a = a; - value->oklab.b = b; - value->oklab.alpha = alpha; - - return value; -} - -static GtkCssValue * -gtk_css_color_value_new_oklch (float L, - float C, - float H, - float alpha, - gboolean missing[4]) -{ - GtkCssValue *value; - - value = gtk_css_value_new (GtkCssValue, >K_CSS_VALUE_COLOR); - value->type = COLOR_TYPE_OKLCH; - value->missing = missing[0] | (missing[1] << 1) | (missing[2] << 2) | missing[3] << 3; - value->oklab.L = L; - value->oklab.a = C; - value->oklab.b = H; - value->oklab.alpha = alpha; - - return value; -} - typedef struct { GtkCssValue *color; @@ -1076,7 +1014,7 @@ parse_hsl_channel_value (GtkCssParser *parser, return FALSE; *value = gtk_css_number_value_get_canonical (val, 100); - *value = CLAMP (*value, 0.0, 100.0) / 100.0; + *value = CLAMP (*value, 0.0, 100.0); gtk_css_value_unref (val); } @@ -1141,6 +1079,9 @@ parse_hue_value (GtkCssParser *parser, return FALSE; *value = gtk_css_number_value_get_canonical (hue, 360); + *value = fmod (*value, 360); + if (*value < 0) + *value += 360; gtk_css_value_unref (hue); } @@ -1622,7 +1563,7 @@ gtk_css_color_value_parse (GtkCssParser *parser) if (!parse_color_function (parser, COLOR_SYNTAX_DETECTING, FALSE, has_alpha, has_alpha, parse_rgba_color_channel, &data)) return NULL; - return gtk_css_color_value_new_literal (&rgba, data.missing); + return gtk_css_color_value_new_color (GTK_CSS_COLOR_SPACE_SRGB, TRUE, (float *) &rgba, data.missing); } else if (gtk_css_parser_has_function (parser, "hsl") || gtk_css_parser_has_function (parser, "hsla")) { @@ -1633,30 +1574,16 @@ gtk_css_color_value_parse (GtkCssParser *parser) if (!parse_color_function (parser, COLOR_SYNTAX_DETECTING, FALSE, TRUE, FALSE, parse_hsla_color_channel, &data)) return NULL; - _gdk_rgba_init_from_hsla (&rgba, data.hsla); - - /* FIXME */ - return gtk_css_color_value_new_literal (&rgba, (gboolean[]) { 0, 0, 0, 0 } ); + return gtk_css_color_value_new_color (GTK_CSS_COLOR_SPACE_HSL, FALSE, (float *) &hsla, data.missing); } else if (gtk_css_parser_has_function (parser, "hwb")) { HwbData hwb = { 0, 0, 0, 1, { FALSE, } }; - float red, green, blue; if (!parse_color_function (parser, COLOR_SYNTAX_MODERN, FALSE, TRUE, FALSE, parse_hwb_color_channel, &hwb)) return NULL; - hwb.white /= 100.0; - hwb.black /= 100.0; - - gtk_hwb_to_rgb (hwb.hue, hwb.white, hwb.black, &red, &green, &blue); - - rgba.red = red; - rgba.green = green; - rgba.blue = blue; - rgba.alpha = hwb.alpha; - - return gtk_css_color_value_new_literal (&rgba, (gboolean[]) { 0, 0, 0, 0 } ); + return gtk_css_color_value_new_color (GTK_CSS_COLOR_SPACE_HWB, FALSE, (float *) &hwb, hwb.missing); } else if (gtk_css_parser_has_function (parser, "oklab")) { @@ -1665,8 +1592,7 @@ gtk_css_color_value_parse (GtkCssParser *parser) if (!parse_color_function (parser, COLOR_SYNTAX_MODERN, FALSE, TRUE, FALSE, parse_oklab_color_channel, &oklab)) return NULL; - return gtk_css_color_value_new_oklab (oklab.L, oklab.a, oklab.b, oklab.alpha, - oklab.missing); + return gtk_css_color_value_new_color (GTK_CSS_COLOR_SPACE_OKLAB, FALSE, (float *) &oklab, oklab.missing); } else if (gtk_css_parser_has_function (parser, "oklch")) { @@ -1675,8 +1601,7 @@ gtk_css_color_value_parse (GtkCssParser *parser) if (!parse_color_function (parser, COLOR_SYNTAX_MODERN, FALSE, TRUE, FALSE, parse_oklch_color_channel, &oklch)) return NULL; - return gtk_css_color_value_new_oklch (oklch.L, oklch.C, oklch.H, oklch.alpha, - oklch.missing); + return gtk_css_color_value_new_color (GTK_CSS_COLOR_SPACE_OKLCH, FALSE, (float *) &oklch, oklch.missing); } else if (gtk_css_parser_has_function (parser, "color")) { @@ -1685,7 +1610,7 @@ gtk_css_color_value_parse (GtkCssParser *parser) if (!parse_color_function (parser, COLOR_SYNTAX_MODERN, TRUE, TRUE, FALSE, parse_color_color_channel, &data)) return NULL; - return gtk_css_value_value_new_color (data.color_space, data.values, data.missing); + return gtk_css_color_value_new_color (data.color_space, FALSE, data.values, data.missing); } else if (gtk_css_parser_has_function (parser, "lighter")) { @@ -1750,7 +1675,7 @@ gtk_css_color_value_parse (GtkCssParser *parser) } if (gdk_rgba_parser_parse (parser, &rgba)) - return gtk_css_color_value_new_literal (&rgba, (gboolean[]) { 0, 0, 0, 0 }); + return gtk_css_color_value_new_literal (&rgba); else return NULL; } diff --git a/gtk/meson.build b/gtk/meson.build index e3b6bb824f..2a83114158 100644 --- a/gtk/meson.build +++ b/gtk/meson.build @@ -51,6 +51,7 @@ gtk_private_sources = files([ 'gtkcssbgsizevalue.c', 'gtkcssbordervalue.c', 'gtkcsscalcvalue.c', + 'gtkcsscolor.c', 'gtkcsscolorvalue.c', 'gtkcsscornervalue.c', 'gtkcsscustompropertypool.c', diff --git a/testsuite/css/parser/color.ref.css b/testsuite/css/parser/color.ref.css index 5e6a4e103b..1da7938d42 100644 --- a/testsuite/css/parser/color.ref.css +++ b/testsuite/css/parser/color.ref.css @@ -113,11 +113,11 @@ ab { } ac { - color: oklab(0.80000001192092896 0 0.30000001192092896 / 0.5); + color: oklab(0.8 0 0.3 / 0.5); } ad { - color: oklch(0.80000001192092896 0.30000001192092896 200 / 0.5); + color: oklch(0.8 0.3 200 / 0.5); } ae {