summaryrefslogtreecommitdiff
path: root/src/cssparser.cc
diff options
context:
space:
mode:
authorSebastian Geerken <devnull@localhost>2013-12-09 14:44:42 +0100
committerSebastian Geerken <devnull@localhost>2013-12-09 14:44:42 +0100
commit01f697091153846bdffc73b3150ba37c763301cc (patch)
tree84773dff07a8498e7cc62695d89a6ecb29378a82 /src/cssparser.cc
parentee66f4f97e38d11e68b9515b7043aa8ac6f63c74 (diff)
parent6c7572f8bd23064f96ba716e1ba8ba8a34847001 (diff)
Merge (large!).
Diffstat (limited to 'src/cssparser.cc')
-rw-r--r--src/cssparser.cc173
1 files changed, 155 insertions, 18 deletions
diff --git a/src/cssparser.cc b/src/cssparser.cc
index 67d8ff54..4ff8f4f7 100644
--- a/src/cssparser.cc
+++ b/src/cssparser.cc
@@ -47,6 +47,14 @@ typedef struct {
const char *const *enum_symbols;
} CssPropertyInfo;
+static const char *const Css_background_attachment_enum_vals[] = {
+ "scroll", "fixed", NULL
+};
+
+static const char *const Css_background_repeat_enum_vals[] = {
+ "repeat", "repeat-x", "repeat-y", "no-repeat", NULL
+};
+
static const char *const Css_border_collapse_enum_vals[] = {
"separate", "collapse", NULL
};
@@ -151,11 +159,14 @@ static const char *const Css_word_spacing_enum_vals[] = {
};
const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = {
- {"background-attachment", {CSS_TYPE_UNUSED}, NULL},
+ {"background-attachment", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED},
+ Css_background_attachment_enum_vals},
{"background-color", {CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, NULL},
- {"background-image", {CSS_TYPE_UNUSED}, NULL},
- {"background-position", {CSS_TYPE_UNUSED}, NULL},
- {"background-repeat", {CSS_TYPE_UNUSED}, NULL},
+ {"background-image", {CSS_TYPE_URI, CSS_TYPE_UNUSED}, NULL},
+ {"background-position", {CSS_TYPE_BACKGROUND_POSITION, CSS_TYPE_UNUSED},
+ NULL},
+ {"background-repeat", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED},
+ Css_background_repeat_enum_vals},
{"border-bottom-color", {CSS_TYPE_ENUM, CSS_TYPE_COLOR, CSS_TYPE_UNUSED},
Css_border_color_enum_vals},
{"border-bottom-style", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED},
@@ -206,8 +217,8 @@ const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = {
Css_font_variant_enum_vals},
{"font-weight", {CSS_TYPE_ENUM, CSS_TYPE_FONT_WEIGHT, CSS_TYPE_UNUSED},
Css_font_weight_enum_vals},
- {"height", {CSS_TYPE_LENGTH_PERCENTAGE, CSS_TYPE_UNUSED}, NULL},
- {"left", {CSS_TYPE_LENGTH_PERCENTAGE, CSS_TYPE_UNUSED}, NULL},
+ {"height", {CSS_TYPE_LENGTH_PERCENTAGE, CSS_TYPE_AUTO, CSS_TYPE_UNUSED}, NULL},
+ {"left", {CSS_TYPE_UNUSED}, NULL},
{"letter-spacing", {CSS_TYPE_ENUM, CSS_TYPE_SIGNED_LENGTH, CSS_TYPE_UNUSED},
Css_letter_spacing_enum_vals},
{"line-height",
@@ -218,10 +229,14 @@ const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = {
Css_list_style_position_enum_vals},
{"list-style-type", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED},
Css_list_style_type_enum_vals},
- {"margin-bottom", {CSS_TYPE_SIGNED_LENGTH, CSS_TYPE_UNUSED}, NULL},
- {"margin-left", {CSS_TYPE_SIGNED_LENGTH, CSS_TYPE_UNUSED}, NULL},
- {"margin-right", {CSS_TYPE_SIGNED_LENGTH, CSS_TYPE_UNUSED}, NULL},
- {"margin-top", {CSS_TYPE_SIGNED_LENGTH, CSS_TYPE_UNUSED}, NULL},
+ {"margin-bottom",
+ {CSS_TYPE_SIGNED_LENGTH, CSS_TYPE_AUTO, CSS_TYPE_UNUSED}, NULL},
+ {"margin-left",
+ {CSS_TYPE_SIGNED_LENGTH, CSS_TYPE_AUTO, CSS_TYPE_UNUSED}, NULL},
+ {"margin-right",
+ {CSS_TYPE_SIGNED_LENGTH, CSS_TYPE_AUTO, CSS_TYPE_UNUSED}, NULL},
+ {"margin-top",
+ {CSS_TYPE_SIGNED_LENGTH, CSS_TYPE_AUTO, CSS_TYPE_UNUSED}, NULL},
{"marker-offset", {CSS_TYPE_UNUSED}, NULL},
{"marks", {CSS_TYPE_UNUSED}, NULL},
{"max-height", {CSS_TYPE_UNUSED}, NULL},
@@ -251,7 +266,7 @@ const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = {
{"vertical-align",{CSS_TYPE_ENUM, CSS_TYPE_UNUSED},Css_vertical_align_vals},
{"visibility", {CSS_TYPE_UNUSED}, NULL},
{"white-space", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, Css_white_space_vals},
- {"width", {CSS_TYPE_LENGTH_PERCENTAGE, CSS_TYPE_UNUSED}, NULL},
+ {"width", {CSS_TYPE_LENGTH_PERCENTAGE, CSS_TYPE_AUTO, CSS_TYPE_UNUSED}, NULL},
{"word-spacing", {CSS_TYPE_ENUM, CSS_TYPE_SIGNED_LENGTH, CSS_TYPE_UNUSED},
Css_word_spacing_enum_vals},
{"z-index", {CSS_TYPE_UNUSED}, NULL},
@@ -706,6 +721,15 @@ bool CssParser::tokenMatchesProperty(CssPropertyName prop, CssValueType *type)
}
break;
+ case CSS_TYPE_BACKGROUND_POSITION:
+ if (ttype == CSS_TK_SYMBOL &&
+ (dStrAsciiCasecmp(tval, "center") == 0 ||
+ dStrAsciiCasecmp(tval, "left") == 0 ||
+ dStrAsciiCasecmp(tval, "right") == 0 ||
+ dStrAsciiCasecmp(tval, "top") == 0 ||
+ dStrAsciiCasecmp(tval, "bottom") == 0))
+ return true;
+ // Fall Through (lenght and percentage)
case CSS_TYPE_LENGTH_PERCENTAGE:
case CSS_TYPE_LENGTH_PERCENTAGE_NUMBER:
case CSS_TYPE_LENGTH:
@@ -713,9 +737,12 @@ bool CssParser::tokenMatchesProperty(CssPropertyName prop, CssValueType *type)
return false;
// Fall Through
case CSS_TYPE_SIGNED_LENGTH:
- if (ttype == CSS_TK_DECINT ||
- ttype == CSS_TK_FLOAT ||
- (ttype == CSS_TK_SYMBOL && dStrAsciiCasecmp(tval, "auto") == 0))
+ if (ttype == CSS_TK_DECINT || ttype == CSS_TK_FLOAT)
+ return true;
+ break;
+
+ case CSS_TYPE_AUTO:
+ if (ttype == CSS_TK_SYMBOL && dStrAsciiCasecmp(tval, "auto") == 0)
return true;
break;
@@ -746,6 +773,12 @@ bool CssParser::tokenMatchesProperty(CssPropertyName prop, CssValueType *type)
}
break;
+ case CSS_TYPE_URI:
+ if (ttype == CSS_TK_SYMBOL &&
+ dStrAsciiCasecmp(tval, "url") == 0)
+ return true;
+ break;
+
case CSS_TYPE_UNUSED:
case CSS_TYPE_INTEGER:
/* Not used for parser values. */
@@ -939,13 +972,16 @@ bool CssParser::parseValue(CssPropertyName prop,
ret = true;
val->intVal = CSS_CREATE_LENGTH(fval, lentype);
- } else if (ttype == CSS_TK_SYMBOL && !dStrAsciiCasecmp(tval, "auto")) {
- ret = true;
- val->intVal = CSS_LENGTH_TYPE_AUTO;
- nextToken();
}
break;
+ case CSS_TYPE_AUTO:
+ assert (ttype == CSS_TK_SYMBOL && !dStrAsciiCasecmp(tval, "auto"));
+ ret = true;
+ val->intVal = CSS_LENGTH_TYPE_AUTO;
+ nextToken();
+ break;
+
case CSS_TYPE_COLOR:
if (ttype == CSS_TK_COLOR) {
val->intVal = a_Color_parse(tval, -1, &err);
@@ -1016,6 +1052,107 @@ bool CssParser::parseValue(CssPropertyName prop,
}
break;
+ case CSS_TYPE_URI:
+ if (ttype == CSS_TK_SYMBOL &&
+ dStrAsciiCasecmp(tval, "url") == 0) {
+ val->strVal = parseUrl();
+ nextToken();
+ if (val->strVal)
+ ret = true;
+ }
+ break;
+
+ case CSS_TYPE_BACKGROUND_POSITION:
+ // 'background-position' consists of one or two values: vertical and
+ // horizontal position; in most cases in this order. However, as long it
+ // is unambigous, the order can be switched: "10px left" and "left 10px"
+ // are both possible and have the same effect. For this reason, all
+ // possibilities are tested in parallel.
+
+ bool h[2], v[2];
+ int pos[2];
+ h[0] = v[0] = h[1] = v[1] = false;
+
+ // First: collect values in pos[0] and pos[1], and determine whether
+ // they can be used for a horizontal (h[i]) or vertical (v[i]) position
+ // (or both). When neither h[i] or v[i] is set, pos[i] is undefined.
+ for (i = 0; i < 2; i++) {
+ CssValueType typeTmp;
+ // tokenMatchesProperty will, for CSS_PROPERTY_BACKGROUND_POSITION,
+ // work on both parts, since they are exchangable.
+ if (tokenMatchesProperty (CSS_PROPERTY_BACKGROUND_POSITION,
+ &typeTmp)) {
+ h[i] = ttype != CSS_TK_SYMBOL ||
+ (dStrAsciiCasecmp(tval, "top") != 0 &&
+ dStrAsciiCasecmp(tval, "bottom") != 0);
+ v[i] = ttype != CSS_TK_SYMBOL ||
+ (dStrAsciiCasecmp(tval, "left") != 0 &&
+ dStrAsciiCasecmp(tval, "right") != 0);
+ } else
+ // No match.
+ h[i] = v[i] = false;
+
+ if (h[i] || v[i]) {
+ // Calculate values.
+ if (ttype == CSS_TK_SYMBOL) {
+ if (dStrAsciiCasecmp(tval, "top") == 0 ||
+ dStrAsciiCasecmp(tval, "left") == 0) {
+ pos[i] = CSS_CREATE_LENGTH (0.0, CSS_LENGTH_TYPE_PERCENTAGE);
+ nextToken();
+ } else if (dStrAsciiCasecmp(tval, "center") == 0) {
+ pos[i] = CSS_CREATE_LENGTH (0.5, CSS_LENGTH_TYPE_PERCENTAGE);
+ nextToken();
+ } else if (dStrAsciiCasecmp(tval, "bottom") == 0 ||
+ dStrAsciiCasecmp(tval, "right") == 0) {
+ pos[i] = CSS_CREATE_LENGTH (1.0, CSS_LENGTH_TYPE_PERCENTAGE);
+ nextToken();
+ } else
+ // tokenMatchesProperty should have returned "false" already.
+ lout::misc::assertNotReached ();
+ } else {
+ // We can assume <length> or <percentage> here ...
+ CssPropertyValue valTmp;
+ if (parseValue(prop, CSS_TYPE_LENGTH_PERCENTAGE, &valTmp)) {
+ pos[i] = valTmp.intVal;
+ ret = true;
+ } else
+ // ... but something may still fail.
+ h[i] = v[i] = false;
+ }
+ }
+
+ // If the first value cannot be read, do not read the second.
+ if (!h[i] && !v[i])
+ break;
+ }
+
+ // Second: Create the final value. Order will be determined here.
+ if (v[0] || h[0]) {
+ // If second value is not set, it is set to "center", i. e. 50%, (see
+ // CSS specification), which is suitable for both dimensions.
+ if (!h[1] && !v[1]) {
+ pos[1] = CSS_CREATE_LENGTH (0.5, CSS_LENGTH_TYPE_PERCENTAGE);
+ h[1] = v[1] = true;
+ }
+
+ // Only valid, when a combination h/v or v/h is possible.
+ if ((h[0] && v[1]) || (v[0] && h[1])) {
+ ret = true;
+ val->posVal = dNew(CssBackgroundPosition, 1);
+
+ // Prefer combination h/v:
+ if (h[0] && v[1]) {
+ val->posVal->posX = pos[0];
+ val->posVal->posY = pos[1];
+ } else {
+ // This should be v/h:
+ val->posVal->posX = pos[1];
+ val->posVal->posY = pos[0];
+ }
+ }
+ }
+ break;
+
case CSS_TYPE_UNUSED:
/* nothing */
break;