loader/svg: Ignore unrecognized commands following 'z'

If the command after `m` is not recognized, it must be recognized as `l` or `L`.
However, if it is not recognized after ending with `z`, all commands after it are ignored.

```
<svg width="100" version="1.0" xmlns="http://www.w3.org/2000/svg" height="100" xmlns:xlink="http://www.w3.org/1999/xlink">

<path style="stroke:#F00" d="m 20,20 0,50 50 0 -50 -50 z  70,70 0,50 50 0 -50 -50 z  "/>

</svg>
```
This commit is contained in:
JunsuChoi 2024-04-05 17:16:34 +09:00 committed by Hermet Park
parent 75e587a9a9
commit 387d82a80e

View file

@ -311,7 +311,7 @@ static int _numberCount(char cmd)
}
static bool _processCommand(Array<PathCommand>* cmds, Array<Point>* pts, char cmd, float* arr, int count, Point* cur, Point* curCtl, Point* startPoint, bool *isQuadratic)
static bool _processCommand(Array<PathCommand>* cmds, Array<Point>* pts, char cmd, float* arr, int count, Point* cur, Point* curCtl, Point* startPoint, bool *isQuadratic, bool* closed)
{
switch (cmd) {
case 'm':
@ -464,6 +464,7 @@ static bool _processCommand(Array<PathCommand>* cmds, Array<Point>* pts, char cm
case 'Z': {
cmds->push(PathCommand::Close);
*cur = *startPoint;
*closed = true;
break;
}
case 'a':
@ -488,7 +489,7 @@ static bool _processCommand(Array<PathCommand>* cmds, Array<Point>* pts, char cm
}
static char* _nextCommand(char* path, char* cmd, float* arr, int* count)
static char* _nextCommand(char* path, char* cmd, float* arr, int* count, bool* closed)
{
int large, sweep;
@ -500,6 +501,9 @@ static char* _nextCommand(char* path, char* cmd, float* arr, int* count)
} else {
if (*cmd == 'm') *cmd = 'l';
else if (*cmd == 'M') *cmd = 'L';
else {
if (*closed) return nullptr;
}
}
if (*count == 7) {
//Special case for arc command
@ -548,6 +552,7 @@ bool svgPathToShape(const char* svgPath, Shape* shape)
Point startPoint = { 0, 0 };
char cmd = 0;
bool isQuadratic = false;
bool closed = false;
char* path = (char*)svgPath;
auto& pts = P(shape)->rs.path.pts;
@ -555,9 +560,10 @@ bool svgPathToShape(const char* svgPath, Shape* shape)
auto lastCmds = cmds.count;
while ((path[0] != '\0')) {
path = _nextCommand(path, &cmd, numberArray, &numberCount);
path = _nextCommand(path, &cmd, numberArray, &numberCount, &closed);
if (!path) break;
if (!_processCommand(&cmds, &pts, cmd, numberArray, numberCount, &cur, &curCtl, &startPoint, &isQuadratic)) break;
closed = false;
if (!_processCommand(&cmds, &pts, cmd, numberArray, numberCount, &cur, &curCtl, &startPoint, &isQuadratic, &closed)) break;
}
if (cmds.count > lastCmds && cmds[lastCmds] != PathCommand::MoveTo) return false;