common scene: complete scene tranfsormation feature. 18/233618/3
authorHermet Park <chuneon.park@samsung.com>
Sun, 17 May 2020 12:33:56 +0000 (21:33 +0900)
committerHermet Park <chuneon.park@samsung.com>
Sun, 17 May 2020 12:38:15 +0000 (21:38 +0900)
Each scene could conserve its own transformation,
the origin could be the parent Paint (if they were beloned to)

Thus, you can compose the multi-tranformed scene group which
simultenoulsly working in own spaces.

See testTransform and testSceneTransform, how they work.

Change-Id: I51deb4d66f8fcd024f8dc7a1e1af57c398a9d7fe

src/lib/gl_engine/tvgGlRenderer.cpp
src/lib/gl_engine/tvgGlRenderer.h
src/lib/sw_engine/tvgSwCommon.h
src/lib/sw_engine/tvgSwRenderer.cpp
src/lib/sw_engine/tvgSwRenderer.h
src/lib/sw_engine/tvgSwShape.cpp
src/lib/tvgRenderCommon.h
src/lib/tvgSceneImpl.h
src/lib/tvgShapeImpl.h
test/testSceneTransform.cpp

index 48a0ee5..792e524 100644 (file)
@@ -65,7 +65,7 @@ bool GlRenderer::dispose(const Shape& shape, void *data)
 }
 
 
-void* GlRenderer::prepare(const Shape& shape, void* data, const RenderMatrix* transform, RenderUpdateFlag flags)
+void* GlRenderer::prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags)
 {
     //prepare shape data
     GlShape* sdata = static_cast<GlShape*>(data);
index 557f9e7..4d6ba79 100644 (file)
@@ -23,7 +23,7 @@ namespace tvg
 class GlRenderer : public RenderMethod
 {
 public:
-    void* prepare(const Shape& shape, void* data, const RenderMatrix* transform, RenderUpdateFlag flags) override;
+    void* prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags) override;
     bool dispose(const Shape& shape, void *data) override;
     bool render(const Shape& shape, void *data) override;
     bool clear() override;
index 3068b9b..62a6b29 100644 (file)
@@ -96,7 +96,7 @@ void shapeReset(SwShape& sdata);
 bool shapeGenOutline(const Shape& shape, SwShape& sdata);
 void shapeDelOutline(SwShape& sdata);
 bool shapeGenRle(const Shape& shape, SwShape& sdata, const SwSize& clip);
-void shapeTransformOutline(const Shape& shape, SwShape& sdata, const RenderMatrix& transform);
+void shapeTransformOutline(const Shape& shape, SwShape& sdata, const RenderTransform& transform);
 SwRleData* rleRender(const SwShape& sdata, const SwSize& clip);
 
 bool rasterShape(Surface& surface, SwShape& sdata, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
index 2d97445..36e367b 100644 (file)
@@ -81,7 +81,7 @@ bool SwRenderer::dispose(const Shape& shape, void *data)
     return true;
 }
 
-void* SwRenderer::prepare(const Shape& shape, void* data, const RenderMatrix* transform, RenderUpdateFlag flags)
+void* SwRenderer::prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags)
 {
     //prepare shape data
     SwShape* sdata = static_cast<SwShape*>(data);
index 4c0a7ba..3dfb076 100644 (file)
@@ -22,7 +22,7 @@ class SwRenderer : public RenderMethod
 public:
     Surface surface;
 
-    void* prepare(const Shape& shape, void* data, const RenderMatrix* transform, RenderUpdateFlag flags) override;
+    void* prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags) override;
     bool dispose(const Shape& shape, void *data) override;
     bool render(const Shape& shape, void *data) override;
     bool target(uint32_t* buffer, size_t stride, size_t w, size_t h);
index efad932..d7229dc 100644 (file)
@@ -215,7 +215,7 @@ void _deleteRle(SwShape& sdata)
 /* External Class Implementation                                        */
 /************************************************************************/
 
