testDirectUpdate
testScene
testTransform
+testSceneTransform
}
-void* GlRenderer::prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags)
+void* GlRenderer::prepare(const Shape& shape, void* data, const RenderMatrix* transform, RenderUpdateFlag flags)
{
//prepare shape data
GlShape* sdata = static_cast<GlShape*>(data);
class GlRenderer : public RenderMethod
{
public:
- void* prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags) override;
+ void* prepare(const Shape& shape, void* data, const RenderMatrix* transform, RenderUpdateFlag flags) override;
bool dispose(const Shape& shape, void *data) override;
bool render(const Shape& shape, void *data) override;
bool clear() override;
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 RenderTransform& transform);
+void shapeTransformOutline(const Shape& shape, SwShape& sdata, const RenderMatrix& 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);
return true;
}
-void* SwRenderer::prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags)
+void* SwRenderer::prepare(const Shape& shape, void* data, const RenderMatrix* transform, RenderUpdateFlag flags)
{
//prepare shape data
SwShape* sdata = static_cast<SwShape*>(data);
public:
Surface surface;
- void* prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags) override;
+ void* prepare(const Shape& shape, void* data, const RenderMatrix* 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);
/* External Class Implementation */
/************************************************************************/
-void shapeTransformOutline(const Shape& shape, SwShape& sdata, const RenderTransform& transform)
+void shapeTransformOutline(const Shape& shape, SwShape& sdata, const RenderMatrix& transform)
{
auto outline = sdata.outline;
assert(outline);
for(auto paint: paints) {
if (auto scene = dynamic_cast<Scene*>(paint)) {
- if (!SCENE_IMPL->update(*renderer)) return -1;
+ if (!SCENE_IMPL->update(*renderer, nullptr)) return -1;
} else if (auto shape = dynamic_cast<Shape*>(paint)) {
- if (!SHAPE_IMPL->update(*shape, *renderer)) return -1;
+ if (!SHAPE_IMPL->update(*shape, *renderer, nullptr)) return -1;
}
}
return 0;
enum RenderUpdateFlag {None = 0, Path = 1, Fill = 2, Transform = 4, All = 8};
-struct RenderTransform
+struct RenderMatrix
{
//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
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;
}
- //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;
-
- //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;
- }
-
- //scale
- e11 *= factor;
- e22 *= factor;
- e33 *= factor;
-
- //translate
- e31 += x;
- e32 += y;
+ RenderMatrix::identity(&m);
+ RenderMatrix::scale(&m, factor);
+ RenderMatrix::rotate(&m, degree);
+ RenderMatrix::translate(&m, x, y);
return true;
}
-
- RenderTransform& operator*=(const RenderTransform rhs)
- {
- e11 = e11 * rhs.e11 + e12 * rhs.e21 + e13 * rhs.e31;
- e12 = e11 * rhs.e12 + e12 * rhs.e22 + e13 * rhs.e32;
- e13 = e11 * rhs.e13 + e12 * rhs.e23 + e13 * rhs.e33;
-
- e21 = e21 * rhs.e11 + e22 * rhs.e21 + e23 * rhs.e31;
- e22 = e21 * rhs.e12 + e22 * rhs.e22 + e23 * rhs.e32;
- e23 = e21 * rhs.e13 + e22 * rhs.e23 + e23 * rhs.e33;
-
- e31 = e31 * rhs.e11 + e32 * rhs.e21 + e33 * rhs.e31;
- e32 = e31 * rhs.e12 + e32 * rhs.e22 + e33 * rhs.e32;
- e33 = e31 * rhs.e13 + e32 * rhs.e23 + e33 * rhs.e33;
-
- return *this;
- }
};
{
public:
virtual ~RenderMethod() {}
- virtual void* prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags) = 0;
+ virtual void* prepare(const Shape& shape, void* data, const RenderMatrix* 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;
}
-int Scene::scale(float scaleFacator) noexcept
+int Scene::scale(float factor) noexcept
{
- return 0;
+ auto impl = pImpl.get();
+ assert(impl);
+
+ return impl->scale(factor);
}
int Scene::rotate(float degree) noexcept
{
- return 0;
+ auto impl = pImpl.get();
+ assert(impl);
+
+ return impl->rotate(degree);
}
int Scene::translate(float x, float y) noexcept
{
- return 0;
+ auto impl = pImpl.get();
+ assert(impl);
+
+ return impl->translate(x, y);
}
struct Scene::Impl
{
vector<Paint*> paints;
+ RenderTransform *transform = nullptr;
+ size_t flag = RenderUpdateFlag::None;
~Impl()
{
//Are you sure clear() prior to this?
assert(paints.empty());
+ if (transform) delete(transform);
}
bool clear(RenderMethod& renderer)
return true;
}
- bool update(RenderMethod &renderer)
+ bool updateInternal(RenderMethod &renderer, const RenderMatrix* transform, size_t flag)
{
for(auto paint: paints) {
if (auto scene = dynamic_cast<Scene*>(paint)) {
- if (!SCENE_IMPL->update(renderer)) return false;
+ if (!SCENE_IMPL->update(renderer, transform, flag)) return false;
} else if (auto shape = dynamic_cast<Shape*>(paint)) {
- if (!SHAPE_IMPL->update(*shape, renderer)) return false;
+ if (!SHAPE_IMPL->update(*shape, renderer, transform, flag)) return false;
}
}
return true;
}
+ bool update(RenderMethod &renderer, const RenderMatrix* pTransform = nullptr, size_t pFlag = 0)
+ {
+ if (flag & RenderUpdateFlag::Transform) {
+ assert(transform);
+ if (!transform->update()) {
+ delete(transform);
+ transform = nullptr;
+ }
+ }
+
+ auto ret = true;
+
+ if (transform && pTransform) {
+ RenderMatrix outTransform;
+ RenderMatrix::multiply(pTransform, &transform->m, &outTransform);
+ ret = updateInternal(renderer, &outTransform, pFlag | flag);
+ } else {
+ auto outTransform = pTransform ? pTransform : &transform->m;
+ ret = updateInternal(renderer, outTransform, pFlag | flag);
+ }
+
+ flag = RenderUpdateFlag::None;
+
+ return ret;
+ }
+
bool render(RenderMethod &renderer)
{
for(auto paint: paints) {
}
return true;
}
+
+ bool scale(float factor)
+ {
+ if (transform) {
+ if (fabsf(factor - transform->factor) <= FLT_EPSILON) return -1;
+ } else {
+ if (fabsf(factor) <= FLT_EPSILON) return -1;
+ transform = new RenderTransform();
+ assert(transform);
+ }
+ transform->factor = factor;
+ flag |= RenderUpdateFlag::Transform;
+
+ return 0;
+ }
+
+ bool rotate(float degree)
+ {
+ if (transform) {
+ if (fabsf(degree - transform->degree) <= FLT_EPSILON) return -1;
+ } else {
+ if (fabsf(degree) <= FLT_EPSILON) return -1;
+ transform = new RenderTransform();
+ assert(transform);
+ }
+ transform->degree = degree;
+ flag |= RenderUpdateFlag::Transform;
+
+ return 0;
+ }
+
+ bool translate(float x, float y)
+ {
+ if (transform) {
+ if (fabsf(x - transform->x) <= FLT_EPSILON && fabsf(y - transform->y) <= FLT_EPSILON) return -1;
+ } else {
+ if (fabsf(x) <= FLT_EPSILON && fabsf(y) <= FLT_EPSILON) return -1;
+ transform = new RenderTransform();
+ assert(transform);
+ }
+ transform->x = x;
+ transform->y = y;
+ flag |= RenderUpdateFlag::Transform;
+
+ return 0;
+ }
};
#endif //_TVG_SCENE_IMPL_H_
\ No newline at end of file
return renderer.render(shape, edata);
}
- bool update(Shape& shape, RenderMethod& renderer)
+ bool update(Shape& shape, RenderMethod& renderer, const RenderMatrix* pTransform = nullptr, size_t pFlag = 0)
{
if (flag & RenderUpdateFlag::Transform) {
assert(transform);
transform = nullptr;
}
}
- edata = renderer.prepare(shape, edata, transform, static_cast<RenderUpdateFlag>(flag));
+
+ if (transform && pTransform) {
+ RenderMatrix outTransform;
+ RenderMatrix::multiply(pTransform, &transform->m, &outTransform);
+ edata = renderer.prepare(shape, edata, &outTransform, static_cast<RenderUpdateFlag>(pFlag | flag));
+ } else {
+ auto outTransform = pTransform ? pTransform : &transform->m;
+ edata = renderer.prepare(shape, edata, outTransform, static_cast<RenderUpdateFlag>(pFlag | flag));
+ }
+
flag = RenderUpdateFlag::None;
if (edata) return true;
gcc -o testDirectUpdate testDirectUpdate.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg`
gcc -o testScene testScene.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg`
gcc -o testTransform testTransform.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg`
+ gcc -o testSceneTransform testSceneTransform.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg`
--- /dev/null
+#include <tizenvg.h>
+#include <Elementary.h>
+
+using namespace std;
+
+#define WIDTH 800
+#define HEIGHT 800
+
+static uint32_t buffer[WIDTH * HEIGHT];
+unique_ptr<tvg::SwCanvas> canvas = nullptr;
+tvg::Scene* pScene1 = nullptr;
+tvg::Scene* pScene2 = nullptr;
+
+void tvgtest()
+{
+ //Initialize TizenVG Engine
+ tvg::Engine::init();
+
+ //Create a Canvas
+ canvas = tvg::SwCanvas::gen();
+ canvas->target(buffer, WIDTH, WIDTH, HEIGHT);
+
+ //Create a Scene
+ auto scene = tvg::Scene::gen();
+ pScene1 = scene.get();
+ scene->reserve(3); //reserve 3 shape nodes (optional)
+
+ //Prepare Round Rectangle
+ 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
+ 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
+ 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);
+
+ //Create another Scene
+ auto scene2 = tvg::Scene::gen();
+ pScene2 = scene2.get();
+ scene2->reserve(2); //reserve 2 shape nodes (optional)
+
+#if 0
+ //Star
+ auto shape4 = tvg::Shape::gen();
+
+ //Appends Paths
+ shape4->moveTo(0, -114.5);
+ shape4->lineTo(54, -5.5);
+ shape4->lineTo(175, 11.5);
+ shape4->lineTo(88, 95.5);
+ shape4->lineTo(108, 216.5);
+ shape4->lineTo(0, 160.5);
+ shape4->lineTo(-102, 216.5);
+ shape4->lineTo(-87, 96.5);
+ shape4->lineTo(-173, 12.5);
+ 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
+ auto shape5 = tvg::Shape::gen();
+
+ auto cx = -150.0f;
+ auto cy = -150.0f;
+ auto radius = 125.0f;
+ auto halfRadius = radius * 0.552284f;
+
+ //Append Paths
+ shape5->moveTo(cx, cy - radius);
+ shape5->cubicTo(cx + halfRadius, cy - radius, cx + radius, cy - halfRadius, cx + radius, cy);
+ shape5->cubicTo(cx + radius, cy + halfRadius, cx + halfRadius, cy + radius, cx, cy+ radius);
+ shape5->cubicTo(cx - halfRadius, cy + radius, cx - radius, cy + halfRadius, cx - radius, cy);
+ shape5->cubicTo(cx - radius, cy - halfRadius, cx - halfRadius, cy - radius, cx, cy - radius);
+ shape5->fill(127, 0, 0, 127);
+ scene2->push(move(shape5));
+
+ scene2->translate(300, 300);
+
+ //Push scene2 onto the scene
+ scene->push(move(scene2));
+#endif
+ //Draw the Scene onto the Canvas
+ canvas->push(move(scene));
+
+ canvas->draw();
+ canvas->sync();
+
+ //Terminate TizenVG Engine
+ tvg::Engine::term();
+}
+
+void transit_cb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress)
+{
+ /* Update scene directly.
+ You can update only necessary properties of this scene,
+ while retaining other properties. */
+
+ pScene1->rotate(360 * progress);
+
+ //Update shape for drawing (this may work asynchronously)
+ canvas->update(pScene1);
+
+ //Draw Next frames
+ canvas->draw();
+ canvas->sync();
+
+ //Update Efl Canvas
+ Eo* img = (Eo*) effect;
+ evas_object_image_data_update_add(img, 0, 0, WIDTH, HEIGHT);
+}
+
+void
+win_del(void *data, Evas_Object *o, void *ev)
+{
+ elm_exit();
+}
+
+int main(int argc, char **argv)
+{
+ //Initialize TizenVG Engine
+ tvg::Engine::init();
+
+ tvgtest();
+
+ //Show the result using EFL...
+ elm_init(argc, argv);
+
+ Eo* win = elm_win_util_standard_add(NULL, "TizenVG Test");
+ evas_object_smart_callback_add(win, "delete,request", win_del, 0);
+
+ Eo* img = evas_object_image_filled_add(evas_object_evas_get(win));
+ evas_object_image_size_set(img, WIDTH, HEIGHT);
+ evas_object_image_data_set(img, buffer);
+ evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_show(img);
+
+ elm_win_resize_object_add(win, img);
+ evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT);
+ evas_object_show(win);
+
+ Elm_Transit *transit = elm_transit_add();
+ elm_transit_effect_add(transit, transit_cb, img, nullptr);
+ elm_transit_duration_set(transit, 2);
+ elm_transit_repeat_times_set(transit, -1);
+ elm_transit_go(transit);
+
+ elm_run();
+ elm_shutdown();
+
+ //Terminate TizenVG Engine
+ tvg::Engine::term();
+}