summaryrefslogtreecommitdiff
path: root/source/fitz/draw-affine.c
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2016-05-23 17:44:09 +0100
committerRobin Watts <robin.watts@artifex.com>2016-05-23 17:48:53 +0100
commita0a9ce485579352ce9c3c4568c07e56b7029a8c8 (patch)
tree6e3e814ea2d79d5796eb74b5d31bc9ad13740f39 /source/fitz/draw-affine.c
parent36f41bc1ace9a986d9f021a777c6b9cfe6b62f9c (diff)
downloadmupdf-a0a9ce485579352ce9c3c4568c07e56b7029a8c8.tar.xz
Bug 696795: Proper fix.
When affine plotting with linear interpolation, we need to perform different calculations for the texture and for the edge of the shape. The edge of the shape needs to be calculated in exactly the same way as for non-linear interpolated shapes. The 'texture' position needs to be offset by 1/2 a texture unit in each direction so that the 'pure' color is given in the middle of the texture cells image, not in the top left corner. To achieve these aims, we actually offset the u/v positions by 1/2 (32768, given the fixed point we are using) and adjust for this in the boundary tests. I have a test file that shows this working, which I will attach to the bug, and add to the regression suite.
Diffstat (limited to 'source/fitz/draw-affine.c')
-rw-r--r--source/fitz/draw-affine.c53
1 files changed, 26 insertions, 27 deletions
diff --git a/source/fitz/draw-affine.c b/source/fitz/draw-affine.c
index 110c0085..068878cc 100644
--- a/source/fitz/draw-affine.c
+++ b/source/fitz/draw-affine.c
@@ -17,9 +17,9 @@ static inline byte *sample_nearest(byte *s, int w, int h, int n, int u, int v)
{
if (u < 0) u = 0;
if (v < 0) v = 0;
- if (u >= w) u = w - 1;
- if (v >= h) v = h - 1;
- return s + (v * w + u) * n;
+ if (u >= (w>>16)) u = (w>>16) - 1;
+ if (v >= (h>>16)) v = (h>>16) - 1;
+ return s + (v * (w>>16) + u) * n;
}
/* Blend premultiplied source image in constant alpha over destination */
@@ -32,10 +32,10 @@ fz_paint_affine_alpha_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, i
while (w--)
{
- int ui = u >> 16;
- int vi = v >> 16;
- if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
+ if (u + 32768 >= 0 && u < sw && v + 32768 >= 0 && v < sh)
{
+ int ui = u >> 16;
+ int vi = v >> 16;
int uf = u & 0xffff;
int vf = v & 0xffff;
byte *a = sample_nearest(sp, sw, sh, n, ui, vi);
@@ -69,10 +69,10 @@ fz_paint_affine_alpha_g2rgb_lerp(byte *dp, byte *sp, int sw, int sh, int u, int
{
while (w--)
{
- int ui = u >> 16;
- int vi = v >> 16;
- if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
+ if (u + 32768 >= 0 && u < sw && v + 32768 >= 0 && v < sh)
{
+ int ui = u >> 16;
+ int vi = v >> 16;
int uf = u & 0xffff;
int vf = v & 0xffff;
byte *a = sample_nearest(sp, sw, sh, 2, ui, vi);
@@ -283,10 +283,10 @@ fz_paint_affine_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa,
while (w--)
{
- int ui = u >> 16;
- int vi = v >> 16;
- if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
+ if (u + 32768 >= 0 && u < sw && v + 32768 >= 0 && v < sh)
{
+ int ui = u >> 16;
+ int vi = v >> 16;
int uf = u & 0xffff;
int vf = v & 0xffff;
byte *a = sample_nearest(sp, sw, sh, n, ui, vi);
@@ -317,10 +317,10 @@ fz_paint_affine_solid_g2rgb_lerp(byte *dp, byte *sp, int sw, int sh, int u, int
{
while (w--)
{
- int ui = u >> 16;
- int vi = v >> 16;
- if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
+ if (u + 32768 >= 0 && u < sw && v + 32768 >= 0 && v < sh)
{
+ int ui = u >> 16;
+ int vi = v >> 16;
int uf = u & 0xffff;
int vf = v & 0xffff;
byte *a = sample_nearest(sp, sw, sh, 2, ui, vi);
@@ -640,10 +640,10 @@ fz_paint_affine_color_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, i
while (w--)
{
- int ui = u >> 16;
- int vi = v >> 16;
- if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
+ if (u + 32768 >= 0 && u < sw && v + 32768 >= 0 && v < sh)
{
+ int ui = u >> 16;
+ int vi = v >> 16;
int uf = u & 0xffff;
int vf = v & 0xffff;
byte *a = sample_nearest(sp, sw, sh, 1, ui, vi);
@@ -1062,15 +1062,6 @@ fz_paint_image_imp(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz
u = (int)((local_ctm.a * x) + (local_ctm.c * y) + local_ctm.e + ((local_ctm.a + local_ctm.c) * .5f));
v = (int)((local_ctm.b * x) + (local_ctm.d * y) + local_ctm.f + ((local_ctm.b + local_ctm.d) * .5f));
- /* If we are not linearly interpolating, then we use 'nearest'. We round u and v downwards
- * each time, which isn't really "nearest". Bias them by a rounding constant now to adjust
- * for this. */
- if (!dolerp)
- {
- u += 32768;
- v += 32768;
- }
-
dp = dst->samples + (unsigned int)(((y - dst->y) * dst->w + (x - dst->x)) * dst->n);
n = dst->n;
sp = img->samples;
@@ -1115,6 +1106,14 @@ fz_paint_image_imp(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz
}
}
+ if (dolerp)
+ {
+ u -= 32768;
+ v -= 32768;
+ sw = (sw<<16) + 32768;
+ sh = (sh<<16) + 32768;
+ }
+
while (h--)
{
paintfn(dp, sp, sw, sh, u, v, fa, fb, w, n, alpha, color, hp);