svg_loader: handling svg width/height in percentages

The percentages should refer to the size of the viewbox.
This was not the case for not knowing the viewbox before
reading the width/height.

@Issue: https://github.com/thorvg/thorvg/issues/1409
This commit is contained in:
Mira Grudzinska 2023-04-30 10:41:29 +02:00 committed by Hermet Park
parent cf41e1edf7
commit 92346c4119
3 changed files with 27 additions and 4 deletions

View file

@ -861,10 +861,18 @@ static bool _attrParseSvgNode(void* data, const char* key, const char* value)
if (!strcmp(key, "width")) {
doc->w = _toFloat(loader->svgParse, value, SvgParserLengthType::Horizontal);
if (strstr(value, "%")) {
doc->sw = svgUtilStrtof(value, nullptr) / 100.0f;
} else {
doc->viewFlag = (doc->viewFlag | SvgViewFlag::Width);
}
} else if (!strcmp(key, "height")) {
doc->h = _toFloat(loader->svgParse, value, SvgParserLengthType::Vertical);
if (strstr(value, "%")) {
doc->sh = svgUtilStrtof(value, nullptr) / 100.0f;
} else {
doc->viewFlag = (doc->viewFlag | SvgViewFlag::Height);
}
} else if (!strcmp(key, "viewBox")) {
if (_parseNumber(&value, &doc->vx)) {
if (_parseNumber(&value, &doc->vy)) {
@ -1347,6 +1355,8 @@ static SvgNode* _createSvgNode(SvgLoaderData* loader, SvgNode* parent, const cha
doc->align = AspectRatioAlign::XMidYMid;
doc->meetOrSlice = AspectRatioMeetOrSlice::Meet;
doc->viewFlag = SvgViewFlag::None;
doc->sw = 1.0f;
doc->sh = 1.0f;
func(buf, bufLength, _attrParseSvgNode, loader);
if (!(doc->viewFlag & SvgViewFlag::Viewbox)) {
@ -3530,8 +3540,16 @@ bool SvgLoader::header()
vw = loaderData.doc->node.doc.vw;
vh = loaderData.doc->node.doc.vh;
if (!(viewFlag & SvgViewFlag::Width)) w = vw;
if (!(viewFlag & SvgViewFlag::Height)) h = vh;
if (!(viewFlag & SvgViewFlag::Width)) {
w = vw * loaderData.doc->node.doc.sw;
loaderData.doc->node.doc.sw = 1.0f;
viewFlag = (viewFlag | SvgViewFlag::Width);
}
if (!(viewFlag & SvgViewFlag::Height)) {
h = vh * loaderData.doc->node.doc.sh;
loaderData.doc->node.doc.sh = 1.0f;
viewFlag = (viewFlag | SvgViewFlag::Height);
}
} else {
vw = w;
vh = h;

View file

@ -260,6 +260,8 @@ struct SvgDocNode
float vy;
float vw;
float vh;
float sw;
float sh;
SvgViewFlag viewFlag;
SvgNode* defs;
SvgNode* style;

View file

@ -796,7 +796,10 @@ unique_ptr<Scene> svgSceneBuild(SvgNode* node, float& vx, float& vy, float& vw,
Box vBox = {vx, vy, vw, vh};
auto docNode = _sceneBuildHelper(node, vBox, svgPath, false, 0);
_applySvgViewFlag(docNode.get(), vx, vy, vw, vh, w, h, viewFlag);
w *= node->node.doc.sw;
h *= node->node.doc.sh;
if (!mathEqual(w, vw) || !mathEqual(h, vh)) {
Matrix m = _calculateAspectRatioMatrix(align, meetOrSlice, w, h, {vx, vy, vw, vh});