[Tizen] Revert "svg_loader: preserveAspectRatio attrib handled according to the svg... 54/292354/1
authorPatryk Kaczmarek <patryk.k@partner.samsung.com>
Thu, 4 May 2023 09:17:29 +0000 (11:17 +0200)
committerPatryk Kaczmarek <patryk.k@partner.samsung.com>
Thu, 4 May 2023 09:26:13 +0000 (11:26 +0200)
This reverts commit 69a417076a436065a20b54925031aa6f6a7fa526.

Change-Id: I45e4c6ef332d42d08cef47ff3b4c85b3538881ef

src/lib/tvgLoadModule.h
src/loaders/svg/tvgSvgLoader.cpp
src/loaders/svg/tvgSvgLoader.h
src/loaders/svg/tvgSvgLoaderCommon.h
src/loaders/svg/tvgSvgSceneBuilder.cpp
src/loaders/svg/tvgSvgSceneBuilder.h

index 4637c90..ad5d7b6 100644 (file)
@@ -38,6 +38,7 @@ public:
     float vh = 0;
     float w = 0, h = 0;         //default image size
     uint32_t colorSpace = SwCanvas::ARGB8888;
+    bool preserveAspect = true; //keep aspect ratio by default.
 
     virtual ~LoadModule() {}
 
index 1365663..83df473 100644 (file)
@@ -119,48 +119,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;
-    }
-}
-
-
 /**
  * According to https://www.w3.org/TR/SVG/coords.html#Units
  */
@@ -858,7 +816,7 @@ static bool _attrParseSvgNode(void* data, const char* key, const char* value)
             loader->svgParse->global.w = loader->svgParse->global.h = 1.0f;
         }
     } 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, strlen(value), _parseStyleAttr, loader);
 #ifdef THORVG_LOG_ENABLED
@@ -1212,7 +1170,7 @@ static bool _attrParseSymbolNode(void* data, const char* key, const char* value)
         symbol->h = _toFloat(loader->svgParse, value, SvgParserLengthType::Vertical);
         symbol->hasHeight = true;
     } else if (!strcmp(key, "preserveAspectRatio")) {
-        _parseAspectRatio(&value, &symbol->align, &symbol->meetOrSlice);
+        if (!strcmp(value, "none")) symbol->preserveAspect = false;
     } else if (!strcmp(key, "overflow")) {
         if (!strcmp(value, "visible")) symbol->overflowVisible = true;
     } else {
@@ -1304,9 +1262,8 @@ static SvgNode* _createSvgNode(SvgLoaderData* loader, SvgNode* parent, const cha
     loader->svgParse->global.w = 1.0f;
     loader->svgParse->global.h = 1.0f;
 
-    doc->align = AspectRatioAlign::XMidYMid;
-    doc->meetOrSlice = AspectRatioMeetOrSlice::Meet;
     doc->viewFlag = SvgViewFlag::None;
+    doc->preserveAspect = true;
     func(buf, bufLength, _attrParseSvgNode, loader);
 
     if (!((uint32_t)doc->viewFlag & (uint32_t)SvgViewFlag::Viewbox)) {
@@ -1366,8 +1323,7 @@ static SvgNode* _createSymbolNode(SvgLoaderData* loader, SvgNode* parent, const
     if (!loader->svgParse->node) return nullptr;
 
     loader->svgParse->node->display = false;
-    loader->svgParse->node->node.symbol.align = AspectRatioAlign::XMidYMid;
-    loader->svgParse->node->node.symbol.meetOrSlice = AspectRatioMeetOrSlice::Meet;
+    loader->svgParse->node->node.symbol.preserveAspect = true;
     loader->svgParse->node->node.symbol.overflowVisible = false;
 
     loader->svgParse->node->node.symbol.hasViewBox = false;
@@ -3210,7 +3166,7 @@ void SvgLoader::run(unsigned tid)
 
         _updateStyle(loaderData.doc, nullptr);
     }
-    root = svgSceneBuild(loaderData.doc, vx, vy, vw, vh, w, h, align, meetOrSlice, svgPath, viewFlag);
+    root = svgSceneBuild(loaderData.doc, vx, vy, vw, vh, w, h, preserveAspect, svgPath, viewFlag);
 }
 
 
@@ -3229,8 +3185,6 @@ bool SvgLoader::header()
 
     if (loaderData.doc && loaderData.doc->type == SvgNodeType::Doc) {
         viewFlag = loaderData.doc->node.doc.viewFlag;
-        align = loaderData.doc->node.doc.align;
-        meetOrSlice = loaderData.doc->node.doc.meetOrSlice;
         w = 1.0f;
         h = 1.0f;
 
@@ -3254,6 +3208,7 @@ bool SvgLoader::header()
             vw = w;
             vh = h;
         }
+        preserveAspect = loaderData.doc->node.doc.preserveAspect;
     } else {
         TVGLOG("SVG", "No SVG File. There is no <svg/>");
         return false;
@@ -3308,9 +3263,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;
 }
 
index 43882b7..4c4fe13 100644 (file)
@@ -52,10 +52,8 @@ public:
 
 private:
     SvgViewFlag viewFlag = SvgViewFlag::None;
-    AspectRatioAlign align = AspectRatioAlign::XMidYMid;
-    AspectRatioMeetOrSlice meetOrSlice = AspectRatioMeetOrSlice::Meet;
     bool renderingDisabled = false;
-
+    
     bool header();
     void clear();
     void run(unsigned tid) override;
index ebcbf01..6fed159 100644 (file)
@@ -154,26 +154,6 @@ enum class SvgViewFlag
     Viewbox = 0x04  //viewBox x,y,w,h - used only if all 4 are correctly set
 };
 
