diff --git a/src/lib/tvgRenderCommon.h b/src/lib/tvgRenderCommon.h index b21c2440..a3bfcb6d 100644 --- a/src/lib/tvgRenderCommon.h +++ b/src/lib/tvgRenderCommon.h @@ -32,12 +32,27 @@ enum RenderUpdateFlag {None = 0, Path = 1, Fill = 2, Transform = 4, All = 8}; 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; @@ -47,44 +62,38 @@ struct RenderTransform 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); - if (fabsf(degree) <= FLT_EPSILON) return; + 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; - auto radian = degree / 180.0f * PI; - auto cosVal = cosf(radian); - auto sinVal = sinf(radian); + e11 = t11; + e12 = t12; + e21 = t21; + e22 = t22; + e31 = t31; + e32 = t32; + } - 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) - { + //scale e11 *= factor; e22 *= factor; e33 *= factor; + + //translate + e31 += x; + e32 += y; + + return true; } RenderTransform& operator*=(const RenderTransform rhs) diff --git a/src/lib/tvgShape.cpp b/src/lib/tvgShape.cpp index 6665a558..432a8a66 100644 --- a/src/lib/tvgShape.cpp +++ b/src/lib/tvgShape.cpp @@ -247,12 +247,7 @@ int Shape::scale(float factor) noexcept 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); } @@ -261,12 +256,7 @@ int Shape::rotate(float degree) noexcept 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); } @@ -275,13 +265,7 @@ int Shape::translate(float x, float y) noexcept 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); } diff --git a/src/lib/tvgShapeImpl.h b/src/lib/tvgShapeImpl.h index 6b81dc03..e552a3ba 100644 --- a/src/lib/tvgShapeImpl.h +++ b/src/lib/tvgShapeImpl.h @@ -38,13 +38,11 @@ struct Shape::Impl 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) { @@ -55,6 +53,7 @@ struct Shape::Impl if (path) delete(path); if (stroke) delete(stroke); if (fill) delete(fill); + if (transform) delete(transform); } bool dispose(Shape& shape, RenderMethod& renderer) @@ -70,16 +69,13 @@ struct Shape::Impl 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(flag)); - } else { - edata = renderer.prepare(shape, edata, nullptr, static_cast(flag)); + assert(transform); + if (!transform->update()) { + delete(transform); + transform = nullptr; + } } - + edata = renderer.prepare(shape, edata, transform, static_cast(flag)); flag = RenderUpdateFlag::None; if (edata) return true; @@ -91,6 +87,52 @@ struct Shape::Impl 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