mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 13:43:43 +00:00
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
This commit is contained in:
parent
1f6da2d0b6
commit
a5f15a588c
10 changed files with 89 additions and 108 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue