diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index 57e3d164..76a7ac96 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -299,6 +299,7 @@ bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, Sw SwFixed mathMean(SwFixed angle1, SwFixed angle2); SwPoint mathTransform(const Point* to, const Matrix* transform); bool mathUpdateOutlineBBox(const SwOutline* outline, const SwBBox& clipRegion, SwBBox& renderRegion); +bool mathInverse(const Matrix* m, Matrix* invM); void shapeReset(SwShape* shape); bool shapePrepare(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid); diff --git a/src/lib/sw_engine/tvgSwFill.cpp b/src/lib/sw_engine/tvgSwFill.cpp index 25348f00..01a8dc5b 100644 --- a/src/lib/sw_engine/tvgSwFill.cpp +++ b/src/lib/sw_engine/tvgSwFill.cpp @@ -106,15 +106,6 @@ bool _prepareLinear(SwFill* fill, const LinearGradient* linear, const Matrix* tr float x1, x2, y1, y2; if (linear->linear(&x1, &y1, &x2, &y2) != Result::Success) return false; - if (transform) { - auto t1 = x1; - x1 = t1 * transform->e11 + y1 * transform->e12 + transform->e13; - y1 = t1 * transform->e21 + y1 * transform->e22 + transform->e23; - auto t2 = x2; - x2 = t2 * transform->e11 + y2 * transform->e12 + transform->e13; - y2 = t2 * transform->e21 + y2 * transform->e22 + transform->e23; - } - fill->linear.dx = x2 - x1; fill->linear.dy = y2 - y1; fill->linear.len = fill->linear.dx * fill->linear.dx + fill->linear.dy * fill->linear.dy; @@ -123,7 +114,21 @@ bool _prepareLinear(SwFill* fill, const LinearGradient* linear, const Matrix* tr fill->linear.dx /= fill->linear.len; fill->linear.dy /= fill->linear.len; - fill->linear.offset = -fill->linear.dx * x1 -fill->linear.dy * y1; + fill->linear.offset = -fill->linear.dx * x1 - fill->linear.dy * y1; + + if (transform) { + Matrix invTransform; + if (!mathInverse(transform, &invTransform)) return false; + + fill->linear.offset += fill->linear.dx * invTransform.e13 + fill->linear.dy * invTransform.e23; + + auto dx = fill->linear.dx; + fill->linear.dx = dx * invTransform.e11 + fill->linear.dy * invTransform.e21; + fill->linear.dy = dx * invTransform.e12 + fill->linear.dy * invTransform.e22; + + fill->linear.len = fill->linear.dx * fill->linear.dx + fill->linear.dy * fill->linear.dy; + if (fill->linear.len < FLT_EPSILON) return true; + } return true; } diff --git a/src/lib/sw_engine/tvgSwMath.cpp b/src/lib/sw_engine/tvgSwMath.cpp index b6247aa4..b5e3c6b5 100644 --- a/src/lib/sw_engine/tvgSwMath.cpp +++ b/src/lib/sw_engine/tvgSwMath.cpp @@ -20,6 +20,7 @@ * SOFTWARE. */ #include +#include #include "tvgSwCommon.h" @@ -485,3 +486,27 @@ bool mathUpdateOutlineBBox(const SwOutline* outline, const SwBBox& clipRegion, S return true; } + + +bool mathInverse(const Matrix* m, Matrix* invM) +{ + auto det = m->e11 * (m->e22 * m->e33 - m->e32 * m->e23) - + m->e12 * (m->e21 * m->e33 - m->e23 * m->e31) + + m->e13 * (m->e21 * m->e32 - m->e22 * m->e31); + + if (fabsf(det) < FLT_EPSILON) return false; + + auto invDet = 1 / det; + + invM->e11 = (m->e22 * m->e33 - m->e32 * m->e23) * invDet; + invM->e12 = (m->e13 * m->e32 - m->e12 * m->e33) * invDet; + invM->e13 = (m->e12 * m->e23 - m->e13 * m->e22) * invDet; + invM->e21 = (m->e23 * m->e31 - m->e21 * m->e33) * invDet; + invM->e22 = (m->e11 * m->e33 - m->e13 * m->e31) * invDet; + invM->e23 = (m->e21 * m->e13 - m->e11 * m->e23) * invDet; + invM->e31 = (m->e21 * m->e32 - m->e31 * m->e22) * invDet; + invM->e32 = (m->e31 * m->e12 - m->e11 * m->e32) * invDet; + invM->e33 = (m->e11 * m->e22 - m->e21 * m->e12) * invDet; + + return true; +} diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index e5b36812..9dcbc799 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -49,31 +49,6 @@ static uint32_t _argbJoin(uint8_t r, uint8_t g, uint8_t b, uint8_t a) } -static bool _inverse(const Matrix* transform, Matrix* invM) -{ - //computes the inverse of a matrix m - auto det = transform->e11 * (transform->e22 * transform->e33 - transform->e32 * transform->e23) - - transform->e12 * (transform->e21 * transform->e33 - transform->e23 * transform->e31) + - transform->e13 * (transform->e21 * transform->e32 - transform->e22 * transform->e31); - - if (fabsf(det) < FLT_EPSILON) return false; - - auto invDet = 1 / det; - - invM->e11 = (transform->e22 * transform->e33 - transform->e32 * transform->e23) * invDet; - invM->e12 = (transform->e13 * transform->e32 - transform->e12 * transform->e33) * invDet; - invM->e13 = (transform->e12 * transform->e23 - transform->e13 * transform->e22) * invDet; - invM->e21 = (transform->e23 * transform->e31 - transform->e21 * transform->e33) * invDet; - invM->e22 = (transform->e11 * transform->e33 - transform->e13 * transform->e31) * invDet; - invM->e23 = (transform->e21 * transform->e13 - transform->e11 * transform->e23) * invDet; - invM->e31 = (transform->e21 * transform->e32 - transform->e31 * transform->e22) * invDet; - invM->e32 = (transform->e31 * transform->e12 - transform->e11 * transform->e32) * invDet; - invM->e33 = (transform->e11 * transform->e22 - transform->e21 * transform->e12) * invDet; - - return true; -} - - static bool _identify(const Matrix* transform) { if (transform) { @@ -1560,7 +1535,7 @@ bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, co float scaling = 1.0f; if (transform) { - if (!_inverse(transform, &invTransform)) return false; + if (!mathInverse(transform, &invTransform)) return false; scaling = sqrtf((transform->e11 * transform->e11) + (transform->e21 * transform->e21)); auto scalingY = sqrtf((transform->e22 * transform->e22) + (transform->e12 * transform->e12)); //TODO:If the x and y axis scaling is different, a separate algorithm for each axis should be applied.