[gtk+] css: Add GtkCssNumber
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] css: Add GtkCssNumber
- Date: Thu, 2 Feb 2012 02:19:11 +0000 (UTC)
commit 893807bee0e9a5777a8c93c76e9529fecf6fa85f
Author: Benjamin Otte <otte redhat com>
Date: Fri Jan 13 23:48:42 2012 +0100
css: Add GtkCssNumber
gtk/gtkcssparser.c | 117 +++++++++++++++++++++++++++++++++++++++++++++
gtk/gtkcssparserprivate.h | 15 +++++-
gtk/gtkcssstylefuncs.c | 11 ++++
gtk/gtkcsstypes.c | 87 +++++++++++++++++++++++++++++++++
gtk/gtkcsstypesprivate.h | 36 ++++++++++++++
5 files changed, 265 insertions(+), 1 deletions(-)
---
diff --git a/gtk/gtkcssparser.c b/gtk/gtkcssparser.c
index 44b00c3..6c36253 100644
--- a/gtk/gtkcssparser.c
+++ b/gtk/gtkcssparser.c
@@ -529,6 +529,123 @@ _gtk_css_parser_try_double (GtkCssParser *parser,
return TRUE;
}
+gboolean
+_gtk_css_parser_has_number (GtkCssParser *parser)
+{
+ /* ahem */
+ return strchr ("+-0123456789.", parser->data[0]) != NULL;
+}
+
+gboolean
+_gtk_css_parser_read_number (GtkCssParser *parser,
+ GtkCssNumber *number,
+ GtkCssNumberParseFlags flags)
+{
+ static const struct {
+ const char *name;
+ GtkCssUnit unit;
+ GtkCssNumberParseFlags required_flags;
+ } units[] = {
+ { "px", GTK_CSS_PX, GTK_CSS_PARSE_LENGTH },
+ { "pt", GTK_CSS_PT, GTK_CSS_PARSE_LENGTH },
+ { "em", GTK_CSS_EM, GTK_CSS_PARSE_LENGTH },
+ { "ex", GTK_CSS_EX, GTK_CSS_PARSE_LENGTH },
+ { "pc", GTK_CSS_PC, GTK_CSS_PARSE_LENGTH },
+ { "in", GTK_CSS_IN, GTK_CSS_PARSE_LENGTH },
+ { "cm", GTK_CSS_CM, GTK_CSS_PARSE_LENGTH },
+ { "mm", GTK_CSS_MM, GTK_CSS_PARSE_LENGTH }
+ };
+ char *end, *unit;
+
+ g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), FALSE);
+ g_return_val_if_fail (number != NULL, FALSE);
+
+ errno = 0;
+ number->unit = GTK_CSS_NUMBER;
+ number->value = g_ascii_strtod (parser->data, &end);
+ if (errno)
+ {
+ _gtk_css_parser_error (parser, "not a number: %s", g_strerror (errno));
+ return FALSE;
+ }
+ if (parser->data == end)
+ {
+ _gtk_css_parser_error (parser, "not a number");
+ return FALSE;
+ }
+
+ parser->data = end;
+
+ if (flags & GTK_CSS_POSITIVE_ONLY &&
+ number->value < 0)
+ {
+ _gtk_css_parser_error (parser, "negative values are not allowed.");
+ return FALSE;
+ }
+
+ unit = _gtk_css_parser_try_ident (parser, FALSE);
+
+ if (unit)
+ {
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (units); i++)
+ {
+ if (flags & units[i].required_flags &&
+ g_ascii_strcasecmp (unit, units[i].name) == 0)
+ break;
+ }
+
+ if (i >= G_N_ELEMENTS (units))
+ {
+ _gtk_css_parser_error (parser, "`%s' is not a valid unit.", unit);
+ g_free (unit);
+ return FALSE;
+ }
+
+ number->unit = units[i].unit;
+ g_free (unit);
+ }
+ else
+ {
+ if ((flags & GTK_CSS_PARSE_PERCENT) &&
+ _gtk_css_parser_try (parser, "%", FALSE))
+ {
+ number->unit = GTK_CSS_PERCENT;
+ }
+ else if (number->value == 0.0)
+ {
+ if (flags & GTK_CSS_PARSE_NUMBER)
+ number->unit = GTK_CSS_NUMBER;
+ else if (flags & GTK_CSS_PARSE_LENGTH)
+ number->unit = GTK_CSS_PX;
+ else
+ number->unit = GTK_CSS_PERCENT;
+ }
+ else if (flags & GTK_CSS_NUMBER_AS_PIXELS)
+ {
+ GError *error = g_error_new_literal (GTK_CSS_PROVIDER_ERROR,
+ GTK_CSS_PROVIDER_ERROR_DEPRECATED,
+ "Not using units is deprecated. Assuming 'px'.");
+ _gtk_css_parser_take_error (parser, error);
+ number->unit = GTK_CSS_PX;
+ }
+ else if (flags & GTK_CSS_PARSE_NUMBER)
+ {
+ number->unit = GTK_CSS_NUMBER;
+ }
+ else
+ {
+ _gtk_css_parser_error (parser, "Unit is missing.");
+ return FALSE;
+ }
+ }
+
+ _gtk_css_parser_skip_whitespace (parser);
+
+ return TRUE;
+}
+
/* XXX: we should introduce GtkCssLenght that deals with
* different kind of units */
gboolean
diff --git a/gtk/gtkcssparserprivate.h b/gtk/gtkcssparserprivate.h
index d267530..e5661d5 100644
--- a/gtk/gtkcssparserprivate.h
+++ b/gtk/gtkcssparserprivate.h
@@ -20,10 +20,19 @@
#ifndef __GTK_CSS_PARSER_PRIVATE_H__
#define __GTK_CSS_PARSER_PRIVATE_H__
+#include "gtk/gtkcsstypesprivate.h"
#include <gtk/gtksymboliccolor.h>
G_BEGIN_DECLS
+typedef enum /*< skip >*/ {
+ GTK_CSS_POSITIVE_ONLY = (1 << 0),
+ GTK_CSS_PARSE_PERCENT = (1 << 1),
+ GTK_CSS_PARSE_NUMBER = (1 << 2),
+ GTK_CSS_NUMBER_AS_PIXELS = (1 << 3),
+ GTK_CSS_PARSE_LENGTH = (1 << 4)
+} GtkCssNumberParseFlags;
+
typedef struct _GtkCssParser GtkCssParser;
typedef void (* GtkCssParserErrorFunc) (GtkCssParser *parser,
@@ -78,7 +87,10 @@ gboolean _gtk_css_parser_try_enum (GtkCssParser *parser
GType enum_type,
int *value);
-void _gtk_css_parser_skip_whitespace (GtkCssParser *parser);
+gboolean _gtk_css_parser_has_number (GtkCssParser *parser);
+gboolean _gtk_css_parser_read_number (GtkCssParser *parser,
+ GtkCssNumber *number,
+ GtkCssNumberParseFlags flags);
char * _gtk_css_parser_read_string (GtkCssParser *parser);
char * _gtk_css_parser_read_value (GtkCssParser *parser);
GtkSymbolicColor *_gtk_css_parser_read_symbolic_color
@@ -86,6 +98,7 @@ GtkSymbolicColor *_gtk_css_parser_read_symbolic_color
GFile * _gtk_css_parser_read_url (GtkCssParser *parser,
GFile *base);
+void _gtk_css_parser_skip_whitespace (GtkCssParser *parser);
void _gtk_css_parser_resync (GtkCssParser *parser,
gboolean sync_at_semicolon,
char terminator);
diff --git a/gtk/gtkcssstylefuncs.c b/gtk/gtkcssstylefuncs.c
index 0045f93..02873ec 100644
--- a/gtk/gtkcssstylefuncs.c
+++ b/gtk/gtkcssstylefuncs.c
@@ -1058,6 +1058,13 @@ border_image_repeat_value_print (const GValue *value,
}
}
+static void
+css_number_print (const GValue *value,
+ GString *string)
+{
+ _gtk_css_number_print (g_value_get_boxed (value), string);
+}
+
static gboolean
enum_value_parse (GtkCssParser *parser,
GFile *base,
@@ -1233,6 +1240,10 @@ gtk_css_style_funcs_init (void)
shadow_value_parse,
shadow_value_print,
shadow_value_compute);
+ register_conversion_function (GTK_TYPE_CSS_NUMBER,
+ NULL,
+ css_number_print,
+ NULL);
register_conversion_function (G_TYPE_ENUM,
enum_value_parse,
enum_value_print,
diff --git a/gtk/gtkcsstypes.c b/gtk/gtkcsstypes.c
index 674fd02..c2929d6 100644
--- a/gtk/gtkcsstypes.c
+++ b/gtk/gtkcsstypes.c
@@ -20,6 +20,7 @@
#include "config.h"
#include "gtkcsstypesprivate.h"
+#include "gtkstylecontextprivate.h"
#define DEFINE_BOXED_TYPE_WITH_COPY_FUNC(TypeName, type_name) \
\
@@ -33,3 +34,89 @@ G_DEFINE_BOXED_TYPE (TypeName, type_name, type_name ## _copy, g_free)
DEFINE_BOXED_TYPE_WITH_COPY_FUNC (GtkCssBorderCornerRadius, _gtk_css_border_corner_radius)
DEFINE_BOXED_TYPE_WITH_COPY_FUNC (GtkCssBorderImageRepeat, _gtk_css_border_image_repeat)
+DEFINE_BOXED_TYPE_WITH_COPY_FUNC (GtkCssNumber, _gtk_css_number)
+
+void
+_gtk_css_number_init (GtkCssNumber *number,
+ double value,
+ GtkCssUnit unit)
+{
+ number->value = value;
+ number->unit = unit;
+}
+
+void
+_gtk_css_number_compute (GtkCssNumber *dest,
+ const GtkCssNumber *src,
+ GtkStyleContext *context)
+{
+ switch (src->unit)
+ {
+ default:
+ g_assert_not_reached();
+ /* fall through */
+ case GTK_CSS_PERCENT:
+ case GTK_CSS_NUMBER:
+ case GTK_CSS_PX:
+ dest->value = src->value;
+ dest->unit = src->unit;
+ break;
+ case GTK_CSS_PT:
+ dest->value = src->value * 96.0 / 72.0;
+ dest->unit = GTK_CSS_PX;
+ break;
+ case GTK_CSS_PC:
+ dest->value = src->value * 96.0 / 72.0 * 12.0;
+ dest->unit = GTK_CSS_PX;
+ break;
+ case GTK_CSS_IN:
+ dest->value = src->value * 96.0;
+ dest->unit = GTK_CSS_PX;
+ break;
+ case GTK_CSS_CM:
+ dest->value = src->value * 96.0 * 0.39370078740157477;
+ dest->unit = GTK_CSS_PX;
+ break;
+ case GTK_CSS_MM:
+ dest->value = src->value * 96.0 * 0.039370078740157477;
+ dest->unit = GTK_CSS_PX;
+ break;
+ case GTK_CSS_EM:
+ dest->value = src->value * g_value_get_double (_gtk_style_context_peek_property (context, "font-size"));
+ dest->unit = GTK_CSS_PX;
+ break;
+ case GTK_CSS_EX:
+ /* for now we pretend ex is half of em */
+ dest->value = src->value * g_value_get_double (_gtk_style_context_peek_property (context, "font-size"));
+ dest->unit = GTK_CSS_PX;
+ break;
+ }
+}
+
+void
+_gtk_css_number_print (const GtkCssNumber *number,
+ GString *string)
+{
+ char buf[G_ASCII_DTOSTR_BUF_SIZE];
+
+ g_return_if_fail (number != NULL);
+ g_return_if_fail (string != NULL);
+
+ const char *names[] = {
+ /* [GTK_CSS_NUMBER] = */ "",
+ /* [GTK_CSS_PERCENT] = */ "%",
+ /* [GTK_CSS_PX] = */ "px",
+ /* [GTK_CSS_PT] = */ "pt",
+ /* [GTK_CSS_EM] = */ "em",
+ /* [GTK_CSS_EX] = */ "ex",
+ /* [GTK_CSS_PC] = */ "pc",
+ /* [GTK_CSS_IN] = */ "in",
+ /* [GTK_CSS_CM] = */ "cm",
+ /* [GTK_CSS_MM] = */ "mm"
+ };
+
+ g_ascii_dtostr (buf, sizeof (buf), number->value);
+ g_string_append (string, buf);
+ if (number->value != 0.0)
+ g_string_append (string, names[number->unit]);
+}
diff --git a/gtk/gtkcsstypesprivate.h b/gtk/gtkcsstypesprivate.h
index 244f98d..6422d9a 100644
--- a/gtk/gtkcsstypesprivate.h
+++ b/gtk/gtkcsstypesprivate.h
@@ -21,6 +21,7 @@
#define __GTK_CSS_TYPES_PRIVATE_H__
#include <glib-object.h>
+#include <gtk/gtkstylecontext.h>
G_BEGIN_DECLS
@@ -77,9 +78,31 @@ typedef enum /*< skip >*/ {
GTK_CSS_BOTTOM_LEFT
} GtkCssCorner;
+typedef enum /*< skip >*/ {
+ /* CSS term: <number> */
+ GTK_CSS_NUMBER,
+ /* CSS term: <percentage> */
+ GTK_CSS_PERCENT,
+ /* CSS term: <length> */
+ GTK_CSS_PX,
+ GTK_CSS_PT,
+ GTK_CSS_EM,
+ GTK_CSS_EX,
+ GTK_CSS_PC,
+ GTK_CSS_IN,
+ GTK_CSS_CM,
+ GTK_CSS_MM
+} GtkCssUnit;
+
+typedef struct _GtkCssNumber GtkCssNumber;
typedef struct _GtkCssBorderCornerRadius GtkCssBorderCornerRadius;
typedef struct _GtkCssBorderImageRepeat GtkCssBorderImageRepeat;
+struct _GtkCssNumber {
+ gdouble value;
+ GtkCssUnit unit;
+};
+
struct _GtkCssBorderCornerRadius {
double horizontal;
double vertical;
@@ -92,9 +115,22 @@ struct _GtkCssBorderImageRepeat {
#define GTK_TYPE_CSS_BORDER_CORNER_RADIUS _gtk_css_border_corner_radius_get_type ()
#define GTK_TYPE_CSS_BORDER_IMAGE_REPEAT _gtk_css_border_image_repeat_get_type ()
+#define GTK_TYPE_CSS_NUMBER _gtk_css_number_get_type ()
GType _gtk_css_border_corner_radius_get_type (void);
GType _gtk_css_border_image_repeat_get_type (void);
+GType _gtk_css_number_get_type (void);
+
+#define GTK_CSS_NUMBER_INIT(_value,_unit) { (_value), (_unit) }
+void _gtk_css_number_init (GtkCssNumber *number,
+ double value,
+ GtkCssUnit unit);
+void _gtk_css_number_compute (GtkCssNumber *dest,
+ const GtkCssNumber *src,
+ GtkStyleContext *context);
+void _gtk_css_number_print (const GtkCssNumber *number,
+ GString *string);
+
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]