gdk: Add GdkColorState

This is mostly an empty shell for now. We only have static instances
for srgb and srgb-linear, which we will use as markers during our
node processing.

In the future, this object may grow more instances, as well as the
ability to create them from and save them to icc profiles or cicp
data. And a color conversion API.
This commit is contained in:
Matthias Clasen 2024-06-08 14:37:51 -04:00 committed by Benjamin Otte
parent 01ca59ea91
commit aa746bc0c8
8 changed files with 357 additions and 0 deletions

View File

@ -30,6 +30,7 @@
#include <gdk/gdkcairo.h>
#include <gdk/gdkcairocontext.h>
#include <gdk/gdkclipboard.h>
#include <gdk/gdkcolorstate.h>
#include <gdk/gdkconfig.h>
#include <gdk/gdkcontentdeserializer.h>
#include <gdk/gdkcontentformats.h>

183
gdk/gdkcolorstate.c Normal file
View File

@ -0,0 +1,183 @@
/* gdkcolorstate.c
*
* Copyright 2024 Matthias Clasen
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gdkcolorstateprivate.h"
#include <glib/gi18n-lib.h>
/**
* GdkColorState:
*
* A `GdkColorState` object provides the information to interpret
* colors and pixels in a variety of ways.
*
* They are also known as
* [*color spaces*](https://en.wikipedia.org/wiki/Color_space).
*
* Crucially, GTK knows how to convert colors from one color
* state to another.
*
* `GdkColorState objects are immutable and therefore threadsafe.
*
* Since 4.16
*/
G_DEFINE_BOXED_TYPE (GdkColorState, gdk_color_state,
gdk_color_state_ref, gdk_color_state_unref);
/* {{{ Public API */
/**
* gdk_color_state_ref:
* @self: a `GdkColorState`
*
* Increase the reference count of @self.
*
* Returns: the object that was passed in
*
* Since: 4.16
*/
GdkColorState *
(gdk_color_state_ref) (GdkColorState *self)
{
return _gdk_color_state_ref (self);
}
/**
* gdk_color_state_unref:
* @self:a `GdkColorState`
*
* Decrease the reference count of @self.
*
* Unless @self is static, it will be freed
* when the reference count reaches zero.
*
* Since: 4.16
*/
void
(gdk_color_state_unref) (GdkColorState *self)
{
_gdk_color_state_unref (self);
}
/**
* gdk_color_state_get_srgb:
*
* Returns the color state object representing the sRGB color space.
*
* Since: 4.16
*/
GdkColorState *
gdk_color_state_get_srgb (void)
{
return GDK_COLOR_STATE_SRGB;
}
/**
* gdk_color_state_get_srgb_linear:
*
* Returns the color state object representing the linearized sRGB color space.
*
* Since: 4.16
*/
GdkColorState *
gdk_color_state_get_srgb_linear (void)
{
return GDK_COLOR_STATE_SRGB_LINEAR;
}
/**
* gdk_color_state_equal:
* @self: a `GdkColorState`
* @other: another `GdkColorStatee`
*
* Compares two `GdkColorStates` for equality.
*
* Note that this function is not guaranteed to be perfect and two objects
* describing the same color state may compare not equal. However, different
* color states will never compare equal.
*
* Returns: %TRUE if the two color states compare equal
*
* Since: 4.16
*/
gboolean
(gdk_color_state_equal) (GdkColorState *self,
GdkColorState *other)
{
return _gdk_color_state_equal (self, other);
}
/* }}} */
/* {{{ Default implementation */
static gboolean
gdk_default_color_state_equal (GdkColorState *self,
GdkColorState *other)
{
return self == other;
}
static const char *
gdk_default_color_state_get_name (GdkColorState *color_state)
{
GdkDefaultColorState *self = (GdkDefaultColorState *) color_state;
return self->name;
}
static const
GdkColorStateClass GDK_DEFAULT_COLOR_STATE_CLASS = {
.free = NULL, /* crash here if this ever happens */
.equal = gdk_default_color_state_equal,
.get_name = gdk_default_color_state_get_name,
};
GdkDefaultColorState gdk_default_color_states[] = {
[GDK_COLOR_STATE_ID_SRGB] = {
.parent = {
.klass = &GDK_DEFAULT_COLOR_STATE_CLASS,
.ref_count = 0,
.depth = GDK_MEMORY_U8,
},
.name = "srgb",
},
[GDK_COLOR_STATE_ID_SRGB_LINEAR] = {
.parent = {
.klass = &GDK_DEFAULT_COLOR_STATE_CLASS,
.ref_count = 0,
.depth = GDK_MEMORY_U8,
},
.name = "srgb-linear",
},
};
/* }}} */
/* {{{ Private API */
const char *
gdk_color_state_get_name (GdkColorState *self)
{
return self->klass->get_name (self);
}
/* }}} */
/* vim:set foldmethod=marker expandtab: */

50
gdk/gdkcolorstate.h Normal file
View File

