summaryrefslogtreecommitdiff
path: root/gtk
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2011-05-29 07:03:59 +0200
committerBenjamin Otte <otte@redhat.com>2011-06-15 12:52:53 +0200
commit0d253b67f41fd9f8956f763dda275cfa8353cd7f (patch)
tree2a4a9882a8cfa7422a93c3afc546058fa81801d0 /gtk
parent0c162851ed3be918748724df8535f63b82626bb7 (diff)
downloadgtk+-0d253b67f41fd9f8956f763dda275cfa8353cd7f.tar.gz
css: Make font property a shorthand
... and implement the CSS font properties: - font-size - font-style - font-family - font-weight - font-variant This is the second try at this. The first was backed out previously due to bugginess. Let's hope this one survives a bit longer. Also makes the font-family CSS test work again.
Diffstat (limited to 'gtk')
-rw-r--r--gtk/gtkcssparser.c5
-rw-r--r--gtk/gtkcssprovider.c30
-rw-r--r--gtk/gtkstylecontext.c30
-rw-r--r--gtk/gtkstyleproperty.c245
4 files changed, 302 insertions, 8 deletions
diff --git a/gtk/gtkcssparser.c b/gtk/gtkcssparser.c
index 80544515e1..1b2710d047 100644
--- a/gtk/gtkcssparser.c
+++ b/gtk/gtkcssparser.c
@@ -386,7 +386,10 @@ _gtk_css_parser_read_string (GtkCssParser *parser)
quote = *parser->data;
if (quote != '"' && quote != '\'')
- return NULL;
+ {
+ _gtk_css_parser_error (parser, "Expected a string.");
+ return NULL;
+ }
parser->data++;
str = g_string_new (NULL);
diff --git a/gtk/gtkcssprovider.c b/gtk/gtkcssprovider.c
index 2e67a47579..4be5b7516b 100644
--- a/gtk/gtkcssprovider.c
+++ b/gtk/gtkcssprovider.c
@@ -725,6 +725,36 @@
* <entry>[transparent|color]{1,4}</entry>
* </row>
* <row>
+ * <entry>font-family</entry>
+ * <entry>@family [, @family]*</entry>
+ * <entry>#gchararray</entry>
+ * <entry>font-family: Sans, Arial;</entry>
+ * </row>
+ * <row>
+ * <entry>font-style</entry>
+ * <entry>[normal|oblique|italic]</entry>
+ * <entry>#PANGO_TYPE_STYLE</entry>
+ * <entry>font-style: italic;</entry>
+ * </row>
+ * <row>
+ * <entry>font-variant</entry>
+ * <entry>[normal|small-caps]</entry>
+ * <entry>#PANGO_TYPE_VARIANT</entry>
+ * <entry>font-variant: normal;</entry>
+ * </row>
+ * <row>
+ * <entry>font-weight</entry>
+ * <entry>[normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900]</entry>
+ * <entry>#PANGO_TYPE_WEIGHT</entry>
+ * <entry>font-weight: bold;</entry>
+ * </row>
+ * <row>
+ * <entry>font-size</entry>
+ * <entry>Font size in point</entry>
+ * <entry>#gint</entry>
+ * <entry>font-size: 13;</entry>
+ * </row>
+ * <row>
* <entry>font</entry>
* <entry>@family [@style] [@size]</entry>
* <entry>#PangoFontDescription</entry>
diff --git a/gtk/gtkstylecontext.c b/gtk/gtkstylecontext.c
index 762f889e8a..9ac9b47b67 100644
--- a/gtk/gtkstylecontext.c
+++ b/gtk/gtkstylecontext.c
@@ -3562,7 +3562,8 @@ gtk_style_context_get_font (GtkStyleContext *context,
{
GtkStyleContextPrivate *priv;
StyleData *data;
- const GValue *value;
+ GHashTable *font_cache;
+ PangoFontDescription *description;
g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
@@ -3570,12 +3571,31 @@ gtk_style_context_get_font (GtkStyleContext *context,
g_return_val_if_fail (priv->widget_path != NULL, NULL);
data = style_data_lookup (context);
- value = _gtk_style_properties_peek_property (data->store, "font", state, NULL);
- if (value)
- return g_value_get_boxed (value);
+ /* Yuck, fonts are created on-demand but we don't return a ref.
+ * Do bad things to achieve this requirement */
+ font_cache = g_object_get_data (G_OBJECT (data->store), "font-cache-for-get_font");
+ if (font_cache)
+ {
+ description = g_hash_table_lookup (font_cache, GUINT_TO_POINTER (state));
+ }
+ else
+ {
+ font_cache = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) pango_font_description_free);
+ g_object_set_data_full (G_OBJECT (data->store),
+ "font-cache-for-get_font",
+ font_cache,
+ (GDestroyNotify) g_hash_table_unref);
+ description = NULL;
+ }
- return NULL;
+ if (description == NULL)
+ {
+ gtk_style_properties_get (data->store, state, "font", &description, NULL);
+ g_hash_table_insert (font_cache, GUINT_TO_POINTER (state), description);
+ }
+
+ return description;
}
static void
diff --git a/gtk/gtkstyleproperty.c b/gtk/gtkstyleproperty.c
index 27cc9b26e7..f3c19980de 100644
--- a/gtk/gtkstyleproperty.c
+++ b/gtk/gtkstyleproperty.c
@@ -22,6 +22,7 @@
#include "gtkstylepropertyprivate.h"
#include <errno.h>
+#include <math.h>
#include <stdlib.h>
#include <string.h>
@@ -227,6 +228,74 @@ symbolic_color_value_print (const GValue *value,
}
}
+static gboolean
+font_family_parse (GtkCssParser *parser,
+ GFile *base,
+ GValue *value)
+{
+ GPtrArray *names;
+ char *name;
+
+ /* We don't special case generic families. Pango should do
+ * that for us */
+
+ names = g_ptr_array_new ();
+
+ do {
+ name = _gtk_css_parser_try_ident (parser, TRUE);
+ if (name)
+ {
+ GString *string = g_string_new (name);
+ g_free (name);
+ while ((name = _gtk_css_parser_try_ident (parser, TRUE)))
+ {
+ g_string_append_c (string, ' ');
+ g_string_append (string, name);
+ g_free (name);
+ }
+ name = g_string_free (string, FALSE);
+ }
+ else
+ {
+ name = _gtk_css_parser_read_string (parser);
+ if (name == NULL)
+ {
+ g_ptr_array_free (names, TRUE);
+ return FALSE;
+ }
+ }
+
+ g_ptr_array_add (names, name);
+ } while (_gtk_css_parser_try (parser, ",", TRUE));
+
+ /* NULL-terminate array */
+ g_ptr_array_add (names, NULL);
+ g_value_set_boxed (value, g_ptr_array_free (names, FALSE));
+ return TRUE;
+}
+
+static void
+font_family_value_print (const GValue *value,
+ GString *string)
+{
+ const char **names = g_value_get_boxed (value);
+
+ if (names == NULL || *names == NULL)
+ {
+ g_string_append (string, "none");
+ return;
+ }
+
+ string_append_string (string, *names);
+ names++;
+ while (*names)
+ {
+ g_string_append (string, ", ");
+ string_append_string (string, *names);
+ names++;
+ }
+}
+
static gboolean
font_description_value_parse (GtkCssParser *parser,
GFile *base,
@@ -1755,6 +1824,119 @@ pack_border_radius (GValue *value,
}
static GParameter *
+unpack_font_description (const GValue *value,
+ guint *n_params)
+{
+ GParameter *parameter = g_new0 (GParameter, 5);
+ PangoFontDescription *description;
+ PangoFontMask mask;
+ guint n;
+
+ /* For backwards compat, we only unpack values that are indeed set.
+ * For strict CSS conformance we need to unpack all of them.
+ * Note that we do set all of them in the parse function, so it
+ * will not have effects when parsing CSS files. It will though
+ * for custom style providers.
+ */
+
+ description = g_value_get_boxed (value);
+ n = 0;
+
+ if (description)
+ mask = pango_font_description_get_set_fields (description);
+ else
+ mask = 0;
+
+ if (mask & PANGO_FONT_MASK_FAMILY)
+ {
+ GPtrArray *strv = g_ptr_array_new ();
+
+ g_ptr_array_add (strv, g_strdup (pango_font_description_get_family (description)));
+ g_ptr_array_add (strv, NULL);
+ parameter[n].name = "font-family";
+ g_value_init (&parameter[n].value, G_TYPE_STRV);
+ g_value_take_boxed (&parameter[n].value,
+ g_ptr_array_free (strv, FALSE));
+ n++;
+ }
+
+ if (mask & PANGO_FONT_MASK_STYLE)
+ {
+ parameter[n].name = "font-style";
+ g_value_init (&parameter[n].value, PANGO_TYPE_STYLE);
+ g_value_set_enum (&parameter[n].value,
+ pango_font_description_get_style (description));
+ n++;
+ }
+
+ if (mask & PANGO_FONT_MASK_VARIANT)
+ {
+ parameter[n].name = "font-variant";
+ g_value_init (&parameter[n].value, PANGO_TYPE_VARIANT);
+ g_value_set_enum (&parameter[n].value,
+ pango_font_description_get_variant (description));
+ n++;
+ }
+
+ if (mask & PANGO_FONT_MASK_WEIGHT)
+ {
+ parameter[n].name = "font-weight";
+ g_value_init (&parameter[n].value, PANGO_TYPE_WEIGHT);
+ g_value_set_enum (&parameter[n].value,
+ pango_font_description_get_weight (description));
+ n++;
+ }
+
+ if (mask & PANGO_FONT_MASK_SIZE)
+ {
+ parameter[n].name = "font-size";
+ g_value_init (&parameter[n].value, G_TYPE_DOUBLE);
+ g_value_set_double (&parameter[n].value,
+ (double) pango_font_description_get_size (description) / PANGO_SCALE);
+ n++;
+ }
+
+ *n_params = n;
+
+ return parameter;
+}
+
+static void
+pack_font_description (GValue *value,
+ GtkStyleProperties *props,
+ GtkStateFlags state)
+{
+ PangoFontDescription *description;
+ char **families;
+ PangoStyle style;
+ PangoVariant variant;
+ PangoWeight weight;
+ double size;
+
+ gtk_style_properties_get (props,
+ state,
+ "font-family", &families,
+ "font-style", &style,
+ "font-variant", &variant,
+ "font-weight", &weight,
+ "font-size", &size,
+ NULL);
+
+ description = pango_font_description_new ();
+ /* xxx: Can we set all the families here somehow? */
+ if (families)
+ pango_font_description_set_family (description, families[0]);
+ pango_font_description_set_size (description, round (size * PANGO_SCALE));
+ pango_font_description_set_style (description, style);
+ pango_font_description_set_variant (description, variant);
+ pango_font_description_set_weight (description, weight);
+
+ g_free (families);
+
+ g_value_take_boxed (value, description);
+}
+
+static GParameter *
unpack_border_color (const GValue *value,
guint *n_params)
{
@@ -2220,14 +2402,73 @@ gtk_style_property_init (void)
"Background color",
GDK_TYPE_RGBA, 0));
+ _gtk_style_property_register (g_param_spec_boxed ("font-family",
+ "Font family",
+ "Font family",
+ G_TYPE_STRV, 0),
+ GTK_STYLE_PROPERTY_INHERIT,
+ NULL,
+ NULL,
+ NULL,
+ font_family_parse,
+ font_family_value_print,
+ NULL);
+ _gtk_style_property_register (g_param_spec_enum ("font-style",
+ "Font style",
+ "Font style",
+ PANGO_TYPE_STYLE,
+ PANGO_STYLE_NORMAL, 0),
+ GTK_STYLE_PROPERTY_INHERIT,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ _gtk_style_property_register (g_param_spec_enum ("font-variant",
+ "Font variant",
+ "Font variant",
+ PANGO_TYPE_VARIANT,
+ PANGO_VARIANT_NORMAL, 0),
+ GTK_STYLE_PROPERTY_INHERIT,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ /* xxx: need to parse this properly, ie parse the numbers */
+ _gtk_style_property_register (g_param_spec_enum ("font-weight",
+ "Font weight",
+ "Font weight",
+ PANGO_TYPE_WEIGHT,
+ PANGO_WEIGHT_NORMAL, 0),
+ GTK_STYLE_PROPERTY_INHERIT,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ _gtk_style_property_register (g_param_spec_double ("font-size",
+ "Font size",
+ "Font size",
+ 0, G_MAXDOUBLE, 0, 0),
+ GTK_STYLE_PROPERTY_INHERIT,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
_gtk_style_property_register (g_param_spec_boxed ("font",
"Font Description",
"Font Description",
PANGO_TYPE_FONT_DESCRIPTION, 0),
GTK_STYLE_PROPERTY_INHERIT,
NULL,
- NULL,
- NULL,
+ unpack_font_description,
+ pack_font_description,
font_description_value_parse,
font_description_value_print,
NULL);