css: Add GtkCssNumber
This commit is contained in:
@ -529,6 +529,123 @@ _gtk_css_parser_try_double (GtkCssParser *parser,
|
|||||||
return TRUE;
|
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
|
/* XXX: we should introduce GtkCssLenght that deals with
|
||||||
* different kind of units */
|
* different kind of units */
|
||||||
gboolean
|
gboolean
|
||||||
|
|||||||
@ -20,10 +20,19 @@
|
|||||||
#ifndef __GTK_CSS_PARSER_PRIVATE_H__
|
#ifndef __GTK_CSS_PARSER_PRIVATE_H__
|
||||||
#define __GTK_CSS_PARSER_PRIVATE_H__
|
#define __GTK_CSS_PARSER_PRIVATE_H__
|
||||||
|
|
||||||
|
#include "gtk/gtkcsstypesprivate.h"
|
||||||
#include <gtk/gtksymboliccolor.h>
|
#include <gtk/gtksymboliccolor.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
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 struct _GtkCssParser GtkCssParser;
|
||||||
|
|
||||||
typedef void (* GtkCssParserErrorFunc) (GtkCssParser *parser,
|
typedef void (* GtkCssParserErrorFunc) (GtkCssParser *parser,
|
||||||
@ -78,7 +87,10 @@ gboolean _gtk_css_parser_try_enum (GtkCssParser *parser
|
|||||||
GType enum_type,
|
GType enum_type,
|
||||||
int *value);
|
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_string (GtkCssParser *parser);
|
||||||
char * _gtk_css_parser_read_value (GtkCssParser *parser);
|
char * _gtk_css_parser_read_value (GtkCssParser *parser);
|
||||||
GtkSymbolicColor *_gtk_css_parser_read_symbolic_color
|
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 * _gtk_css_parser_read_url (GtkCssParser *parser,
|
||||||
GFile *base);
|
GFile *base);
|
||||||
|
|
||||||
|
void _gtk_css_parser_skip_whitespace (GtkCssParser *parser);
|
||||||
void _gtk_css_parser_resync (GtkCssParser *parser,
|
void _gtk_css_parser_resync (GtkCssParser *parser,
|
||||||
gboolean sync_at_semicolon,
|
gboolean sync_at_semicolon,
|
||||||
char terminator);
|
char terminator);
|
||||||
|
|||||||
@ -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
|
static gboolean
|
||||||
enum_value_parse (GtkCssParser *parser,
|
enum_value_parse (GtkCssParser *parser,
|
||||||
GFile *base,
|
GFile *base,
|
||||||
@ -1233,6 +1240,10 @@ gtk_css_style_funcs_init (void)
|
|||||||
shadow_value_parse,
|
shadow_value_parse,
|
||||||
shadow_value_print,
|
shadow_value_print,
|
||||||
shadow_value_compute);
|
shadow_value_compute);
|
||||||
|
register_conversion_function (GTK_TYPE_CSS_NUMBER,
|
||||||
|
NULL,
|
||||||
|
css_number_print,
|
||||||
|
NULL);
|
||||||
register_conversion_function (G_TYPE_ENUM,
|
register_conversion_function (G_TYPE_ENUM,
|
||||||
enum_value_parse,
|
enum_value_parse,
|
||||||
enum_value_print,
|
enum_value_print,
|
||||||
|
|||||||
@ -20,6 +20,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "gtkcsstypesprivate.h"
|
#include "gtkcsstypesprivate.h"
|
||||||
|
#include "gtkstylecontextprivate.h"
|
||||||
|
|
||||||
#define DEFINE_BOXED_TYPE_WITH_COPY_FUNC(TypeName, type_name) \
|
#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 (GtkCssBorderCornerRadius, _gtk_css_border_corner_radius)
|
||||||
DEFINE_BOXED_TYPE_WITH_COPY_FUNC (GtkCssBorderImageRepeat, _gtk_css_border_image_repeat)
|
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]);
|
||||||
|
}
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
#define __GTK_CSS_TYPES_PRIVATE_H__
|
#define __GTK_CSS_TYPES_PRIVATE_H__
|
||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
#include <gtk/gtkstylecontext.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
@ -77,9 +78,31 @@ typedef enum /*< skip >*/ {
|
|||||||
GTK_CSS_BOTTOM_LEFT
|
GTK_CSS_BOTTOM_LEFT
|
||||||
} GtkCssCorner;
|
} 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 _GtkCssBorderCornerRadius GtkCssBorderCornerRadius;
|
||||||
typedef struct _GtkCssBorderImageRepeat GtkCssBorderImageRepeat;
|
typedef struct _GtkCssBorderImageRepeat GtkCssBorderImageRepeat;
|
||||||
|
|
||||||
|
struct _GtkCssNumber {
|
||||||
|
gdouble value;
|
||||||
|
GtkCssUnit unit;
|
||||||
|
};
|
||||||
|
|
||||||
struct _GtkCssBorderCornerRadius {
|
struct _GtkCssBorderCornerRadius {
|
||||||
double horizontal;
|
double horizontal;
|
||||||
double vertical;
|
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_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_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_corner_radius_get_type (void);
|
||||||
GType _gtk_css_border_image_repeat_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
|
G_END_DECLS
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user