* for t:
*
* t = (-2·B ± ⎷(B² - 4·A·C)) / 2·A
+ *
+ * When computing t over a scanline, we notice that some expressions are
+ * constant so we can compute them just once.
*/
gradient_t *gradient = (gradient_t *)image;
if (affine)
{
+ double r1 = radial->c1.radius / 65536.;
+ double r1sq = r1 * r1;
+ double pdx = rx - radial->c1.x / 65536.;
+ double pdy = ry - radial->c1.y / 65536.;
+ double A = radial->A;
+ double invA = -65536. / (2. * A);
+ double A4 = -4. * A;
+ double B = -2. * (pdx*radial->cdx + pdy*radial->cdy + r1*radial->dr);
+ double cB = -2. * (cx*radial->cdx + cy*radial->cdy);
+ pixman_bool_t invert = A * radial->dr < 0;
+
while (buffer < end)
{
if (!mask || *mask++ & mask_bits)
{
- double pdx, pdy;
- double B, C;
- double det;
- double c1x = radial->c1.x / 65536.0;
- double c1y = radial->c1.y / 65536.0;
- double r1 = radial->c1.radius / 65536.0;
pixman_fixed_48_16_t t;
-
- pdx = rx - c1x;
- pdy = ry - c1y;
-
- B = -2 * (pdx * radial->cdx +
- pdy * radial->cdy +
- r1 * radial->dr);
- C = pdx * pdx + pdy * pdy - r1 * r1;
-
- det = (B * B) - (4 * radial->A * C);
- if (det < 0.0)
- det = 0.0;
-
- if (radial->A < 0)
- t = (pixman_fixed_48_16_t) ((-B - sqrt (det)) / (2.0 * radial->A) * 65536);
+ double det = B * B + A4 * (pdx * pdx + pdy * pdy - r1sq);
+ if (det <= 0.)
+ t = (pixman_fixed_48_16_t) (B * invA);
+ else if (invert)
+ t = (pixman_fixed_48_16_t) ((B + sqrt (det)) * invA);
else
- t = (pixman_fixed_48_16_t) ((-B + sqrt (det)) / (2.0 * radial->A) * 65536);
+ t = (pixman_fixed_48_16_t) ((B - sqrt (det)) * invA);
*buffer = _pixman_gradient_walker_pixel (&walker, t);
}
++buffer;
- rx += cx;
- ry += cy;
+ pdx += cx;
+ pdy += cy;
+ B += cB;
}
}
else
if (det < 0.0)
det = 0.0;
- if (radial->A < 0)
+ if (radial->A * radial->dr < 0)
t = (pixman_fixed_48_16_t) ((-B - sqrt (det)) / (2.0 * radial->A) * 65536);
else
t = (pixman_fixed_48_16_t) ((-B + sqrt (det)) / (2.0 * radial->A) * 65536);