cogl: Add missing functions from ClutterColor to CoglColor
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3544>
This commit is contained in:
parent
8709fc5353
commit
ac3aa35489
2 changed files with 396 additions and 1 deletions
|
@ -72,6 +72,296 @@ cogl_color_init_from_4f (CoglColor *color,
|
|||
color->alpha = (alpha * 255);
|
||||
}
|
||||
|
||||
static inline void
|
||||
skip_whitespace (gchar **str)
|
||||
{
|
||||
while (g_ascii_isspace (**str))
|
||||
*str += 1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
parse_rgb_value (gchar *str,
|
||||
guint8 *color,
|
||||
gchar **endp)
|
||||
{
|
||||
gdouble number;
|
||||
gchar *p;
|
||||
|
||||
skip_whitespace (&str);
|
||||
|
||||
number = g_ascii_strtod (str, endp);
|
||||
|
||||
p = *endp;
|
||||
|
||||
skip_whitespace (&p);
|
||||
|
||||
if (*p == '%')
|
||||
{
|
||||
*endp = (gchar *) (p + 1);
|
||||
|
||||
*color = CLAMP (number / 100.0, 0.0, 1.0) * 255;
|
||||
}
|
||||
else
|
||||
*color = CLAMP (number, 0, 255);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_rgba (CoglColor *color,
|
||||
gchar *str,
|
||||
gboolean has_alpha)
|
||||
{
|
||||
skip_whitespace (&str);
|
||||
|
||||
if (*str != '(')
|
||||
return FALSE;
|
||||
|
||||
str += 1;
|
||||
|
||||
/* red */
|
||||
parse_rgb_value (str, &color->red, &str);
|
||||
skip_whitespace (&str);
|
||||
if (*str != ',')
|
||||
return FALSE;
|
||||
|
||||
str += 1;
|
||||
|
||||
/* green */
|
||||
parse_rgb_value (str, &color->green, &str);
|
||||
skip_whitespace (&str);
|
||||
if (*str != ',')
|
||||
return FALSE;
|
||||
|
||||
str += 1;
|
||||
|
||||
/* blue */
|
||||
parse_rgb_value (str, &color->blue, &str);
|
||||
skip_whitespace (&str);
|
||||
|
||||
/* alpha (optional); since the alpha channel value can only
|
||||
* be between 0 and 1 we don't use the parse_rgb_value()
|
||||
* function
|
||||
*/
|
||||
if (has_alpha)
|
||||
{
|
||||
gdouble number;
|
||||
|
||||
if (*str != ',')
|
||||
return FALSE;
|
||||
|
||||
str += 1;
|
||||
|
||||
skip_whitespace (&str);
|
||||
number = g_ascii_strtod (str, &str);
|
||||
|
||||
color->alpha = CLAMP (number * 255.0, 0, 255);
|
||||
}
|
||||
else
|
||||
color->alpha = 255;
|
||||
|
||||
skip_whitespace (&str);
|
||||
if (*str != ')')
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_hsla (CoglColor *color,
|
||||
gchar *str,
|
||||
gboolean has_alpha)
|
||||
{
|
||||
gdouble number;
|
||||
gdouble h, l, s;
|
||||
|
||||
skip_whitespace (&str);
|
||||
|
||||
if (*str != '(')
|
||||
return FALSE;
|
||||
|
||||
str += 1;
|
||||
|
||||
/* hue */
|
||||
skip_whitespace (&str);
|
||||
/* we don't do any angle normalization here because
|
||||
* cogl_color_from_hls() will do it for us
|
||||
*/
|
||||
number = g_ascii_strtod (str, &str);
|
||||
skip_whitespace (&str);
|
||||
if (*str != ',')
|
||||
return FALSE;
|
||||
|
||||
h = number;
|
||||
|
||||
str += 1;
|
||||
|
||||
/* saturation */
|
||||
skip_whitespace (&str);
|
||||
number = g_ascii_strtod (str, &str);
|
||||
skip_whitespace (&str);
|
||||
if (*str != '%')
|
||||
return FALSE;
|
||||
|
||||
str += 1;
|
||||
|
||||
s = CLAMP (number / 100.0, 0.0, 1.0);
|
||||
skip_whitespace (&str);
|
||||
if (*str != ',')
|
||||
return FALSE;
|
||||
|
||||
str += 1;
|
||||
|
||||
/* luminance */
|
||||
skip_whitespace (&str);
|
||||
number = g_ascii_strtod (str, &str);
|
||||
skip_whitespace (&str);
|
||||
if (*str != '%')
|
||||
return FALSE;
|
||||
|
||||
str += 1;
|
||||
|
||||
l = CLAMP (number / 100.0, 0.0, 1.0);
|
||||
skip_whitespace (&str);
|
||||
|
||||
/* alpha (optional); since the alpha channel value can only
|
||||
* be between 0 and 1 we don't use the parse_rgb_value()
|
||||
* function
|
||||
*/
|
||||
if (has_alpha)
|
||||
{
|
||||
if (*str != ',')
|
||||
return FALSE;
|
||||
|
||||
str += 1;
|
||||
|
||||
skip_whitespace (&str);
|
||||
number = g_ascii_strtod (str, &str);
|
||||
|
||||
color->alpha = CLAMP (number * 255.0, 0, 255);
|
||||
}
|
||||
else
|
||||
color->alpha = 255;
|
||||
|
||||
skip_whitespace (&str);
|
||||
if (*str != ')')
|
||||
return FALSE;
|
||||
|
||||
cogl_color_init_from_hsl (color, h, s, l);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
cogl_color_from_string (CoglColor *color,
|
||||
const gchar *str)
|
||||
{
|
||||
g_return_val_if_fail (color != NULL, FALSE);
|
||||
g_return_val_if_fail (str != NULL, FALSE);
|
||||
|
||||
if (strncmp (str, "rgb", 3) == 0)
|
||||
{
|
||||
gchar *s = (gchar *) str;
|
||||
gboolean res;
|
||||
|
||||
if (strncmp (str, "rgba", 4) == 0)
|
||||
res = parse_rgba (color, s + 4, TRUE);
|
||||
else
|
||||
res = parse_rgba (color, s + 3, FALSE);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
if (strncmp (str, "hsl", 3) == 0)
|
||||
{
|
||||
gchar *s = (gchar *) str;
|
||||
gboolean res;
|
||||
|
||||
if (strncmp (str, "hsla", 4) == 0)
|
||||
res = parse_hsla (color, s + 4, TRUE);
|
||||
else
|
||||
res = parse_hsla (color, s + 3, FALSE);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* if the string contains a color encoded using the hexadecimal
|
||||
* notations (#rrggbbaa or #rgba) we attempt a rough pass at
|
||||
* parsing the color ourselves, as we need the alpha channel that
|
||||
* Pango can't retrieve.
|
||||
*/
|
||||
if (str[0] == '#' && str[1] != '\0')
|
||||
{
|
||||
gsize length = strlen (str + 1);
|
||||
gint32 result;
|
||||
|
||||
if (sscanf (str + 1, "%x", &result) == 1)
|
||||
{
|
||||
switch (length)
|
||||
{
|
||||
case 8: /* rrggbbaa */
|
||||
color->red = (result >> 24) & 0xff;
|
||||
color->green = (result >> 16) & 0xff;
|
||||
color->blue = (result >> 8) & 0xff;
|
||||
|
||||
color->alpha = result & 0xff;
|
||||
|
||||
return TRUE;
|
||||
|
||||
case 6: /* #rrggbb */
|
||||
color->red = (result >> 16) & 0xff;
|
||||
color->green = (result >> 8) & 0xff;
|
||||
color->blue = result & 0xff;
|
||||
|
||||
color->alpha = 0xff;
|
||||
|
||||
return TRUE;
|
||||
|
||||
case 4: /* #rgba */
|
||||
color->red = ((result >> 12) & 0xf);
|
||||
color->green = ((result >> 8) & 0xf);
|
||||
color->blue = ((result >> 4) & 0xf);
|
||||
color->alpha = result & 0xf;
|
||||
|
||||
color->red = (color->red << 4) | color->red;
|
||||
color->green = (color->green << 4) | color->green;
|
||||
color->blue = (color->blue << 4) | color->blue;
|
||||
color->alpha = (color->alpha << 4) | color->alpha;
|
||||
|
||||
return TRUE;
|
||||
|
||||
case 3: /* #rgb */
|
||||
color->red = ((result >> 8) & 0xf);
|
||||
color->green = ((result >> 4) & 0xf);
|
||||
color->blue = result & 0xf;
|
||||
|
||||
color->red = (color->red << 4) | color->red;
|
||||
color->green = (color->green << 4) | color->green;
|
||||
color->blue = (color->blue << 4) | color->blue;
|
||||
|
||||
color->alpha = 0xff;
|
||||
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gchar *
|
||||
cogl_color_to_string (const CoglColor *color)
|
||||
{
|
||||
g_return_val_if_fail (color != NULL, NULL);
|
||||
|
||||
return g_strdup_printf ("#%02x%02x%02x%02x",
|
||||
color->red,
|
||||
color->green,
|
||||
color->blue,
|
||||
color->alpha);
|
||||
}
|
||||
|
||||
float
|
||||
cogl_color_get_red (const CoglColor *color)
|
||||
{
|
||||
|
@ -116,6 +406,19 @@ cogl_color_equal (const void *v1, const void *v2)
|
|||
return *c1 == *c2 ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
guint
|
||||
cogl_color_hash (gconstpointer v)
|
||||
{
|
||||
const CoglColor *color;
|
||||
g_return_val_if_fail (v != NULL, 0);
|
||||
|
||||
color = v;
|
||||
return (color->alpha |
|
||||
color->blue << 8 |
|
||||
color->green << 16 |
|
||||
color->red << 24);
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_color_get_rgba_4ubv (const CoglColor *color,
|
||||
uint8_t *dest)
|
||||
|
|
|
@ -50,6 +50,23 @@
|
|||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* COGL_COLOR_INIT:
|
||||
* @r: value for the red channel, between 0 and 255
|
||||
* @g: value for the green channel, between 0 and 255
|
||||
* @b: value for the blue channel, between 0 and 255
|
||||
* @a: value for the alpha channel, between 0 and 255
|
||||
*
|
||||
* A macro that initializes a #CoglColor, to be used when declaring it.
|
||||
*/
|
||||
#define COGL_COLOR_INIT(_r, _g, _b, _a) \
|
||||
(CoglColor) { \
|
||||
.red = (_r), \
|
||||
.green = (_g), \
|
||||
.blue = (_b), \
|
||||
.alpha = (_a) \
|
||||
}
|
||||
|
||||
#define COGL_TYPE_COLOR (cogl_color_get_type ())
|
||||
|
||||
/**
|
||||
|
@ -81,6 +98,66 @@ cogl_color_copy (const CoglColor *color);
|
|||
COGL_EXPORT void
|
||||
cogl_color_free (CoglColor *color);
|
||||
|
||||
|
||||
/**
|
||||
* cogl_color_to_string:
|
||||
* @color: a #CoglColor
|
||||
*
|
||||
* Returns a textual specification of @color in the hexadecimal form
|
||||
* `#rrggbbaa`, where `r`, `g`, `b` and `a` are
|
||||
* hexadecimal digits representing the red, green, blue and alpha components
|
||||
* respectively.
|
||||
*
|
||||
* Return value: (transfer full): a newly-allocated text string
|
||||
*/
|
||||
COGL_EXPORT
|
||||
gchar * cogl_color_to_string (const CoglColor *color);
|
||||
|
||||
/**
|
||||
* cogl_color_from_string:
|
||||
* @color: (out caller-allocates): return location for a #CoglColor
|
||||
* @str: a string specifying a color
|
||||
*
|
||||
* Parses a string definition of a color, filling the #CoglColor.red,
|
||||
* #CoglColor.green, #CoglColor.blue and #CoglColor.alpha fields
|
||||
* of @color.
|
||||
*
|
||||
* The @color is not allocated.
|
||||
*
|
||||
* The format of @str can be either one of:
|
||||
*
|
||||
* - an hexadecimal value in the form: `#rgb`, `#rrggbb`, `#rgba`, or `#rrggbbaa`
|
||||
* - a RGB color in the form: `rgb(r, g, b)`
|
||||
* - a RGB color in the form: `rgba(r, g, b, a)`
|
||||
* - a HSL color in the form: `hsl(h, s, l)`
|
||||
* -a HSL color in the form: `hsla(h, s, l, a)`
|
||||
*
|
||||
* where 'r', 'g', 'b' and 'a' are (respectively) the red, green, blue color
|
||||
* intensities and the opacity. The 'h', 's' and 'l' are (respectively) the
|
||||
* hue, saturation and luminance values.
|
||||
*
|
||||
* In the rgb() and rgba() formats, the 'r', 'g', and 'b' values are either
|
||||
* integers between 0 and 255, or percentage values in the range between 0%
|
||||
* and 100%; the percentages require the '%' character. The 'a' value, if
|
||||
* specified, can only be a floating point value between 0.0 and 1.0.
|
||||
*
|
||||
* In the hls() and hlsa() formats, the 'h' value (hue) is an angle between
|
||||
* 0 and 360.0 degrees; the 'l' and 's' values (luminance and saturation) are
|
||||
* percentage values in the range between 0% and 100%. The 'a' value, if specified,
|
||||
* can only be a floating point value between 0.0 and 1.0.
|
||||
*
|
||||
* Whitespace inside the definitions is ignored; no leading whitespace
|
||||
* is allowed.
|
||||
*
|
||||
* If the alpha component is not specified then it is assumed to be set to
|
||||
* be fully opaque.
|
||||
*
|
||||
* Return value: %TRUE if parsing succeeded, and %FALSE otherwise
|
||||
*/
|
||||
COGL_EXPORT
|
||||
gboolean cogl_color_from_string (CoglColor *color,
|
||||
const gchar *str);
|
||||
|
||||
/**
|
||||
* cogl_color_init_from_4f:
|
||||
* @color: A pointer to a #CoglColor to initialize
|
||||
|
@ -170,7 +247,22 @@ cogl_color_premultiply (CoglColor *color);
|
|||
* Return value: %TRUE if the two colors are the same.
|
||||
*/
|
||||
COGL_EXPORT gboolean
|
||||
cogl_color_equal (const void *v1, const void *v2);
|
||||
cogl_color_equal (const void *v1,
|
||||
const void *v2);
|
||||
|
||||
/**
|
||||
* cogl_color_hash:
|
||||
* @v: (type Cogl.Color): a #CoglColor
|
||||
*
|
||||
* Converts a #CoglColor to a hash value.
|
||||
*
|
||||
* This function can be passed to g_hash_table_new() as the @hash_func
|
||||
* parameter, when using `CoglColor`s as keys in a #GHashTable.
|
||||
*
|
||||
* Return value: a hash value corresponding to the color
|
||||
*/
|
||||
COGL_EXPORT
|
||||
guint cogl_color_hash (gconstpointer v);
|
||||
|
||||
/**
|
||||
* cogl_color_to_hsl:
|
||||
|
|
Loading…
Reference in a new issue