-void shapeTransformOutline(const Shape& shape, SwShape& sdata, const RenderMatrix& transform)
+void shapeTransformOutline(const Shape& shape, SwShape& sdata, const RenderTransform& transform)
 {
     auto outline = sdata.outline;
     assert(outline);
index 0ad1d55..f40639d 100644 (file)
@@ -30,85 +30,13 @@ struct Surface
 
 enum RenderUpdateFlag {None = 0, Path = 1, Fill = 2, Transform = 4, All = 8};
 
-struct RenderMatrix
+struct RenderTransform
 {
     //3x3 Matrix Elements
     float e11, e12, e13;
     float e21, e22, e23;
     float e31, e32, e33;
 
-    static void rotate(RenderMatrix* out, float degree)
-    {
-        constexpr auto PI = 3.141592f;
-
-        if (fabsf(degree) < FLT_EPSILON) return;
-
-        auto radian = degree / 180.0f * PI;
-        auto cosVal = cosf(radian);
-        auto sinVal = sinf(radian);
-
-        auto t11 = out->e11 * cosVal + out->e12 * sinVal;
-        auto t12 = out->e11 * -sinVal + out->e12 * cosVal;
-        auto t21 = out->e21 * cosVal + out->e22 * sinVal;
-        auto t22 = out->e21 * -sinVal + out->e22 * cosVal;
-        auto t31 = out->e31 * cosVal + out->e32 * sinVal;
-        auto t32 = out->e31 * -sinVal + out->e32 * cosVal;
-
-        out->e11 = t11;
-        out->e12 = t12;
-        out->e21 = t21;
-        out->e22 = t22;
-        out->e31 = t31;
-        out->e32 = t32;
-    }
-
-    static void scale(RenderMatrix* out, float factor)
-    {
-        out->e11 *= factor;
-        out->e22 *= factor;
-        out->e33 *= factor;
-    }
-
-    static void identity(RenderMatrix* out)
-    {
-        out->e11 = 1.0f;
-        out->e12 = 0.0f;
-        out->e13 = 0.0f;
-        out->e21 = 0.0f;
-        out->e22 = 1.0f;
-        out->e23 = 0.0f;
-        out->e31 = 0.0f;
-        out->e32 = 0.0f;
-        out->e33 = 1.0f;
-    }
-
-    static void translate(RenderMatrix* out, float x, float y)
-    {
-        out->e31 += x;
-        out->e32 += y;
-    }
-
-    static void multiply(const RenderMatrix* lhs, const RenderMatrix* rhs, RenderMatrix* out)
-    {
-        assert(lhs && rhs && out);
-
-        out->e11 = lhs->e11 * rhs->e11 + lhs->e12 * rhs->e21 + lhs->e13 * rhs->e31;
-        out->e12 = lhs->e11 * rhs->e12 + lhs->e12 * rhs->e22 + lhs->e13 * rhs->e32;
-        out->e13 = lhs->e11 * rhs->e13 + lhs->e12 * rhs->e23 + lhs->e13 * rhs->e33;
-
-        out->e21 = lhs->e21 * rhs->e11 + lhs->e22 * rhs->e21 + lhs->e23 * rhs->e31;
-        out->e22 = lhs->e21 * rhs->e12 + lhs->e22 * rhs->e22 + lhs->e23 * rhs->e32;
-        out->e23 = lhs->e21 * rhs->e13 + lhs->e22 * rhs->e23 + lhs->e23 * rhs->e33;
-
-        out->e31 = lhs->e31 * rhs->e11 + lhs->e32 * rhs->e21 + lhs->e33 * rhs->e31;
-        out->e32 = lhs->e31 * rhs->e12 + lhs->e32 * rhs->e22 + lhs->e33 * rhs->e32;
-        out->e33 = lhs->e31 * rhs->e13 + lhs->e32 * rhs->e23 + lhs->e33 * rhs->e33;
-    }
-};
-
-struct RenderTransform
-{
-    RenderMatrix m;
     float x = 0.0f;
     float y = 0.0f;
     float degree = 0.0f;  //rotation degree
@@ -116,19 +44,77 @@ struct RenderTransform
 
     bool update()
     {
+        constexpr auto PI = 3.141592f;
+
         //Init Status
         if (fabsf(x) <= FLT_EPSILON && fabsf(y) <= FLT_EPSILON &&
             fabsf(degree) <= FLT_EPSILON && fabsf(factor - 1) <= FLT_EPSILON) {
             return false;
         }
 
-        RenderMatrix::identity(&m);
-        RenderMatrix::scale(&m, factor);
-        RenderMatrix::rotate(&m, degree);
-        RenderMatrix::translate(&m, x, y);
+        //identity
+        e11 = 1.0f;
+        e12 = 0.0f;
+        e13 = 0.0f;
+        e21 = 0.0f;
+        e22 = 1.0f;
+        e23 = 0.0f;
+        e31 = 0.0f;
+        e32 = 0.0f;
+        e33 = 1.0f;
+
+        //scale
+        e11 *= factor;
+        e22 *= factor;
+        e33 *= factor;
+
+        //rotation
+        if (fabsf(degree) > FLT_EPSILON) {
+            auto radian = degree / 180.0f * PI;
+            auto cosVal = cosf(radian);
+            auto sinVal = sinf(radian);
+
+            auto t11 = e11 * cosVal + e12 * sinVal;
+            auto t12 = e11 * -sinVal + e12 * cosVal;
+            auto t21 = e21 * cosVal + e22 * sinVal;
+            auto t22 = e21 * -sinVal + e22 * cosVal;
+            auto t31 = e31 * cosVal + e32 * sinVal;
+            auto t32 = e31 * -sinVal + e32 * cosVal;
+
+            e11 = t11;
+            e12 = t12;
+            e21 = t21;
+            e22 = t22;
+            e31 = t31;
+            e32 = t32;
+        }
+
+        e31 += x;
+        e32 += y;
 
         return true;
     }
+
+    RenderTransform()
+    {
+    }
+
+    RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs)
+    {
+        assert(lhs && rhs);
+
+        auto dx = rhs->x * lhs->factor;
+        auto dy = rhs->y * lhs->factor;
+        auto tx = dx * lhs->e11 + dy * lhs->e12 + lhs->e13;
+        auto ty = dx * lhs->e21 + dy * lhs->e22 + lhs->e23;
+
+        x = lhs->x + tx;
+        y = lhs->y + ty;
+        degree = lhs->degree + rhs->degree;
+        factor = lhs->factor * rhs->factor;
+
+        update();
+    }
 };
 
 