-enum class AspectRatioAlign
-{
-    None,
-    XMinYMin,
-    XMidYMin,
-    XMaxYMin,
-    XMinYMid,
-    XMidYMid,
-    XMaxYMid,
-    XMinYMax,
-    XMidYMax,
-    XMaxYMax
-};
-
-enum class AspectRatioMeetOrSlice
-{
-    Meet,
-    Slice
-};
-
 struct SvgDocNode
 {
     float w;
@@ -185,8 +165,7 @@ struct SvgDocNode
     SvgViewFlag viewFlag;
     SvgNode* defs;
     SvgNode* style;
-    AspectRatioAlign align;
-    AspectRatioMeetOrSlice meetOrSlice;
+    bool preserveAspect;
 };
 
 struct SvgGNode
@@ -202,8 +181,7 @@ struct SvgSymbolNode
 {
     float w, h;
     float vx, vy, vw, vh;
-    AspectRatioAlign align;
-    AspectRatioMeetOrSlice meetOrSlice;
+    bool preserveAspect;
     bool overflowVisible;
     bool hasViewBox;
     bool hasWidth;
index 1d519c4..c6ad906 100644 (file)
@@ -558,80 +558,6 @@ static unique_ptr<Picture> _imageBuildHelper(SvgNode* node, const Box& vBox, con
 }
 
 
-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};
-}
-
-
 static unique_ptr<Scene> _useBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath, int depth, bool* isMaskWhite)
 {
     unique_ptr<Scene> finalScene;
@@ -657,8 +583,20 @@ static unique_ptr<Scene> _useBuildHelper(const SvgNode* node, const Box& vBox, c
 
         Matrix mViewBox = {1, 0, 0, 0, 1, 0, 0, 0, 1};
         if ((!mathEqual(width, vw) || !mathEqual(height, vh)) && vw > 0 && vh > 0) {
-            Box box = {symbol.vx, symbol.vy, vw, vh};
-            mViewBox = _calculateAspectRatioMatrix(symbol.align, symbol.meetOrSlice, width, height, box);
+            auto sx = width / vw;
+            auto sy = height / vh;
+            if (symbol.preserveAspect) {
+                if (sx < sy) sy = sx;
+                else sx = sy;
+            }
+
+            auto tvx = symbol.vx * sx;
+            auto tvy = symbol.vy * sy;
+            auto tvw = vw * sx;
+            auto tvh = vh * sy;
+            tvy -= (symbol.h - tvh) * 0.5f;
+            tvx -= (symbol.w - tvw) * 0.5f;
+            mViewBox = {sx, 0, -tvx, 0, sy, -tvy, 0, 0, 1};
         } else if (!mathZero(symbol.vx) || !mathZero(symbol.vy)) {
             mViewBox = {1, 0, -symbol.vx, 0, 1, -symbol.vy, 0, 0, 1};
         }
@@ -769,10 +707,8 @@ static void _applySvgViewFlag(const Scene* scene, float& vx, float& vy, float& v
 /* External Class Implementation                                        */
 /************************************************************************/
 
-unique_ptr<Scene> svgSceneBuild(SvgNode* node, float& vx, float& vy, float& vw, float& vh, float& w, float& h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath, SvgViewFlag viewFlag)
+unique_ptr<Scene> svgSceneBuild(SvgNode* node, float vx, float vy, float vw, float vh, float w, float h, bool preserveAspect, const string& svgPath, SvgViewFlag viewFlag)
 {
-    //TODO: aspect ratio is valid only if viewBox was set
-
     if (!node || (node->type != SvgNodeType::Doc)) return nullptr;
 
     Box vBox = {vx, vy, vw, vh};
@@ -780,8 +716,28 @@ unique_ptr<Scene> svgSceneBuild(SvgNode* node, float& vx, float& vy, float& vw,
     _applySvgViewFlag(docNode.get(), vx, vy, vw, vh, w, h, viewFlag);
 
     if (!mathEqual(w, vw) || !mathEqual(h, vh)) {
-        Matrix m = _calculateAspectRatioMatrix(align, meetOrSlice, w, h, {vx, vy, vw, vh});
-        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;
+            tvx -= (w - tvw) * 0.5f;
+            tvy -= (h - tvh) * 0.5f;
+            docNode->translate(-tvx, -tvy);
+        } else {
+            //Align
+            auto tvx = vx * sx;
+            auto tvy = vy * sy;
+            Matrix m = {sx, 0, -tvx, 0, sy, -tvy, 0, 0, 1};
+            docNode->transform(m);
+        }
     } else if (!mathZero(vx) || !mathZero(vy)) {
         docNode->translate(-vx, -vy);
     }
index 0de8c9a..4f4fe54 100644 (file)
@@ -25,6 +25,6 @@
 
 #include "tvgCommon.h"
 
-unique_ptr<Scene> svgSceneBuild(SvgNode* node, float& vx, float& vy, float& vw, float& vh, float& w, float& h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath, SvgViewFlag viewFlag);
+unique_ptr<Scene> svgSceneBuild(SvgNode* node, float vx, float vy, float vw, float vh, float w, float h, bool preserveAspect, const string& svgPath, SvgViewFlag viewFlag);
 
 #endif //_TVG_SVG_SCENE_BUILDER_H_