From 7ca3b85c5468da8c7d8c90fd862886a03a607a6c Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sat, 4 May 2019 10:18:24 +0300 Subject: [PATCH] Changed: background shorthand parsing --HG-- branch : develop --- code/nel/src/gui/css_style.cpp | 258 ++++++++++++++++++++++++++------ code/nel/src/gui/group_html.cpp | 4 +- 2 files changed, 215 insertions(+), 47 deletions(-) diff --git a/code/nel/src/gui/css_style.cpp b/code/nel/src/gui/css_style.cpp index 88e438870..8dcfa5deb 100644 --- a/code/nel/src/gui/css_style.cpp +++ b/code/nel/src/gui/css_style.cpp @@ -227,7 +227,7 @@ namespace NLGUI // child of - immediate parent must match previous selector if (!child->parent) { - return false; + return false; } child = child->parent; mustMatchNext = true; @@ -430,8 +430,8 @@ namespace NLGUI } } - // second pass: rest of style - for (it=styleRules.begin(); it != styleRules.end(); ++it) + // second pass: use style own StyleRules as its updated from first pass + for (it=style.StyleRules.begin(); it != style.StyleRules.end(); ++it) { if (it->first == "border" || it->first == "border-width") { @@ -456,7 +456,7 @@ namespace NLGUI { style.BorderWidth = 5; } - else + else { std::string unit; if (getCssLength(tmpf, unit, it->second.c_str())) @@ -763,7 +763,7 @@ namespace NLGUI else if (it->second == "transparent") style.BackgroundColorOver = CRGBA(0, 0, 0, 0); else if (it->second == "currentcolor") - style.BackgroundColorOver = style.TextColor; + style.BackgroundColorOver = style.TextColor; else scanHTMLColor(it->second.c_str(), style.BackgroundColorOver); } @@ -795,115 +795,278 @@ namespace NLGUI "background-attachment", "background-origin", "background-clip", "background-color"}; std::string values[nbProps]; bool found[nbProps] = {false}; - + bool bgClipFound = false; + std::string bgClipValue; + std::string bgPositionX; + std::string bgPositionY; uint partIndex = 0; std::vector parts; std::vector::iterator it; // FIXME: this will fail if url() contains ' ' chars + // FIXME: this will also fail on 'background: rgb(255, 0, 0)' NLMISC::splitString(value, " ", parts); bool failed = false; - for(uint index = 0; index < parts.size(); index++) + bool allowSize = false; + uint index = 0; + while(!failed && index < parts.size()) { - const std::string val = toLower(trim(parts[index])); - + std::string val = toLower(parts[index]); + bool matches = false; for(uint i = 0; i < nbProps; i++) { - if (found[i]) - { - continue; - } + if (found[i]) continue; if (props[i] == "background-image") { if (val.substr(0, 4) == "url(") { + matches = true; + found[i] = true; // use original value as 'val' is lowercase values[i] = parts[index]; - found[i] = true; } } else if (props[i] == "background-position") { - // TODO: + uint next = index; + bool loop = false; + do + { + float fval; + std::string unit; + + // first loop -> true + // second loop -> false && break + loop = !loop; + + val = toLower(parts[next]); + if (val == "center") + { + if (bgPositionX.empty()) bgPositionX = "center"; + if (bgPositionY.empty()) bgPositionY = "center"; + // consume 'center' + next++; + } + else if (val == "left" || val == "right") + { + bgPositionX = val; + // consume 'left|right' + next++; + if(next < parts.size() && getCssLength(fval, unit, parts[next])) + { + bgPositionX += " " + toString("%.0f%s", fval, unit.c_str()); + // consume css length + next++; + } + } + else if (val == "top" || val == "bottom") + { + bgPositionY = val; + // consume top|bottom + next++; + if (next < parts.size() && getCssLength(fval, unit, parts[next])) + { + bgPositionY += " " + toString("%.0f%s", fval, unit.c_str()); + // consume css length + next++; + } + } + } while (loop); + + // + if (!bgPositionX.empty() && !bgPositionY.empty()) + { + matches = true; + found[i] = true; + // consume position values if there were any + index = next-1; + + // look ahead to see if size is next + if (next < parts.size() && parts[next] == "/") + allowSize = true; + } } else if (props[i] == "background-size") { - // TODO: [ | auto ]{1,2} cover | contain + if (allowSize && val == "/") + { + uint next = index + 1; + if (next < parts.size()) + { + val = toLower(parts[next]); + if (val == "cover" || val == "contain") + { + matches = true; + found[i] = true; + values[i] = val; + index = next; + } + else + { + float fval; + std::string unit; + std::string h, v; + + if (val == "auto" || getCssLength(fval, unit, val)) + { + if (val == "auto") + h = v = "auto"; + else + h = v = toString("%.0f%s", fval, unit.c_str()); + + next++; + if (next < parts.size()) + { + val = toLower(parts[next]); + if (val == "auto") + v = "auto"; + else if (getCssLength(fval, unit, val)) + v = toString("%.0f%s", fval, unit.c_str()); + else + next--; // not size token + } + else + { + // not size token + next--; + } + } + + if (!h.empty() && !v.empty()) + { + matches = true; + found[i] = true; + values[i] = h + " " + v; + index = next; + } + } + } + else + { + // no size, just '/' + failed = true; + break; + } + } } else if (props[i] == "background-repeat") { if (val == "repeat-x" || val == "repeat-y" || val == "repeat" || val == "space" || val == "round" || val == "no-repeat") { + matches = true; + found[i] = true; + if (val == "repeat-x") { values[i] = "repeat no-repeat"; } else if (val == "repeat-y") { - values[i] = "no-repeat repeat"; + values[i] = "no-repeat repeat"; } else { std::string horiz = val; std::string vert = val; - if (index+1 < parts.size()) + uint next = index + 1; + if (next < parts.size()) { - std::string next = toLower(trim(parts[index+1])); - if (next == "repeat" || next == "space" || next == "round" || next == "no-repeat") + val = toLower(parts[next]); + if (val == "repeat" || val == "space" || val == "round" || val == "no-repeat") { - vert = next; - index++; + vert = val; + index = next; } } - - values[i] = horiz + " " + vert; + if (vert == horiz) + values[i] = vert; + else + values[i] = horiz + " " + vert; } - - found[i] = true; } } else if (props[i] == "background-attachment") { - // TODO: scroll | fixed | local + if (val == "scroll" || val == "fixed" || val == "local") + { + matches = true; + found[i] = true; + values[i] = val; + } } - else if (props[i] == "background-origin" || props[i] == "background-clip") + else if (props[i] == "background-origin") { - // same values for both if (val == "padding-box" || val == "border-box" || val == "content-box") { - values[i] = val; + matches = true; found[i] = true; + values[i] = val; + + // first time background-origin is set, also set background-clip + if (!bgClipFound) + bgClipValue = val; + } + } + else if (props[i] == "background-clip") + { + if (val == "text" || val == "padding-box" || val == "border-box" || val == "content-box") + { + matches = true; + found[i] = true; + bgClipFound = true; + bgClipValue = val; } } else if (props[i] == "background-color") { CRGBA color; - if (!scanHTMLColor(val.c_str(), color)) + if (val == "transparent" || val == "currentcolor" || scanHTMLColor(val.c_str(), color)) { - failed = true; - break; + matches = true; + found[i] = true; + values[i] = val; } - values[i] = val; - // color should come as last item - break; } + + // prop was found and parsed + if (found[i]) + break; } + failed = !matches; + + index++; } // invalidate whole rule if (failed) { - return; + bgClipFound = false; + for(uint i = 0; i < nbProps; i++) + { + found[i] = false; + } } - // apply found styles + // apply found styles or use default for(uint i = 0; i < nbProps; i++) { if (found[i]) { - style.StyleRules[props[i]] = values[i]; + if (props[i] == "background-position") + { + style.StyleRules["background-position-x"] = bgPositionX; + style.StyleRules["background-position-y"] = bgPositionY; + } + else if (props[i] == "background-clip") + { + style.StyleRules["background-clip"] = bgClipValue; + } + else + { + style.StyleRules[props[i]] = values[i]; + } } else { @@ -914,27 +1077,32 @@ namespace NLGUI } else if (props[i] == "background-position") { - //style.StyleRules[props[i]] = "0% 0%"; + style.StyleRules[props[i]] = "0% 0%"; + style.StyleRules["background-position-x"] = "left 0%"; + style.StyleRules["background-position-y"] = "top 0%"; } else if (props[i] == "background-size") { - //style.StyleRules[props[i]] = "auto auto"; + style.StyleRules[props[i]] = "auto auto"; } else if (props[i] == "background-repeat") { - style.StyleRules[props[i]] = "repeat repeat"; + style.StyleRules[props[i]] = "repeat"; } else if(props[i] == "background-attachment") { - //style.StyleRules[props[i]] = "scroll"; + style.StyleRules[props[i]] = "scroll"; } else if(props[i] == "background-origin") { - //style.StyleRules[props[i]] = "padding-box"; + style.StyleRules[props[i]] = "padding-box"; } else if (props[i] == "background-clip") { - //style.StyleRules[props[i]] = "border-box"; + if (bgClipFound) + style.StyleRules[props[i]] = bgClipValue; + else + style.StyleRules[props[i]] = "border-box"; } else if (props[i] == "background-color") { diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index e11369014..a6ced170f 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -3545,7 +3545,7 @@ namespace NLGUI // todo handle unicode POST here if (form.Entries[i].Checkbox->getPushed ()) { - entryData = form.Entries[i].Value; + entryData = form.Entries[i].Value; addEntry = true; } } @@ -5048,7 +5048,7 @@ namespace NLGUI // TODO: else // default background color is transparent, so image does not show - if (!_Style.hasStyle("background-color")) + if (!_Style.hasStyle("background-color") || _Style.checkStyle("background-color", "transparent")) { _Style.applyStyle("background-color: #fff;"); }