From f85123c6506371a6fe50879ace0cef3996dc1d10 Mon Sep 17 00:00:00 2001 From: Chun Date: Mon, 14 Nov 2022 01:23:09 +0000 Subject: [PATCH] Revert "svg_loader: the preserveAspectRatio attrib handled" This reverts commit 2111930048843b2373907f4e9813f97a3b2d6206. Change-Id: I608f73c16e8bb9c6caf2a3fb40254e6eca056dcf --- src/lib/tvgLoadModule.h | 1 + src/loaders/svg/tvgSvgLoader.cpp | 80 +++++++++---------------- src/loaders/svg/tvgSvgLoader.h | 2 - src/loaders/svg/tvgSvgLoaderCommon.h | 23 +------- src/loaders/svg/tvgSvgSceneBuilder.cpp | 104 +++++++++------------------------ src/loaders/svg/tvgSvgSceneBuilder.h | 2 +- 6 files changed, 58 insertions(+), 154 deletions(-) diff --git a/src/lib/tvgLoadModule.h b/src/lib/tvgLoadModule.h index a496b09..0c34ecb 100644 --- a/src/lib/tvgLoadModule.h +++ b/src/lib/tvgLoadModule.h @@ -36,6 +36,7 @@ public: float vw = 0; float vh = 0; float w = 0, h = 0; //default image size + bool preserveAspect = true; //keep aspect ratio by default. virtual ~LoadModule() {} diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index 050611f..def8ae1 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -116,49 +116,6 @@ static bool _parseNumber(const char** content, float* number) return true; } - -static constexpr struct -{ - AspectRatioAlign align; - const char* tag; -} alignTags[] = { - { AspectRatioAlign::XMinYMin, "xMinYMin" }, - { AspectRatioAlign::XMidYMin, "xMidYMin" }, - { AspectRatioAlign::XMaxYMin, "xMaxYMin" }, - { AspectRatioAlign::XMinYMid, "xMinYMid" }, - { AspectRatioAlign::XMidYMid, "xMidYMid" }, - { AspectRatioAlign::XMaxYMid, "xMaxYMid" }, - { AspectRatioAlign::XMinYMax, "xMinYMax" }, - { AspectRatioAlign::XMidYMax, "xMidYMax" }, - { AspectRatioAlign::XMaxYMax, "xMaxYMax" }, -}; - - -static void _parseAspectRatio(const char** content, AspectRatioAlign* align, AspectRatioMeetOrSlice* meetOrSlice) -{ - if (!strcmp(*content, "none")) { - *align = AspectRatioAlign::None; - return; - } - - for (unsigned int i = 0; i < sizeof(alignTags) / sizeof(alignTags[0]); i++) { - if (!strncmp(*content, alignTags[i].tag, 8)) { - *align = alignTags[i].align; - *content += 8; - *content = _skipSpace(*content, nullptr); - break; - } - } - - if (!strcmp(*content, "meet")) - *meetOrSlice = AspectRatioMeetOrSlice::Meet; - else if (!strcmp(*content, "slice")) - *meetOrSlice = AspectRatioMeetOrSlice::Slice; - - return; -} - - /** * According to https://www.w3.org/TR/SVG/coords.html#Units */ @@ -826,7 +783,7 @@ static bool _attrParseSvgNode(void* data, const char* key, const char* value) } loader->svgParse->global.x = (int)doc->vx; } else if (!strcmp(key, "preserveAspectRatio")) { - _parseAspectRatio(&value, &doc->align, &doc->meetOrSlice); + if (!strcmp(value, "none")) doc->preserveAspect = false; } else if (!strcmp(key, "style")) { return simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader); } @@ -1193,9 +1150,7 @@ static SvgNode* _createSvgNode(SvgLoaderData* loader, SvgNode* parent, const cha loader->svgParse->global.w = 0; loader->svgParse->global.h = 0; - doc->align = AspectRatioAlign::XMidYMid; - doc->meetOrSlice = AspectRatioMeetOrSlice::Meet; - + doc->preserveAspect = true; simpleXmlParseAttributes(buf, bufLength, _attrParseSvgNode, loader); if (loader->svgParse->global.w == 0) { @@ -2891,7 +2846,7 @@ void SvgLoader::run(unsigned tid) if (loaderData.cloneNodes.count > 0) _clonePostponedNodes(&loaderData.cloneNodes); } - root = svgSceneBuild(loaderData.doc, vx, vy, vw, vh, w, h, align, meetOrSlice, svgPath); + root = svgSceneBuild(loaderData.doc, vx, vy, vw, vh, w, h, preserveAspect, svgPath); } @@ -2924,8 +2879,7 @@ bool SvgLoader::header() if (vh < FLT_EPSILON) vh = h; } - align = loaderData.doc->node.doc.align; - meetOrSlice = loaderData.doc->node.doc.meetOrSlice; + preserveAspect = loaderData.doc->node.doc.preserveAspect; } else { TVGLOG("SVG", "No SVG File. There is no "); return false; @@ -2980,9 +2934,31 @@ bool SvgLoader::resize(Paint* paint, float w, float h) auto sx = w / this->w; auto sy = h / this->h; - Matrix m = {sx, 0, 0, 0, sy, 0, 0, 0, 1}; - paint->transform(m); + if (preserveAspect) { + //Scale + auto scale = sx < sy ? sx : sy; + paint->scale(scale); + //Align + auto tx = 0.0f; + auto ty = 0.0f; + auto tw = this->w * scale; + auto th = this->h * scale; + if (tw > th) ty -= (h - th) * 0.5f; + else tx -= (w - tw) * 0.5f; + paint->translate(-tx, -ty); + } else { + //Align + auto tx = 0.0f; + auto ty = 0.0f; + auto tw = this->w * sx; + auto th = this->h * sy; + if (tw > th) ty -= (h - th) * 0.5f; + else tx -= (w - tw) * 0.5f; + + Matrix m = {sx, 0, -tx, 0, sy, -ty, 0, 0, 1}; + paint->transform(m); + } return true; } diff --git a/src/loaders/svg/tvgSvgLoader.h b/src/loaders/svg/tvgSvgLoader.h index 8c5b233..468f058 100644 --- a/src/loaders/svg/tvgSvgLoader.h +++ b/src/loaders/svg/tvgSvgLoader.h @@ -32,8 +32,6 @@ public: string svgPath = ""; const char* content = nullptr; uint32_t size = 0; - AspectRatioAlign align = AspectRatioAlign::XMidYMid; - AspectRatioMeetOrSlice meetOrSlice = AspectRatioMeetOrSlice::Meet; SvgLoaderData loaderData; unique_ptr root; diff --git a/src/loaders/svg/tvgSvgLoaderCommon.h b/src/loaders/svg/tvgSvgLoaderCommon.h index 0a6f019..cceef91 100644 --- a/src/loaders/svg/tvgSvgLoaderCommon.h +++ b/src/loaders/svg/tvgSvgLoaderCommon.h @@ -136,26 +136,6 @@ enum class SvgParserLengthType Other }; -enum class AspectRatioAlign -{ - None, - XMinYMin, - XMidYMin, - XMaxYMin, - XMinYMid, - XMidYMid, - XMaxYMid, - XMinYMax, - XMidYMax, - XMaxYMax -}; - -enum class AspectRatioMeetOrSlice -{ - Meet, - Slice -}; - struct SvgDocNode { float w; @@ -165,8 +145,7 @@ struct SvgDocNode float vw; float vh; SvgNode* defs; - AspectRatioAlign align; - AspectRatioMeetOrSlice meetOrSlice; + bool preserveAspect; }; struct SvgGNode diff --git a/src/loaders/svg/tvgSvgSceneBuilder.cpp b/src/loaders/svg/tvgSvgSceneBuilder.cpp index 243fe7b..8701fe3 100644 --- a/src/loaders/svg/tvgSvgSceneBuilder.cpp +++ b/src/loaders/svg/tvgSvgSceneBuilder.cpp @@ -595,85 +595,11 @@ static unique_ptr _sceneBuildHelper(const SvgNode* node, const Box& vBox, } -static Matrix _calculateAspectRatioMatrix(AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, float width, float height, const Box& box) -{ - auto sx = width / box.w; - auto sy = height / box.h; - auto tvx = box.x * sx; - auto tvy = box.y * sy; - - if (align == AspectRatioAlign::None) - return {sx, 0, -tvx, 0, sy, -tvy, 0, 0, 1}; - - //Scale - if (meetOrSlice == AspectRatioMeetOrSlice::Meet) { - if (sx < sy) sy = sx; - else sx = sy; - } else { - if (sx < sy) sx = sy; - else sy = sx; - } - - //Align - tvx = box.x * sx; - tvy = box.y * sy; - auto tvw = box.w * sx; - auto tvh = box.h * sy; - - switch (align) { - case AspectRatioAlign::XMinYMin: { - break; - } - case AspectRatioAlign::XMidYMin: { - tvx -= (width - tvw) * 0.5f; - break; - } - case AspectRatioAlign::XMaxYMin: { - tvx -= width - tvw; - break; - } - case AspectRatioAlign::XMinYMid: { - tvy -= (height - tvh) * 0.5f; - break; - } - case AspectRatioAlign::XMidYMid: { - tvx -= (width - tvw) * 0.5f; - tvy -= (height - tvh) * 0.5f; - break; - } - case AspectRatioAlign::XMaxYMid: { - tvx -= width - tvw; - tvy -= (height - tvh) * 0.5f; - break; - } - case AspectRatioAlign::XMinYMax: { - tvy -= height - tvh; - break; - } - case AspectRatioAlign::XMidYMax: { - tvx -= (width - tvw) * 0.5f; - tvy -= height - tvh; - break; - } - case AspectRatioAlign::XMaxYMax: { - tvx -= width - tvw; - tvy -= height - tvh; - break; - } - default: { - break; - } - } - - return {sx, 0, -tvx, 0, sy, -tvy, 0, 0, 1}; -} - - /************************************************************************/ /* External Class Implementation */ /************************************************************************/ -unique_ptr svgSceneBuild(SvgNode* node, float vx, float vy, float vw, float vh, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath) +unique_ptr svgSceneBuild(SvgNode* node, float vx, float vy, float vw, float vh, float w, float h, bool preserveAspect, const string& svgPath) { if (!node || (node->type != SvgNodeType::Doc)) return nullptr; @@ -681,8 +607,32 @@ unique_ptr svgSceneBuild(SvgNode* node, float vx, float vy, float vw, flo auto docNode = _sceneBuildHelper(node, vBox, svgPath, false); if (!mathEqual(w, vw) || !mathEqual(h, vh)) { - Matrix m = _calculateAspectRatioMatrix(align, meetOrSlice, w, h, vBox); - docNode->transform(m); + auto sx = w / vw; + auto sy = h / vh; + + if (preserveAspect) { + //Scale + auto scale = sx < sy ? sx : sy; + docNode->scale(scale); + //Align + auto tvx = vx * scale; + auto tvy = vy * scale; + auto tvw = vw * scale; + auto tvh = vh * scale; + if (vw > vh) tvy -= (h - tvh) * 0.5f; + else tvx -= (w - tvw) * 0.5f; + docNode->translate(-tvx, -tvy); + } else { + //Align + auto tvx = vx * sx; + auto tvy = vy * sy; + auto tvw = vw * sx; + auto tvh = vh * sy; + if (tvw > tvh) tvy -= (h - tvh) * 0.5f; + else tvx -= (w - tvw) * 0.5f; + Matrix m = {sx, 0, -tvx, 0, sy, -tvy, 0, 0, 1}; + docNode->transform(m); + } } else if (!mathZero(vx) || !mathZero(vy)) { docNode->translate(-vx, -vy); } diff --git a/src/loaders/svg/tvgSvgSceneBuilder.h b/src/loaders/svg/tvgSvgSceneBuilder.h index 20b6b2b..4232aca 100644 --- a/src/loaders/svg/tvgSvgSceneBuilder.h +++ b/src/loaders/svg/tvgSvgSceneBuilder.h @@ -25,6 +25,6 @@ #include "tvgCommon.h" -unique_ptr svgSceneBuild(SvgNode* node, float vx, float vy, float vw, float vh, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath); +unique_ptr svgSceneBuild(SvgNode* node, float vx, float vy, float vw, float vh, float w, float h, bool preserveAspect, const string& svgPath); #endif //_TVG_SVG_SCENE_BUILDER_H_ -- 2.7.4