1 | /* GTK - The GIMP Toolkit |
2 | * Copyright (C) 2011 Red Hat, Inc. |
3 | * |
4 | * This library is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU Lesser General Public |
6 | * License as published by the Free Software Foundation; either |
7 | * version 2 of the License, or (at your option) any later version. |
8 | * |
9 | * This library is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * Lesser General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU Lesser General Public |
15 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
16 | */ |
17 | |
18 | #include "config.h" |
19 | |
20 | #include "gtkcssdimensionvalueprivate.h" |
21 | |
22 | GtkCssValue * |
23 | gtk_css_dimension_value_parse (GtkCssParser *parser, |
24 | GtkCssNumberParseFlags flags) |
25 | { |
26 | static const struct { |
27 | const char *name; |
28 | GtkCssUnit unit; |
29 | GtkCssNumberParseFlags required_flags; |
30 | } units[] = { |
31 | { "px" , GTK_CSS_PX, GTK_CSS_PARSE_LENGTH }, |
32 | { "pt" , GTK_CSS_PT, GTK_CSS_PARSE_LENGTH }, |
33 | { "em" , GTK_CSS_EM, GTK_CSS_PARSE_LENGTH }, |
34 | { "ex" , GTK_CSS_EX, GTK_CSS_PARSE_LENGTH }, |
35 | { "rem" , GTK_CSS_REM, GTK_CSS_PARSE_LENGTH }, |
36 | { "pc" , GTK_CSS_PC, GTK_CSS_PARSE_LENGTH }, |
37 | { "in" , GTK_CSS_IN, GTK_CSS_PARSE_LENGTH }, |
38 | { "cm" , GTK_CSS_CM, GTK_CSS_PARSE_LENGTH }, |
39 | { "mm" , GTK_CSS_MM, GTK_CSS_PARSE_LENGTH }, |
40 | { "rad" , GTK_CSS_RAD, GTK_CSS_PARSE_ANGLE }, |
41 | { "deg" , GTK_CSS_DEG, GTK_CSS_PARSE_ANGLE }, |
42 | { "grad" , GTK_CSS_GRAD, GTK_CSS_PARSE_ANGLE }, |
43 | { "turn" , GTK_CSS_TURN, GTK_CSS_PARSE_ANGLE }, |
44 | { "s" , GTK_CSS_S, GTK_CSS_PARSE_TIME }, |
45 | { "ms" , GTK_CSS_MS, GTK_CSS_PARSE_TIME } |
46 | }; |
47 | const GtkCssToken *token; |
48 | GtkCssValue *result; |
49 | GtkCssUnit unit; |
50 | double number; |
51 | |
52 | token = gtk_css_parser_get_token (self: parser); |
53 | |
54 | /* Handle percentages first */ |
55 | if (gtk_css_token_is (token, GTK_CSS_TOKEN_PERCENTAGE)) |
56 | { |
57 | if (!(flags & GTK_CSS_PARSE_PERCENT)) |
58 | { |
59 | gtk_css_parser_error_value (self: parser, format: "Percentages are not allowed here" ); |
60 | return NULL; |
61 | } |
62 | number = token->number.number; |
63 | unit = GTK_CSS_PERCENT; |
64 | } |
65 | else if (gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_INTEGER) || |
66 | gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_INTEGER) || |
67 | gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_NUMBER) || |
68 | gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_NUMBER)) |
69 | { |
70 | number = token->number.number; |
71 | if (number == 0.0) |
72 | { |
73 | if (flags & GTK_CSS_PARSE_NUMBER) |
74 | unit = GTK_CSS_NUMBER; |
75 | else if (flags & GTK_CSS_PARSE_LENGTH) |
76 | unit = GTK_CSS_PX; |
77 | else if (flags & GTK_CSS_PARSE_ANGLE) |
78 | unit = GTK_CSS_DEG; |
79 | else if (flags & GTK_CSS_PARSE_TIME) |
80 | unit = GTK_CSS_S; |
81 | else |
82 | unit = GTK_CSS_PERCENT; |
83 | } |
84 | else if (flags & GTK_CSS_PARSE_NUMBER) |
85 | { |
86 | unit = GTK_CSS_NUMBER; |
87 | } |
88 | else |
89 | { |
90 | gtk_css_parser_error_syntax (self: parser, format: "Unit is missing." ); |
91 | return NULL; |
92 | } |
93 | } |
94 | else if (gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_INTEGER_DIMENSION) || |
95 | gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_INTEGER_DIMENSION) || |
96 | gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_DIMENSION) || |
97 | gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_DIMENSION)) |
98 | { |
99 | guint i; |
100 | |
101 | for (i = 0; i < G_N_ELEMENTS (units); i++) |
102 | { |
103 | if (flags & units[i].required_flags && |
104 | g_ascii_strcasecmp (s1: token->dimension.dimension, s2: units[i].name) == 0) |
105 | break; |
106 | } |
107 | |
108 | if (i >= G_N_ELEMENTS (units)) |
109 | { |
110 | gtk_css_parser_error_syntax (self: parser, format: "'%s' is not a valid unit" , token->dimension.dimension); |
111 | return NULL; |
112 | } |
113 | |
114 | unit = units[i].unit; |
115 | number = token->dimension.value; |
116 | } |
117 | else |
118 | { |
119 | gtk_css_parser_error_syntax (self: parser, format: "Expected a number" ); |
120 | return NULL; |
121 | } |
122 | |
123 | if (flags & GTK_CSS_POSITIVE_ONLY && |
124 | number < 0) |
125 | { |
126 | gtk_css_parser_error_value (self: parser, format: "Negative values are not allowed" ); |
127 | return NULL; |
128 | } |
129 | |
130 | result = gtk_css_dimension_value_new (value: number, unit); |
131 | gtk_css_parser_consume_token (self: parser); |
132 | |
133 | return result; |
134 | } |
135 | |