mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-12-01 18:45:39 +00:00
Squashed 'external/lunasvg/' changes from a92aa90fa..0562a5dcc
0562a5dcc Support SVG files with invalid size #117 5732df547 Refactor parsePath git-subtree-dir: external/lunasvg git-subtree-split: 0562a5dcc8c25e59c060ee73d6d4d538f172d642
This commit is contained in:
parent
aad9e2d48d
commit
f44be39f5e
|
@ -173,6 +173,7 @@ Path Parser::parsePath(const std::string& string)
|
||||||
return Path{};
|
return Path{};
|
||||||
|
|
||||||
auto command = *ptr++;
|
auto command = *ptr++;
|
||||||
|
auto lastCommand = command;
|
||||||
double c[6];
|
double c[6];
|
||||||
bool f[2];
|
bool f[2];
|
||||||
|
|
||||||
|
@ -184,9 +185,7 @@ Path Parser::parsePath(const std::string& string)
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
Utils::skipWs(ptr, end);
|
Utils::skipWs(ptr, end);
|
||||||
switch(command) {
|
if(command == 'M' || command == 'm') {
|
||||||
case 'M':
|
|
||||||
case 'm':
|
|
||||||
if(!parseNumberList(ptr, end, c, 2))
|
if(!parseNumberList(ptr, end, c, 2))
|
||||||
return path;
|
return path;
|
||||||
|
|
||||||
|
@ -197,12 +196,10 @@ Path Parser::parsePath(const std::string& string)
|
||||||
}
|
}
|
||||||
|
|
||||||
path.moveTo(c[0], c[1]);
|
path.moveTo(c[0], c[1]);
|
||||||
startPoint.x = currentPoint.x = controlPoint.x = c[0];
|
startPoint.x = currentPoint.x = c[0];
|
||||||
startPoint.y = currentPoint.y = controlPoint.y = c[1];
|
startPoint.y = currentPoint.y = c[1];
|
||||||
command = command == 'm' ? 'l' : 'L';
|
command = command == 'm' ? 'l' : 'L';
|
||||||
break;
|
} else if(command == 'L' || command == 'l') {
|
||||||
case 'L':
|
|
||||||
case 'l':
|
|
||||||
if(!parseNumberList(ptr, end, c, 2))
|
if(!parseNumberList(ptr, end, c, 2))
|
||||||
return path;
|
return path;
|
||||||
|
|
||||||
|
@ -213,11 +210,27 @@ Path Parser::parsePath(const std::string& string)
|
||||||
}
|
}
|
||||||
|
|
||||||
path.lineTo(c[0], c[1]);
|
path.lineTo(c[0], c[1]);
|
||||||
currentPoint.x = controlPoint.x = c[0];
|
currentPoint.x = c[0];
|
||||||
currentPoint.y = controlPoint.y = c[1];
|
currentPoint.y = c[1];
|
||||||
break;
|
} else if(command == 'H' || command == 'h') {
|
||||||
case 'Q':
|
if(!parseNumberList(ptr, end, c, 1))
|
||||||
case 'q':
|
return path;
|
||||||
|
|
||||||
|
if(command == 'h')
|
||||||
|
c[0] += currentPoint.x;
|
||||||
|
|
||||||
|
path.lineTo(c[0], currentPoint.y);
|
||||||
|
currentPoint.x = c[0];
|
||||||
|
} else if(command == 'V' || command == 'v') {
|
||||||
|
if(!parseNumberList(ptr, end, c + 1, 1))
|
||||||
|
return path;
|
||||||
|
|
||||||
|
if(command == 'v')
|
||||||
|
c[1] += currentPoint.y;
|
||||||
|
|
||||||
|
path.lineTo(currentPoint.x, c[1]);
|
||||||
|
currentPoint.y = c[1];
|
||||||
|
} else if(command == 'Q' || command == 'q') {
|
||||||
if(!parseNumberList(ptr, end, c, 4))
|
if(!parseNumberList(ptr, end, c, 4))
|
||||||
return path;
|
return path;
|
||||||
|
|
||||||
|
@ -234,9 +247,7 @@ Path Parser::parsePath(const std::string& string)
|
||||||
controlPoint.y = c[1];
|
controlPoint.y = c[1];
|
||||||
currentPoint.x = c[2];
|
currentPoint.x = c[2];
|
||||||
currentPoint.y = c[3];
|
currentPoint.y = c[3];
|
||||||
break;
|
} else if(command == 'C' || command == 'c') {
|
||||||
case 'C':
|
|
||||||
case 'c':
|
|
||||||
if(!parseNumberList(ptr, end, c, 6))
|
if(!parseNumberList(ptr, end, c, 6))
|
||||||
return path;
|
return path;
|
||||||
|
|
||||||
|
@ -255,11 +266,15 @@ Path Parser::parsePath(const std::string& string)
|
||||||
controlPoint.y = c[3];
|
controlPoint.y = c[3];
|
||||||
currentPoint.x = c[4];
|
currentPoint.x = c[4];
|
||||||
currentPoint.y = c[5];
|
currentPoint.y = c[5];
|
||||||
break;
|
} else if(command == 'T' || command == 't') {
|
||||||
case 'T':
|
if(lastCommand != 'Q' && lastCommand != 'q' && lastCommand != 'T' && lastCommand != 't') {
|
||||||
case 't':
|
c[0] = currentPoint.x;
|
||||||
|
c[1] = currentPoint.y;
|
||||||
|
} else {
|
||||||
c[0] = 2 * currentPoint.x - controlPoint.x;
|
c[0] = 2 * currentPoint.x - controlPoint.x;
|
||||||
c[1] = 2 * currentPoint.y - controlPoint.y;
|
c[1] = 2 * currentPoint.y - controlPoint.y;
|
||||||
|
}
|
||||||
|
|
||||||
if(!parseNumberList(ptr, end, c + 2, 2))
|
if(!parseNumberList(ptr, end, c + 2, 2))
|
||||||
return path;
|
return path;
|
||||||
|
|
||||||
|
@ -274,11 +289,15 @@ Path Parser::parsePath(const std::string& string)
|
||||||
controlPoint.y = c[1];
|
controlPoint.y = c[1];
|
||||||
currentPoint.x = c[2];
|
currentPoint.x = c[2];
|
||||||
currentPoint.y = c[3];
|
currentPoint.y = c[3];
|
||||||
break;
|
} else if(command == 'S' || command == 's') {
|
||||||
case 'S':
|
if(lastCommand != 'C' && lastCommand != 'c' && lastCommand != 'S' && lastCommand != 's') {
|
||||||
case 's':
|
c[0] = currentPoint.x;
|
||||||
|
c[1] = currentPoint.y;
|
||||||
|
} else {
|
||||||
c[0] = 2 * currentPoint.x - controlPoint.x;
|
c[0] = 2 * currentPoint.x - controlPoint.x;
|
||||||
c[1] = 2 * currentPoint.y - controlPoint.y;
|
c[1] = 2 * currentPoint.y - controlPoint.y;
|
||||||
|
}
|
||||||
|
|
||||||
if(!parseNumberList(ptr, end, c + 2, 4))
|
if(!parseNumberList(ptr, end, c + 2, 4))
|
||||||
return path;
|
return path;
|
||||||
|
|
||||||
|
@ -295,33 +314,7 @@ Path Parser::parsePath(const std::string& string)
|
||||||
controlPoint.y = c[3];
|
controlPoint.y = c[3];
|
||||||
currentPoint.x = c[4];
|
currentPoint.x = c[4];
|
||||||
currentPoint.y = c[5];
|
currentPoint.y = c[5];
|
||||||
break;
|
} else if(command == 'A' || command == 'a') {
|
||||||
case 'H':
|
|
||||||
case 'h':
|
|
||||||
if(!parseNumberList(ptr, end, c, 1))
|
|
||||||
return path;
|
|
||||||
|
|
||||||
if(command == 'h')
|
|
||||||
c[0] += currentPoint.x;
|
|
||||||
|
|
||||||
path.lineTo(c[0], currentPoint.y);
|
|
||||||
currentPoint.x = controlPoint.x = c[0];
|
|
||||||
controlPoint.y = currentPoint.y;
|
|
||||||
break;
|
|
||||||
case 'V':
|
|
||||||
case 'v':
|
|
||||||
if(!parseNumberList(ptr, end, c + 1, 1))
|
|
||||||
return path;
|
|
||||||
|
|
||||||
if(command == 'v')
|
|
||||||
c[1] += currentPoint.y;
|
|
||||||
|
|
||||||
path.lineTo(currentPoint.x, c[1]);
|
|
||||||
controlPoint.x = currentPoint.x;
|
|
||||||
currentPoint.y = controlPoint.y = c[1];
|
|
||||||
break;
|
|
||||||
case 'A':
|
|
||||||
case 'a':
|
|
||||||
if(!parseNumberList(ptr, end, c, 3)
|
if(!parseNumberList(ptr, end, c, 3)
|
||||||
|| !parseArcFlag(ptr, end, f[0])
|
|| !parseArcFlag(ptr, end, f[0])
|
||||||
|| !parseArcFlag(ptr, end, f[1])
|
|| !parseArcFlag(ptr, end, f[1])
|
||||||
|
@ -335,16 +328,13 @@ Path Parser::parsePath(const std::string& string)
|
||||||
}
|
}
|
||||||
|
|
||||||
path.arcTo(currentPoint.x, currentPoint.y, c[0], c[1], c[2], f[0], f[1], c[3], c[4]);
|
path.arcTo(currentPoint.x, currentPoint.y, c[0], c[1], c[2], f[0], f[1], c[3], c[4]);
|
||||||
currentPoint.x = controlPoint.x = c[3];
|
currentPoint.x = c[3];
|
||||||
currentPoint.y = controlPoint.y = c[4];
|
currentPoint.y = c[4];
|
||||||
break;
|
} else if(command == 'Z' || command == 'z') {
|
||||||
case 'Z':
|
|
||||||
case 'z':
|
|
||||||
path.close();
|
path.close();
|
||||||
currentPoint.x = controlPoint.x = startPoint.x;
|
currentPoint.x = startPoint.x;
|
||||||
currentPoint.y = controlPoint.y = startPoint.y;
|
currentPoint.y = startPoint.y;
|
||||||
break;
|
} else {
|
||||||
default:
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,6 +342,7 @@ Path Parser::parsePath(const std::string& string)
|
||||||
if(ptr >= end)
|
if(ptr >= end)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
lastCommand = command;
|
||||||
if(IS_ALPHA(*ptr))
|
if(IS_ALPHA(*ptr))
|
||||||
command = *ptr++;
|
command = *ptr++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,12 @@ std::unique_ptr<LayoutSymbol> SVGElement::build(const TreeBuilder* builder) cons
|
||||||
root->masker = context.getMasker(mask());
|
root->masker = context.getMasker(mask());
|
||||||
root->clipper = context.getClipper(clip_path());
|
root->clipper = context.getClipper(clip_path());
|
||||||
layoutChildren(&context, root.get());
|
layoutChildren(&context, root.get());
|
||||||
|
if((w.isRelative() || h.isRelative()) && !has(PropertyID::ViewBox)) {
|
||||||
|
auto box = root->map(root->strokeBoundingBox());
|
||||||
|
root->width = w.value(box.x + box.w);
|
||||||
|
root->height = h.value(box.y + box.h);
|
||||||
|
}
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue