Changed: background shorthand parsing

--HG--
branch : develop
This commit is contained in:
Nimetu 2019-05-04 10:18:24 +03:00
parent 4f4ba7120d
commit 7ca3b85c54
2 changed files with 215 additions and 47 deletions

View file

@ -227,7 +227,7 @@ namespace NLGUI
// child of - immediate parent must match previous selector // child of - immediate parent must match previous selector
if (!child->parent) if (!child->parent)
{ {
return false; return false;
} }
child = child->parent; child = child->parent;
mustMatchNext = true; mustMatchNext = true;
@ -430,8 +430,8 @@ namespace NLGUI
} }
} }
// second pass: rest of style // second pass: use style own StyleRules as its updated from first pass
for (it=styleRules.begin(); it != styleRules.end(); ++it) for (it=style.StyleRules.begin(); it != style.StyleRules.end(); ++it)
{ {
if (it->first == "border" || it->first == "border-width") if (it->first == "border" || it->first == "border-width")
{ {
@ -456,7 +456,7 @@ namespace NLGUI
{ {
style.BorderWidth = 5; style.BorderWidth = 5;
} }
else else
{ {
std::string unit; std::string unit;
if (getCssLength(tmpf, unit, it->second.c_str())) if (getCssLength(tmpf, unit, it->second.c_str()))
@ -763,7 +763,7 @@ namespace NLGUI
else if (it->second == "transparent") else if (it->second == "transparent")
style.BackgroundColorOver = CRGBA(0, 0, 0, 0); style.BackgroundColorOver = CRGBA(0, 0, 0, 0);
else if (it->second == "currentcolor") else if (it->second == "currentcolor")
style.BackgroundColorOver = style.TextColor; style.BackgroundColorOver = style.TextColor;
else else
scanHTMLColor(it->second.c_str(), style.BackgroundColorOver); scanHTMLColor(it->second.c_str(), style.BackgroundColorOver);
} }
@ -795,115 +795,278 @@ namespace NLGUI
"background-attachment", "background-origin", "background-clip", "background-color"}; "background-attachment", "background-origin", "background-clip", "background-color"};
std::string values[nbProps]; std::string values[nbProps];
bool found[nbProps] = {false}; bool found[nbProps] = {false};
bool bgClipFound = false;
std::string bgClipValue;
std::string bgPositionX;
std::string bgPositionY;
uint partIndex = 0; uint partIndex = 0;
std::vector<std::string> parts; std::vector<std::string> parts;
std::vector<std::string>::iterator it; std::vector<std::string>::iterator it;
// FIXME: this will fail if url() contains ' ' chars // FIXME: this will fail if url() contains ' ' chars
// FIXME: this will also fail on 'background: rgb(255, 0, 0)'
NLMISC::splitString(value, " ", parts); NLMISC::splitString(value, " ", parts);
bool failed = false; 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++) for(uint i = 0; i < nbProps; i++)
{ {
if (found[i]) if (found[i]) continue;
{
continue;
}
if (props[i] == "background-image") if (props[i] == "background-image")
{ {
if (val.substr(0, 4) == "url(") if (val.substr(0, 4) == "url(")
{ {
matches = true;
found[i] = true;
// use original value as 'val' is lowercase // use original value as 'val' is lowercase
values[i] = parts[index]; values[i] = parts[index];
found[i] = true;
} }
} }
else if (props[i] == "background-position") 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") else if (props[i] == "background-size")
{ {
// TODO: [<length-percentage> | 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") else if (props[i] == "background-repeat")
{ {
if (val == "repeat-x" || val == "repeat-y" || val == "repeat" || val == "space" || val == "round" || val == "no-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") if (val == "repeat-x")
{ {
values[i] = "repeat no-repeat"; values[i] = "repeat no-repeat";
} }
else if (val == "repeat-y") else if (val == "repeat-y")
{ {
values[i] = "no-repeat repeat"; values[i] = "no-repeat repeat";
} }
else else
{ {
std::string horiz = val; std::string horiz = val;
std::string vert = 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])); val = toLower(parts[next]);
if (next == "repeat" || next == "space" || next == "round" || next == "no-repeat") if (val == "repeat" || val == "space" || val == "round" || val == "no-repeat")
{ {
vert = next; vert = val;
index++; index = next;
} }
} }
if (vert == horiz)
values[i] = horiz + " " + vert; values[i] = vert;
else
values[i] = horiz + " " + vert;
} }
found[i] = true;
} }
} }
else if (props[i] == "background-attachment") 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") if (val == "padding-box" || val == "border-box" || val == "content-box")
{ {
values[i] = val; matches = true;
found[i] = 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") else if (props[i] == "background-color")
{ {
CRGBA color; CRGBA color;
if (!scanHTMLColor(val.c_str(), color)) if (val == "transparent" || val == "currentcolor" || scanHTMLColor(val.c_str(), color))
{ {
failed = true; matches = true;
break; 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 // invalidate whole rule
if (failed) 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++) for(uint i = 0; i < nbProps; i++)
{ {
if (found[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 else
{ {
@ -914,27 +1077,32 @@ namespace NLGUI
} }
else if (props[i] == "background-position") 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") else if (props[i] == "background-size")
{ {
//style.StyleRules[props[i]] = "auto auto"; style.StyleRules[props[i]] = "auto auto";
} }
else if (props[i] == "background-repeat") else if (props[i] == "background-repeat")
{ {
style.StyleRules[props[i]] = "repeat repeat"; style.StyleRules[props[i]] = "repeat";
} }
else if(props[i] == "background-attachment") else if(props[i] == "background-attachment")
{ {
//style.StyleRules[props[i]] = "scroll"; style.StyleRules[props[i]] = "scroll";
} }
else if(props[i] == "background-origin") else if(props[i] == "background-origin")
{ {
//style.StyleRules[props[i]] = "padding-box"; style.StyleRules[props[i]] = "padding-box";
} }
else if (props[i] == "background-clip") 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") else if (props[i] == "background-color")
{ {

View file

@ -3545,7 +3545,7 @@ namespace NLGUI
// todo handle unicode POST here // todo handle unicode POST here
if (form.Entries[i].Checkbox->getPushed ()) if (form.Entries[i].Checkbox->getPushed ())
{ {
entryData = form.Entries[i].Value; entryData = form.Entries[i].Value;
addEntry = true; addEntry = true;
} }
} }
@ -5048,7 +5048,7 @@ namespace NLGUI
// TODO: else // TODO: else
// default background color is transparent, so image does not show // 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;"); _Style.applyStyle("background-color: #fff;");
} }