diff options
author | Sebastian Geerken <devnull@localhost> | 2013-12-09 14:44:42 +0100 |
---|---|---|
committer | Sebastian Geerken <devnull@localhost> | 2013-12-09 14:44:42 +0100 |
commit | 01f697091153846bdffc73b3150ba37c763301cc (patch) | |
tree | 84773dff07a8498e7cc62695d89a6ecb29378a82 /src/cssparser.cc | |
parent | ee66f4f97e38d11e68b9515b7043aa8ac6f63c74 (diff) | |
parent | 6c7572f8bd23064f96ba716e1ba8ba8a34847001 (diff) |
Merge (large!).
Diffstat (limited to 'src/cssparser.cc')
-rw-r--r-- | src/cssparser.cc | 173 |
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; |