@ -0,0 +1,50 @@
/* gdkcolorstate.h
*
* Copyright 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#if !defined (__GDK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/gdk.h> can be included directly."
#endif
#include <gdk/gdktypes.h>
G_BEGIN_DECLS
#define GDK_TYPE_COLOR_STATE (gdk_color_state_get_type ())
GDK_AVAILABLE_IN_4_16
GType gdk_color_state_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_4_16
GdkColorState * gdk_color_state_ref (GdkColorState *self);
GDK_AVAILABLE_IN_4_16
void gdk_color_state_unref (GdkColorState *self);
GDK_AVAILABLE_IN_4_16
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
gboolean gdk_color_state_equal (GdkColorState *self,
GdkColorState *other);
G_END_DECLS

View File

@ -0,0 +1,94 @@
#pragma once
#include "gdkcolorstate.h"
#include "gdkmemoryformatprivate.h"
typedef enum
{
GDK_COLOR_STATE_ID_SRGB,
GDK_COLOR_STATE_ID_SRGB_LINEAR,
GDK_COLOR_STATE_N_IDS
} GdkColorStateId;
typedef struct _GdkColorStateClass GdkColorStateClass;
struct _GdkColorState
{
const GdkColorStateClass *klass;
gatomicrefcount ref_count;
GdkMemoryDepth depth;
};
struct _GdkColorStateClass
{
void (* free) (GdkColorState *self);
gboolean (* equal) (GdkColorState *self,
GdkColorState *other);
const char * (* get_name) (GdkColorState *self);
};
typedef struct _GdkDefaultColorState GdkDefaultColorState;
struct _GdkDefaultColorState
{
GdkColorState parent;
const char *name;
};
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_IS_DEFAULT_COLOR_STATE(c) ((GdkDefaultColorState *) (c) >= &gdk_default_color_states[0] && \
(GdkDefaultColorState *) (c) < &gdk_default_color_states[GDK_COLOR_STATE_N_IDS])
#define GDK_DEFAULT_COLOR_STATE_ID(c) ((GdkColorStateId) (((GdkDefaultColorState *) c) - gdk_default_color_states))
const char * gdk_color_state_get_name (GdkColorState *color_state);
static inline GdkMemoryDepth
gdk_color_state_get_depth (GdkColorState *self)
{
return self->depth;
}
#define gdk_color_state_ref(self) _gdk_color_state_ref (self)
static inline GdkColorState *
_gdk_color_state_ref (GdkColorState *self)
{
if (GDK_IS_DEFAULT_COLOR_STATE (self))
return self;
g_atomic_ref_count_inc (&self->ref_count);
return self;
}
#define gdk_color_state_unref(self) _gdk_color_state_unref (self)
static inline void
_gdk_color_state_unref (GdkColorState *self)
{
if (GDK_IS_DEFAULT_COLOR_STATE (self))
return;
if (g_atomic_ref_count_dec (&self->ref_count))
self->klass->free (self);
}
#define gdk_color_state_equal(a,b) _gdk_color_state_equal ((a), (b))
static inline gboolean
_gdk_color_state_equal (GdkColorState *self,
GdkColorState *other)
{
if (self == other)
return TRUE;
if (self->klass != other->klass)
return FALSE;
return self->klass->equal (self, other);
}

View File

@ -74,6 +74,7 @@ typedef cairo_rectangle_int_t GdkRectangle;
/* Forward declarations of commonly used types */
typedef struct _GdkRGBA GdkRGBA;
typedef struct _GdkColorState GdkColorState;
typedef struct _GdkContentFormats GdkContentFormats;
typedef struct _GdkContentProvider GdkContentProvider;
typedef struct _GdkCursor GdkCursor;

View File

@ -6,6 +6,7 @@ gdk_public_sources = files([
'gdkcairo.c',
'gdkcairocontext.c',
'gdkclipboard.c',
'gdkcolorstate.c',
'gdkcontentdeserializer.c',
'gdkcontentformats.c',
'gdkcontentprovider.c',
@ -76,6 +77,7 @@ gdk_public_headers = files([
'gdkcairo.h',
'gdkcairocontext.h',
'gdkclipboard.h',
'gdkcolorstate.h',
'gdkcontentdeserializer.h',
'gdkcontentformats.h',
'gdkcontentprovider.h',

View File

@ -0,0 +1,25 @@
#include <gdk/gdk.h>
static void
test_srgb (void)
{
GdkColorState *srgb;
GdkColorState *srgb_linear;
srgb = gdk_color_state_get_srgb ();
srgb_linear = gdk_color_state_get_srgb_linear ();
g_assert_true (gdk_color_state_equal (srgb, srgb));
g_assert_true (gdk_color_state_equal (srgb_linear, srgb_linear));
g_assert_false (gdk_color_state_equal (srgb, srgb_linear));
}
int
main (int argc, char *argv[])
{
(g_test_init) (&argc, &argv, NULL);
g_test_add_func ("/colorstate/srgb", test_srgb);
return g_test_run ();
}

View File

@ -57,6 +57,7 @@ foreach t : tests
endforeach
internal_tests = [
{ 'name': 'colorstate' },
{ 'name': 'dihedral' },
{ 'name': 'image' },
{ 'name': 'texture' },