sw_engine: including gradient transformation into gradient preparation

The gradient transformation has to be taken into account as the last
step of the gradient preparation.
This commit is contained in:
Mira Grudzinska 2021-10-23 01:50:18 +02:00 committed by Hermet Park
parent 7b778cd878
commit 8cfe4ef708
4 changed files with 52 additions and 18 deletions

View file

@ -300,6 +300,8 @@ 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);
bool mathMultiply(const Matrix* lhs, Matrix* rhs);
bool mathIdentity(const Matrix* m);
void shapeReset(SwShape* shape);
bool shapePrepare(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid);

View file

@ -116,9 +116,19 @@ bool _prepareLinear(SwFill* fill, const LinearGradient* linear, const Matrix* tr
fill->linear.dy /= fill->linear.len;
fill->linear.offset = -fill->linear.dx * x1 - fill->linear.dy * y1;
if (transform) {
auto gradTransform = linear->transform();
bool isTransformation = !mathIdentity(&gradTransform);
if (isTransformation) {
if (transform) mathMultiply(transform, &gradTransform);
} else if (transform) {
gradTransform = *transform;
isTransformation = true;
}
if (isTransformation) {
Matrix invTransform;
if (!mathInverse(transform, &invTransform)) return false;
if (!mathInverse(&gradTransform, &invTransform)) return false;
fill->linear.offset += fill->linear.dx * invTransform.e13 + fill->linear.dy * invTransform.e23;

View file

@ -510,3 +510,39 @@ bool mathInverse(const Matrix* m, Matrix* invM)
return true;
}
bool mathMultiply(const Matrix* lhs, Matrix* rhs)
{
Matrix m;
m.e11 = lhs->e11 * rhs->e11 + lhs->e12 * rhs->e21 + lhs->e13 * rhs->e31;
m.e12 = lhs->e11 * rhs->e12 + lhs->e12 * rhs->e22 + lhs->e13 * rhs->e32;
m.e13 = lhs->e11 * rhs->e13 + lhs->e12 * rhs->e23 + lhs->e13 * rhs->e33;
m.e21 = lhs->e21 * rhs->e11 + lhs->e22 * rhs->e21 + lhs->e23 * rhs->e31;
m.e22 = lhs->e21 * rhs->e12 + lhs->e22 * rhs->e22 + lhs->e23 * rhs->e32;
m.e23 = lhs->e21 * rhs->e13 + lhs->e22 * rhs->e23 + lhs->e23 * rhs->e33;
m.e31 = lhs->e31 * rhs->e11 + lhs->e32 * rhs->e21 + lhs->e33 * rhs->e31;
m.e32 = lhs->e31 * rhs->e12 + lhs->e32 * rhs->e22 + lhs->e33 * rhs->e32;
m.e33 = lhs->e31 * rhs->e13 + lhs->e32 * rhs->e23 + lhs->e33 * rhs->e33;
*rhs = m;
return true;
}
bool mathIdentity(const Matrix* m)
{
if (m) {
if (m->e11 != 1.0f || m->e12 != 0.0f || m->e13 != 0.0f ||
m->e21 != 0.0f || m->e22 != 1.0f || m->e23 != 0.0f ||
m->e31 != 0.0f || m->e32 != 0.0f || m->e33 != 1.0f) {
return false;
}
}
return true;
}

View file

@ -49,20 +49,6 @@ static uint32_t _argbJoin(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
}
static bool _identify(const Matrix* transform)
{
if (transform) {
if (transform->e11 != 1.0f || transform->e12 != 0.0f || transform->e13 != 0.0f ||
transform->e21 != 0.0f || transform->e22 != 1.0f || transform->e23 != 0.0f ||
transform->e31 != 0.0f || transform->e32 != 0.0f || transform->e33 != 1.0f) {
return false;
}
}
return true;
}
static bool _translucent(const SwSurface* surface, uint8_t a)
{
if (a < 255) return true;
@ -1548,7 +1534,7 @@ bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, co
if (image->rle) {
//Fast track
if (_identify(transform)) {
if (mathIdentity(transform)) {
//OPTIMIZE ME: Support non transformed image. Only shifted image can use these routines.
if (translucent) return _rasterTranslucentImageRle(surface, image->rle, image->data, image->w, image->h, opacity);
return _rasterImageRle(surface, image->rle, image->data, image->w, image->h);
@ -1565,7 +1551,7 @@ bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, co
}
else {
//Fast track
if (_identify(transform)) {
if (mathIdentity(transform)) {
//OPTIMIZE ME: Support non transformed image. Only shifted image can use these routines.
if (translucent) return _rasterTranslucentImage(surface, image->data, image->w, image->h, opacity, bbox);
return _rasterImage(surface, image->data, image->w, image->h, bbox);