@@ -136,7 +122,7 @@ class RenderMethod
 {
 public:
     virtual ~RenderMethod() {}
-    virtual void* prepare(const Shape& shape, void* data, const RenderMatrix* transform, RenderUpdateFlag flags) = 0;
+    virtual void* prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags) = 0;
     virtual bool dispose(const Shape& shape, void *data) = 0;
     virtual bool render(const Shape& shape, void *data) = 0;
     virtual bool clear() = 0;
index 4def223..abd29e6 100644 (file)
@@ -51,7 +51,7 @@ struct Scene::Impl
         return true;
     }
 
-    bool updateInternal(RenderMethod &renderer, const RenderMatrix* transform, size_t flag)
+    bool updateInternal(RenderMethod &renderer, const RenderTransform* transform, size_t flag)
     {
         for(auto paint: paints) {
             if (auto scene = dynamic_cast<Scene*>(paint)) {
@@ -63,7 +63,7 @@ struct Scene::Impl
         return true;
     }
 
-    bool update(RenderMethod &renderer, const RenderMatrix* pTransform = nullptr, size_t pFlag = 0)
+    bool update(RenderMethod &renderer, const RenderTransform* pTransform = nullptr, size_t pFlag = 0)
     {
         if (flag & RenderUpdateFlag::Transform) {
             assert(transform);
@@ -76,11 +76,10 @@ struct Scene::Impl
         auto ret = true;
 
         if (transform && pTransform) {
-            RenderMatrix outTransform;
-            RenderMatrix::multiply(pTransform, &transform->m, &outTransform);
+            RenderTransform outTransform(pTransform, transform);
             ret = updateInternal(renderer, &outTransform, pFlag | flag);
         } else {
-            auto outTransform = pTransform ? pTransform : &transform->m;
+            auto outTransform = pTransform ? pTransform : transform;
             ret = updateInternal(renderer, outTransform, pFlag | flag);
         }
 
index 3087426..b7f9927 100644 (file)
@@ -66,7 +66,7 @@ struct Shape::Impl
         return renderer.render(shape, edata);
     }
 
-    bool update(Shape& shape, RenderMethod& renderer, const RenderMatrix* pTransform = nullptr, size_t pFlag = 0)
+    bool update(Shape& shape, RenderMethod& renderer, const RenderTransform* pTransform = nullptr, size_t pFlag = 0)
     {
         if (flag & RenderUpdateFlag::Transform) {
             assert(transform);
@@ -77,11 +77,10 @@ struct Shape::Impl
         }
 
         if (transform && pTransform) {
-            RenderMatrix outTransform;
-            RenderMatrix::multiply(pTransform, &transform->m, &outTransform);
+            RenderTransform outTransform(pTransform, transform);
             edata = renderer.prepare(shape, edata, &outTransform, static_cast<RenderUpdateFlag>(pFlag | flag));
         } else {
-            auto outTransform = pTransform ? pTransform : &transform->m;
+            auto outTransform = pTransform ? pTransform : transform;
             edata = renderer.prepare(shape, edata, outTransform, static_cast<RenderUpdateFlag>(pFlag | flag));
         }
 
index 622dafc..38bfb0f 100644 (file)
@@ -20,39 +20,38 @@ void tvgtest()
     canvas = tvg::SwCanvas::gen();
     canvas->target(buffer, WIDTH, WIDTH, HEIGHT);
 
-    //Create a Scene
+    //Create a Scene1
     auto scene = tvg::Scene::gen();
     pScene1 = scene.get();
     scene->reserve(3);   //reserve 3 shape nodes (optional)
 
-    //Prepare Round Rectangle
+    //Prepare Round Rectangle (Scene1)
     auto shape1 = tvg::Shape::gen();
     shape1->appendRect(-235, -250, 400, 400, 50);      //x, y, w, h, cornerRadius
     shape1->fill(0, 255, 0, 255);                //r, g, b, a
     scene->push(move(shape1));
 
-    //Prepare Circle
+    //Prepare Circle (Scene1)
     auto shape2 = tvg::Shape::gen();
     shape2->appendCircle(-165, -150, 200, 200);    //cx, cy, radiusW, radiusH
     shape2->fill(255, 255, 0, 255);              //r, g, b, a
     scene->push(move(shape2));
 
-    //Prepare Ellipse
+    //Prepare Ellipse (Scene1)
     auto shape3 = tvg::Shape::gen();
     shape3->appendCircle(265, 250, 150, 100);    //cx, cy, radiusW, radiusH
     shape3->fill(0, 255, 255, 255);              //r, g, b, a
     scene->push(move(shape3));
 
     scene->translate(350, 350);
-    scene->scale(0.7);
+    scene->scale(0.5);
 
-    //Create another Scene
+    //Create Scene2
     auto scene2 = tvg::Scene::gen();
     pScene2 = scene2.get();
     scene2->reserve(2);   //reserve 2 shape nodes (optional)
 
-#if 0
-    //Star
+    //Star (Scene2)
     auto shape4 = tvg::Shape::gen();
 
     //Appends Paths
@@ -68,17 +67,14 @@ void tvgtest()
     shape4->lineTo(-53, -5.5);
     shape4->close();
     shape4->fill(0, 0, 127, 127);
-
-    float x, y, w, h;
-    shape4->bounds(x, y, w, h);
     scene2->push(move(shape4));
 
-    //Circle
+    //Circle (Scene2)
     auto shape5 = tvg::Shape::gen();
 
     auto cx = -150.0f;
     auto cy = -150.0f;
-    auto radius = 125.0f;
+    auto radius = 100.0f;
     auto halfRadius = radius * 0.552284f;
 
     //Append Paths
@@ -90,11 +86,11 @@ void tvgtest()
     shape5->fill(127, 0, 0, 127);
     scene2->push(move(shape5));
 
-    scene2->translate(300, 300);
+    scene2->translate(500, 350);
 
     //Push scene2 onto the scene
     scene->push(move(scene2));
-#endif
+
     //Draw the Scene onto the Canvas
     canvas->push(move(scene));
 
@@ -112,6 +108,7 @@ void transit_cb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progres
        while retaining other properties. */
 
     pScene1->rotate(360 * progress);
+    pScene2->rotate(360 * progress);
 
     //Update shape for drawing (this may work asynchronously)
     canvas->update(pScene1);