forked from AuroraMiddleware/gtk
gtk: Implement -gtk-icon-filter
This uses the new GskColorMatrixNode to implement a filter that applies to icons. It's meant to replace -gtk-icon-effect.
This commit is contained in:
parent
8973191278
commit
2645b5a7d7
@ -401,6 +401,7 @@ gtk_private_h_sources = \
|
|||||||
gtkcssdimensionvalueprivate.h \
|
gtkcssdimensionvalueprivate.h \
|
||||||
gtkcsseasevalueprivate.h \
|
gtkcsseasevalueprivate.h \
|
||||||
gtkcssenumvalueprivate.h \
|
gtkcssenumvalueprivate.h \
|
||||||
|
gtkcssfiltervalueprivate.h \
|
||||||
gtkcssgadgetprivate.h \
|
gtkcssgadgetprivate.h \
|
||||||
gtkcssiconthemevalueprivate.h \
|
gtkcssiconthemevalueprivate.h \
|
||||||
gtkcssimagebuiltinprivate.h \
|
gtkcssimagebuiltinprivate.h \
|
||||||
@ -668,6 +669,7 @@ gtk_base_c_sources = \
|
|||||||
gtkcssdimensionvalue.c \
|
gtkcssdimensionvalue.c \
|
||||||
gtkcsseasevalue.c \
|
gtkcsseasevalue.c \
|
||||||
gtkcssenumvalue.c \
|
gtkcssenumvalue.c \
|
||||||
|
gtkcssfiltervalue.c \
|
||||||
gtkcssgadget.c \
|
gtkcssgadget.c \
|
||||||
gtkcssiconthemevalue.c \
|
gtkcssiconthemevalue.c \
|
||||||
gtkcssimage.c \
|
gtkcssimage.c \
|
||||||
|
863
gtk/gtkcssfiltervalue.c
Normal file
863
gtk/gtkcssfiltervalue.c
Normal file
@ -0,0 +1,863 @@
|
|||||||
|
/* GTK - The GIMP Toolkit
|
||||||
|
* Copyright (C) 2017 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "gtkcssbgsizevalueprivate.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "gtkcssfiltervalueprivate.h"
|
||||||
|
#include "gtkcssnumbervalueprivate.h"
|
||||||
|
|
||||||
|
typedef union _GtkCssFilter GtkCssFilter;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GTK_CSS_FILTER_NONE,
|
||||||
|
GTK_CSS_FILTER_BLUR,
|
||||||
|
GTK_CSS_FILTER_BRIGHTNESS,
|
||||||
|
GTK_CSS_FILTER_CONTRAST,
|
||||||
|
GTK_CSS_FILTER_DROP_SHADOW,
|
||||||
|
GTK_CSS_FILTER_GRAYSCALE,
|
||||||
|
GTK_CSS_FILTER_HUE_ROTATE,
|
||||||
|
GTK_CSS_FILTER_INVERT,
|
||||||
|
GTK_CSS_FILTER_OPACITY,
|
||||||
|
GTK_CSS_FILTER_SATURATE,
|
||||||
|
GTK_CSS_FILTER_SEPIA
|
||||||
|
} GtkCssFilterType;
|
||||||
|
|
||||||
|
union _GtkCssFilter {
|
||||||
|
GtkCssFilterType type;
|
||||||
|
struct {
|
||||||
|
GtkCssFilterType type;
|
||||||
|
GtkCssValue *value;
|
||||||
|
} brightness, contrast, grayscale, hue_rotate, invert, opacity, saturate, sepia;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GtkCssValue {
|
||||||
|
GTK_CSS_VALUE_BASE
|
||||||
|
guint n_filters;
|
||||||
|
GtkCssFilter filters[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
static GtkCssValue * gtk_css_filter_value_alloc (guint n_values);
|
||||||
|
static gboolean gtk_css_filter_value_is_none (const GtkCssValue *value);
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_css_filter_clear (GtkCssFilter *filter)
|
||||||
|
{
|
||||||
|
switch (filter->type)
|
||||||
|
{
|
||||||
|
case GTK_CSS_FILTER_BRIGHTNESS:
|
||||||
|
_gtk_css_value_unref (filter->brightness.value);
|
||||||
|
break;
|
||||||
|
case GTK_CSS_FILTER_CONTRAST:
|
||||||
|
_gtk_css_value_unref (filter->contrast.value);
|
||||||
|
break;
|
||||||
|
case GTK_CSS_FILTER_GRAYSCALE:
|
||||||
|
_gtk_css_value_unref (filter->grayscale.value);
|
||||||
|
break;
|
||||||
|
case GTK_CSS_FILTER_HUE_ROTATE:
|
||||||
|
_gtk_css_value_unref (filter->hue_rotate.value);
|
||||||
|
break;
|
||||||
|
case GTK_CSS_FILTER_INVERT:
|
||||||
|
_gtk_css_value_unref (filter->invert.value);
|
||||||
|
break;
|
||||||
|
case GTK_CSS_FILTER_OPACITY:
|
||||||
|
_gtk_css_value_unref (filter->opacity.value);
|
||||||
|
break;
|
||||||
|
case GTK_CSS_FILTER_SATURATE:
|
||||||
|
_gtk_css_value_unref (filter->saturate.value);
|
||||||
|
break;
|
||||||
|
case GTK_CSS_FILTER_SEPIA:
|
||||||
|
_gtk_css_value_unref (filter->sepia.value);
|
||||||
|
break;
|
||||||
|
case GTK_CSS_FILTER_NONE:
|
||||||
|
case GTK_CSS_FILTER_BLUR:
|
||||||
|
case GTK_CSS_FILTER_DROP_SHADOW:
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_css_filter_init_identity (GtkCssFilter *filter,
|
||||||
|
GtkCssFilterType type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case GTK_CSS_FILTER_BRIGHTNESS:
|
||||||
|
filter->brightness.value = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
|
||||||
|
break;
|
||||||
|
case GTK_CSS_FILTER_CONTRAST:
|
||||||
|
filter->contrast.value = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
|
||||||
|
break;
|
||||||
|
case GTK_CSS_FILTER_GRAYSCALE:
|
||||||
|
filter->grayscale.value = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
|
||||||
|
break;
|
||||||
|
case GTK_CSS_FILTER_HUE_ROTATE:
|
||||||
|
filter->hue_rotate.value = _gtk_css_number_value_new (0, GTK_CSS_DEG);
|
||||||
|
break;
|
||||||
|
case GTK_CSS_FILTER_INVERT:
|
||||||
|
filter->invert.value = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
|
||||||
|
break;
|
||||||
|
case GTK_CSS_FILTER_OPACITY:
|
||||||
|
filter->opacity.value = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
|
||||||
|
break;
|
||||||
|
case GTK_CSS_FILTER_SATURATE:
|
||||||
|
filter->saturate.value = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
|
||||||
|
break;
|
||||||
|
case GTK_CSS_FILTER_SEPIA:
|
||||||
|
filter->sepia.value = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
|
||||||
|
break;
|
||||||
|
case GTK_CSS_FILTER_NONE:
|
||||||
|
case GTK_CSS_FILTER_BLUR:
|
||||||
|
case GTK_CSS_FILTER_DROP_SHADOW:
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
filter->type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define R 0.2126
|
||||||
|
#define G 0.7152
|
||||||
|
#define B 0.0722
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_css_filter_get_matrix (const GtkCssFilter *filter,
|
||||||
|
graphene_matrix_t *matrix,
|
||||||
|
graphene_vec4_t *offset)
|
||||||
|
{
|
||||||
|
double value;
|
||||||
|
|
||||||
|
switch (filter->type)
|
||||||
|
{
|
||||||
|
case GTK_CSS_FILTER_BRIGHTNESS:
|
||||||
|
value = _gtk_css_number_value_get (filter->brightness.value, 1.0);
|
||||||
|
graphene_matrix_init_scale (matrix, value, value, value);
|
||||||
|
graphene_vec4_init (offset, 0.0, 0.0, 0.0, 0.0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_CONTRAST:
|
||||||
|
value = _gtk_css_number_value_get (filter->contrast.value, 1.0);
|
||||||
|
graphene_matrix_init_scale (matrix, value, value, value);
|
||||||
|
graphene_vec4_init (offset, 0.5 - 0.5 * value, 0.5 - 0.5 * value, 0.5 - 0.5 * value, 0.0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_GRAYSCALE:
|
||||||
|
value = _gtk_css_number_value_get (filter->grayscale.value, 1.0);
|
||||||
|
graphene_matrix_init_from_float (matrix, (float[16]) {
|
||||||
|
1.0 - (1.0 - R) * value, R * value, R * value, 0.0,
|
||||||
|
G * value, 1.0 - (1.0 - G) * value, G * value, 0.0,
|
||||||
|
B * value, B * value, 1.0 - (1.0 - B) * value, 0.0,
|
||||||
|
0.0, 0.0, 0.0, 1.0
|
||||||
|
});
|
||||||
|
graphene_vec4_init (offset, 0.0, 0.0, 0.0, 0.0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_HUE_ROTATE:
|
||||||
|
{
|
||||||
|
double c, s;
|
||||||
|
value = _gtk_css_number_value_get (filter->grayscale.value, 1.0) * G_PI / 180.0;
|
||||||
|
c = cos (value);
|
||||||
|
s = sin (value);
|
||||||
|
graphene_matrix_init_from_float (matrix, (float[16]) {
|
||||||
|
0.213 + 0.787 * c - 0.213 * s,
|
||||||
|
0.213 - 0.213 * c + 0.143 * s,
|
||||||
|
0.213 - 0.213 * c - 0.787 * s,
|
||||||
|
0,
|
||||||
|
0.715 - 0.715 * c - 0.715 * s,
|
||||||
|
0.715 + 0.285 * c + 0.140 * s,
|
||||||
|
0.715 - 0.715 * c + 0.715 * s,
|
||||||
|
0,
|
||||||
|
0.072 - 0.072 * c + 0.928 * s,
|
||||||
|
0.072 - 0.072 * c - 0.283 * s,
|
||||||
|
0.072 + 0.928 * c + 0.072 * s,
|
||||||
|
0,
|
||||||
|
0, 0, 0, 1
|
||||||
|
});
|
||||||
|
graphene_vec4_init (offset, 0.0, 0.0, 0.0, 0.0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_INVERT:
|
||||||
|
value = _gtk_css_number_value_get (filter->invert.value, 1.0);
|
||||||
|
graphene_matrix_init_scale (matrix, 1.0 - 2 * value, 1.0 - 2 * value, 1.0 - 2 * value);
|
||||||
|
graphene_vec4_init (offset, value, value, value, 0.0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_OPACITY:
|
||||||
|
value = _gtk_css_number_value_get (filter->invert.value, 1.0);
|
||||||
|
graphene_matrix_init_from_float (matrix, (float[16]) {
|
||||||
|
1.0, 0.0, 0.0, 0.0,
|
||||||
|
0.0, 1.0, 0.0, 0.0,
|
||||||
|
0.0, 0.0, 1.0, 0.0,
|
||||||
|
0.0, 0.0, 0.0, value
|
||||||
|
});
|
||||||
|
graphene_vec4_init (offset, 0.0, 0.0, 0.0, 0.0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_SATURATE:
|
||||||
|
value = _gtk_css_number_value_get (filter->saturate.value, 1.0);
|
||||||
|
graphene_matrix_init_from_float (matrix, (float[16]) {
|
||||||
|
R + (1.0 - R) * value, R - R * value, R - R * value, 0.0,
|
||||||
|
G - G * value, G + (1.0 - G) * value, G - G * value, 0.0,
|
||||||
|
B - B * value, B - B * value, B + (1.0 - B) * value, 0.0,
|
||||||
|
0.0, 0.0, 0.0, 1.0
|
||||||
|
});
|
||||||
|
graphene_vec4_init (offset, 0.0, 0.0, 0.0, 0.0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_SEPIA:
|
||||||
|
value = _gtk_css_number_value_get (filter->sepia.value, 1.0);
|
||||||
|
graphene_matrix_init_from_float (matrix, (float[16]) {
|
||||||
|
1.0 - 0.607 * value, 0.349 * value, 0.272 * value, 0.0,
|
||||||
|
0.769 * value, 1.0 - 0.314 * value, 0.534 * value, 0.0,
|
||||||
|
0.189 * value, 0.168 * value, 1.0 - 0.869 * value, 0.0,
|
||||||
|
0.0, 0.0, 0.0, 1.0
|
||||||
|
});
|
||||||
|
graphene_vec4_init (offset, 0.0, 0.0, 0.0, 0.0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_NONE:
|
||||||
|
case GTK_CSS_FILTER_BLUR:
|
||||||
|
case GTK_CSS_FILTER_DROP_SHADOW:
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef R
|
||||||
|
#undef G
|
||||||
|
#undef B
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_css_filter_value_compute_matrix (const GtkCssValue *value,
|
||||||
|
graphene_matrix_t *matrix,
|
||||||
|
graphene_vec4_t *offset)
|
||||||
|
{
|
||||||
|
graphene_matrix_t m, m2;
|
||||||
|
graphene_vec4_t o, o2;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
gtk_css_filter_get_matrix (&value->filters[0], matrix, offset);
|
||||||
|
|
||||||
|
for (i = 1; i < value->n_filters; i++)
|
||||||
|
{
|
||||||
|
gtk_css_filter_get_matrix (&value->filters[i], &m, &o);
|
||||||
|
|
||||||
|
graphene_matrix_multiply (matrix, &m, &m2);
|
||||||
|
graphene_matrix_transform_vec4 (&m, offset, &o2);
|
||||||
|
|
||||||
|
graphene_matrix_init_from_matrix (matrix, &m2);
|
||||||
|
graphene_vec4_add (&o, &o2, offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_css_value_filter_free (GtkCssValue *value)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < value->n_filters; i++)
|
||||||
|
{
|
||||||
|
gtk_css_filter_clear (&value->filters[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_slice_free1 (sizeof (GtkCssValue) + sizeof (GtkCssFilter) * (value->n_filters - 1), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* returns TRUE if dest == src */
|
||||||
|
static gboolean
|
||||||
|
gtk_css_filter_compute (GtkCssFilter *dest,
|
||||||
|
GtkCssFilter *src,
|
||||||
|
guint property_id,
|
||||||
|
GtkStyleProviderPrivate *provider,
|
||||||
|
GtkCssStyle *style,
|
||||||
|
GtkCssStyle *parent_style)
|
||||||
|
{
|
||||||
|
dest->type = src->type;
|
||||||
|
|
||||||
|
switch (src->type)
|
||||||
|
{
|
||||||
|
case GTK_CSS_FILTER_BRIGHTNESS:
|
||||||
|
dest->brightness.value = _gtk_css_value_compute (src->brightness.value, property_id, provider, style, parent_style);
|
||||||
|
return dest->brightness.value == src->brightness.value;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_CONTRAST:
|
||||||
|
dest->contrast.value = _gtk_css_value_compute (src->contrast.value, property_id, provider, style, parent_style);
|
||||||
|
return dest->contrast.value == src->contrast.value;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_GRAYSCALE:
|
||||||
|
dest->grayscale.value = _gtk_css_value_compute (src->grayscale.value, property_id, provider, style, parent_style);
|
||||||
|
return dest->grayscale.value == src->grayscale.value;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_HUE_ROTATE:
|
||||||
|
dest->hue_rotate.value = _gtk_css_value_compute (src->hue_rotate.value, property_id, provider, style, parent_style);
|
||||||
|
return dest->hue_rotate.value == src->hue_rotate.value;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_INVERT:
|
||||||
|
dest->invert.value = _gtk_css_value_compute (src->invert.value, property_id, provider, style, parent_style);
|
||||||
|
return dest->invert.value == src->invert.value;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_OPACITY:
|
||||||
|
dest->opacity.value = _gtk_css_value_compute (src->opacity.value, property_id, provider, style, parent_style);
|
||||||
|
return dest->opacity.value == src->opacity.value;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_SATURATE:
|
||||||
|
dest->saturate.value = _gtk_css_value_compute (src->saturate.value, property_id, provider, style, parent_style);
|
||||||
|
return dest->saturate.value == src->saturate.value;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_SEPIA:
|
||||||
|
dest->sepia.value = _gtk_css_value_compute (src->sepia.value, property_id, provider, style, parent_style);
|
||||||
|
return dest->sepia.value == src->sepia.value;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_NONE:
|
||||||
|
case GTK_CSS_FILTER_BLUR:
|
||||||
|
case GTK_CSS_FILTER_DROP_SHADOW:
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkCssValue *
|
||||||
|
gtk_css_value_filter_compute (GtkCssValue *value,
|
||||||
|
guint property_id,
|
||||||
|
GtkStyleProviderPrivate *provider,
|
||||||
|
GtkCssStyle *style,
|
||||||
|
GtkCssStyle *parent_style)
|
||||||
|
{
|
||||||
|
GtkCssValue *result;
|
||||||
|
gboolean changes;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
/* Special case the 99% case of "none" */
|
||||||
|
if (gtk_css_filter_value_is_none (value))
|
||||||
|
return _gtk_css_value_ref (value);
|
||||||
|
|
||||||
|
changes = FALSE;
|
||||||
|
result = gtk_css_filter_value_alloc (value->n_filters);
|
||||||
|
|
||||||
|
for (i = 0; i < value->n_filters; i++)
|
||||||
|
{
|
||||||
|
changes |= !gtk_css_filter_compute (&result->filters[i],
|
||||||
|
&value->filters[i],
|
||||||
|
property_id,
|
||||||
|
provider,
|
||||||
|
style,
|
||||||
|
parent_style);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!changes)
|
||||||
|
{
|
||||||
|
_gtk_css_value_unref (result);
|
||||||
|
result = _gtk_css_value_ref (value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gtk_css_filter_equal (const GtkCssFilter *filter1,
|
||||||
|
const GtkCssFilter *filter2)
|
||||||
|
{
|
||||||
|
if (filter1->type != filter2->type)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
switch (filter1->type)
|
||||||
|
{
|
||||||
|
case GTK_CSS_FILTER_BRIGHTNESS:
|
||||||
|
return _gtk_css_value_equal (filter1->brightness.value, filter2->brightness.value);
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_CONTRAST:
|
||||||
|
return _gtk_css_value_equal (filter1->contrast.value, filter2->contrast.value);
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_GRAYSCALE:
|
||||||
|
return _gtk_css_value_equal (filter1->grayscale.value, filter2->grayscale.value);
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_HUE_ROTATE:
|
||||||
|
return _gtk_css_value_equal (filter1->hue_rotate.value, filter2->hue_rotate.value);
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_INVERT:
|
||||||
|
return _gtk_css_value_equal (filter1->invert.value, filter2->invert.value);
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_OPACITY:
|
||||||
|
return _gtk_css_value_equal (filter1->opacity.value, filter2->opacity.value);
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_SATURATE:
|
||||||
|
return _gtk_css_value_equal (filter1->saturate.value, filter2->saturate.value);
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_SEPIA:
|
||||||
|
return _gtk_css_value_equal (filter1->sepia.value, filter2->sepia.value);
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_NONE:
|
||||||
|
case GTK_CSS_FILTER_BLUR:
|
||||||
|
case GTK_CSS_FILTER_DROP_SHADOW:
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gtk_css_value_filter_equal (const GtkCssValue *value1,
|
||||||
|
const GtkCssValue *value2)
|
||||||
|
{
|
||||||
|
const GtkCssValue *larger;
|
||||||
|
guint i, n;
|
||||||
|
|
||||||
|
n = MIN (value1->n_filters, value2->n_filters);
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
if (!gtk_css_filter_equal (&value1->filters[i], &value2->filters[i]))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
larger = value1->n_filters > value2->n_filters ? value1 : value2;
|
||||||
|
|
||||||
|
for (; i < larger->n_filters; i++)
|
||||||
|
{
|
||||||
|
GtkCssFilter filter;
|
||||||
|
|
||||||
|
gtk_css_filter_init_identity (&filter, larger->filters[i].type);
|
||||||
|
|
||||||
|
if (!gtk_css_filter_equal (&larger->filters[i], &filter))
|
||||||
|
{
|
||||||
|
gtk_css_filter_clear (&filter);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_css_filter_clear (&filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_css_filter_transition (GtkCssFilter *result,
|
||||||
|
const GtkCssFilter *start,
|
||||||
|
const GtkCssFilter *end,
|
||||||
|
guint property_id,
|
||||||
|
double progress)
|
||||||
|
{
|
||||||
|
result->type = start->type;
|
||||||
|
|
||||||
|
switch (start->type)
|
||||||
|
{
|
||||||
|
case GTK_CSS_FILTER_BRIGHTNESS:
|
||||||
|
result->brightness.value = _gtk_css_value_transition (start->brightness.value, end->brightness.value, property_id, progress);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_CONTRAST:
|
||||||
|
result->contrast.value = _gtk_css_value_transition (start->contrast.value, end->contrast.value, property_id, progress);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_GRAYSCALE:
|
||||||
|
result->grayscale.value = _gtk_css_value_transition (start->grayscale.value, end->grayscale.value, property_id, progress);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_HUE_ROTATE:
|
||||||
|
result->hue_rotate.value = _gtk_css_value_transition (start->hue_rotate.value, end->hue_rotate.value, property_id, progress);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_INVERT:
|
||||||
|
result->invert.value = _gtk_css_value_transition (start->invert.value, end->invert.value, property_id, progress);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_OPACITY:
|
||||||
|
result->opacity.value = _gtk_css_value_transition (start->opacity.value, end->opacity.value, property_id, progress);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_SATURATE:
|
||||||
|
result->saturate.value = _gtk_css_value_transition (start->saturate.value, end->saturate.value, property_id, progress);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_SEPIA:
|
||||||
|
result->sepia.value = _gtk_css_value_transition (start->sepia.value, end->sepia.value, property_id, progress);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_NONE:
|
||||||
|
case GTK_CSS_FILTER_BLUR:
|
||||||
|
case GTK_CSS_FILTER_DROP_SHADOW:
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkCssValue *
|
||||||
|
gtk_css_value_filter_transition (GtkCssValue *start,
|
||||||
|
GtkCssValue *end,
|
||||||
|
guint property_id,
|
||||||
|
double progress)
|
||||||
|
{
|
||||||
|
GtkCssValue *result;
|
||||||
|
guint i, n;
|
||||||
|
|
||||||
|
if (gtk_css_filter_value_is_none (start))
|
||||||
|
{
|
||||||
|
if (gtk_css_filter_value_is_none (end))
|
||||||
|
return _gtk_css_value_ref (start);
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
}
|
||||||
|
else if (gtk_css_filter_value_is_none (end))
|
||||||
|
{
|
||||||
|
n = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
n = MIN (start->n_filters, end->n_filters);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check filters are compatible. If not, transition between
|
||||||
|
* their result matrices.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
if (start->filters[i].type != end->filters[i].type)
|
||||||
|
{
|
||||||
|
/* XXX: can we improve this? */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = gtk_css_filter_value_alloc (MAX (start->n_filters, end->n_filters));
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
gtk_css_filter_transition (&result->filters[i],
|
||||||
|
&start->filters[i],
|
||||||
|
&end->filters[i],
|
||||||
|
property_id,
|
||||||
|
progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < start->n_filters; i++)
|
||||||
|
{
|
||||||
|
GtkCssFilter filter;
|
||||||
|
|
||||||
|
gtk_css_filter_init_identity (&filter, start->filters[i].type);
|
||||||
|
gtk_css_filter_transition (&result->filters[i],
|
||||||
|
&start->filters[i],
|
||||||
|
&filter,
|
||||||
|
property_id,
|
||||||
|
progress);
|
||||||
|
gtk_css_filter_clear (&filter);
|
||||||
|
}
|
||||||
|
for (; i < end->n_filters; i++)
|
||||||
|
{
|
||||||
|
GtkCssFilter filter;
|
||||||
|
|
||||||
|
gtk_css_filter_init_identity (&filter, end->filters[i].type);
|
||||||
|
gtk_css_filter_transition (&result->filters[i],
|
||||||
|
&filter,
|
||||||
|
&end->filters[i],
|
||||||
|
property_id,
|
||||||
|
progress);
|
||||||
|
gtk_css_filter_clear (&filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert (i == MAX (start->n_filters, end->n_filters));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_css_filter_print (const GtkCssFilter *filter,
|
||||||
|
GString *string)
|
||||||
|
{
|
||||||
|
switch (filter->type)
|
||||||
|
{
|
||||||
|
case GTK_CSS_FILTER_BRIGHTNESS:
|
||||||
|
g_string_append (string, "brightness(");
|
||||||
|
_gtk_css_value_print (filter->brightness.value, string);
|
||||||
|
g_string_append (string, ")");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_CONTRAST:
|
||||||
|
g_string_append (string, "contrast(");
|
||||||
|
_gtk_css_value_print (filter->contrast.value, string);
|
||||||
|
g_string_append (string, ")");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_GRAYSCALE:
|
||||||
|
g_string_append (string, "grayscale(");
|
||||||
|
_gtk_css_value_print (filter->grayscale.value, string);
|
||||||
|
g_string_append (string, ")");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_HUE_ROTATE:
|
||||||
|
g_string_append (string, "hue-rotate(");
|
||||||
|
_gtk_css_value_print (filter->hue_rotate.value, string);
|
||||||
|
g_string_append (string, ")");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_INVERT:
|
||||||
|
g_string_append (string, "invert(");
|
||||||
|
_gtk_css_value_print (filter->invert.value, string);
|
||||||
|
g_string_append (string, ")");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_OPACITY:
|
||||||
|
g_string_append (string, "opacity(");
|
||||||
|
_gtk_css_value_print (filter->opacity.value, string);
|
||||||
|
g_string_append (string, ")");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_SATURATE:
|
||||||
|
g_string_append (string, "saturate(");
|
||||||
|
_gtk_css_value_print (filter->saturate.value, string);
|
||||||
|
g_string_append (string, ")");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_SEPIA:
|
||||||
|
g_string_append (string, "sepia(");
|
||||||
|
_gtk_css_value_print (filter->sepia.value, string);
|
||||||
|
g_string_append (string, ")");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_CSS_FILTER_NONE:
|
||||||
|
case GTK_CSS_FILTER_BLUR:
|
||||||
|
case GTK_CSS_FILTER_DROP_SHADOW:
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_css_value_filter_print (const GtkCssValue *value,
|
||||||
|
GString *string)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
if (gtk_css_filter_value_is_none (value))
|
||||||
|
{
|
||||||
|
g_string_append (string, "none");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < value->n_filters; i++)
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
g_string_append_c (string, ' ');
|
||||||
|
|
||||||
|
gtk_css_filter_print (&value->filters[i], string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const GtkCssValueClass GTK_CSS_VALUE_FILTER = {
|
||||||
|
gtk_css_value_filter_free,
|
||||||
|
gtk_css_value_filter_compute,
|
||||||
|
gtk_css_value_filter_equal,
|
||||||
|
gtk_css_value_filter_transition,
|
||||||
|
gtk_css_value_filter_print
|
||||||
|
};
|
||||||
|
|
||||||
|
static GtkCssValue none_singleton = { >K_CSS_VALUE_FILTER, 1, 0, { { GTK_CSS_FILTER_NONE } } };
|
||||||
|
|
||||||
|
static GtkCssValue *
|
||||||
|
gtk_css_filter_value_alloc (guint n_filters)
|
||||||
|
{
|
||||||
|
GtkCssValue *result;
|
||||||
|
|
||||||
|
g_return_val_if_fail (n_filters > 0, NULL);
|
||||||
|
|
||||||
|
result = _gtk_css_value_alloc (>K_CSS_VALUE_FILTER, sizeof (GtkCssValue) + sizeof (GtkCssFilter) * (n_filters - 1));
|
||||||
|
result->n_filters = n_filters;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkCssValue *
|
||||||
|
gtk_css_filter_value_new_none (void)
|
||||||
|
{
|
||||||
|
return _gtk_css_value_ref (&none_singleton);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gtk_css_filter_value_is_none (const GtkCssValue *value)
|
||||||
|
{
|
||||||
|
return value->n_filters == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gtk_css_filter_parse (GtkCssFilter *filter,
|
||||||
|
GtkCssParser *parser)
|
||||||
|
{
|
||||||
|
if (_gtk_css_parser_try (parser, "brightness(", TRUE))
|
||||||
|
{
|
||||||
|
filter->type = GTK_CSS_FILTER_BRIGHTNESS;
|
||||||
|
|
||||||
|
filter->brightness.value = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_PARSE_PERCENT);
|
||||||
|
if (filter->brightness.value == NULL)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else if (_gtk_css_parser_try (parser, "contrast(", TRUE))
|
||||||
|
{
|
||||||
|
filter->type = GTK_CSS_FILTER_CONTRAST;
|
||||||
|
|
||||||
|
filter->contrast.value = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_PARSE_PERCENT);
|
||||||
|
if (filter->contrast.value == NULL)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else if (_gtk_css_parser_try (parser, "grayscale(", TRUE))
|
||||||
|
{
|
||||||
|
filter->type = GTK_CSS_FILTER_GRAYSCALE;
|
||||||
|
|
||||||
|
filter->grayscale.value = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_PARSE_PERCENT);
|
||||||
|
if (filter->grayscale.value == NULL)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else if (_gtk_css_parser_try (parser, "hue-rotate(", TRUE))
|
||||||
|
{
|
||||||
|
filter->type = GTK_CSS_FILTER_HUE_ROTATE;
|
||||||
|
|
||||||
|
filter->hue_rotate.value = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_ANGLE);
|
||||||
|
if (filter->hue_rotate.value == NULL)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else if (_gtk_css_parser_try (parser, "invert(", TRUE))
|
||||||
|
{
|
||||||
|
filter->type = GTK_CSS_FILTER_INVERT;
|
||||||
|
|
||||||
|
filter->invert.value = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_PARSE_PERCENT);
|
||||||
|
if (filter->invert.value == NULL)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else if (_gtk_css_parser_try (parser, "opacity(", TRUE))
|
||||||
|
{
|
||||||
|
filter->type = GTK_CSS_FILTER_OPACITY;
|
||||||
|
|
||||||
|
filter->opacity.value = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_PARSE_PERCENT);
|
||||||
|
if (filter->opacity.value == NULL)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else if (_gtk_css_parser_try (parser, "saturate(", TRUE))
|
||||||
|
{
|
||||||
|
filter->type = GTK_CSS_FILTER_SATURATE;
|
||||||
|
|
||||||
|
filter->saturate.value = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_PARSE_PERCENT);
|
||||||
|
if (filter->saturate.value == NULL)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else if (_gtk_css_parser_try (parser, "sepia(", TRUE))
|
||||||
|
{
|
||||||
|
filter->type = GTK_CSS_FILTER_SEPIA;
|
||||||
|
|
||||||
|
filter->sepia.value = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_PARSE_PERCENT);
|
||||||
|
if (filter->sepia.value == NULL)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_gtk_css_parser_error (parser, "unknown syntax for filter");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_gtk_css_parser_try (parser, ")", TRUE))
|
||||||
|
{
|
||||||
|
gtk_css_filter_clear (filter);
|
||||||
|
_gtk_css_parser_error (parser, "Expected closing ')'");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkCssValue *
|
||||||
|
gtk_css_filter_value_parse (GtkCssParser *parser)
|
||||||
|
{
|
||||||
|
GtkCssValue *value;
|
||||||
|
GArray *array;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
if (_gtk_css_parser_try (parser, "none", TRUE))
|
||||||
|
return gtk_css_filter_value_new_none ();
|
||||||
|
|
||||||
|
array = g_array_new (FALSE, FALSE, sizeof (GtkCssFilter));
|
||||||
|
|
||||||
|
do {
|
||||||
|
GtkCssFilter filter;
|
||||||
|
|
||||||
|
if (!gtk_css_filter_parse (&filter, parser))
|
||||||
|
{
|
||||||
|
for (i = 0; i < array->len; i++)
|
||||||
|
{
|
||||||
|
gtk_css_filter_clear (&g_array_index (array, GtkCssFilter, i));
|
||||||
|
}
|
||||||
|
g_array_free (array, TRUE);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
g_array_append_val (array, filter);
|
||||||
|
} while (!_gtk_css_parser_begins_with (parser, ';'));
|
||||||
|
|
||||||
|
value = gtk_css_filter_value_alloc (array->len);
|
||||||
|
memcpy (value->filters, array->data, sizeof (GtkCssFilter) * array->len);
|
||||||
|
|
||||||
|
g_array_free (array, TRUE);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gtk_css_filter_value_get_color_matrix (const GtkCssValue *filter,
|
||||||
|
graphene_matrix_t *matrix,
|
||||||
|
graphene_vec4_t *offset)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (filter->class == >K_CSS_VALUE_FILTER, FALSE);
|
||||||
|
g_return_val_if_fail (matrix != NULL, FALSE);
|
||||||
|
|
||||||
|
gtk_css_filter_value_compute_matrix (filter, matrix, offset);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_css_filter_value_push_snapshot (const GtkCssValue *filter,
|
||||||
|
GtkSnapshot *snapshot)
|
||||||
|
{
|
||||||
|
graphene_matrix_t matrix;
|
||||||
|
graphene_vec4_t offset;
|
||||||
|
|
||||||
|
if (gtk_css_filter_value_is_none (filter))
|
||||||
|
return;
|
||||||
|
|
||||||
|
gtk_css_filter_value_get_color_matrix (filter, &matrix, &offset);
|
||||||
|
|
||||||
|
gtk_snapshot_push_color_matrix (snapshot,
|
||||||
|
&matrix,
|
||||||
|
&offset,
|
||||||
|
"IconFilter<%u>", filter->n_filters);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_css_filter_value_pop_snapshot (const GtkCssValue *filter,
|
||||||
|
GtkSnapshot *snapshot)
|
||||||
|
{
|
||||||
|
if (gtk_css_filter_value_is_none (filter))
|
||||||
|
return;
|
||||||
|
|
||||||
|
gtk_snapshot_pop_and_append (snapshot);
|
||||||
|
}
|
42
gtk/gtkcssfiltervalueprivate.h
Normal file
42
gtk/gtkcssfiltervalueprivate.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2017 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.1 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/>.
|
||||||
|
*
|
||||||
|
* Authors: Benjamin Otte <otte@gnome.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GTK_CSS_FILTER_VALUE_PRIVATE_H__
|
||||||
|
#define __GTK_CSS_FILTER_VALUE_PRIVATE_H__
|
||||||
|
|
||||||
|
#include "gtkcssparserprivate.h"
|
||||||
|
#include "gtkcssvalueprivate.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
GtkCssValue * gtk_css_filter_value_new_none (void);
|
||||||
|
GtkCssValue * gtk_css_filter_value_parse (GtkCssParser *parser);
|
||||||
|
|
||||||
|
gboolean gtk_css_filter_value_get_color_matrix (const GtkCssValue *filter,
|
||||||
|
graphene_matrix_t *matrix,
|
||||||
|
graphene_vec4_t *offset);
|
||||||
|
|
||||||
|
void gtk_css_filter_value_push_snapshot (const GtkCssValue *filter,
|
||||||
|
GtkSnapshot *snapshot);
|
||||||
|
void gtk_css_filter_value_pop_snapshot (const GtkCssValue *filter,
|
||||||
|
GtkSnapshot *snapshot);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GTK_CSS_FILTER_VALUE_PRIVATE_H__ */
|
@ -44,6 +44,7 @@
|
|||||||
#include "gtkcsscolorvalueprivate.h"
|
#include "gtkcsscolorvalueprivate.h"
|
||||||
#include "gtkcsscornervalueprivate.h"
|
#include "gtkcsscornervalueprivate.h"
|
||||||
#include "gtkcsseasevalueprivate.h"
|
#include "gtkcsseasevalueprivate.h"
|
||||||
|
#include "gtkcssfiltervalueprivate.h"
|
||||||
#include "gtkcssiconthemevalueprivate.h"
|
#include "gtkcssiconthemevalueprivate.h"
|
||||||
#include "gtkcssimageprivate.h"
|
#include "gtkcssimageprivate.h"
|
||||||
#include "gtkcssimagebuiltinprivate.h"
|
#include "gtkcssimagebuiltinprivate.h"
|
||||||
@ -562,6 +563,13 @@ transform_value_parse (GtkCssStyleProperty *property,
|
|||||||
return _gtk_css_transform_value_parse (parser);
|
return _gtk_css_transform_value_parse (parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GtkCssValue *
|
||||||
|
filter_value_parse (GtkCssStyleProperty *property,
|
||||||
|
GtkCssParser *parser)
|
||||||
|
{
|
||||||
|
return gtk_css_filter_value_parse (parser);
|
||||||
|
}
|
||||||
|
|
||||||
static GtkCssValue *
|
static GtkCssValue *
|
||||||
border_spacing_value_parse (GtkCssStyleProperty *property,
|
border_spacing_value_parse (GtkCssStyleProperty *property,
|
||||||
GtkCssParser *parser)
|
GtkCssParser *parser)
|
||||||
@ -1454,6 +1462,14 @@ _gtk_css_style_property_init_properties (void)
|
|||||||
transform_value_parse,
|
transform_value_parse,
|
||||||
NULL,
|
NULL,
|
||||||
_gtk_css_transform_value_new_none ());
|
_gtk_css_transform_value_new_none ());
|
||||||
|
gtk_css_style_property_register ("-gtk-icon-filter",
|
||||||
|
GTK_CSS_PROPERTY_ICON_FILTER,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
GTK_STYLE_PROPERTY_ANIMATED,
|
||||||
|
GTK_CSS_AFFECTS_ICON | GTK_CSS_AFFECTS_SYMBOLIC_ICON | GTK_CSS_AFFECTS_CLIP,
|
||||||
|
filter_value_parse,
|
||||||
|
NULL,
|
||||||
|
gtk_css_filter_value_new_none ());
|
||||||
|
|
||||||
gtk_css_style_property_register ("border-spacing",
|
gtk_css_style_property_register ("border-spacing",
|
||||||
GTK_CSS_PROPERTY_BORDER_SPACING,
|
GTK_CSS_PROPERTY_BORDER_SPACING,
|
||||||
|
@ -208,6 +208,7 @@ enum { /*< skip >*/
|
|||||||
GTK_CSS_PROPERTY_ICON_SHADOW,
|
GTK_CSS_PROPERTY_ICON_SHADOW,
|
||||||
GTK_CSS_PROPERTY_ICON_STYLE,
|
GTK_CSS_PROPERTY_ICON_STYLE,
|
||||||
GTK_CSS_PROPERTY_ICON_TRANSFORM,
|
GTK_CSS_PROPERTY_ICON_TRANSFORM,
|
||||||
|
GTK_CSS_PROPERTY_ICON_FILTER,
|
||||||
GTK_CSS_PROPERTY_BORDER_SPACING,
|
GTK_CSS_PROPERTY_BORDER_SPACING,
|
||||||
GTK_CSS_PROPERTY_MIN_WIDTH,
|
GTK_CSS_PROPERTY_MIN_WIDTH,
|
||||||
GTK_CSS_PROPERTY_MIN_HEIGHT,
|
GTK_CSS_PROPERTY_MIN_HEIGHT,
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "gtkrendericonprivate.h"
|
#include "gtkrendericonprivate.h"
|
||||||
|
|
||||||
|
#include "gtkcssfiltervalueprivate.h"
|
||||||
#include "gtkcssimagebuiltinprivate.h"
|
#include "gtkcssimagebuiltinprivate.h"
|
||||||
#include "gtkcssimagevalueprivate.h"
|
#include "gtkcssimagevalueprivate.h"
|
||||||
#include "gtkcssshadowsvalueprivate.h"
|
#include "gtkcssshadowsvalueprivate.h"
|
||||||
@ -95,7 +96,7 @@ gtk_css_style_snapshot_icon (GtkCssStyle *style,
|
|||||||
double height,
|
double height,
|
||||||
GtkCssImageBuiltinType builtin_type)
|
GtkCssImageBuiltinType builtin_type)
|
||||||
{
|
{
|
||||||
const GtkCssValue *shadows_value, *transform;
|
const GtkCssValue *shadows_value, *transform_value, *filter_value;
|
||||||
graphene_matrix_t transform_matrix;
|
graphene_matrix_t transform_matrix;
|
||||||
GtkCssImage *image;
|
GtkCssImage *image;
|
||||||
GskShadow *shadows;
|
GskShadow *shadows;
|
||||||
@ -109,11 +110,14 @@ gtk_css_style_snapshot_icon (GtkCssStyle *style,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
shadows_value = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_SHADOW);
|
shadows_value = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_SHADOW);
|
||||||
transform = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_TRANSFORM);
|
transform_value = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_TRANSFORM);
|
||||||
|
filter_value = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_FILTER);
|
||||||
|
|
||||||
if (!gtk_css_transform_value_get_matrix (transform, &transform_matrix))
|
if (!gtk_css_transform_value_get_matrix (transform_value, &transform_matrix))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
gtk_css_filter_value_push_snapshot (filter_value, snapshot);
|
||||||
|
|
||||||
shadows = gtk_css_shadows_value_get_shadows (shadows_value, &n_shadows);
|
shadows = gtk_css_shadows_value_get_shadows (shadows_value, &n_shadows);
|
||||||
if (shadows)
|
if (shadows)
|
||||||
gtk_snapshot_push_shadow (snapshot, shadows, n_shadows, "IconShadow<%zu>", n_shadows);
|
gtk_snapshot_push_shadow (snapshot, shadows, n_shadows, "IconShadow<%zu>", n_shadows);
|
||||||
@ -144,6 +148,8 @@ gtk_css_style_snapshot_icon (GtkCssStyle *style,
|
|||||||
gtk_snapshot_pop_and_append (snapshot);
|
gtk_snapshot_pop_and_append (snapshot);
|
||||||
g_free (shadows);
|
g_free (shadows);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gtk_css_filter_value_pop_snapshot (filter_value, snapshot);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -266,7 +272,7 @@ gtk_css_style_snapshot_icon_texture (GtkCssStyle *style,
|
|||||||
GskTexture *texture,
|
GskTexture *texture,
|
||||||
double texture_scale)
|
double texture_scale)
|
||||||
{
|
{
|
||||||
const GtkCssValue *shadows_value, *transform;
|
const GtkCssValue *shadows_value, *transform_value, *filter_value;
|
||||||
graphene_matrix_t transform_matrix;
|
graphene_matrix_t transform_matrix;
|
||||||
graphene_rect_t bounds;
|
graphene_rect_t bounds;
|
||||||
double width, height;
|
double width, height;
|
||||||
@ -279,13 +285,16 @@ gtk_css_style_snapshot_icon_texture (GtkCssStyle *style,
|
|||||||
g_return_if_fail (texture_scale > 0);
|
g_return_if_fail (texture_scale > 0);
|
||||||
|
|
||||||
shadows_value = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_SHADOW);
|
shadows_value = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_SHADOW);
|
||||||
transform = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_TRANSFORM);
|
transform_value = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_TRANSFORM);
|
||||||
|
filter_value = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_FILTER);
|
||||||
width = gsk_texture_get_width (texture) / texture_scale;
|
width = gsk_texture_get_width (texture) / texture_scale;
|
||||||
height = gsk_texture_get_height (texture) / texture_scale;
|
height = gsk_texture_get_height (texture) / texture_scale;
|
||||||
|
|
||||||
if (!gtk_css_transform_value_get_matrix (transform, &transform_matrix))
|
if (!gtk_css_transform_value_get_matrix (transform_value, &transform_matrix))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
gtk_css_filter_value_push_snapshot (filter_value, snapshot);
|
||||||
|
|
||||||
shadows = gtk_css_shadows_value_get_shadows (shadows_value, &n_shadows);
|
shadows = gtk_css_shadows_value_get_shadows (shadows_value, &n_shadows);
|
||||||
if (shadows)
|
if (shadows)
|
||||||
gtk_snapshot_push_shadow (snapshot, shadows, n_shadows, "IconShadow<%zu>", n_shadows);
|
gtk_snapshot_push_shadow (snapshot, shadows, n_shadows, "IconShadow<%zu>", n_shadows);
|
||||||
@ -321,4 +330,6 @@ gtk_css_style_snapshot_icon_texture (GtkCssStyle *style,
|
|||||||
gtk_snapshot_pop_and_append (snapshot);
|
gtk_snapshot_pop_and_append (snapshot);
|
||||||
g_free (shadows);
|
g_free (shadows);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gtk_css_filter_value_pop_snapshot (filter_value, snapshot);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user