summaryrefslogtreecommitdiff
path: root/gtk
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2012-04-04 16:15:41 +0200
committerBenjamin Otte <otte@redhat.com>2012-04-17 08:59:18 +0200
commit56f79fecce885e05b7fe1677a70b98c64ea4a85c (patch)
tree7b2e19ed13500e3c7075873a0326b3b29e510bf8 /gtk
parentcfc64627304916e1a1848230dbb426e7dc22251f (diff)
downloadgtk+-56f79fecce885e05b7fe1677a70b98c64ea4a85c.tar.gz
cssvalue: Add a border value
.. and parse border-image-slice with it.
Diffstat (limited to 'gtk')
-rw-r--r--gtk/Makefile.am2
-rw-r--r--gtk/gtkborderimage.c12
-rw-r--r--gtk/gtkborderimageprivate.h2
-rw-r--r--gtk/gtkcssbordervalue.c235
-rw-r--r--gtk/gtkcssbordervalueprivate.h48
-rw-r--r--gtk/gtkcssshorthandpropertyimpl.c16
-rw-r--r--gtk/gtkcssstylepropertyimpl.c75
-rw-r--r--gtk/gtkcssvalue.c13
-rw-r--r--gtk/gtkcssvalueprivate.h2
9 files changed, 372 insertions, 33 deletions
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 01ea4cac1c..062b99916b 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -425,6 +425,7 @@ gtk_private_h_sources = \
gtkcontainerprivate.h \
gtkcssarrayvalueprivate.h \
gtkcssbgsizevalueprivate.h \
+ gtkcssbordervalueprivate.h \
gtkcsscomputedvaluesprivate.h \
gtkcsscornervalueprivate.h \
gtkcsscustompropertyprivate.h \
@@ -638,6 +639,7 @@ gtk_base_c_sources = \
gtkcontainer.c \
gtkcssarrayvalue.c \
gtkcssbgsizevalue.c \
+ gtkcssbordervalue.c \
gtkcsscomputedvalues.c \
gtkcsscornervalue.c \
gtkcsscustomproperty.c \
diff --git a/gtk/gtkborderimage.c b/gtk/gtkborderimage.c
index 934786075c..f75d7e0e4e 100644
--- a/gtk/gtkborderimage.c
+++ b/gtk/gtkborderimage.c
@@ -25,7 +25,9 @@
#include <math.h>
#include "gtkborderimageprivate.h"
+#include "gtkcssbordervalueprivate.h"
#include "gtkcssimagevalueprivate.h"
+#include "gtkcssnumbervalueprivate.h"
#include "gtkcssrepeatvalueprivate.h"
#include "gtkstylepropertiesprivate.h"
#include "gtkthemingengineprivate.h"
@@ -45,7 +47,7 @@ _gtk_border_image_init (GtkBorderImage *image,
if (image->source == NULL)
return FALSE;
- image->slice = *(GtkBorder *) _gtk_css_value_get_boxed (_gtk_theming_engine_peek_property (engine, GTK_CSS_PROPERTY_BORDER_IMAGE_SLICE));
+ image->slice = _gtk_theming_engine_peek_property (engine, GTK_CSS_PROPERTY_BORDER_IMAGE_SLICE);
width = _gtk_css_value_get_boxed (_gtk_theming_engine_peek_property (engine, GTK_CSS_PROPERTY_BORDER_IMAGE_WIDTH));
if (width)
{
@@ -254,12 +256,12 @@ _gtk_border_image_render (GtkBorderImage *image,
gtk_border_image_compute_slice_size (horizontal_slice,
source_width,
- image->slice.left,
- image->slice.right);
+ _gtk_css_number_value_get (_gtk_css_border_value_get_left (image->slice), source_width),
+ _gtk_css_number_value_get (_gtk_css_border_value_get_right (image->slice), source_width));
gtk_border_image_compute_slice_size (vertical_slice,
source_height,
- image->slice.top,
- image->slice.bottom);
+ _gtk_css_number_value_get (_gtk_css_border_value_get_top (image->slice), source_height),
+ _gtk_css_number_value_get (_gtk_css_border_value_get_bottom (image->slice), source_height));
gtk_border_image_compute_border_size (horizontal_border,
x,
width,
diff --git a/gtk/gtkborderimageprivate.h b/gtk/gtkborderimageprivate.h
index c77de04d97..f57149ccfe 100644
--- a/gtk/gtkborderimageprivate.h
+++ b/gtk/gtkborderimageprivate.h
@@ -34,7 +34,7 @@ typedef struct _GtkBorderImage GtkBorderImage;
struct _GtkBorderImage {
GtkCssImage *source;
- GtkBorder slice;
+ GtkCssValue *slice;
gboolean has_width;
GtkBorder width;
GtkCssValue *repeat;
diff --git a/gtk/gtkcssbordervalue.c b/gtk/gtkcssbordervalue.c
new file mode 100644
index 0000000000..92ae98a9c6
--- /dev/null
+++ b/gtk/gtkcssbordervalue.c
@@ -0,0 +1,235 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2011 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 "gtkcssbordervalueprivate.h"
+
+#include "gtkcssnumbervalueprivate.h"
+
+struct _GtkCssValue {
+ GTK_CSS_VALUE_BASE
+ guint fill :1;
+ GtkCssValue *values[4];
+};
+
+static void
+gtk_css_value_border_free (GtkCssValue *value)
+{
+ guint i;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (value->values[i])
+ _gtk_css_value_unref (value->values[i]);
+ }
+
+ g_slice_free (GtkCssValue, value);
+}
+
+static gboolean
+gtk_css_value_border_equal (const GtkCssValue *value1,
+ const GtkCssValue *value2)
+{
+ guint i;
+
+ if (value1->fill != value2->fill)
+ return FALSE;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (!_gtk_css_value_equal0 (value1->values[i], value2->values[i]))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static GtkCssValue *
+gtk_css_value_border_transition (GtkCssValue *start,
+ GtkCssValue *end,
+ double progress)
+{
+ return NULL;
+}
+
+static void
+gtk_css_value_border_print (const GtkCssValue *value,
+ GString *string)
+{
+ guint i, n;
+
+ if (!_gtk_css_value_equal0 (value->values[GTK_CSS_RIGHT], value->values[GTK_CSS_LEFT]))
+ n = 4;
+ else if (!_gtk_css_value_equal0 (value->values[GTK_CSS_TOP], value->values[GTK_CSS_BOTTOM]))
+ n = 3;
+ else if (!_gtk_css_value_equal0 (value->values[GTK_CSS_TOP], value->values[GTK_CSS_RIGHT]))
+ n = 2;
+ else
+ n = 1;
+
+ for (i = 0; i < n; i++)
+ {
+ if (i > 0)
+ g_string_append_c (string, ' ');
+
+ if (value->values[i] == NULL)
+ g_string_append (string, "auto");
+ else
+ _gtk_css_value_print (value->values[i], string);
+ }
+
+ if (value->fill)
+ g_string_append (string, " fill");
+}
+
+static const GtkCssValueClass GTK_CSS_VALUE_BORDER = {
+ gtk_css_value_border_free,
+ gtk_css_value_border_equal,
+ gtk_css_value_border_transition,
+ gtk_css_value_border_print
+};
+
+GtkCssValue *
+_gtk_css_border_value_new (GtkCssValue *top,
+ GtkCssValue *right,
+ GtkCssValue *bottom,
+ GtkCssValue *left)
+{
+ GtkCssValue *result;
+
+ result = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_BORDER);
+ result->values[GTK_CSS_TOP] = top;
+ result->values[GTK_CSS_RIGHT] = right;
+ result->values[GTK_CSS_BOTTOM] = bottom;
+ result->values[GTK_CSS_LEFT] = left;
+
+ return result;
+}
+
+GtkCssValue *
+_gtk_css_border_value_parse (GtkCssParser *parser,
+ GtkCssNumberParseFlags flags,
+ gboolean allow_auto,
+ gboolean allow_fill)
+{
+ GtkCssValue *result;
+ guint i;
+
+ result = _gtk_css_border_value_new (NULL, NULL, NULL, NULL);
+
+ if (allow_fill)
+ result->fill = _gtk_css_parser_try (parser, "fill", TRUE);
+
+ for (i = 0; i < 4; i++)
+ {
+ if (allow_auto && _gtk_css_parser_try (parser, "auto", TRUE))
+ continue;
+
+ if (!_gtk_css_parser_has_number (parser))
+ break;
+
+ result->values[i] = _gtk_css_number_value_parse (parser, flags);
+ if (result->values[i] == NULL)
+ {
+ _gtk_css_value_unref (result);
+ return NULL;
+ }
+ }
+
+ if (i == 0)
+ {
+ _gtk_css_parser_error (parser, "Expected a number");
+ _gtk_css_value_unref (result);
+ return NULL;
+ }
+
+ if (allow_fill && !result->fill)
+ result->fill = _gtk_css_parser_try (parser, "fill", TRUE);
+
+ for (; i < 4; i++)
+ {
+ if (result->values[(i - 1) >> 1])
+ result->values[i] = _gtk_css_value_ref (result->values[(i - 1) >> 1]);
+ }
+
+ return result;
+}
+
+GtkCssValue *
+_gtk_css_border_value_get_top (const GtkCssValue *value)
+{
+ g_return_val_if_fail (value->class == &GTK_CSS_VALUE_BORDER, NULL);
+
+ return value->values[GTK_CSS_TOP];
+}
+
+GtkCssValue *
+_gtk_css_border_value_get_right (const GtkCssValue *value)
+{
+ g_return_val_if_fail (value->class == &GTK_CSS_VALUE_BORDER, NULL);
+
+ return value->values[GTK_CSS_RIGHT];
+}
+
+GtkCssValue *
+_gtk_css_border_value_get_bottom (const GtkCssValue *value)
+{
+ g_return_val_if_fail (value->class == &GTK_CSS_VALUE_BORDER, NULL);
+
+ return value->values[GTK_CSS_BOTTOM];
+}
+
+GtkCssValue *
+_gtk_css_border_value_get_left (const GtkCssValue *value)
+{
+ g_return_val_if_fail (value->class == &GTK_CSS_VALUE_BORDER, NULL);
+
+ return value->values[GTK_CSS_LEFT];
+}
+
+GtkCssValue *
+_gtk_css_border_value_compute (GtkCssValue *value,
+ GtkStyleContext *context)
+{
+ GtkCssValue *computed;
+ gboolean changed = FALSE;
+ guint i;
+
+ g_return_val_if_fail (value->class == &GTK_CSS_VALUE_BORDER, NULL);
+
+ computed = _gtk_css_border_value_new (NULL, NULL, NULL, NULL);
+ computed->fill = value->fill;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (value->values[i])
+ {
+ computed->values[i] = _gtk_css_number_value_compute (value->values[i], context);
+ changed |= (computed->values[i] != value->values[i]);
+ }
+ }
+
+ if (!changed)
+ {
+ _gtk_css_value_unref (computed);
+ return _gtk_css_value_ref (value);
+ }
+
+ return computed;
+}
+
diff --git a/gtk/gtkcssbordervalueprivate.h b/gtk/gtkcssbordervalueprivate.h
new file mode 100644
index 0000000000..458462b615
--- /dev/null
+++ b/gtk/gtkcssbordervalueprivate.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright © 2012 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: Alexander Larsson <alexl@gnome.org>
+ */
+
+#ifndef __GTK_CSS_BORDER_VALUE_PRIVATE_H__
+#define __GTK_CSS_BORDER_VALUE_PRIVATE_H__
+
+#include "gtkcssparserprivate.h"
+#include "gtkcssvalueprivate.h"
+
+G_BEGIN_DECLS
+
+GtkCssValue * _gtk_css_border_value_new (GtkCssValue *top,
+ GtkCssValue *right,
+ GtkCssValue *bottom,
+ GtkCssValue *left);
+GtkCssValue * _gtk_css_border_value_parse (GtkCssParser *parser,
+ GtkCssNumberParseFlags flags,
+ gboolean allow_auto,
+ gboolean allow_fill);
+
+GtkCssValue * _gtk_css_border_value_get_top (const GtkCssValue *value);
+GtkCssValue * _gtk_css_border_value_get_right (const GtkCssValue *value);
+GtkCssValue * _gtk_css_border_value_get_bottom (const GtkCssValue *value);
+GtkCssValue * _gtk_css_border_value_get_left (const GtkCssValue *value);
+
+GtkCssValue * _gtk_css_border_value_compute (GtkCssValue *border,
+ GtkStyleContext *context);
+
+
+G_END_DECLS
+
+#endif /* __GTK_CSS_BORDER_VALUE_PRIVATE_H__ */
diff --git a/gtk/gtkcssshorthandpropertyimpl.c b/gtk/gtkcssshorthandpropertyimpl.c
index f93859cba2..3a26a28afd 100644
--- a/gtk/gtkcssshorthandpropertyimpl.c
+++ b/gtk/gtkcssshorthandpropertyimpl.c
@@ -25,6 +25,7 @@
#include <math.h>
#include "gtkcssarrayvalueprivate.h"
+#include "gtkcssbordervalueprivate.h"
#include "gtkcsscornervalueprivate.h"
#include "gtkcssenumvalueprivate.h"
#include "gtkcssimageprivate.h"
@@ -304,16 +305,19 @@ parse_border_image (GtkCssShorthandProperty *shorthand,
}
else if (values[1] == NULL)
{
- GValue value = G_VALUE_INIT;
-
- g_value_init (&value, GTK_TYPE_BORDER);
- if (!_gtk_css_style_parse_value (&value, parser, base))
+ values[1] = _gtk_css_border_value_parse (parser,
+ GTK_CSS_PARSE_PERCENT
+ | GTK_CSS_PARSE_NUMBER
+ | GTK_CSS_POSITIVE_ONLY,
+ FALSE,
+ TRUE);
+ if (values[1] == NULL)
return FALSE;
- values[1] = _gtk_css_value_new_from_gvalue (&value);
- g_value_unset (&value);
if (_gtk_css_parser_try (parser, "/", TRUE))
{
+ GValue value = G_VALUE_INIT;
+
g_value_init (&value, GTK_TYPE_BORDER);
if (!_gtk_css_style_parse_value (&value, parser, base))
return FALSE;
diff --git a/gtk/gtkcssstylepropertyimpl.c b/gtk/gtkcssstylepropertyimpl.c
index e5b3461c8d..530a85ec3c 100644
--- a/gtk/gtkcssstylepropertyimpl.c
+++ b/gtk/gtkcssstylepropertyimpl.c
@@ -42,6 +42,7 @@
#include "gtkbindings.h"
#include "gtkcssarrayvalueprivate.h"
#include "gtkcssbgsizevalueprivate.h"
+#include "gtkcssbordervalueprivate.h"
#include "gtkcsscornervalueprivate.h"
#include "gtkcsseasevalueprivate.h"
#include "gtkcssenginevalueprivate.h"
@@ -159,6 +160,38 @@ assign_length_from_double (GtkCssStyleProperty *property,
return _gtk_css_number_value_new (g_value_get_double (value), GTK_CSS_PX);
}
+static void
+query_border (GtkCssStyleProperty *property,
+ const GtkCssValue *css_value,
+ GValue *value)
+{
+ GtkBorder border;
+
+ g_value_init (value, GTK_TYPE_BORDER);
+
+ border.top = round (_gtk_css_number_value_get (_gtk_css_border_value_get_top (css_value), 100));
+ border.right = round (_gtk_css_number_value_get (_gtk_css_border_value_get_right (css_value), 100));
+ border.bottom = round (_gtk_css_number_value_get (_gtk_css_border_value_get_bottom (css_value), 100));
+ border.left = round (_gtk_css_number_value_get (_gtk_css_border_value_get_left (css_value), 100));
+
+ g_value_set_boxed (value, &border);
+}
+
+static GtkCssValue *
+assign_border (GtkCssStyleProperty *property,
+ const GValue *value)
+{
+ const GtkBorder *border = g_value_get_boxed (value);
+
+ if (border == NULL)
+ return _gtk_css_value_ref (_gtk_css_style_property_get_initial_value (property));
+ else
+ return _gtk_css_border_value_new (_gtk_css_number_value_new (border->top, GTK_CSS_PX),
+ _gtk_css_number_value_new (border->right, GTK_CSS_PX),
+ _gtk_css_number_value_new (border->bottom, GTK_CSS_PX),
+ _gtk_css_number_value_new (border->left, GTK_CSS_PX));
+}
+
static GtkCssValue *
color_parse (GtkCssStyleProperty *property,
GtkCssParser *parser,
@@ -683,20 +716,12 @@ border_image_slice_parse (GtkCssStyleProperty *property,
GtkCssParser *parser,
GFile *base)
{
- GValue value = G_VALUE_INIT;
- GtkCssValue *result;
-
- g_value_init (&value, GTK_TYPE_BORDER);
- if (!_gtk_css_style_parse_value (&value, parser, base))
- {
- g_value_unset (&value);
- return NULL;
- }
-
- result = _gtk_css_value_new_from_gvalue (&value);
- g_value_unset (&value);
-
- return result;
+ return _gtk_css_border_value_parse (parser,
+ GTK_CSS_PARSE_PERCENT
+ | GTK_CSS_PARSE_NUMBER
+ | GTK_CSS_POSITIVE_ONLY,
+ FALSE,
+ TRUE);
}
static GtkCssValue *
@@ -721,6 +746,14 @@ border_image_width_parse (GtkCssStyleProperty *property,
}
static GtkCssValue *
+compute_border (GtkCssStyleProperty *property,
+ GtkStyleContext *context,
+ GtkCssValue *specified)
+{
+ return _gtk_css_border_value_compute (specified, context);
+}
+
+static GtkCssValue *
transition_property_parse_one (GtkCssParser *parser)
{
GtkCssValue *value;
@@ -942,8 +975,6 @@ gtk_symbolic_color_new_rgba (double red,
void
_gtk_css_style_property_init_properties (void)
{
- GtkBorder border_of_ones = { 1, 1, 1, 1 };
-
/* Initialize "color" and "font-size" first,
* so that when computing values later they are
* done first. That way, 'currentColor' and font
@@ -1492,18 +1523,20 @@ _gtk_css_style_property_init_properties (void)
_gtk_css_border_repeat_value_new (GTK_CSS_REPEAT_STYLE_STRETCH,
GTK_CSS_REPEAT_STYLE_STRETCH));
- /* XXX: The initial value is wrong, it should be 100% */
gtk_css_style_property_register ("border-image-slice",
GTK_CSS_PROPERTY_BORDER_IMAGE_SLICE,
GTK_TYPE_BORDER,
0,
border_image_slice_parse,
NULL,
+ compute_border,
+ query_border,
+ assign_border,
NULL,
- query_simple,
- assign_simple,
- NULL,
- _gtk_css_value_new_from_boxed (GTK_TYPE_BORDER, &border_of_ones));
+ _gtk_css_border_value_new (_gtk_css_number_value_new (100, GTK_CSS_PERCENT),
+ _gtk_css_number_value_new (100, GTK_CSS_PERCENT),
+ _gtk_css_number_value_new (100, GTK_CSS_PERCENT),
+ _gtk_css_number_value_new (100, GTK_CSS_PERCENT)));
gtk_css_style_property_register ("border-image-width",
GTK_CSS_PROPERTY_BORDER_IMAGE_WIDTH,
GTK_TYPE_BORDER,
diff --git a/gtk/gtkcssvalue.c b/gtk/gtkcssvalue.c
index 80ccd54585..477d7b1f0d 100644
--- a/gtk/gtkcssvalue.c
+++ b/gtk/gtkcssvalue.c
@@ -349,6 +349,19 @@ _gtk_css_value_equal (const GtkCssValue *value1,
return value1->class->equal (value1, value2);
}
+gboolean
+_gtk_css_value_equal0 (const GtkCssValue *value1,
+ const GtkCssValue *value2)
+{
+ if (value1 == NULL && value2 == NULL)
+ return TRUE;
+
+ if (value1 == NULL || value2 == NULL)
+ return FALSE;
+
+ return _gtk_css_value_equal (value1, value2);
+}
+
GtkCssValue *
_gtk_css_value_transition (GtkCssValue *start,
GtkCssValue *end,
diff --git a/gtk/gtkcssvalueprivate.h b/gtk/gtkcssvalueprivate.h
index 0dc1f9af66..66453cc6a5 100644
--- a/gtk/gtkcssvalueprivate.h
+++ b/gtk/gtkcssvalueprivate.h
@@ -66,6 +66,8 @@ void _gtk_css_value_unref (GtkCssValue
gboolean _gtk_css_value_equal (const GtkCssValue *value1,
const GtkCssValue *value2);
+gboolean _gtk_css_value_equal0 (const GtkCssValue *value1,
+ const GtkCssValue *value2);
GtkCssValue *_gtk_css_value_transition (GtkCssValue *start,
GtkCssValue *end,
double progress);