virtual int rotate(float degree) = 0;
virtual int scale(float factor) = 0;
+ virtual int translate(float x, float y) = 0;
virtual int bounds(float&x, float& y, float& w, float& h) const = 0;
- virtual float scale() const = 0;
- virtual float rotate() const = 0;
};
int rotate(float degree) noexcept override;
int scale(float factor) noexcept override;
+ int translate(float x, float y) noexcept override;
size_t pathCommands(const PathCommand** cmds) const noexcept;
size_t pathCoords(const Point** pts) const noexcept;
int fill(size_t* r, size_t* g, size_t* b, size_t* a) const noexcept;
int bounds(float&x, float& y, float& w, float& h) const noexcept override;
- float scale() const noexcept override;
- float rotate() const noexcept override;
static std::unique_ptr<Shape> gen() noexcept;
int rotate(float degree) noexcept override;
int scale(float factor) noexcept override;
+ int translate(float x, float y) noexcept override;
int bounds(float&x, float& y, float& w, float& h) const noexcept override;
- float scale() const noexcept override;
- float rotate() const noexcept override;
static std::unique_ptr<Scene> gen() noexcept;
}
-void* GlRenderer::prepare(const Shape& shape, void* data, RenderUpdateFlag flags)
+void* GlRenderer::prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags)
{
//prepare shape data
GlShape* sdata = static_cast<GlShape*>(data);
assert(sdata);
}
+ if (RenderUpdateFlag::Path) {
+ //TODO: Updated Vertices
+ }
+
+ if (RenderUpdateFlag::Transform) {
+ //TODO: Updated Transform
+ }
+
//TODO:
return sdata;
class GlRenderer : public RenderMethod
{
public:
- void* prepare(const Shape& shape, void* data, 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;
bool shapeGenOutline(const Shape& shape, SwShape& sdata);
void shapeDelOutline(SwShape& sdata);
bool shapeGenRle(const Shape& shape, SwShape& sdata, const SwSize& clip);
-bool shapeTransformOutline(const Shape& shape, SwShape& sdata);
+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);
return true;
}
-void* SwRenderer::prepare(const Shape& shape, void* data, RenderUpdateFlag flags)
+void* SwRenderer::prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags)
{
//prepare shape data
SwShape* sdata = static_cast<SwShape*>(data);
if (alpha == 0) return sdata;
//TODO: Threading
- if (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Transform)) {
+ if (flags & RenderUpdateFlag::Path || RenderUpdateFlag::Transform) {
shapeReset(*sdata);
if (!shapeGenOutline(shape, *sdata)) return sdata;
- if (!shapeTransformOutline(shape, *sdata)) return sdata;
+ if (transform) shapeTransformOutline(shape, *sdata, *transform);
SwSize clip = {static_cast<SwCoord>(surface.w), static_cast<SwCoord>(surface.h)};
if (!shapeGenRle(shape, *sdata, clip)) return sdata;
public:
Surface surface;
- void* prepare(const Shape& shape, void* data, 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);
/* External Class Implementation */
/************************************************************************/
-bool shapeTransformOutline(const Shape& shape, SwShape& sdata)
+void shapeTransformOutline(const Shape& shape, SwShape& sdata, const RenderTransform& transform)
{
- constexpr auto PI = 3.141592f;
-
- auto degree = shape.rotate();
- auto scale = shape.scale();
- bool rotateOn = false;
- bool scaleOn = false;
-
- if (fabsf(degree) > FLT_EPSILON) rotateOn = true;
- if (fabsf(scale - 1) > FLT_EPSILON) scaleOn = true;
-
- if (!rotateOn && !scaleOn) return true;
-
auto outline = sdata.outline;
assert(outline);
- float x, y, w, h;
- shape.bounds(x, y, w, h);
-
- auto cx = x + w * 0.5f;
- auto cy = y + h * 0.5f;
-
- float radian, cosVal, sinVal;
- if (rotateOn) {
- radian = degree / 180.0f * PI;
- cosVal = cosf(radian);
- sinVal = sinf(radian);
- }
-
for(size_t i = 0; i < outline->ptsCnt; ++i) {
- auto dx = static_cast<float>(outline->pts[i].x >> 6) - cx;
- auto dy = static_cast<float>(outline->pts[i].y >> 6) - cy;
- if (rotateOn) {
- auto tx = (cosVal * dx - sinVal * dy);
- auto ty = (sinVal * dx + cosVal * dy);
- dx = tx;
- dy = ty;
- }
- if (scaleOn) {
- dx *= scale;
- dy *= scale;
- }
- auto pt = Point{dx + cx, dy + cy};
+ auto dx = static_cast<float>(outline->pts[i].x >> 6);
+ auto dy = static_cast<float>(outline->pts[i].y >> 6);
+ auto tx = dx * transform.e11 + dy * transform.e12 + transform.e13;
+ auto ty = dx * transform.e21 + dy * transform.e22 + transform.e23;
+ auto pt = Point{tx + transform.e31, ty + transform.e32};
outline->pts[i] = TO_SWPOINT(&pt);
}
-
- return true;
}
enum RenderUpdateFlag {None = 0, Path = 1, Fill = 2, Transform = 4, All = 8};
+struct RenderTransform
+{
+ float e11, e12, e13;
+ float e21, e22, e23;
+ float e31, e32, e33;
+
+ void 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;
+ }
+
+ void rotate(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 = 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;
+ }
+
+ void translate(float x, float y)
+ {
+ e31 += x;
+ e32 += y;
+ }
+
+ void scale(float factor)
+ {
+ e11 *= factor;
+ e22 *= factor;
+ e33 *= factor;
+ }
+
+ 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;
+ }
+};
+
+
class RenderMethod
{
public:
virtual ~RenderMethod() {}
- virtual void* prepare(const Shape& shape, void* data, 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;
}
+int Scene::translate(float x, float y) noexcept
+{
+ return 0;
+}
+
+
int Scene::bounds(float& x, float& y, float& w, float& h) const noexcept
{
auto impl = pImpl.get();
return 0;
}
-
-float Scene::scale() const noexcept
-{
- return 0;
-}
-
-
-float Scene::rotate() const noexcept
-{
- return 0;
-}
-
#endif /* _TVG_SCENE_CPP_ */
\ No newline at end of file
auto impl = pImpl.get();
assert(impl);
- if (fabsf(factor) < FLT_EPSILON || fabsf(factor - impl->scale) <= FLT_EPSILON) return -1;
+ if (fabsf(factor - impl->scale) <= FLT_EPSILON) return -1;
impl->scale = factor;
impl->flag |= RenderUpdateFlag::Transform;
}
-int Shape::bounds(float& x, float& y, float& w, float& h) const noexcept
+int Shape::translate(float x, float y) noexcept
{
auto impl = pImpl.get();
assert(impl);
- if (!impl->bounds(x, y, w, h)) return -1;
+ if (fabsf(x - impl->x) <= FLT_EPSILON && fabsf(y - impl->y) <= FLT_EPSILON) return -1;
+
+ impl->x = x;
+ impl->y = y;
+ impl->flag |= RenderUpdateFlag::Transform;
return 0;
}
-float Shape::scale() const noexcept
+int Shape::bounds(float& x, float& y, float& w, float& h) const noexcept
{
auto impl = pImpl.get();
assert(impl);
- return impl->scale;
-}
-
-
-float Shape::rotate() const noexcept
-{
- auto impl = pImpl.get();
- assert(impl);
+ if (!impl->bounds(x, y, w, h)) return -1;
- return impl->rotate;
+ return 0;
}
+
#endif //_TVG_SHAPE_CPP_
uint8_t color[4] = {0, 0, 0, 0}; //r, g, b, a
float scale = 1;
float rotate = 0;
+ float x = 0;
+ float y = 0;
void *edata = nullptr; //engine data
size_t flag = RenderUpdateFlag::None;
bool update(Shape& shape, RenderMethod& renderer)
{
- edata = renderer.prepare(shape, edata, static_cast<RenderUpdateFlag>(flag));
+ if (flag & RenderUpdateFlag::Transform) {
+ RenderTransform transform;
+ transform.identity();
+ transform.rotate(rotate);
+ transform.scale(scale);
+ transform.translate(x, y);
+ edata = renderer.prepare(shape, edata, &transform, static_cast<RenderUpdateFlag>(flag));
+ } else {
+ edata = renderer.prepare(shape, edata, nullptr, static_cast<RenderUpdateFlag>(flag));
+ }
+
flag = RenderUpdateFlag::None;
+
if (edata) return true;
return false;
}
instead, you should consider not to interrupt this pointer life-cycle. */
pShape = shape.get();
- shape->appendRect(0, 0, 200, 200, 0);
- shape->appendRect(100, 100, 300, 300, 100);
- shape->appendCircle(400, 400, 100, 100);
- shape->appendCircle(400, 500, 170, 100);
+ shape->appendRect(-285, -300, 200, 200, 0);
+ shape->appendRect(-185, -200, 300, 300, 100);
+ shape->appendCircle(115, 100, 100, 100);
+ shape->appendCircle(115, 200, 170, 100);
shape->fill(255, 255, 255, 255);
+ shape->translate(285, 300);
canvas->push(move(shape));
//Shape
auto shape = tvg::Shape::gen();
- shape->appendRect(-100 + (800 * progress), -100 + (800 * progress), 200, 200, (100 * progress));
+ shape->appendRect(-100, -100, 200, 200, (100 * progress));
shape->fill(rand()%255, rand()%255, rand()%255, 255);
+ shape->translate(800 * progress, 800 * progress);
shape->scale(1 - 0.75 * progress);
shape->rotate(360 * progress);