From: Hermet Park Date: Sun, 17 May 2020 12:33:56 +0000 (+0900) Subject: common scene: complete scene tranfsormation feature. X-Git-Tag: accepted/tizen/unified/20200806.062539~144 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a5f15a588c5dda01456b6848380aff0547bb541c;p=platform%2Fcore%2Fgraphics%2Ftizenvg.git common scene: complete scene tranfsormation feature. 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 --- diff --git a/src/lib/gl_engine/tvgGlRenderer.cpp b/src/lib/gl_engine/tvgGlRenderer.cpp index 48a0ee5..792e524 100644 --- a/src/lib/gl_engine/tvgGlRenderer.cpp +++ b/src/lib/gl_engine/tvgGlRenderer.cpp @@ -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(data); diff --git a/src/lib/gl_engine/tvgGlRenderer.h b/src/lib/gl_engine/tvgGlRenderer.h index 557f9e7..4d6ba79 100644 --- a/src/lib/gl_engine/tvgGlRenderer.h +++ b/src/lib/gl_engine/tvgGlRenderer.h @@ -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; diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index 3068b9b..62a6b29 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -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); diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index 2d97445..36e367b 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -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(data); diff --git a/src/lib/sw_engine/tvgSwRenderer.h b/src/lib/sw_engine/tvgSwRenderer.h index 4c0a7ba..3dfb076 100644 --- a/src/lib/sw_engine/tvgSwRenderer.h +++ b/src/lib/sw_engine/tvgSwRenderer.h @@ -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); diff --git a/src/lib/sw_engine/tvgSwShape.cpp b/src/lib/sw_engine/tvgSwShape.cpp index efad932..d7229dc 100644 --- a/src/lib/sw_engine/tvgSwShape.cpp +++ b/src/lib/sw_engine/tvgSwShape.cpp @@ -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); diff --git a/src/lib/tvgRenderCommon.h b/src/lib/tvgRenderCommon.h index 0ad1d55..f40639d 100644 --- a/src/lib/tvgRenderCommon.h +++ b/src/lib/tvgRenderCommon.h @@ -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; diff --git a/src/lib/tvgSceneImpl.h b/src/lib/tvgSceneImpl.h index 4def223..abd29e6 100644 --- a/src/lib/tvgSceneImpl.h +++ b/src/lib/tvgSceneImpl.h @@ -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(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); } diff --git a/src/lib/tvgShapeImpl.h b/src/lib/tvgShapeImpl.h index 3087426..b7f9927 100644 --- a/src/lib/tvgShapeImpl.h +++ b/src/lib/tvgShapeImpl.h @@ -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(pFlag | flag)); } else { - auto outTransform = pTransform ? pTransform : &transform->m; + auto outTransform = pTransform ? pTransform : transform; edata = renderer.prepare(shape, edata, outTransform, static_cast(pFlag | flag)); } diff --git a/test/testSceneTransform.cpp b/test/testSceneTransform.cpp index 622dafc..38bfb0f 100644 --- a/test/testSceneTransform.cpp +++ b/test/testSceneTransform.cpp @@ -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);