diff options
author | Sebastian Geerken <devnull@localhost> | 2013-10-01 14:57:30 +0200 |
---|---|---|
committer | Sebastian Geerken <devnull@localhost> | 2013-10-01 14:57:30 +0200 |
commit | 8ef9399d0e4f92ebb00d7cc6c0ec273c4b5ca4bd (patch) | |
tree | 62d58090b5d74252b8b34a6d67f2448d8186c0e4 /src/cssparser.cc | |
parent | 1bc80ace64c68cad386bdcb3efc37fd9a8ccc558 (diff) |
Parsing of <background-position> is complete.
Diffstat (limited to 'src/cssparser.cc')
-rw-r--r-- | src/cssparser.cc | 105 |
1 files changed, 97 insertions, 8 deletions
diff --git a/src/cssparser.cc b/src/cssparser.cc index ed90f275..ce6225dd 100644 --- a/src/cssparser.cc +++ b/src/cssparser.cc @@ -706,6 +706,14 @@ 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: @@ -1033,14 +1041,95 @@ bool CssParser::parseValue(CssPropertyName prop, break; case CSS_TYPE_BACKGROUND_POSITION: - CssPropertyValue posX, posY; - if (parseValue(prop, CSS_TYPE_LENGTH_PERCENTAGE, &posX) && - parseValue(prop, CSS_TYPE_LENGTH_PERCENTAGE, &posY)) { - CssBackgroundPosition *position = (CssBackgroundPosition *) malloc(sizeof(CssBackgroundPosition)); - position->posX = posX.intVal; - position->posY = posY.intVal; - val->posVal = position; - ret = true; + // '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 parrallel. + + 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; + CssBackgroundPosition *position = + (CssBackgroundPosition *) malloc(sizeof(CssBackgroundPosition)); + val->posVal = position; + + // Prefer combination h/v: + if (h[0] && v[1]) { + position->posX = pos[0]; + position->posY = pos[1]; + } else { + // This should be v/h: + position->posX = pos[1]; + position->posY = pos[0]; + } + } } break; |