colorstate: Add xyz
This is mainly to test that our colorstate machinery is exensible. We will also use xyz as the central hub for converting between arbitrary color states.
This commit is contained in:
@@ -103,6 +103,19 @@ gdk_color_state_get_srgb_linear (void)
|
||||
return GDK_COLOR_STATE_SRGB_LINEAR;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_state_get_xyz:
|
||||
*
|
||||
* Returns the color state object representing the XYZ color space.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkColorState *
|
||||
gdk_color_state_get_xyz (void)
|
||||
{
|
||||
return GDK_COLOR_STATE_XYZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_state_equal:
|
||||
* @self: a `GdkColorState`
|
||||
@@ -202,6 +215,62 @@ srgb_eotf (float v)
|
||||
COORDINATE_TRANSFORM(gdk_default_srgb_to_srgb_linear, srgb_eotf)
|
||||
COORDINATE_TRANSFORM(gdk_default_srgb_linear_to_srgb, srgb_oetf)
|
||||
|
||||
static inline void
|
||||
vec3_multiply (const float matrix[3][3],
|
||||
const float vec[3],
|
||||
float res[3])
|
||||
{
|
||||
res[0] = matrix[0][0] * vec[0] + matrix[0][1] * vec[1] + matrix[0][2] * vec[2];
|
||||
res[1] = matrix[1][0] * vec[0] + matrix[1][1] * vec[1] + matrix[1][2] * vec[2];
|
||||
res[2] = matrix[2][0] * vec[0] + matrix[2][1] * vec[1] + matrix[2][2] * vec[2];
|
||||
}
|
||||
|
||||
#define LINEAR_TRANSFORM(name, matrix) \
|
||||
static void \
|
||||
name (GdkColorState *self, \
|
||||
float (*values)[4], \
|
||||
gsize n_values) \
|
||||
{ \
|
||||
for (gsize i = 0; i < n_values; i++) \
|
||||
{ \
|
||||
float res[3]; \
|
||||
\
|
||||
vec3_multiply (matrix, values[i], res); \
|
||||
\
|
||||
values[i][0] = res[0]; \
|
||||
values[i][1] = res[1]; \
|
||||
values[i][2] = res[2]; \
|
||||
} \
|
||||
}
|
||||
|
||||
static const float srgb_linear_to_xyz[3][3] = {
|
||||
{ (506752.0 / 1228815.0), (87881.0 / 245763.0), (12673.0 / 70218.0) },
|
||||
{ (87098.0 / 409605.0), (175762.0 / 245763.0), (12673.0 / 175545.0) },
|
||||
{ ( 7918.0 / 409605.0), (87881.0 / 737289.0), (1001167.0 / 1053270.0) },
|
||||
};
|
||||
|
||||
static const float xyz_to_srgb_linear[3][3] = {
|
||||
{ (12831.0 / 3959.0), - (329.0 / 214.0), - (1974.0 / 3959.0) },
|
||||
{ - (851781.0 / 878810.0), (1648619.0 / 878810.0), (36519.0 / 878810.0) },
|
||||
{ (705.0 / 12673.0), - (2585.0 / 12673.0), (705.0 / 667.0) },
|
||||
};
|
||||
|
||||
LINEAR_TRANSFORM(gdk_default_xyz_to_srgb_linear, xyz_to_srgb_linear)
|
||||
LINEAR_TRANSFORM(gdk_default_srgb_linear_to_xyz, srgb_linear_to_xyz)
|
||||
|
||||
#define CONCAT(name, f1, f2) \
|
||||
static void \
|
||||
name (GdkColorState *self, \
|
||||
float (*values)[4], \
|
||||
gsize n_values) \
|
||||
{ \
|
||||
f1 (self, values, n_values); \
|
||||
f2 (self, values, n_values); \
|
||||
}
|
||||
|
||||
CONCAT(gdk_default_xyz_to_srgb, gdk_default_xyz_to_srgb_linear, gdk_default_srgb_linear_to_srgb);
|
||||
CONCAT(gdk_default_srgb_to_xyz, gdk_default_srgb_to_srgb_linear, gdk_default_srgb_linear_to_xyz);
|
||||
|
||||
/* }}} */
|
||||
|
||||
static const
|
||||
@@ -225,6 +294,7 @@ GdkDefaultColorState gdk_default_color_states[] = {
|
||||
.no_srgb = GDK_COLOR_STATE_SRGB_LINEAR,
|
||||
.convert_to = {
|
||||
[GDK_COLOR_STATE_ID_SRGB_LINEAR] = gdk_default_srgb_to_srgb_linear,
|
||||
[GDK_COLOR_STATE_ID_XYZ] = gdk_default_srgb_to_xyz,
|
||||
},
|
||||
},
|
||||
[GDK_COLOR_STATE_ID_SRGB_LINEAR] = {
|
||||
@@ -238,6 +308,21 @@ GdkDefaultColorState gdk_default_color_states[] = {
|
||||
.no_srgb = NULL,
|
||||
.convert_to = {
|
||||
[GDK_COLOR_STATE_ID_SRGB] = gdk_default_srgb_linear_to_srgb,
|
||||
[GDK_COLOR_STATE_ID_XYZ] = gdk_default_srgb_linear_to_xyz,
|
||||
},
|
||||
},
|
||||
[GDK_COLOR_STATE_ID_XYZ] = {
|
||||
.parent = {
|
||||
.klass = &GDK_DEFAULT_COLOR_STATE_CLASS,
|
||||
.ref_count = 0,
|
||||
.depth = GDK_MEMORY_FLOAT16,
|
||||
.rendering_color_state = GDK_COLOR_STATE_XYZ,
|
||||
},
|
||||
.name = "xyz",
|
||||
.no_srgb = NULL,
|
||||
.convert_to = {
|
||||
[GDK_COLOR_STATE_ID_SRGB] = gdk_default_xyz_to_srgb,
|
||||
[GDK_COLOR_STATE_ID_SRGB_LINEAR] = gdk_default_xyz_to_srgb_linear,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -43,6 +43,9 @@ GdkColorState * gdk_color_state_get_srgb (void);
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_color_state_get_srgb_linear (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_color_state_get_xyz (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
gboolean gdk_color_state_equal (GdkColorState *self,
|
||||
GdkColorState *other);
|
||||
|
||||
@@ -10,6 +10,7 @@ typedef enum
|
||||
{
|
||||
GDK_COLOR_STATE_ID_SRGB,
|
||||
GDK_COLOR_STATE_ID_SRGB_LINEAR,
|
||||
GDK_COLOR_STATE_ID_XYZ,
|
||||
|
||||
GDK_COLOR_STATE_N_IDS
|
||||
} GdkColorStateId;
|
||||
@@ -55,6 +56,7 @@ extern GdkDefaultColorState gdk_default_color_states[GDK_COLOR_STATE_N_IDS];
|
||||
|
||||
#define GDK_COLOR_STATE_SRGB ((GdkColorState *) &gdk_default_color_states[GDK_COLOR_STATE_ID_SRGB])
|
||||
#define GDK_COLOR_STATE_SRGB_LINEAR ((GdkColorState *) &gdk_default_color_states[GDK_COLOR_STATE_ID_SRGB_LINEAR])
|
||||
#define GDK_COLOR_STATE_XYZ ((GdkColorState *) &gdk_default_color_states[GDK_COLOR_STATE_ID_XYZ])
|
||||
|
||||
#define GDK_IS_DEFAULT_COLOR_STATE(c) ((GdkDefaultColorState *) (c) >= &gdk_default_color_states[0] && \
|
||||
(GdkDefaultColorState *) (c) < &gdk_default_color_states[GDK_COLOR_STATE_N_IDS])
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
|
||||
#define GDK_COLOR_STATE_ID_SRGB 0u
|
||||
#define GDK_COLOR_STATE_ID_SRGB_LINEAR 1u
|
||||
#define GDK_COLOR_STATE_ID_XYZ 2u
|
||||
|
||||
#define TOP 0u
|
||||
#define RIGHT 1u
|
||||
|
||||
@@ -44,6 +44,32 @@ srgb_linear_to_srgb (vec4 color)
|
||||
color.a);
|
||||
}
|
||||
|
||||
vec4
|
||||
srgb_linear_to_xyz (vec4 color)
|
||||
{
|
||||
mat3 m = mat3 (506752.0 / 1228815.0, 87881.0 / 245763.0, 12673.0 / 70218.0,
|
||||
87098.0 / 409605.0, 175762.0 / 245763.0, 12673.0 / 175545.0,
|
||||
7918.0 / 409605.0, 87881.0 / 737289.0, 1001167.0 / 1053270.0);
|
||||
|
||||
return vec4 (color.rgb * m, color.a);
|
||||
}
|
||||
|
||||
vec4
|
||||
xyz_to_srgb_linear (vec4 color)
|
||||
{
|
||||
mat3 m = mat3 ( 12831.0 / 3959.0, -329.0 / 214.0, -1974.0 / 3959.0,
|
||||
-851781.0 / 878810.0, 1648619.0 / 878810.0, 36519.0 / 878810.0,
|
||||
705.0 / 12673.0, -2585.0 / 12673.0, 705.0 / 667.0);
|
||||
|
||||
return vec4 (color.xyz * m, color.a);
|
||||
}
|
||||
|
||||
#define CONCAT(f, f1, f2) vec4 f(vec4 color) { return f2(f1(color)); }
|
||||
|
||||
CONCAT(srgb_to_xyz, srgb_to_srgb_linear, srgb_linear_to_xyz)
|
||||
CONCAT(xyz_to_srgb, xyz_to_srgb_linear, srgb_linear_to_srgb)
|
||||
|
||||
|
||||
#define PAIR(_from_cs, _to_cs) ((_from_cs) << 16 | (_to_cs))
|
||||
|
||||
bool
|
||||
@@ -60,6 +86,18 @@ do_conversion (vec4 color,
|
||||
case PAIR (GDK_COLOR_STATE_ID_SRGB_LINEAR, GDK_COLOR_STATE_ID_SRGB):
|
||||
result = srgb_linear_to_srgb (color);
|
||||
break;
|
||||
case PAIR (GDK_COLOR_STATE_ID_SRGB_LINEAR, GDK_COLOR_STATE_ID_XYZ):
|
||||
result = srgb_linear_to_xyz (color);
|
||||
break;
|
||||
case PAIR (GDK_COLOR_STATE_ID_SRGB, GDK_COLOR_STATE_ID_XYZ):
|
||||
result = srgb_to_xyz (color);
|
||||
break;
|
||||
case PAIR (GDK_COLOR_STATE_ID_XYZ, GDK_COLOR_STATE_ID_SRGB_LINEAR):
|
||||
result = xyz_to_srgb_linear (color);
|
||||
break;
|
||||
case PAIR (GDK_COLOR_STATE_ID_XYZ, GDK_COLOR_STATE_ID_SRGB):
|
||||
result = xyz_to_srgb (color);
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
|
||||
@@ -111,6 +111,7 @@ main (int argc, char *argv[])
|
||||
|
||||
g_test_add_func ("/colorstate/srgb", test_srgb);
|
||||
g_test_add_data_func ("/colorstate/convert/srgb<->srgb-linear", GUINT_TO_POINTER (GDK_COLOR_STATE_ID_SRGB_LINEAR), test_convert);
|
||||
g_test_add_data_func ("/colorstate/convert/srgb<->xyz", GUINT_TO_POINTER (GDK_COLOR_STATE_ID_XYZ), test_convert);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user