mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-13 19:44:28 +00:00
sw_engine: proper linear gradient transformation
In the case of any shape transformation, the gradient fill was not correct.
This commit is contained in:
parent
664e95859c
commit
7b778cd878
4 changed files with 42 additions and 36 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Add table
Reference in a new issue