diff --git a/inc/thorvg.h b/inc/thorvg.h index 20f1942a..47414d85 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -281,6 +281,9 @@ public: * The rotational axis passes through the point on the object with zero coordinates. * * @param[in] degree The value of the angle in degrees. + * + * @retval Result::InsufficientCondition in case a custom transform is applied. + * @see Paint::transform() */ Result rotate(float degree) noexcept; @@ -288,6 +291,9 @@ public: * @brief Sets the scale value of the object. * * @param[in] factor The value of the scaling factor. The default value is 1. + * + * @retval Result::InsufficientCondition in case a custom transform is applied. + * @see Paint::transform() */ Result scale(float factor) noexcept; @@ -299,6 +305,9 @@ public: * * @param[in] x The value of the horizontal shift. * @param[in] y The value of the vertical shift. + * + * @retval Result::InsufficientCondition in case a custom transform is applied. + * @see Paint::transform() */ Result translate(float x, float y) noexcept; diff --git a/src/bindings/capi/thorvg_capi.h b/src/bindings/capi/thorvg_capi.h index 385ec1a7..5f1c3d0f 100644 --- a/src/bindings/capi/thorvg_capi.h +++ b/src/bindings/capi/thorvg_capi.h @@ -801,6 +801,9 @@ TVG_API Tvg_Result tvg_paint_del(Tvg_Paint* paint); * * \return Tvg_Result enumeration. * \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* \retval TVG_RESULT_INSUFFICIENT_CONDITION in case a custom transform is applied. +* +* \see tvg_paint_set_transform() */ TVG_API Tvg_Result tvg_paint_scale(Tvg_Paint* paint, float factor); @@ -816,6 +819,9 @@ TVG_API Tvg_Result tvg_paint_scale(Tvg_Paint* paint, float factor); * * \return Tvg_Result enumeration. * \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* \retval TVG_RESULT_INSUFFICIENT_CONDITION in case a custom transform is applied. +* +* \see tvg_paint_set_transform() */ TVG_API Tvg_Result tvg_paint_rotate(Tvg_Paint* paint, float degree); @@ -832,6 +838,9 @@ TVG_API Tvg_Result tvg_paint_rotate(Tvg_Paint* paint, float degree); * * \return Tvg_Result enumeration. * \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* \retval TVG_RESULT_INSUFFICIENT_CONDITION in case a custom transform is applied. +* +* \see tvg_paint_set_transform() */ TVG_API Tvg_Result tvg_paint_translate(Tvg_Paint* paint, float x, float y); diff --git a/src/renderer/tvgPaint.cpp b/src/renderer/tvgPaint.cpp index 24d84f37..ec2afcd7 100644 --- a/src/renderer/tvgPaint.cpp +++ b/src/renderer/tvgPaint.cpp @@ -87,7 +87,7 @@ static Result _compFastTrack(RenderMethod* renderer, Paint* cmpTarget, const Ren if (ptsCnt != 4) return Result::InsufficientCondition; - if (rTransform) rTransform->update(); + if (rTransform && (cmpTarget->pImpl->renderFlag & RenderUpdateFlag::Transform)) rTransform->update(); //No rotation and no skewing, still can try out clipping the rect region. auto tryClip = false; @@ -181,13 +181,14 @@ Paint* Paint::Impl::duplicate() bool Paint::Impl::rotate(float degree) { if (rTransform) { + if (rTransform->overriding) return false; if (mathEqual(degree, rTransform->degree)) return true; } else { if (mathZero(degree)) return true; rTransform = new RenderTransform(); } rTransform->degree = degree; - if (!rTransform->overriding) renderFlag |= RenderUpdateFlag::Transform; + renderFlag |= RenderUpdateFlag::Transform; return true; } @@ -196,13 +197,14 @@ bool Paint::Impl::rotate(float degree) bool Paint::Impl::scale(float factor) { if (rTransform) { + if (rTransform->overriding) return false; if (mathEqual(factor, rTransform->scale)) return true; } else { if (mathEqual(factor, 1.0f)) return true; rTransform = new RenderTransform(); } rTransform->scale = factor; - if (!rTransform->overriding) renderFlag |= RenderUpdateFlag::Transform; + renderFlag |= RenderUpdateFlag::Transform; return true; } @@ -211,14 +213,15 @@ bool Paint::Impl::scale(float factor) bool Paint::Impl::translate(float x, float y) { if (rTransform) { - if (mathEqual(x, rTransform->x) && mathEqual(y, rTransform->y)) return true; + if (rTransform->overriding) return false; + if (mathEqual(x, rTransform->m.e13) && mathEqual(y, rTransform->m.e23)) return true; } else { if (mathZero(x) && mathZero(y)) return true; rTransform = new RenderTransform(); } - rTransform->x = x; - rTransform->y = y; - if (!rTransform->overriding) renderFlag |= RenderUpdateFlag::Transform; + rTransform->m.e13 = x; + rTransform->m.e23 = y; + renderFlag |= RenderUpdateFlag::Transform; return true; } @@ -263,10 +266,7 @@ RenderData Paint::Impl::update(RenderMethod* renderer, const RenderTransform* pT this->renderer = renderer; } - if (renderFlag & RenderUpdateFlag::Transform) { - if (!rTransform) return nullptr; - rTransform->update(); - } + if (renderFlag & RenderUpdateFlag::Transform) rTransform->update(); /* 1. Composition Pre Processing */ RenderData trd = nullptr; //composite target render data @@ -390,28 +390,28 @@ Paint :: ~Paint() Result Paint::rotate(float degree) noexcept { if (pImpl->rotate(degree)) return Result::Success; - return Result::FailedAllocation; + return Result::InsufficientCondition; } Result Paint::scale(float factor) noexcept { if (pImpl->scale(factor)) return Result::Success; - return Result::FailedAllocation; + return Result::InsufficientCondition; } Result Paint::translate(float x, float y) noexcept { if (pImpl->translate(x, y)) return Result::Success; - return Result::FailedAllocation; + return Result::InsufficientCondition; } Result Paint::transform(const Matrix& m) noexcept { if (pImpl->transform(m)) return Result::Success; - return Result::FailedAllocation; + return Result::InsufficientCondition; } diff --git a/src/renderer/tvgPaint.h b/src/renderer/tvgPaint.h index 39bc2491..1cce2a29 100644 --- a/src/renderer/tvgPaint.h +++ b/src/renderer/tvgPaint.h @@ -87,7 +87,6 @@ namespace tvg if (!rTransform) { if (mathIdentity(&m)) return true; rTransform = new RenderTransform(); - if (!rTransform) return false; } rTransform->override(m); renderFlag |= RenderUpdateFlag::Transform; @@ -98,7 +97,7 @@ namespace tvg Matrix* transform() { if (rTransform) { - rTransform->update(); + if (renderFlag & RenderUpdateFlag::Transform) rTransform->update(); return &rTransform->m; } return nullptr; diff --git a/src/renderer/tvgRender.cpp b/src/renderer/tvgRender.cpp index 05dcde6c..90432d65 100644 --- a/src/renderer/tvgRender.cpp +++ b/src/renderer/tvgRender.cpp @@ -43,13 +43,18 @@ void RenderTransform::update() { if (overriding) return; - mathIdentity(&m); + m.e11 = 1.0f; + m.e12 = 0.0f; + + m.e21 = 0.0f; + m.e22 = 1.0f; + + m.e31 = 0.0f; + m.e32 = 0.0f; + m.e33 = 1.0f; mathScale(&m, scale, scale); - mathRotate(&m, degree); - - mathTranslate(&m, x, y); } diff --git a/src/renderer/tvgRender.h b/src/renderer/tvgRender.h index a915d68f..96567645 100644 --- a/src/renderer/tvgRender.h +++ b/src/renderer/tvgRender.h @@ -112,9 +112,7 @@ struct RenderRegion struct RenderTransform { - Matrix m; //3x3 Matrix Elements - float x = 0.0f; - float y = 0.0f; + Matrix m; float degree = 0.0f; //rotation degree float scale = 1.0f; //scale factor bool overriding = false; //user transform? @@ -122,7 +120,11 @@ struct RenderTransform void update(); void override(const Matrix& m); - RenderTransform() {} + RenderTransform() + { + m.e13 = m.e23 = 0.0f; + } + RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs); }; diff --git a/test/testPaint.cpp b/test/testPaint.cpp index b488585d..8d5fdf2e 100644 --- a/test/testPaint.cpp +++ b/test/testPaint.cpp @@ -59,11 +59,12 @@ TEST_CASE("Custom Transformation", "[tvgPaint]") REQUIRE(m2.e32 == Approx(m3.e32).margin(0.000001)); REQUIRE(m2.e33 == Approx(m3.e33).margin(0.000001)); - //Verify Transform is not modified - REQUIRE(shape->translate(155.0f, -155.0f) == Result::Success); - REQUIRE(shape->scale(4.7f) == Result::Success); - REQUIRE(shape->rotate(45.0f) == Result::Success); + //It's not allowed if the custom transform is applied. + REQUIRE(shape->translate(155.0f, -155.0f) == Result::InsufficientCondition); + REQUIRE(shape->scale(4.7f) == Result::InsufficientCondition); + REQUIRE(shape->rotate(45.0f) == Result::InsufficientCondition); + //Verify Transform is not modified auto m4 = shape->transform(); REQUIRE(m2.e11 == Approx(m4.e11).margin(0.000001)); REQUIRE(m2.e12 == Approx(m4.e12).margin(0.000001));