struct RenderTransform
{
+ //3x3 Matrix Elements
float e11, e12, e13;
float e21, e22, e23;
float e31, e32, e33;
- void identity()
+ float x = 0.0f;
+ float y = 0.0f;
+ float degree = 0.0f; //rotation degree
+ float factor = 1.0f; //scale factor
+
+ 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;
e31 = 0.0f;
e32 = 0.0f;
e33 = 1.0f;
- }
- void rotate(float degree)
- {
- constexpr auto PI = 3.141592f;
+ //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;
+ }
- 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;
- }
+ //scale
+ e11 *= factor;
+ e22 *= factor;
+ e33 *= factor;
- void translate(float x, float y)
- {
+ //translate
e31 += x;
e32 += y;
- }
- void scale(float factor)
- {
- e11 *= factor;
- e22 *= factor;
- e33 *= factor;
+ return true;
}
RenderTransform& operator*=(const RenderTransform rhs)
auto impl = pImpl.get();
assert(impl);
- if (fabsf(factor - impl->scale) <= FLT_EPSILON) return -1;
-
- impl->scale = factor;
- impl->flag |= RenderUpdateFlag::Transform;
-
- return 0;
+ return impl->scale(factor);
}
auto impl = pImpl.get();
assert(impl);
- if (fabsf(degree - impl->rotate) <= FLT_EPSILON) return -1;
-
- impl->rotate = degree;
- impl->flag |= RenderUpdateFlag::Transform;
-
- return 0;
+ return impl->rotate(degree);
}
auto impl = pImpl.get();
assert(impl);
- 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;
+ return impl->translate(x, y);
}
ShapeFill *fill = nullptr;
ShapeStroke *stroke = nullptr;
ShapePath *path = nullptr;
+ RenderTransform *transform = nullptr;
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;
+ void *edata = nullptr; //engine data
+
Impl() : path(new ShapePath)
{
if (path) delete(path);
if (stroke) delete(stroke);
if (fill) delete(fill);
+ if (transform) delete(transform);
}
bool dispose(Shape& shape, RenderMethod& renderer)
bool update(Shape& shape, RenderMethod& renderer)
{
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));
+ assert(transform);
+ if (!transform->update()) {
+ delete(transform);
+ transform = nullptr;
+ }
}
-
+ edata = renderer.prepare(shape, edata, transform, static_cast<RenderUpdateFlag>(flag));
flag = RenderUpdateFlag::None;
if (edata) return true;
assert(path);
return path->bounds(x, y, w, h);
}
+
+ 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_SHAPE_IMPL_H_
\ No newline at end of file