summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2016-05-23 17:45:21 +0100
committerRobin Watts <robin.watts@artifex.com>2016-05-24 12:48:35 +0100
commitd0b78f4166a1503ce522944002b3aab035724cd9 (patch)
treeb8c680dc401db56a28be1110759219c7c175dd8d /source
parent841952db71d6541a2e98fd4d1d49dede284b2cf8 (diff)
downloadmupdf-d0b78f4166a1503ce522944002b3aab035724cd9.tar.xz
fz_pixmap revamp: add stride and make alpha optional
fz_pixmaps now have an explicit stride value. By default no change from before, but code all copes with extra gaps at the end of the line. The alpha data in fz_pixmaps is no longer compulsory. mudraw: use rgb not rgba (ppmraw), cmyk not cmyka (pkmraw). Update halftone code to not expect alpha plane. Update PNG writing to cope with alpha less input. Also hide repeated params within the png output context. ARM code needs updating.
Diffstat (limited to 'source')
-rw-r--r--source/fitz/colorspace.c1309
-rw-r--r--source/fitz/draw-affine.c663
-rw-r--r--source/fitz/draw-blend.c162
-rw-r--r--source/fitz/draw-device.c240
-rw-r--r--source/fitz/draw-edge.c13
-rw-r--r--source/fitz/draw-glyph.c10
-rw-r--r--source/fitz/draw-imp.h7
-rw-r--r--source/fitz/draw-mesh.c44
-rw-r--r--source/fitz/draw-paint.c871
-rw-r--r--source/fitz/draw-scale-simple.c63
-rw-r--r--source/fitz/draw-unpack.c42
-rw-r--r--source/fitz/font.c3
-rw-r--r--source/fitz/glyph.c2
-rw-r--r--source/fitz/halftone.c46
-rw-r--r--source/fitz/image.c61
-rw-r--r--source/fitz/load-bmp.c4
-rw-r--r--source/fitz/load-gif.c2
-rw-r--r--source/fitz/load-jpeg.c6
-rw-r--r--source/fitz/load-jpx.c8
-rw-r--r--source/fitz/load-png.c10
-rw-r--r--source/fitz/load-tiff.c4
-rw-r--r--source/fitz/output-cbz.c2
-rw-r--r--source/fitz/output-pcl.c12
-rw-r--r--source/fitz/output-ps.c7
-rw-r--r--source/fitz/output-pwg.c11
-rw-r--r--source/fitz/paint-glyph.h97
-rw-r--r--source/fitz/pixmap.c541
-rw-r--r--source/fitz/svg-device.c2
-rw-r--r--source/fitz/test-device.c65
-rw-r--r--source/fitz/transition.c99
-rw-r--r--source/fitz/util.c16
-rw-r--r--source/pdf/pdf-image.c43
-rw-r--r--source/pdf/pdf-resources.c10
-rw-r--r--source/tools/mudraw.c21
-rw-r--r--source/tools/murun.c9
-rw-r--r--source/tools/pdfextract.c2
36 files changed, 3261 insertions, 1246 deletions
diff --git a/source/fitz/colorspace.c b/source/fitz/colorspace.c
index 026953cb..b4d511e8 100644
--- a/source/fitz/colorspace.c
+++ b/source/fitz/colorspace.c
@@ -283,15 +283,74 @@ static void fast_gray_to_rgb(fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 3);
+ int s_line_inc = src->stride - w * (src->alpha + 1);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
+ {
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
{
- d[0] = s[0];
- d[1] = s[0];
- d[2] = s[0];
- d[3] = s[1];
- s += 2;
- d += 4;
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = s[0];
+ d[1] = s[0];
+ d[2] = s[0];
+ d[3] = s[1];
+ s += 2;
+ d += 4;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ else
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = s[0];
+ d[1] = s[0];
+ d[2] = s[0];
+ d[3] = 255;
+ s++;
+ d += 4;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ }
+ else
+ {
+ int si = 1 + src->alpha;
+
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = s[0];
+ d[1] = s[0];
+ d[2] = s[0];
+ s += si;
+ d += 3;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
}
@@ -299,16 +358,77 @@ static void fast_gray_to_cmyk(fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 4);
+ int s_line_inc = src->stride - w * (src->alpha + 1);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
+ {
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = 0;
+ d[1] = 0;
+ d[2] = 0;
+ d[3] = 255 - s[0];
+ d[4] = s[1];
+ s += 2;
+ d += 5;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ else
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = 0;
+ d[1] = 0;
+ d[2] = 0;
+ d[3] = 255 - s[0];
+ d[4] = 255;
+ s++;
+ d += 5;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ }
+ else
{
- d[0] = 0;
- d[1] = 0;
- d[2] = 0;
- d[3] = 255 - s[0];
- d[4] = s[1];
- s += 2;
- d += 5;
+ int si = 1 + src->alpha;
+
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = 0;
+ d[1] = 0;
+ d[2] = 0;
+ d[3] = 255 - s[0];
+ s += si;
+ d += 4;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
}
@@ -316,13 +436,68 @@ static void fast_rgb_to_gray(fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 1);
+ int s_line_inc = src->stride - w * (src->alpha + 3);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
+ {
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
+ d[1] = s[3];
+ s += 4;
+ d += 2;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ else
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
+ d[1] = 255;
+ s += 3;
+ d += 2;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ }
+ else
{
- d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
- d[1] = s[3];
- s += 4;
- d += 2;
+ int sn = src->n;
+
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
+ s += sn;
+ d++;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
}
@@ -330,13 +505,68 @@ static void fast_bgr_to_gray(fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 1);
+ int s_line_inc = src->stride - w * (src->alpha + 3);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
+ {
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
+ d[1] = s[3];
+ s += 4;
+ d += 2;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ else
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
+ d[1] = 255;
+ s += 3;
+ d += 2;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ }
+ else
{
- d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
- d[1] = s[3];
- s += 4;
- d += 2;
+ int si = 3 + src->alpha;
+
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
+ s += si;
+ d++;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
}
@@ -344,20 +574,89 @@ static void fast_rgb_to_cmyk(fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 4);
+ int s_line_inc = src->stride - w * (src->alpha + 3);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
+ {
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = 255 - s[0];
+ unsigned char m = 255 - s[1];
+ unsigned char y = 255 - s[2];
+ unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
+ d[0] = c - k;
+ d[1] = m - k;
+ d[2] = y - k;
+ d[3] = k;
+ d[4] = s[3];
+ s += 4;
+ d += 5;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ else
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = 255 - s[0];
+ unsigned char m = 255 - s[1];
+ unsigned char y = 255 - s[2];
+ unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
+ d[0] = c - k;
+ d[1] = m - k;
+ d[2] = y - k;
+ d[3] = k;
+ d[4] = 255;
+ s += 3;
+ d += 5;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ }
+ else
{
- unsigned char c = 255 - s[0];
- unsigned char m = 255 - s[1];
- unsigned char y = 255 - s[2];
- unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
- d[0] = c - k;
- d[1] = m - k;
- d[2] = y - k;
- d[3] = k;
- d[4] = s[3];
- s += 4;
- d += 5;
+ int si = 3 + src->alpha;
+
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = 255 - s[0];
+ unsigned char m = 255 - s[1];
+ unsigned char y = 255 - s[2];
+ unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
+ d[0] = c - k;
+ d[1] = m - k;
+ d[2] = y - k;
+ d[3] = k;
+ s += si;
+ d += 4;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
}
@@ -365,20 +664,89 @@ static void fast_bgr_to_cmyk(fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 4);
+ int s_line_inc = src->stride - w * (src->alpha + 3);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
{
- unsigned char c = 255 - s[2];
- unsigned char m = 255 - s[1];
- unsigned char y = 255 - s[0];
- unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
- d[0] = c - k;
- d[1] = m - k;
- d[2] = y - k;
- d[3] = k;
- d[4] = s[3];
- s += 4;
- d += 5;
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = 255 - s[2];
+ unsigned char m = 255 - s[1];
+ unsigned char y = 255 - s[0];
+ unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
+ d[0] = c - k;
+ d[1] = m - k;
+ d[2] = y - k;
+ d[3] = k;
+ d[4] = s[3];
+ s += 4;
+ d += 5;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ else
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = 255 - s[2];
+ unsigned char m = 255 - s[1];
+ unsigned char y = 255 - s[0];
+ unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
+ d[0] = c - k;
+ d[1] = m - k;
+ d[2] = y - k;
+ d[3] = k;
+ d[4] = 255;
+ s += 3;
+ d += 5;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ }
+ else
+ {
+ int si = 3 + src->alpha;
+
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = 255 - s[2];
+ unsigned char m = 255 - s[1];
+ unsigned char y = 255 - s[0];
+ unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
+ d[0] = c - k;
+ d[1] = m - k;
+ d[2] = y - k;
+ d[3] = k;
+ s += si;
+ d += 4;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
}
@@ -386,16 +754,76 @@ static void fast_cmyk_to_gray(fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 1);
+ int s_line_inc = src->stride - w * (src->alpha + 4);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
{
- unsigned char c = fz_mul255(s[0], 77);
- unsigned char m = fz_mul255(s[1], 150);
- unsigned char y = fz_mul255(s[2], 28);
- d[0] = 255 - (unsigned char)fz_mini(c + m + y + s[3], 255);
- d[1] = s[4];
- s += 5;
- d += 2;
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = fz_mul255(s[0], 77);
+ unsigned char m = fz_mul255(s[1], 150);
+ unsigned char y = fz_mul255(s[2], 28);
+ d[0] = 255 - (unsigned char)fz_mini(c + m + y + s[3], 255);
+ d[1] = s[4];
+ s += 5;
+ d += 2;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ else
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = fz_mul255(s[0], 77);
+ unsigned char m = fz_mul255(s[1], 150);
+ unsigned char y = fz_mul255(s[2], 28);
+ d[0] = 255 - (unsigned char)fz_mini(c + m + y + s[3], 255);
+ d[1] = 255;
+ s += 3;
+ d += 2;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ }
+ else
+ {
+ int si = 4 + src->alpha;
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = fz_mul255(s[0], 77);
+ unsigned char m = fz_mul255(s[1], 150);
+ unsigned char y = fz_mul255(s[2], 28);
+ d[0] = 255 - (unsigned char)fz_mini(c + m + y + s[3], 255);
+ s += si;
+ d++;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
}
@@ -592,15 +1020,150 @@ fast_cmyk_to_rgb_ARM(unsigned char *dst, unsigned char *src, int n)
}
#endif
+static inline void cached_cmyk_conv(unsigned char *restrict const pr, unsigned char *restrict const pg, unsigned char *restrict const pb,
+ unsigned int *restrict const C, unsigned int *restrict const M, unsigned int *restrict const Y, unsigned int *restrict const K,
+ unsigned int c, unsigned int m, unsigned int y, unsigned int k)
+{
+#ifdef SLOWCMYK
+ unsigned int r, g, b;
+ unsigned int cm, c1m, cm1, c1m1, c1m1y, c1m1y1, c1my, c1my1, cm1y, cm1y1, cmy, cmy1;
+ unsigned int x0, x1;
+
+ if (c == *C && m == *M && y == *Y && k == *K)
+ {
+ /* Nothing to do */
+ }
+ else if (k == 0 && c == 0 && m == 0 && y == 0)
+ {
+ *pr = *pg = *pb = 255;
+ *C = 0;
+ *M = 0;
+ *Y = 0;
+ *K = 0;
+ }
+ else if (k == 255)
+ {
+ *pr = *pg = *pb = 0;
+ *C = 0;
+ *M = 0;
+ *Y = 0;
+ *K = 255;
+ }
+ else
+ {
+ c += c>>7;
+ m += m>>7;
+ y += y>>7;
+ k += k>>7;
+ y >>= 1; /* Ditch 1 bit of Y to avoid overflow */
+ cm = c * m;
+ c1m = (m<<8) - cm;
+ cm1 = (c<<8) - cm;
+ c1m1 = ((256 - m)<<8) - cm1;
+ c1m1y = c1m1 * y;
+ c1m1y1 = (c1m1<<7) - c1m1y;
+ c1my = c1m * y;
+ c1my1 = (c1m<<7) - c1my;
+ cm1y = cm1 * y;
+ cm1y1 = (cm1<<7) - cm1y;
+ cmy = cm * y;
+ cmy1 = (cm<<7) - cmy;
+
+ /* this is a matrix multiplication, unrolled for performance */
+ x1 = c1m1y1 * k; /* 0 0 0 1 */
+ x0 = (c1m1y1<<8) - x1; /* 0 0 0 0 */
+ x1 = x1>>8; /* From 23 fractional bits to 15 */
+ r = g = b = x0;
+ r += 35 * x1; /* 0.1373 */
+ g += 31 * x1; /* 0.1216 */
+ b += 32 * x1; /* 0.1255 */
+
+ x1 = c1m1y * k; /* 0 0 1 1 */
+ x0 = (c1m1y<<8) - x1; /* 0 0 1 0 */
+ x1 >>= 8; /* From 23 fractional bits to 15 */
+ r += 28 * x1; /* 0.1098 */
+ g += 26 * x1; /* 0.1020 */
+ r += x0;
+ x0 >>= 8; /* From 23 fractional bits to 15 */
+ g += 243 * x0; /* 0.9490 */
+
+ x1 = c1my1 * k; /* 0 1 0 1 */
+ x0 = (c1my1<<8) - x1; /* 0 1 0 0 */
+ x1 >>= 8; /* From 23 fractional bits to 15 */
+ x0 >>= 8; /* From 23 fractional bits to 15 */
+ r += 36 * x1; /* 0.1412 */
+ r += 237 * x0; /* 0.9255 */
+ b += 141 * x0; /* 0.5490 */
+
+ x1 = c1my * k; /* 0 1 1 1 */
+ x0 = (c1my<<8) - x1; /* 0 1 1 0 */
+ x1 >>= 8; /* From 23 fractional bits to 15 */
+ x0 >>= 8; /* From 23 fractional bits to 15 */
+ r += 34 * x1; /* 0.1333 */
+ r += 238 * x0; /* 0.9294 */
+ g += 28 * x0; /* 0.1098 */
+ b += 36 * x0; /* 0.1412 */
+
+ x1 = cm1y1 * k; /* 1 0 0 1 */
+ x0 = (cm1y1<<8) - x1; /* 1 0 0 0 */
+ x1 >>= 8; /* From 23 fractional bits to 15 */
+ x0 >>= 8; /* From 23 fractional bits to 15 */
+ g += 15 * x1; /* 0.0588 */
+ b += 36 * x1; /* 0.1412 */
+ g += 174 * x0; /* 0.6784 */
+ b += 240 * x0; /* 0.9373 */
+
+ x1 = cm1y * k; /* 1 0 1 1 */
+ x0 = (cm1y<<8) - x1; /* 1 0 1 0 */
+ x1 >>= 8; /* From 23 fractional bits to 15 */
+ x0 >>= 8; /* From 23 fractional bits to 15 */
+ g += 19 * x1; /* 0.0745 */
+ g += 167 * x0; /* 0.6510 */
+ b += 80 * x0; /* 0.3137 */
+
+ x1 = cmy1 * k; /* 1 1 0 1 */
+ x0 = (cmy1<<8) - x1; /* 1 1 0 0 */
+ x1 >>= 8; /* From 23 fractional bits to 15 */
+ x0 >>= 8; /* From 23 fractional bits to 15 */
+ b += 2 * x1; /* 0.0078 */
+ r += 46 * x0; /* 0.1804 */
+ g += 49 * x0; /* 0.1922 */
+ b += 147 * x0; /* 0.5725 */
+
+ x0 = cmy * (256-k); /* 1 1 1 0 */
+ x0 >>= 8; /* From 23 fractional bits to 15 */
+ r += 54 * x0; /* 0.2118 */
+ g += 54 * x0; /* 0.2119 */
+ b += 57 * x0; /* 0.2235 */
+
+ r -= (r>>8);
+ g -= (g>>8);
+ b -= (b>>8);
+ *pr = r>>23;
+ *pg = g>>23;
+ *pb = b>>23;
+ *C = c;
+ *M = m;
+ *Y = y;
+ *K = k;
+ }
+#else
+ *pr = 255 - (unsigned char)fz_mini(c + k, 255);
+ *pg = 255 - (unsigned char)fz_mini(m + k, 255);
+ *pb = 255 - (unsigned char)fz_mini(y + k, 255);
+#endif
+}
+
static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
-#ifdef ARCH_ARM
- fast_cmyk_to_rgb_ARM(d, s, n);
-#else
- unsigned int C,M,Y,K,r,g,b;
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 3);
+ int s_line_inc = src->stride - w * (src->alpha + 4);
+ unsigned int C,M,Y,K;
+ unsigned char r,g,b;
C = 0;
M = 0;
@@ -610,174 +1173,169 @@ static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
g = 255;
b = 255;
- while (n--)
+ if (d_line_inc == 0 && s_line_inc == 0)
{
-#ifdef SLOWCMYK
- unsigned int c = s[0];
- unsigned int m = s[1];
- unsigned int y = s[2];
- unsigned int k = s[3];
- unsigned int cm, c1m, cm1, c1m1, c1m1y, c1m1y1, c1my, c1my1, cm1y, cm1y1, cmy, cmy1;
- unsigned int x0, x1;
-
- if (c == C && m == M && y == Y && k == K)
- {
- /* Nothing to do */
- }
- else if (k == 0 && c == 0 && m == 0 && y == 0)
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
{
- r = g = b = 255;
- C = 0;
- M = 0;
- Y = 0;
- K = 0;
+#ifdef ARCH_ARM
+ if (h == 1)
+ {
+ fast_cmyk_to_rgb_ARM(d, s, w);
+ return;
+ }
+#endif
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ cached_cmyk_conv(&r, &g, &b, &C, &M, &Y, &K, s[0], s[1], s[2], s[3]);
+ d[0] = r;
+ d[1] = g;
+ d[2] = b;
+ d[3] = s[4];
+ s += 5;
+ d += 4;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
- else if (k == 255)
+ else
{
- r = g = b = 0;
- C = 0;
- M = 0;
- Y = 0;
- K = 255;
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ cached_cmyk_conv(&r, &g, &b, &C, &M, &Y, &K, s[0], s[1], s[2], s[3]);
+ d[0] = r;
+ d[1] = g;
+ d[2] = b;
+ d[3] = 255;
+ s += 4;
+ d += 4;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
- else
+ }
+ else
+ {
+ /* We shouldn't lose alpha */
+ assert(src->alpha == 0);
+
+ while (h--)
{
- c += c>>7;
- m += m>>7;
- y += y>>7;
- k += k>>7;
- y >>= 1; /* Ditch 1 bit of Y to avoid overflow */
- cm = c * m;
- c1m = (m<<8) - cm;
- cm1 = (c<<8) - cm;
- c1m1 = ((256 - m)<<8) - cm1;
- c1m1y = c1m1 * y;
- c1m1y1 = (c1m1<<7) - c1m1y;
- c1my = c1m * y;
- c1my1 = (c1m<<7) - c1my;
- cm1y = cm1 * y;
- cm1y1 = (cm1<<7) - cm1y;
- cmy = cm * y;
- cmy1 = (cm<<7) - cmy;
-
- /* this is a matrix multiplication, unrolled for performance */
- x1 = c1m1y1 * k; /* 0 0 0 1 */
- x0 = (c1m1y1<<8) - x1; /* 0 0 0 0 */
- x1 = x1>>8; /* From 23 fractional bits to 15 */
- r = g = b = x0;
- r += 35 * x1; /* 0.1373 */
- g += 31 * x1; /* 0.1216 */
- b += 32 * x1; /* 0.1255 */
-
- x1 = c1m1y * k; /* 0 0 1 1 */
- x0 = (c1m1y<<8) - x1; /* 0 0 1 0 */
- x1 >>= 8; /* From 23 fractional bits to 15 */
- r += 28 * x1; /* 0.1098 */
- g += 26 * x1; /* 0.1020 */
- r += x0;
- x0 >>= 8; /* From 23 fractional bits to 15 */
- g += 243 * x0; /* 0.9490 */
-
- x1 = c1my1 * k; /* 0 1 0 1 */
- x0 = (c1my1<<8) - x1; /* 0 1 0 0 */
- x1 >>= 8; /* From 23 fractional bits to 15 */
- x0 >>= 8; /* From 23 fractional bits to 15 */
- r += 36 * x1; /* 0.1412 */
- r += 237 * x0; /* 0.9255 */
- b += 141 * x0; /* 0.5490 */
-
- x1 = c1my * k; /* 0 1 1 1 */
- x0 = (c1my<<8) - x1; /* 0 1 1 0 */
- x1 >>= 8; /* From 23 fractional bits to 15 */
- x0 >>= 8; /* From 23 fractional bits to 15 */
- r += 34 * x1; /* 0.1333 */
- r += 238 * x0; /* 0.9294 */
- g += 28 * x0; /* 0.1098 */
- b += 36 * x0; /* 0.1412 */
-
- x1 = cm1y1 * k; /* 1 0 0 1 */
- x0 = (cm1y1<<8) - x1; /* 1 0 0 0 */
- x1 >>= 8; /* From 23 fractional bits to 15 */
- x0 >>= 8; /* From 23 fractional bits to 15 */
- g += 15 * x1; /* 0.0588 */
- b += 36 * x1; /* 0.1412 */
- g += 174 * x0; /* 0.6784 */
- b += 240 * x0; /* 0.9373 */
-
- x1 = cm1y * k; /* 1 0 1 1 */
- x0 = (cm1y<<8) - x1; /* 1 0 1 0 */
- x1 >>= 8; /* From 23 fractional bits to 15 */
- x0 >>= 8; /* From 23 fractional bits to 15 */
- g += 19 * x1; /* 0.0745 */
- g += 167 * x0; /* 0.6510 */
- b += 80 * x0; /* 0.3137 */
-
- x1 = cmy1 * k; /* 1 1 0 1 */
- x0 = (cmy1<<8) - x1; /* 1 1 0 0 */
- x1 >>= 8; /* From 23 fractional bits to 15 */
- x0 >>= 8; /* From 23 fractional bits to 15 */
- b += 2 * x1; /* 0.0078 */
- r += 46 * x0; /* 0.1804 */
- g += 49 * x0; /* 0.1922 */
- b += 147 * x0; /* 0.5725 */
-
- x0 = cmy * (256-k); /* 1 1 1 0 */
- x0 >>= 8; /* From 23 fractional bits to 15 */
- r += 54 * x0; /* 0.2118 */
- g += 54 * x0; /* 0.2119 */
- b += 57 * x0; /* 0.2235 */
-
- r -= (r>>8);
- g -= (g>>8);
- b -= (b>>8);
- r = r>>23;
- g = g>>23;
- b = b>>23;
- C = c;
- M = m;
- Y = y;
- K = k;
+ int ww = w;
+ while (ww--)
+ {
+ cached_cmyk_conv(&r, &g, &b, &C, &M, &Y, &K, s[0], s[1], s[2], s[3]);
+ d[0] = r;
+ d[1] = g;
+ d[2] = b;
+ s += 4;
+ d += 3;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
}
- d[0] = r;
- d[1] = g;
- d[2] = b;
-#else
- d[0] = 255 - (unsigned char)fz_mini(s[0] + s[3], 255);
- d[1] = 255 - (unsigned char)fz_mini(s[1] + s[3], 255);
- d[2] = 255 - (unsigned char)fz_mini(s[2] + s[3], 255);
-#endif
- d[3] = s[4];
- s += 5;
- d += 4;
}
-#endif
}
static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 3);
+ int s_line_inc = src->stride - w * (src->alpha + 4);
+ unsigned int C,M,Y,K;
+ unsigned char r,g,b;
+
+ C = 0;
+ M = 0;
+ Y = 0;
+ K = 0;
+ r = 255;
+ g = 255;
+ b = 255;
+
+ if (d_line_inc == 0 && s_line_inc == 0)
{
-#ifdef SLOWCMYK
- float cmyk[4], rgb[3];
- cmyk[0] = s[0] / 255.0f;
- cmyk[1] = s[1] / 255.0f;
- cmyk[2] = s[2] / 255.0f;
- cmyk[3] = s[3] / 255.0f;
- cmyk_to_rgb(ctx, NULL, cmyk, rgb);
- d[0] = rgb[2] * 255;
- d[1] = rgb[1] * 255;
- d[2] = rgb[0] * 255;
-#else
- d[0] = 255 - (unsigned char)fz_mini(s[2] + s[3], 255);
- d[1] = 255 - (unsigned char)fz_mini(s[1] + s[3], 255);
- d[2] = 255 - (unsigned char)fz_mini(s[0] + s[3], 255);
-#endif
- d[3] = s[4];
- s += 5;
- d += 4;
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ cached_cmyk_conv(&r, &g, &b, &C, &M, &Y, &K, s[0], s[1], s[2], s[3]);
+ d[0] = b;
+ d[1] = g;
+ d[2] = r;
+ d[3] = s[4];
+ s += 5;
+ d += 4;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ else
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ cached_cmyk_conv(&r, &g, &b, &C, &M, &Y, &K, s[0], s[1], s[2], s[3]);
+ d[0] = b;
+ d[1] = g;
+ d[2] = r;
+ d[3] = 255;
+ s += 4;
+ d += 4;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ }
+ else
+ {
+ /* We shouldn't lose alpha */
+ assert(src->alpha == 0);
+
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ cached_cmyk_conv(&r, &g, &b, &C, &M, &Y, &K, s[0], s[1], s[2], s[3]);
+ d[0] = b;
+ d[1] = g;
+ d[2] = r;
+ s += 4;
+ d += 3;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
}
@@ -785,15 +1343,69 @@ static void fast_rgb_to_bgr(fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 3);
+ int s_line_inc = src->stride - w * (src->alpha + 3);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
+ {
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = s[2];
+ d[1] = s[1];
+ d[2] = s[0];
+ d[3] = s[3];
+ s += 4;
+ d += 4;
+ }
+ }
+ }
+ else
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = s[2];
+ d[1] = s[1];
+ d[2] = s[0];
+ d[3] = 255;
+ s += 3;
+ d += 4;
+ }
+ }
+ }
+ }
+ else
{
- d[0] = s[2];
- d[1] = s[1];
- d[2] = s[0];
- d[3] = s[3];
- s += 4;
- d += 4;
+ /* We shouldn't lose alpha */
+ assert(src->alpha == 0);
+
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = s[2];
+ d[1] = s[1];
+ d[2] = s[0];
+ s += 3;
+ d += 3;
+ }
+ }
}
}
@@ -804,7 +1416,12 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
float dstv[FZ_MAX_COLORS];
int srcn, dstn;
int k, i;
- unsigned int xy;
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * dst->n;
+ int s_line_inc = src->stride - w * src->n;
+ int da = dst->alpha;
+ int sa = src->alpha;
fz_colorspace *ss = src->colorspace;
fz_colorspace *ds = dst->colorspace;
@@ -812,14 +1429,18 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- assert(src->w == dst->w && src->h == dst->h);
- assert(src->n == ss->n + 1);
- assert(dst->n == ds->n + 1);
-
srcn = ss->n;
dstn = ds->n;
- xy = (unsigned int)(src->w * src->h);
+ assert(src->w == dst->w && src->h == dst->h);
+ assert(src->n == srcn + sa);
+ assert(dst->n == dstn + da);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
+ {
+ w *= h;
+ h = 1;
+ }
/* Special case for Lab colorspace (scaling of components to float) */
if (!strcmp(ss->name, "Lab") && srcn == 3)
@@ -827,38 +1448,52 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
fz_color_converter cc;
fz_lookup_color_converter(ctx, &cc, ds, ss);
- for (; xy > 0; xy--)
+ while (h--)
{
- srcv[0] = *s++ / 255.0f * 100;
- srcv[1] = *s++ - 128;
- srcv[2] = *s++ - 128;
-
- cc.convert(ctx, &cc, dstv, srcv);
+ int ww = w;
+ while (ww--)
+ {
+ srcv[0] = *s++ / 255.0f * 100;
+ srcv[1] = *s++ - 128;
+ srcv[2] = *s++ - 128;
- for (k = 0; k < dstn; k++)
- *d++ = dstv[k] * 255;
+ cc.convert(ctx, &cc, dstv, srcv);
- *d++ = *s++;
+ for (k = 0; k < dstn; k++)
+ *d++ = dstv[k] * 255;
+ if (da)
+ *d++ = (sa ? *s : 255);
+ s += sa;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
}
}
/* Brute-force for small images */
- else if (xy < 256)
+ else if (w*h < 256)
{
fz_color_converter cc;
fz_lookup_color_converter(ctx, &cc, ds, ss);
- for (; xy > 0; xy--)
+ while (h--)
{
- for (k = 0; k < srcn; k++)
- srcv[k] = *s++ / 255.0f;
-
- cc.convert(ctx, &cc, dstv, srcv);
+ int ww = w;
+ while (ww--)
+ {
+ for (k = 0; k < srcn; k++)
+ srcv[k] = *s++ / 255.0f;
- for (k = 0; k < dstn; k++)
- *d++ = dstv[k] * 255;
+ cc.convert(ctx, &cc, dstv, srcv);
- *d++ = *s++;
+ for (k = 0; k < dstn; k++)
+ *d++ = dstv[k] * 255;
+ if (da)
+ *d++ = (sa ? *s : 255);
+ s += sa;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
}
}
@@ -877,12 +1512,20 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
lookup[i * dstn + k] = dstv[k] * 255;
}
- for (; xy > 0; xy--)
+ while (h--)
{
- i = *s++;
- for (k = 0; k < dstn; k++)
- *d++ = lookup[i * dstn + k];
- *d++ = *s++;
+ int ww = w;
+ while (ww--)
+ {
+ i = *s++;
+ for (k = 0; k < dstn; k++)
+ *d++ = lookup[i * dstn + k];
+ if (da)
+ *d++ = (sa ? *s : 255);
+ s += sa;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
}
}
@@ -893,57 +1536,109 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
unsigned char *color;
unsigned char dummy = s[0] ^ 255;
unsigned char *sold = &dummy;
+ unsigned char *dold;
fz_color_converter cc;
fz_lookup_color_converter(ctx, &cc, ds, ss);
lookup = fz_new_hash_table(ctx, 509, srcn, -1);
- for (; xy > 0; xy--)
+ while (h--)
{
- if (*s == *sold && memcmp(sold,s,srcn) == 0)
- {
- sold = s;
- memcpy(d, d-dstn-1, dstn);
- d += dstn;
- s += srcn;
- *d++ = *s++;
- }
- else
+ int ww = w;
+ while (ww--)
{
- sold = s;
- color = fz_hash_find(ctx, lookup, s);
- if (color)
+ if (*s == *sold && memcmp(sold,s,srcn) == 0)
{
- memcpy(d, color, dstn);
- s += srcn;
+ sold = s;
+ memcpy(d, dold, dstn);
d += dstn;
- *d++ = *s++;
+ s += srcn;
+ if (da)
+ *d++ = (sa ? *s : 255);
+ s += sa;
}
else
{
- for (k = 0; k < srcn; k++)
- srcv[k] = *s++ / 255.0f;
- cc.convert(ctx, &cc, dstv, srcv);
- for (k = 0; k < dstn; k++)
- *d++ = dstv[k] * 255;
-
- fz_hash_insert(ctx, lookup, s - srcn, d - dstn);
-
- *d++ = *s++;
+ sold = s;
+ dold = d;
+ color = fz_hash_find(ctx, lookup, s);
+ if (color)
+ {
+ memcpy(d, color, dstn);
+ s += srcn;
+ d += dstn;
+ if (dst->alpha)
+ *d++ = (sa ? *s : 255);
+ s += sa;
+ }
+ else
+ {
+ for (k = 0; k < srcn; k++)
+ srcv[k] = *s++ / 255.0f;
+ cc.convert(ctx, &cc, dstv, srcv);
+ for (k = 0; k < dstn; k++)
+ *d++ = dstv[k] * 255;
+
+ fz_hash_insert(ctx, lookup, s - srcn, d - dstn);
+
+ if (dst->alpha)
+ *d++ = (sa ? *s : 255);
+ s += sa;
+ }
}
}
+ d += d_line_inc;
+ s += s_line_inc;
}
fz_drop_hash(ctx, lookup);
}
}
+static void fast_copy_alpha(fz_pixmap *dst, fz_pixmap *src)
+{
+ unsigned char *s = src->samples;
+ unsigned char *d = dst->samples;
+ int w = src->w;
+ int h = src->h;
+ int n = src->n;
+ int d_line_inc = dst->stride - w * dst->n;
+ int s_line_inc = src->stride - w * src->n;
+
+ assert(dst->alpha && src->alpha && dst->n == 1);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
+ {
+ w *= h;
+ h = 1;
+ }
+
+ s += n-1;
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ *d++ = *s;
+ s += n;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+}
+
void
fz_convert_pixmap(fz_context *ctx, fz_pixmap *dp, fz_pixmap *sp)
{
fz_colorspace *ss = sp->colorspace;
fz_colorspace *ds = dp->colorspace;
+ if (ds == NULL && sp->alpha)
+ {
+ fast_copy_alpha(dp, sp);
+ return;
+ }
+
assert(ss && ds);
dp->interpolate = sp->interpolate;
@@ -993,6 +1688,11 @@ std_conv_color(fz_context *ctx, fz_color_converter *cc, float *dstv, const float
fz_colorspace *srcs = cc->ss;
fz_colorspace *dsts = cc->ds;
+ if (srcs == NULL)
+ srcs = fz_device_rgb(ctx);
+ if (dsts == NULL)
+ dsts = fz_device_rgb(ctx);
+
if (srcs != dsts)
{
assert(srcs->to_rgb && dsts->from_rgb);
@@ -1238,6 +1938,7 @@ fz_expand_indexed_pixmap(fz_context *ctx, fz_pixmap *src)
int y, x, k, n, high;
unsigned char *lookup;
fz_irect bbox;
+ int s_line_inc, d_line_inc;
assert(src->colorspace->to_rgb == indexed_to_rgb);
assert(src->n == 2);
@@ -1247,20 +1948,42 @@ fz_expand_indexed_pixmap(fz_context *ctx, fz_pixmap *src)
lookup = idx->lookup;
n = idx->base->n;
- dst = fz_new_pixmap_with_bbox(ctx, idx->base, fz_pixmap_bbox(ctx, src, &bbox));
+ dst = fz_new_pixmap_with_bbox(ctx, idx->base, fz_pixmap_bbox(ctx, src, &bbox), src->alpha);
s = src->samples;
d = dst->samples;
+ s_line_inc = src->stride - src->w * src->n;
+ d_line_inc = dst->stride - dst->w * dst->n;
- for (y = 0; y < src->h; y++)
+ if (src->alpha)
+ {
+ for (y = 0; y < src->h; y++)
+ {
+ for (x = 0; x < src->w; x++)
+ {
+ int v = *s++;
+ int a = *s++;
+ v = fz_mini(v, high);
+ for (k = 0; k < n; k++)
+ *d++ = fz_mul255(lookup[v * n + k], a);
+ *d++ = a;
+ }
+ s += s_line_inc;
+ d += d_line_inc;
+ }
+ }
+ else
{
- for (x = 0; x < src->w; x++)
+ for (y = 0; y < src->h; y++)
{
- int v = *s++;
- int a = *s++;
- v = fz_mini(v, high);
- for (k = 0; k < n; k++)
- *d++ = fz_mul255(lookup[v * n + k], a);
- *d++ = a;
+ for (x = 0; x < src->w; x++)
+ {
+ int v = *s++;
+ v = fz_mini(v, high);
+ for (k = 0; k < n; k++)
+ *d++ = lookup[v * n + k];
+ }
+ s += s_line_inc;
+ d += d_line_inc;
}
}
diff --git a/source/fitz/draw-affine.c b/source/fitz/draw-affine.c
index 068878cc..e4db9ec8 100644
--- a/source/fitz/draw-affine.c
+++ b/source/fitz/draw-affine.c
@@ -13,22 +13,21 @@ static inline int bilerp(int a, int b, int c, int d, int u, int v)
return lerp(lerp(a, b, u), lerp(c, d, u), v);
}
-static inline byte *sample_nearest(byte *s, int w, int h, int n, int u, int v)
+static inline byte *sample_nearest(byte *s, int w, int h, int str, int n, int u, int v)
{
if (u < 0) u = 0;
if (v < 0) v = 0;
if (u >= (w>>16)) u = (w>>16) - 1;
if (v >= (h>>16)) v = (h>>16) - 1;
- return s + (v * (w>>16) + u) * n;
+ return s + v * str + u * n;
}
/* Blend premultiplied source image in constant alpha over destination */
static inline void
-fz_paint_affine_alpha_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *hp)
+fz_paint_affine_alpha_N_lerp(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int n1, int alpha, byte *hp)
{
int k;
- int n1 = n-1;
while (w--)
{
@@ -38,11 +37,11 @@ fz_paint_affine_alpha_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, i
int vi = v >> 16;
int uf = u & 0xffff;
int vf = v & 0xffff;
- byte *a = sample_nearest(sp, sw, sh, n, ui, vi);
- byte *b = sample_nearest(sp, sw, sh, n, ui+1, vi);
- byte *c = sample_nearest(sp, sw, sh, n, ui, vi+1);
- byte *d = sample_nearest(sp, sw, sh, n, ui+1, vi+1);
- int xa = bilerp(a[n1], b[n1], c[n1], d[n1], uf, vf);
+ byte *a = sample_nearest(sp, sw, sh, ss, n1+sa, ui, vi);
+ byte *b = sample_nearest(sp, sw, sh, ss, n1+sa, ui+1, vi);
+ byte *c = sample_nearest(sp, sw, sh, ss, n1+sa, ui, vi+1);
+ byte *d = sample_nearest(sp, sw, sh, ss, n1+sa, ui+1, vi+1);
+ int xa = sa ? bilerp(a[n1], b[n1], c[n1], d[n1], uf, vf) : 255;
int t;
xa = fz_mul255(xa, alpha);
t = 255 - xa;
@@ -51,11 +50,12 @@ fz_paint_affine_alpha_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, i
int x = bilerp(a[k], b[k], c[k], d[k], uf, vf);
dp[k] = fz_mul255(x, alpha) + fz_mul255(dp[k], t);
}
- dp[n1] = xa + fz_mul255(dp[n1], t);
+ if (da)
+ dp[n1] = xa + fz_mul255(dp[n1], t);
if (hp)
hp[0] = xa + fz_mul255(hp[0], t);
}
- dp += n;
+ dp += n1+da;
if (hp)
hp++;
u += fa;
@@ -65,7 +65,7 @@ fz_paint_affine_alpha_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, i
/* Special case code for gray -> rgb */
static inline void
-fz_paint_affine_alpha_g2rgb_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int alpha, byte *hp)
+fz_paint_affine_alpha_g2rgb_lerp(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int alpha, byte *hp)
{
while (w--)
{
@@ -75,11 +75,11 @@ fz_paint_affine_alpha_g2rgb_lerp(byte *dp, byte *sp, int sw, int sh, int u, int
int vi = v >> 16;
int uf = u & 0xffff;
int vf = v & 0xffff;
- byte *a = sample_nearest(sp, sw, sh, 2, ui, vi);
- byte *b = sample_nearest(sp, sw, sh, 2, ui+1, vi);
- byte *c = sample_nearest(sp, sw, sh, 2, ui, vi+1);
- byte *d = sample_nearest(sp, sw, sh, 2, ui+1, vi+1);
- int y = bilerp(a[1], b[1], c[1], d[1], uf, vf);
+ byte *a = sample_nearest(sp, sw, sh, ss, 1+sa, ui, vi);
+ byte *b = sample_nearest(sp, sw, sh, ss, 1+sa, ui+1, vi);
+ byte *c = sample_nearest(sp, sw, sh, ss, 1+sa, ui, vi+1);
+ byte *d = sample_nearest(sp, sw, sh, ss, 1+sa, ui+1, vi+1);
+ int y = (sa ? bilerp(a[1], b[1], c[1], d[1], uf, vf) : 255);
int x = bilerp(a[0], b[0], c[0], d[0], uf, vf);
int t;
x = fz_mul255(x, alpha);
@@ -88,7 +88,8 @@ fz_paint_affine_alpha_g2rgb_lerp(byte *dp, byte *sp, int sw, int sh, int u, int
dp[0] = x + fz_mul255(dp[0], t);
dp[1] = x + fz_mul255(dp[1], t);
dp[2] = x + fz_mul255(dp[2], t);
- dp[3] = y + fz_mul255(dp[3], t);
+ if (da)
+ dp[3] = y + fz_mul255(dp[3], t);
if (hp)
hp[0] = y + fz_mul255(hp[0], t);
}
@@ -101,33 +102,32 @@ fz_paint_affine_alpha_g2rgb_lerp(byte *dp, byte *sp, int sw, int sh, int u, int
}
static inline void
-fz_paint_affine_alpha_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *hp)
+fz_paint_affine_alpha_N_near(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int n1, int alpha, byte *hp)
{
int k;
- int n1 = n-1;
if (fa == 0)
{
int ui = u >> 16;
if (ui < 0 || ui >= sw)
return;
- sp += ui * n;
- sw *= n;
+ sp += ui * (n1+sa);
while (w--)
{
int vi = v >> 16;
if (vi >= 0 && vi < sh)
{
- byte *sample = sp + (vi * sw);
- int a = fz_mul255(sample[n-1], alpha);
+ byte *sample = sp + (vi * ss);
+ int a = (sa ? fz_mul255(sample[n1], alpha) : 255);
int t = 255 - a;
for (k = 0; k < n1; k++)
dp[k] = fz_mul255(sample[k], alpha) + fz_mul255(dp[k], t);
- dp[n1] = a + fz_mul255(dp[n1], t);
+ if (da)
+ dp[n1] = a + fz_mul255(dp[n1], t);
if (hp)
hp[0] = a + fz_mul255(hp[0], t);
}
- dp += n;
+ dp += n1+da;
if (hp)
hp++;
v += fb;
@@ -138,22 +138,23 @@ fz_paint_affine_alpha_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, i
int vi = v >> 16;
if (vi < 0 || vi >= sh)
return;
- sp += vi * sw * n;
+ sp += vi * ss;
while (w--)
{
int ui = u >> 16;
if (ui >= 0 && ui < sw)
{
- byte *sample = sp + (ui * n);
- int a = fz_mul255(sample[n-1], alpha);
+ byte *sample = sp + (ui * (n1+sa));
+ int a = (sa ? fz_mul255(sample[n1], alpha) : 255);
int t = 255 - a;
for (k = 0; k < n1; k++)
dp[k] = fz_mul255(sample[k], alpha) + fz_mul255(dp[k], t);
- dp[n1] = a + fz_mul255(dp[n1], t);
+ if (da)
+ dp[n1] = a + fz_mul255(dp[n1], t);
if (hp)
hp[0] = a + fz_mul255(hp[0], t);
}
- dp += n;
+ dp += n1+da;
if (hp)
hp++;
u += fa;
@@ -167,16 +168,17 @@ fz_paint_affine_alpha_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, i
int vi = v >> 16;
if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
{
- byte *sample = sp + ((vi * sw + ui) * n);
- int a = fz_mul255(sample[n-1], alpha);
+ byte *sample = sp + (vi * ss) + (ui * (n1+sa));
+ int a = (sa ? fz_mul255(sample[n1], alpha) : 255);
int t = 255 - a;
for (k = 0; k < n1; k++)
dp[k] = fz_mul255(sample[k], alpha) + fz_mul255(dp[k], t);
- dp[n1] = a + fz_mul255(dp[n1], t);
+ if (da)
+ dp[n1] = a + fz_mul255(dp[n1], t);
if (hp)
hp[0] = a + fz_mul255(hp[0], t);
}
- dp += n;
+ dp += n1+da;
if (hp)
hp++;
u += fa;
@@ -186,32 +188,32 @@ fz_paint_affine_alpha_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, i
}
static inline void
-fz_paint_affine_alpha_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int alpha, byte *hp)
+fz_paint_affine_alpha_g2rgb_near(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int alpha, byte *hp)
{
if (fa == 0)
{
int ui = u >> 16;
if (ui < 0 || ui >= sw)
return;
- sp += ui * 2;
- sw *= 2;
+ sp += ui * (1+sa);
while (w--)
{
int vi = v >> 16;
if (vi >= 0 && vi < sh)
{
- byte *sample = sp + (vi * sw);
+ byte *sample = sp + (vi * ss);
int x = fz_mul255(sample[0], alpha);
- int a = fz_mul255(sample[1], alpha);
+ int a = (sa ? fz_mul255(sample[1], alpha) : 255);
int t = 255 - a;
dp[0] = x + fz_mul255(dp[0], t);
dp[1] = x + fz_mul255(dp[1], t);
dp[2] = x + fz_mul255(dp[2], t);
- dp[3] = a + fz_mul255(dp[3], t);
+ if (da)
+ dp[3] = a + fz_mul255(dp[3], t);
if (hp)
hp[0] = a + fz_mul255(hp[0], t);
}
- dp += 4;
+ dp += 3 + da;
if (hp)
hp++;
v += fb;
@@ -222,24 +224,25 @@ fz_paint_affine_alpha_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int
int vi = v >> 16;
if (vi < 0 || vi >= sh)
return;
- sp += vi * sw * 2;
+ sp += vi * ss;
while (w--)
{
int ui = u >> 16;
if (ui >= 0 && ui < sw)
{
- byte *sample = sp + (ui * 2);
+ byte *sample = sp + (ui * (1+sa));
int x = fz_mul255(sample[0], alpha);
- int a = fz_mul255(sample[1], alpha);
+ int a = (sa ? fz_mul255(sample[1], alpha) : 255);
int t = 255 - a;
dp[0] = x + fz_mul255(dp[0], t);
dp[1] = x + fz_mul255(dp[1], t);
dp[2] = x + fz_mul255(dp[2], t);
- dp[3] = a + fz_mul255(dp[3], t);
+ if (da)
+ dp[3] = a + fz_mul255(dp[3], t);
if (hp)
hp[0] = a + fz_mul255(hp[0], t);
}
- dp += 4;
+ dp += 3 + da;
if (hp)
hp++;
u += fa;
@@ -253,18 +256,19 @@ fz_paint_affine_alpha_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int
int vi = v >> 16;
if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
{
- byte *sample = sp + ((vi * sw + ui) * 2);
+ byte *sample = sp + (vi * ss) + (ui * (1+sa));
int x = fz_mul255(sample[0], alpha);
- int a = fz_mul255(sample[1], alpha);
+ int a = (sa ? fz_mul255(sample[1], alpha): 255);
int t = 255 - a;
dp[0] = x + fz_mul255(dp[0], t);
dp[1] = x + fz_mul255(dp[1], t);
dp[2] = x + fz_mul255(dp[2], t);
- dp[3] = a + fz_mul255(dp[3], t);
+ if (da)
+ dp[3] = a + fz_mul255(dp[3], t);
if (hp)
hp[0] = a + fz_mul255(hp[0], t);
}
- dp += 4;
+ dp += 3 + da;
if (hp)
hp++;
u += fa;
@@ -276,10 +280,9 @@ fz_paint_affine_alpha_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int
/* Blend premultiplied source image over destination */
static inline void
-fz_paint_affine_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, byte *hp)
+fz_paint_affine_N_lerp(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int n1, byte *hp)
{
int k;
- int n1 = n-1;
while (w--)
{
@@ -289,22 +292,23 @@ fz_paint_affine_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa,
int vi = v >> 16;
int uf = u & 0xffff;
int vf = v & 0xffff;
- byte *a = sample_nearest(sp, sw, sh, n, ui, vi);
- byte *b = sample_nearest(sp, sw, sh, n, ui+1, vi);
- byte *c = sample_nearest(sp, sw, sh, n, ui, vi+1);
- byte *d = sample_nearest(sp, sw, sh, n, ui+1, vi+1);
- int y = bilerp(a[n1], b[n1], c[n1], d[n1], uf, vf);
+ byte *a = sample_nearest(sp, sw, sh, ss, n1+sa, ui, vi);
+ byte *b = sample_nearest(sp, sw, sh, ss, n1+sa, ui+1, vi);
+ byte *c = sample_nearest(sp, sw, sh, ss, n1+sa, ui, vi+1);
+ byte *d = sample_nearest(sp, sw, sh, ss, n1+sa, ui+1, vi+1);
+ int y = sa ? bilerp(a[n1], b[n1], c[n1], d[n1], uf, vf) : 255;
int t = 255 - y;
for (k = 0; k < n1; k++)
{
int x = bilerp(a[k], b[k], c[k], d[k], uf, vf);
dp[k] = x + fz_mul255(dp[k], t);
}
- dp[n1] = y + fz_mul255(dp[n1], t);
+ if (da)
+ dp[n1] = y + fz_mul255(dp[n1], t);
if (hp)
hp[0] = y + fz_mul255(hp[0], t);
}
- dp += n;
+ dp += n1 + da;
if (hp)
hp++;
u += fa;
@@ -313,7 +317,7 @@ fz_paint_affine_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa,
}
static inline void
-fz_paint_affine_solid_g2rgb_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, byte *hp)
+fz_paint_affine_solid_g2rgb_lerp(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, byte *hp)
{
while (w--)
{
@@ -323,21 +327,22 @@ fz_paint_affine_solid_g2rgb_lerp(byte *dp, byte *sp, int sw, int sh, int u, int
int vi = v >> 16;
int uf = u & 0xffff;
int vf = v & 0xffff;
- byte *a = sample_nearest(sp, sw, sh, 2, ui, vi);
- byte *b = sample_nearest(sp, sw, sh, 2, ui+1, vi);
- byte *c = sample_nearest(sp, sw, sh, 2, ui, vi+1);
- byte *d = sample_nearest(sp, sw, sh, 2, ui+1, vi+1);
- int y = bilerp(a[1], b[1], c[1], d[1], uf, vf);
+ byte *a = sample_nearest(sp, sw, sh, ss, 1+sa, ui, vi);
+ byte *b = sample_nearest(sp, sw, sh, ss, 1+sa, ui+1, vi);
+ byte *c = sample_nearest(sp, sw, sh, ss, 1+sa, ui, vi+1);
+ byte *d = sample_nearest(sp, sw, sh, ss, 1+sa, ui+1, vi+1);
+ int y = (sa ? bilerp(a[1], b[1], c[1], d[1], uf, vf) : 255);
int t = 255 - y;
int x = bilerp(a[0], b[0], c[0], d[0], uf, vf);
dp[0] = x + fz_mul255(dp[0], t);
dp[1] = x + fz_mul255(dp[1], t);
dp[2] = x + fz_mul255(dp[2], t);
- dp[3] = y + fz_mul255(dp[3], t);
+ if (da)
+ dp[3] = y + fz_mul255(dp[3], t);
if (hp)
hp[0] = y + fz_mul255(hp[0], t);
}
- dp += 4;
+ dp += 3 + da;
if (hp)
hp++;
u += fa;
@@ -346,32 +351,30 @@ fz_paint_affine_solid_g2rgb_lerp(byte *dp, byte *sp, int sw, int sh, int u, int
}
static inline void
-fz_paint_affine_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, byte *hp)
+fz_paint_affine_N_near(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int n1, byte *hp)
{
int k;
- int n1 = n-1;
if (fa == 0)
{
int ui = u >> 16;
if (ui < 0 || ui >= sw)
return;
- sp += ui*n;
- sw *= n;
+ sp += ui*(n1+sa);
while (w--)
{
int vi = v >> 16;
if (vi >= 0 && vi < sh)
{
- byte *sample = sp + (vi * sw);
- int a = sample[n1];
+ byte *sample = sp + (vi * ss);
+ int a = (sa ? sample[n1] : 255);
/* If a is 0, then sample[k] = 0 for all k, as premultiplied */
if (a != 0)
{
int t = 255 - a;
if (t == 0)
{
- if (n == 4)
+ if (n1+da == 4)
{
*(int *)dp = *(int *)sample;
}
@@ -379,7 +382,8 @@ fz_paint_affine_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa,
{
for (k = 0; k < n1; k++)
dp[k] = sample[k];
- dp[n1] = a;
+ if (da)
+ dp[n1] = a;
}
if (hp)
hp[0] = a;
@@ -388,13 +392,14 @@ fz_paint_affine_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa,
{
for (k = 0; k < n1; k++)
dp[k] = sample[k] + fz_mul255(dp[k], t);
- dp[n1] = a + fz_mul255(dp[n1], t);
+ if (da)
+ dp[n1] = a + fz_mul255(dp[n1], t);
if (hp)
hp[0] = a + fz_mul255(hp[0], t);
}
}
}
- dp += n;
+ dp += n1+da;
if (hp)
hp++;
v += fb;
@@ -405,21 +410,21 @@ fz_paint_affine_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa,
int vi = v >> 16;
if (vi < 0 || vi >= sh)
return;
- sp += vi * sw * n;
+ sp += vi * ss;
while (w--)
{
int ui = u >> 16;
if (ui >= 0 && ui < sw)
{
- byte *sample = sp + (ui * n);
- int a = sample[n1];
+ byte *sample = sp + (ui * (n1+sa));
+ int a = sa ? sample[n1] : 255;
/* If a is 0, then sample[k] = 0 for all k, as premultiplied */
if (a != 0)
{
int t = 255 - a;
if (t == 0)
{
- if (n == 4)
+ if (n1+da == 4)
{
*(int *)dp = *(int *)sample;
}
@@ -427,7 +432,8 @@ fz_paint_affine_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa,
{
for (k = 0; k < n1; k++)
dp[k] = sample[k];
- dp[n1] = a;
+ if (da)
+ dp[n1] = a;
}
if (hp)
hp[0] = a;
@@ -436,13 +442,14 @@ fz_paint_affine_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa,
{
for (k = 0; k < n1; k++)
dp[k] = sample[k] + fz_mul255(dp[k], t);
- dp[n1] = a + fz_mul255(dp[n1], t);
+ if(da)
+ dp[n1] = a + fz_mul255(dp[n1], t);
if (hp)
hp[0] = a + fz_mul255(hp[0], t);
}
}
}
- dp += n;
+ dp += n1+da;
if (hp)
hp++;
u += fa;
@@ -456,15 +463,15 @@ fz_paint_affine_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa,
int vi = v >> 16;
if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
{
- byte *sample = sp + ((vi * sw + ui) * n);
- int a = sample[n1];
+ byte *sample = sp + (vi * ss) + (ui * (n1+sa));
+ int a = sa ? sample[n1] : 255;
/* If a is 0, then sample[k] = 0 for all k, as premultiplied */
if (a != 0)
{
int t = 255 - a;
if (t == 0)
{
- if (n == 4)
+ if (n1+da == 4)
{
*(int *)dp = *(int *)sample;
}
@@ -472,7 +479,8 @@ fz_paint_affine_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa,
{
for (k = 0; k < n1; k++)
dp[k] = sample[k];
- dp[n1] = a;
+ if (da)
+ dp[n1] = a;
}
if (hp)
hp[0] = a;
@@ -481,13 +489,14 @@ fz_paint_affine_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa,
{
for (k = 0; k < n1; k++)
dp[k] = sample[k] + fz_mul255(dp[k], t);
- dp[n1] = a + fz_mul255(dp[n1], t);
+ if (da)
+ dp[n1] = a + fz_mul255(dp[n1], t);
if (hp)
hp[0] = a + fz_mul255(hp[0], t);
}
}
}
- dp += n;
+ dp += n1+da;
if (hp)
hp++;
u += fa;
@@ -497,22 +506,21 @@ fz_paint_affine_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa,
}
static inline void
-fz_paint_affine_solid_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, byte *hp)
+fz_paint_affine_solid_g2rgb_near(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, byte *hp)
{
if (fa == 0)
{
int ui = u >> 16;
if (ui < 0 || ui >= sw)
return;
- sp += ui * 2;
- sw *= 2;
+ sp += ui * (1+sa);
while (w--)
{
int vi = v >> 16;
if (vi >= 0 && vi < sh)
{
- byte *sample = sp + (vi * sw);
- int a = sample[1];
+ byte *sample = sp + (vi * ss);
+ int a = (sa ? sample[1] : 255);
if (a != 0)
{
int x = sample[0];
@@ -522,7 +530,8 @@ fz_paint_affine_solid_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int
dp[0] = x;
dp[1] = x;
dp[2] = x;
- dp[3] = a;
+ if (da)
+ dp[3] = a;
if (hp)
hp[0] = a;
}
@@ -531,13 +540,14 @@ fz_paint_affine_solid_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int
dp[0] = x + fz_mul255(dp[0], t);
dp[1] = x + fz_mul255(dp[1], t);
dp[2] = x + fz_mul255(dp[2], t);
- dp[3] = a + fz_mul255(dp[3], t);
+ if (da)
+ dp[3] = a + fz_mul255(dp[3], t);
if (hp)
hp[0] = a + fz_mul255(hp[0], t);
}
}
}
- dp += 4;
+ dp += 3 + da;
if (hp)
hp++;
v += fb;
@@ -548,14 +558,14 @@ fz_paint_affine_solid_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int
int vi = v >> 16;
if (vi < 0 || vi >= sh)
return;
- sp += vi * sw * 2;
+ sp += vi * ss;
while (w--)
{
int ui = u >> 16;
if (ui >= 0 && ui < sw)
{
- byte *sample = sp + (ui * 2);
- int a = sample[1];
+ byte *sample = sp + (ui * (1+sa));
+ int a = (sa ? sample[1] : 255);
if (a != 0)
{
int x = sample[0];
@@ -565,7 +575,8 @@ fz_paint_affine_solid_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int
dp[0] = x;
dp[1] = x;
dp[2] = x;
- dp[3] = a;
+ if (da)
+ dp[3] = a;
if (hp)
hp[0] = a;
}
@@ -574,13 +585,14 @@ fz_paint_affine_solid_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int
dp[0] = x + fz_mul255(dp[0], t);
dp[1] = x + fz_mul255(dp[1], t);
dp[2] = x + fz_mul255(dp[2], t);
- dp[3] = a + fz_mul255(dp[3], t);
+ if (da)
+ dp[3] = a + fz_mul255(dp[3], t);
if (hp)
hp[0] = a + fz_mul255(hp[0], t);
}
}
}
- dp += 4;
+ dp += 3 + da;
if (hp)
hp++;
u += fa;
@@ -594,8 +606,8 @@ fz_paint_affine_solid_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int
int vi = v >> 16;
if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
{
- byte *sample = sp + ((vi * sw + ui) * 2);
- int a = sample[1];
+ byte *sample = sp + (vi * ss) + (ui * (1+sa));
+ int a = sa ? sample[1] : 255;
if (a != 0)
{
int x = sample[0];
@@ -605,7 +617,8 @@ fz_paint_affine_solid_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int
dp[0] = x;
dp[1] = x;
dp[2] = x;
- dp[3] = a;
+ if (da)
+ dp[3] = a;
if (hp)
hp[0] = a;
}
@@ -614,13 +627,14 @@ fz_paint_affine_solid_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int
dp[0] = x + fz_mul255(dp[0], t);
dp[1] = x + fz_mul255(dp[1], t);
dp[2] = x + fz_mul255(dp[2], t);
- dp[3] = a + fz_mul255(dp[3], t);
+ if (da)
+ dp[3] = a + fz_mul255(dp[3], t);
if (hp)
hp[0] = a + fz_mul255(hp[0], t);
}
}
}
- dp += 4;
+ dp += 3 + da;
if (hp)
hp++;
u += fa;
@@ -632,9 +646,8 @@ fz_paint_affine_solid_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int
/* Blend non-premultiplied color in source image mask over destination */
static inline void
-fz_paint_affine_color_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, byte *color, byte *hp)
+fz_paint_affine_color_N_lerp(byte *dp, int da, byte *sp, int sw, int sh, int ss, int u, int v, int fa, int fb, int w, int n1, byte *color, byte *hp)
{
- int n1 = n - 1;
int sa = color[n1];
int k;
@@ -646,19 +659,20 @@ fz_paint_affine_color_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, i
int vi = v >> 16;
int uf = u & 0xffff;
int vf = v & 0xffff;
- byte *a = sample_nearest(sp, sw, sh, 1, ui, vi);
- byte *b = sample_nearest(sp, sw, sh, 1, ui+1, vi);
- byte *c = sample_nearest(sp, sw, sh, 1, ui, vi+1);
- byte *d = sample_nearest(sp, sw, sh, 1, ui+1, vi+1);
+ byte *a = sample_nearest(sp, sw, sh, ss, 1, ui, vi);
+ byte *b = sample_nearest(sp, sw, sh, ss, 1, ui+1, vi);
+ byte *c = sample_nearest(sp, sw, sh, ss, 1, ui, vi+1);
+ byte *d = sample_nearest(sp, sw, sh, ss, 1, ui+1, vi+1);
int ma = bilerp(a[0], b[0], c[0], d[0], uf, vf);
int masa = FZ_COMBINE(FZ_EXPAND(ma), sa);
for (k = 0; k < n1; k++)
dp[k] = FZ_BLEND(color[k], dp[k], masa);
- dp[n1] = FZ_BLEND(255, dp[n1], masa);
+ if (da)
+ dp[n1] = FZ_BLEND(255, dp[n1], masa);
if (hp)
hp[0] = FZ_BLEND(255, hp[0], masa);
}
- dp += n;
+ dp += n1 + da;
if (hp)
hp++;
u += fa;
@@ -667,9 +681,8 @@ fz_paint_affine_color_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, i
}
static inline void
-fz_paint_affine_color_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, byte *color, byte *hp)
+fz_paint_affine_color_N_near(byte *dp, int da, byte *sp, int sw, int sh, int ss, int u, int v, int fa, int fb, int w, int n1, byte *color, byte *hp)
{
- int n1 = n-1;
int sa = color[n1];
int k;
@@ -679,15 +692,16 @@ fz_paint_affine_color_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, i
int vi = v >> 16;
if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
{
- int ma = sp[vi * sw + ui];
+ int ma = sp[vi * ss + ui];
int masa = FZ_COMBINE(FZ_EXPAND(ma), sa);
for (k = 0; k < n1; k++)
dp[k] = FZ_BLEND(color[k], dp[k], masa);
- dp[n1] = FZ_BLEND(255, dp[n1], masa);
+ if (da)
+ dp[n1] = FZ_BLEND(255, dp[n1], masa);
if (hp)
hp[0] = FZ_BLEND(255, hp[0], masa);
}
- dp += n;
+ dp += n1+da;
if (hp)
hp++;
u += fa;
@@ -696,104 +710,372 @@ fz_paint_affine_color_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, i
}
static void
-fz_paint_affine_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color/*unused*/, byte *hp)
+fz_paint_affine_lerp(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color/*unused*/, byte *hp)
{
- if (alpha == 255)
+ if (da)
{
- switch (n)
+ if (sa)
{
- case 1: fz_paint_affine_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 1, hp); break;
- case 2: fz_paint_affine_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 2, hp); break;
- case 4: fz_paint_affine_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 4, hp); break;
- default: fz_paint_affine_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, n, hp); break;
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_N_lerp(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 1, hp); break;
+ case 3: fz_paint_affine_N_lerp(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 3, hp); break;
+ case 4: fz_paint_affine_N_lerp(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 4, hp); break;
+ default: fz_paint_affine_N_lerp(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, n, hp); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_alpha_N_lerp(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 1, alpha, hp); break;
+ case 3: fz_paint_affine_alpha_N_lerp(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 3, alpha, hp); break;
+ case 4: fz_paint_affine_alpha_N_lerp(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 4, alpha, hp); break;
+ default: fz_paint_affine_alpha_N_lerp(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, n, alpha, hp); break;
+ }
+ }
+ }
+ else
+ {
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_N_lerp(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 1, hp); break;
+ case 3: fz_paint_affine_N_lerp(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 3, hp); break;
+ case 4: fz_paint_affine_N_lerp(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 4, hp); break;
+ default: fz_paint_affine_N_lerp(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, n, hp); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_alpha_N_lerp(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 1, alpha, hp); break;
+ case 3: fz_paint_affine_alpha_N_lerp(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 3, alpha, hp); break;
+ case 4: fz_paint_affine_alpha_N_lerp(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 4, alpha, hp); break;
+ default: fz_paint_affine_alpha_N_lerp(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, n, alpha, hp); break;
+ }
+ }
}
}
- else if (alpha > 0)
+ else
{
- switch (n)
+ if (sa)
{
- case 1: fz_paint_affine_alpha_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 1, alpha, hp); break;
- case 2: fz_paint_affine_alpha_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 2, alpha, hp); break;
- case 4: fz_paint_affine_alpha_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 4, alpha, hp); break;
- default: fz_paint_affine_alpha_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, n, alpha, hp); break;
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_N_lerp(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, 1, hp); break;
+ case 3: fz_paint_affine_N_lerp(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, 3, hp); break;
+ case 4: fz_paint_affine_N_lerp(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, 4, hp); break;
+ default: fz_paint_affine_N_lerp(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, n, hp); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_alpha_N_lerp(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, 1, alpha, hp); break;
+ case 3: fz_paint_affine_alpha_N_lerp(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, 3, alpha, hp); break;
+ case 4: fz_paint_affine_alpha_N_lerp(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, 4, alpha, hp); break;
+ default: fz_paint_affine_alpha_N_lerp(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, n, alpha, hp); break;
+ }
+ }
+ }
+ else
+ {
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_N_lerp(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, 1, hp); break;
+ case 3: fz_paint_affine_N_lerp(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, 3, hp); break;
+ case 4: fz_paint_affine_N_lerp(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, 4, hp); break;
+ default: fz_paint_affine_N_lerp(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, n, hp); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_alpha_N_lerp(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, 1, alpha, hp); break;
+ case 3: fz_paint_affine_alpha_N_lerp(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, 3, alpha, hp); break;
+ case 4: fz_paint_affine_alpha_N_lerp(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, 4, alpha, hp); break;
+ default: fz_paint_affine_alpha_N_lerp(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, n, alpha, hp); break;
+ }
+ }
}
}
}
static void
-fz_paint_affine_g2rgb_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color/*unused*/, byte *hp)
+fz_paint_affine_g2rgb_lerp(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color/*unused*/, byte *hp)
{
- if (alpha == 255)
+ if (da)
{
- fz_paint_affine_solid_g2rgb_lerp(dp, sp, sw, sh, u, v, fa, fb, w, hp);
+ if (sa)
+ {
+ if (alpha == 255)
+ {
+ fz_paint_affine_solid_g2rgb_lerp(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, hp);
+ }
+ else if (alpha > 0)
+ {
+ fz_paint_affine_alpha_g2rgb_lerp(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, alpha, hp);
+ }
+ }
+ else
+ {
+ if (alpha == 255)
+ {
+ fz_paint_affine_solid_g2rgb_lerp(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, hp);
+ }
+ else if (alpha > 0)
+ {
+ fz_paint_affine_alpha_g2rgb_lerp(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, alpha, hp);
+ }
+ }
}
- else if (alpha > 0)
+ else
{
- fz_paint_affine_alpha_g2rgb_lerp(dp, sp, sw, sh, u, v, fa, fb, w, alpha, hp);
+ if (sa)
+ {
+ if (alpha == 255)
+ {
+ fz_paint_affine_solid_g2rgb_lerp(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, hp);
+ }
+ else if (alpha > 0)
+ {
+ fz_paint_affine_alpha_g2rgb_lerp(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, alpha, hp);
+ }
+ }
+ else
+ {
+ if (alpha == 255)
+ {
+ fz_paint_affine_solid_g2rgb_lerp(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, hp);
+ }
+ else if (alpha > 0)
+ {
+ fz_paint_affine_alpha_g2rgb_lerp(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, alpha, hp);
+ }
+ }
}
}
static void
-fz_paint_affine_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color/*unused */, byte *hp)
+fz_paint_affine_near(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color/*unused */, byte *hp)
{
- if (alpha == 255)
+ if (da)
{
- switch (n)
+ if (sa)
+ {
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 0: fz_paint_affine_N_near(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 0, hp); break;
+ case 1: fz_paint_affine_N_near(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 1, hp); break;
+ case 3: fz_paint_affine_N_near(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 3, hp); break;
+ case 4: fz_paint_affine_N_near(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 4, hp); break;
+ default: fz_paint_affine_N_near(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, n, hp); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 0: fz_paint_affine_alpha_N_near(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 0, alpha, hp); break;
+ case 1: fz_paint_affine_alpha_N_near(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 1, alpha, hp); break;
+ case 3: fz_paint_affine_alpha_N_near(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 3, alpha, hp); break;
+ case 4: fz_paint_affine_alpha_N_near(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 4, alpha, hp); break;
+ default: fz_paint_affine_alpha_N_near(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, n, alpha, hp); break;
+ }
+ }
+ }
+ else
{
- case 1: fz_paint_affine_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 1, hp); break;
- case 2: fz_paint_affine_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 2, hp); break;
- case 4: fz_paint_affine_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 4, hp); break;
- case 5: fz_paint_affine_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 5, hp); break;
- default: fz_paint_affine_N_near(dp, sp, sw, sh, u, v, fa, fb, w, n, hp); break;
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 0: fz_paint_affine_N_near(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 0, hp); break;
+ case 1: fz_paint_affine_N_near(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 1, hp); break;
+ case 3: fz_paint_affine_N_near(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 3, hp); break;
+ case 4: fz_paint_affine_N_near(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 4, hp); break;
+ default: fz_paint_affine_N_near(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, n, hp); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 0: fz_paint_affine_alpha_N_near(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 0, alpha, hp); break;
+ case 1: fz_paint_affine_alpha_N_near(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 1, alpha, hp); break;
+ case 3: fz_paint_affine_alpha_N_near(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 3, alpha, hp); break;
+ case 4: fz_paint_affine_alpha_N_near(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 4, alpha, hp); break;
+ default: fz_paint_affine_alpha_N_near(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, n, alpha, hp); break;
+ }
+ }
}
}
- else if (alpha > 0)
+ else
{
- switch (n)
+ if (sa)
{
- case 1: fz_paint_affine_alpha_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 1, alpha, hp); break;
- case 2: fz_paint_affine_alpha_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 2, alpha, hp); break;
- case 4: fz_paint_affine_alpha_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 4, alpha, hp); break;
- case 5: fz_paint_affine_alpha_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 5, alpha, hp); break;
- default: fz_paint_affine_alpha_N_near(dp, sp, sw, sh, u, v, fa, fb, w, n, alpha, hp); break;
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_N_near(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, 1, hp); break;
+ case 3: fz_paint_affine_N_near(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, 3, hp); break;
+ case 4: fz_paint_affine_N_near(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, 4, hp); break;
+ default: fz_paint_affine_N_near(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, n, hp); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_alpha_N_near(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, 1, alpha, hp); break;
+ case 3: fz_paint_affine_alpha_N_near(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, 3, alpha, hp); break;
+ case 4: fz_paint_affine_alpha_N_near(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, 4, alpha, hp); break;
+ default: fz_paint_affine_alpha_N_near(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, n, alpha, hp); break;
+ }
+ }
+ }
+ else
+ {
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_N_near(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, 1, hp); break;
+ case 3: fz_paint_affine_N_near(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, 3, hp); break;
+ case 4: fz_paint_affine_N_near(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, 4, hp); break;
+ default: fz_paint_affine_N_near(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, n, hp); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_alpha_N_near(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, 1, alpha, hp); break;
+ case 3: fz_paint_affine_alpha_N_near(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, 3, alpha, hp); break;
+ case 4: fz_paint_affine_alpha_N_near(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, 4, alpha, hp); break;
+ default: fz_paint_affine_alpha_N_near(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, n, alpha, hp); break;
+ }
+ }
}
}
}
static void
-fz_paint_affine_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color/*unused*/, byte *hp)
+fz_paint_affine_g2rgb_near(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color/*unused*/, byte *hp)
{
- if (alpha == 255)
+ if (da)
{
- fz_paint_affine_solid_g2rgb_near(dp, sp, sw, sh, u, v, fa, fb, w, hp);
+ if (sa)
+ {
+ if (alpha == 255)
+ {
+ fz_paint_affine_solid_g2rgb_near(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, hp);
+ }
+ else if (alpha > 0)
+ {
+ fz_paint_affine_alpha_g2rgb_near(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, alpha, hp);
+ }
+ }
+ else
+ {
+ if (alpha == 255)
+ {
+ fz_paint_affine_solid_g2rgb_near(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, hp);
+ }
+ else if (alpha > 0)
+ {
+ fz_paint_affine_alpha_g2rgb_near(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, alpha, hp);
+ }
+ }
}
- else if (alpha > 0)
+ else
{
- fz_paint_affine_alpha_g2rgb_near(dp, sp, sw, sh, u, v, fa, fb, w, alpha, hp);
+ if (sa)
+ {
+ if (alpha == 255)
+ {
+ fz_paint_affine_solid_g2rgb_near(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, hp);
+ }
+ else if (alpha > 0)
+ {
+ fz_paint_affine_alpha_g2rgb_near(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, alpha, hp);
+ }
+ }
+ else
+ {
+ if (alpha == 255)
+ {
+ fz_paint_affine_solid_g2rgb_near(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, hp);
+ }
+ else if (alpha > 0)
+ {
+ fz_paint_affine_alpha_g2rgb_near(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, alpha, hp);
+ }
+ }
}
}
static void
-fz_paint_affine_color_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha/*unused*/, byte *color, byte *hp)
+fz_paint_affine_color_lerp(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int n, int alpha/*unused*/, byte *color, byte *hp)
{
- switch (n)
+ if (da)
{
- case 2: fz_paint_affine_color_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 2, color, hp); break;
- case 4: fz_paint_affine_color_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 4, color, hp); break;
- case 5: fz_paint_affine_color_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 5, color, hp); break;
- default: fz_paint_affine_color_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, n, color, hp); break;
+ switch (n)
+ {
+ case 1: fz_paint_affine_color_N_lerp(dp, 1, sp, sw, sh, ss, u, v, fa, fb, w, 1, color, hp); break;
+ case 3: fz_paint_affine_color_N_lerp(dp, 1, sp, sw, sh, ss, u, v, fa, fb, w, 3, color, hp); break;
+ case 4: fz_paint_affine_color_N_lerp(dp, 1, sp, sw, sh, ss, u, v, fa, fb, w, 4, color, hp); break;
+ default: fz_paint_affine_color_N_lerp(dp, 1, sp, sw, sh, ss, u, v, fa, fb, w, n, color, hp); break;
+ }
+ }
+ else
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_color_N_lerp(dp, 0, sp, sw, sh, ss, u, v, fa, fb, w, 1, color, hp); break;
+ case 3: fz_paint_affine_color_N_lerp(dp, 0, sp, sw, sh, ss, u, v, fa, fb, w, 3, color, hp); break;
+ case 4: fz_paint_affine_color_N_lerp(dp, 0, sp, sw, sh, ss, u, v, fa, fb, w, 4, color, hp); break;
+ default: fz_paint_affine_color_N_lerp(dp, 0, sp, sw, sh, ss, u, v, fa, fb, w, n, color, hp); break;
+ }
}
}
static void
-fz_paint_affine_color_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha/*unused*/, byte *color, byte *hp)
+fz_paint_affine_color_near(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int n, int alpha/*unused*/, byte *color, byte *hp)
{
- switch (n)
+ if (da)
{
- case 2: fz_paint_affine_color_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 2, color, hp); break;
- case 4: fz_paint_affine_color_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 4, color, hp); break;
- case 5: fz_paint_affine_color_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 5, color, hp); break;
- default: fz_paint_affine_color_N_near(dp, sp, sw, sh, u, v, fa, fb, w, n, color, hp); break;
+ switch (n)
+ {
+ case 1: fz_paint_affine_color_N_near(dp, 1, sp, sw, sh, ss, u, v, fa, fb, w, 1, color, hp); break;
+ case 3: fz_paint_affine_color_N_near(dp, 1, sp, sw, sh, ss, u, v, fa, fb, w, 3, color, hp); break;
+ case 4: fz_paint_affine_color_N_near(dp, 1, sp, sw, sh, ss, u, v, fa, fb, w, 4, color, hp); break;
+ default: fz_paint_affine_color_N_near(dp, 1, sp, sw, sh, ss, u, v, fa, fb, w, n, color, hp); break;
+ }
+ }
+ else
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_color_N_near(dp, 0, sp, sw, sh, ss, u, v, fa, fb, w, 1, color, hp); break;
+ case 3: fz_paint_affine_color_N_near(dp, 0, sp, sw, sh, ss, u, v, fa, fb, w, 3, color, hp); break;
+ case 4: fz_paint_affine_color_N_near(dp, 0, sp, sw, sh, ss, u, v, fa, fb, w, 4, color, hp); break;
+ default: fz_paint_affine_color_N_near(dp, 0, sp, sw, sh, ss, u, v, fa, fb, w, n, color, hp); break;
+ }
}
}
@@ -994,10 +1276,10 @@ fz_paint_image_imp(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz
byte *dp, *sp, *hp;
int u, v, fa, fb, fc, fd;
int x, y, w, h;
- int sw, sh, n, hw;
+ int sw, sh, ss, sa, n, hs, da;
fz_irect bbox;
int dolerp;
- void (*paintfn)(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color, byte *hp);
+ void (*paintfn)(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color, byte *hp);
fz_matrix local_ctm = *ctm;
fz_rect rect;
int is_rectilinear;
@@ -1062,27 +1344,35 @@ 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));
- dp = dst->samples + (unsigned int)(((y - dst->y) * dst->w + (x - dst->x)) * dst->n);
- n = dst->n;
+ dp = dst->samples + (unsigned int)((y - dst->y) * dst->stride + (x - dst->x) * dst->n);
+ da = dst->alpha;
+ n = dst->n - da;
sp = img->samples;
sw = img->w;
sh = img->h;
+ ss = img->stride;
+ sa = img->alpha;
if (shape)
{
- hw = shape->w;
- hp = shape->samples + (unsigned int)(((y - shape->y) * hw) + x - shape->x);
+ hs = shape->stride;
+ hp = shape->samples + (unsigned int)((y - shape->y) * shape->stride + x - shape->x);
}
else
{
- hw = 0;
+ hs = 0;
hp = NULL;
}
/* TODO: if (fb == 0 && fa == 1) call fz_paint_span */
- if (dst->n == 4 && img->n == 2)
+ /* Sometimes we can get an alpha only input to be
+ * ploted. In this case treat it as a greyscale
+ * input. */
+ if (img->n == sa && n > 0)
+ sa = 0;
+
+ if (n == 3 && img->n == 1 + sa && !color)
{
- assert(!color);
if (dolerp)
paintfn = fz_paint_affine_g2rgb_lerp;
else
@@ -1090,6 +1380,7 @@ fz_paint_image_imp(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz
}
else
{
+ assert((!color && img->n - sa == n) || (color && img->n - sa == 1));
if (dolerp)
{
if (color)
@@ -1116,9 +1407,9 @@ fz_paint_image_imp(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz
while (h--)
{
- paintfn(dp, sp, sw, sh, u, v, fa, fb, w, n, alpha, color, hp);
- dp += dst->w * n;
- hp += hw;
+ paintfn(dp, da, sp, sw, sh, ss, sa, u, v, fa, fb, w, n, alpha, color, hp);
+ dp += dst->stride;
+ hp += hs;
u += fc;
v += fd;
}
@@ -1134,6 +1425,6 @@ fz_paint_image_with_color(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *sh
void
fz_paint_image(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz_pixmap *img, const fz_matrix *ctm, int alpha, int lerp_allowed, int as_tiled)
{
- assert(dst->n == img->n || (dst->n == 4 && img->n == 2));
+ assert(dst->n - dst->alpha == img->n - img->alpha|| (dst->n == 3 + dst->alpha && img->n == 1 + img->alpha));
fz_paint_image_imp(dst, scissor, shape, img, ctm, NULL, alpha, lerp_allowed, as_tiled);
}
diff --git a/source/fitz/draw-blend.c b/source/fitz/draw-blend.c
index 57aa28b1..31914ae1 100644
--- a/source/fitz/draw-blend.c
+++ b/source/fitz/draw-blend.c
@@ -268,15 +268,14 @@ fz_blend_pixel(unsigned char dp[3], unsigned char bp[3], unsigned char sp[3], in
/* Blending loops */
-void
-fz_blend_separable(byte * restrict bp, byte * restrict sp, int n, int w, int blendmode)
+static inline void
+fz_blend_separable(byte * restrict bp, int bal, byte * restrict sp, int sal, int n1, int w, int blendmode)
{
int k;
- int n1 = n - 1;
while (w--)
{
- int sa = sp[n1];
- int ba = bp[n1];
+ int sa = (sal ? sp[n1] : 255);
+ int ba = (bal ? bp[n1] : 255);
int saba = fz_mul255(sa, ba);
/* ugh, division to get non-premul components */
@@ -309,22 +308,23 @@ fz_blend_separable(byte * restrict bp, byte * restrict sp, int n, int w, int ble
bp[k] = fz_mul255(255 - sa, bp[k]) + fz_mul255(255 - ba, sp[k]) + fz_mul255(saba, rc);
}
- bp[k] = ba + sa - saba;
+ if (bal)
+ bp[k] = ba + sa - saba;
- sp += n;
- bp += n;
+ sp += n1 + sal;
+ bp += n1 + bal;
}
}
-void
-fz_blend_nonseparable(byte * restrict bp, byte * restrict sp, int w, int blendmode)
+static void
+fz_blend_nonseparable(byte * restrict bp, int bal, byte * restrict sp, int sal, int w, int blendmode)
{
while (w--)
{
unsigned char rr, rg, rb;
- int sa = sp[3];
- int ba = bp[3];
+ int sa = (sal ? sp[3] : 255);
+ int ba = (bal ? bp[3] : 255);
int saba = fz_mul255(sa, ba);
/* ugh, division to get non-premul components */
@@ -359,18 +359,18 @@ fz_blend_nonseparable(byte * restrict bp, byte * restrict sp, int w, int blendmo
bp[0] = fz_mul255(255 - sa, bp[0]) + fz_mul255(255 - ba, sp[0]) + fz_mul255(saba, rr);
bp[1] = fz_mul255(255 - sa, bp[1]) + fz_mul255(255 - ba, sp[1]) + fz_mul255(saba, rg);
bp[2] = fz_mul255(255 - sa, bp[2]) + fz_mul255(255 - ba, sp[2]) + fz_mul255(saba, rb);
- bp[3] = ba + sa - saba;
+ if (bal)
+ bp[3] = ba + sa - saba;
- sp += 4;
- bp += 4;
+ sp += 3 + sal;
+ bp += 3 + bal;
}
}
-static void
-fz_blend_separable_nonisolated(byte * restrict bp, byte * restrict sp, int n, int w, int blendmode, byte * restrict hp, int alpha)
+static inline void
+fz_blend_separable_nonisolated(byte * restrict bp, int bal, byte * restrict sp, int sal, int n1, int w, int blendmode, byte * restrict hp, int alpha)
{
int k;
- int n1 = n - 1;
if (alpha == 255 && blendmode == 0)
{
@@ -384,14 +384,16 @@ fz_blend_separable_nonisolated(byte * restrict bp, byte * restrict sp, int n, in
/* If ha == 0 then leave everything unchanged */
if (ha != 0)
{
- for (k = 0; k < n; k++)
+ for (k = 0; k < n1; k++)
{
bp[k] = sp[k];
}
+ if (bal)
+ bp[k] = (sal ? sp[k] : 255);
}
- sp += n;
- bp += n;
+ sp += n1 + sal;
+ bp += n1 + bal;
}
return;
}
@@ -403,11 +405,11 @@ fz_blend_separable_nonisolated(byte * restrict bp, byte * restrict sp, int n, in
while (haa != 0) /* Use while, so we can break out */
{
int sa, ba, bahaa, ra, invsa, invba, invha, invra;
- sa = sp[n1];
+ sa = (sal ? sp[n1] : 255);
if (sa == 0)
break; /* No change! */
invsa = sa ? 255 * 256 / sa : 0;
- ba = bp[n1];
+ ba = (bal ? bp[n1] : 255);
if (ba == 0)
{
/* Just copy pixels (allowing for change in
@@ -416,7 +418,8 @@ fz_blend_separable_nonisolated(byte * restrict bp, byte * restrict sp, int n, in
{
bp[k] = fz_mul255((sp[k] * invsa) >> 8, haa);
}
- bp[n1] = haa;
+ if (bal)
+ bp[n1] = haa;
break;
}
bahaa = fz_mul255(ba, haa);
@@ -426,7 +429,9 @@ fz_blend_separable_nonisolated(byte * restrict bp, byte * restrict sp, int n, in
/* Calculate result_alpha - a combination of the
* background alpha, and 'shape' */
- ra = bp[n1] = ba - bahaa + haa;
+ ra = ba - bahaa + haa;
+ if (bal)
+ bp[n1] = ra;
if (ra == 0)
break;
/* Because we are a non-isolated group, we need to
@@ -483,18 +488,18 @@ fz_blend_separable_nonisolated(byte * restrict bp, byte * restrict sp, int n, in
rc = bc + fz_mul255(sa, fz_mul255(255 - ba, sc) + fz_mul255(ba, rc) - bc);
if (rc < 0) rc = 0;
if (rc > 255) rc = 255;
- bp[k] = fz_mul255(rc, ra);
+ bp[k] = fz_mul255(rc, ra);
}
break;
}
- sp += n;
- bp += n;
+ sp += n1 + sal;
+ bp += n1 + bal;
}
}
-static void
-fz_blend_nonseparable_nonisolated(byte * restrict bp, byte * restrict sp, int w, int blendmode, byte * restrict hp, int alpha)
+static inline void
+fz_blend_nonseparable_nonisolated(byte * restrict bp, int bal, byte * restrict sp, int sal, int w, int blendmode, byte * restrict hp, int alpha)
{
while (w--)
{
@@ -502,12 +507,14 @@ fz_blend_nonseparable_nonisolated(byte * restrict bp, byte * restrict sp, int w,
int haa = fz_mul255(ha, alpha);
if (haa != 0)
{
- int sa = sp[3];
- int ba = bp[3];
+ int sa = (sal ? sp[3] : 255);
+ int ba = (bal ? bp[3] : 255);
int baha = fz_mul255(ba, haa);
/* Calculate result_alpha */
- int ra = bp[3] = ba - baha + haa;
+ int ra = ba - baha + haa;
+ if (bal)
+ bp[3] = ra;
if (ra != 0)
{
/* Because we are a non-isolated group, we
@@ -566,8 +573,8 @@ fz_blend_nonseparable_nonisolated(byte * restrict bp, byte * restrict sp, int w,
}
}
- sp += 4;
- bp += 4;
+ sp += 3 + sal;
+ bp += 3 + bal;
}
}
@@ -578,16 +585,24 @@ fz_blend_pixmap(fz_pixmap *dst, fz_pixmap *src, int alpha, int blendmode, int is
fz_irect bbox;
fz_irect bbox2;
int x, y, w, h, n;
+ int da, sa;
/* TODO: fix this hack! */
if (isolated && alpha < 255)
{
+ int nn;
+ h = src->h;
sp = src->samples;
- n = src->w * src->h * src->n;
- while (n--)
+ nn = src->w * src->n;
+ while (h--)
{
- *sp = fz_mul255(*sp, alpha);
- sp++;
+ n = nn;
+ while (n--)
+ {
+ *sp = fz_mul255(*sp, alpha);
+ sp++;
+ }
+ sp += src->stride - nn;
}
}
@@ -601,36 +616,75 @@ fz_blend_pixmap(fz_pixmap *dst, fz_pixmap *src, int alpha, int blendmode, int is
h = bbox.y1 - bbox.y0;
n = src->n;
- sp = src->samples + (unsigned int)(((y - src->y) * src->w + (x - src->x)) * n);
- dp = dst->samples + (unsigned int)(((y - dst->y) * dst->w + (x - dst->x)) * n);
+ sp = src->samples + (unsigned int)((y - src->y) * src->stride + (x - src->x) * src->n);
+ sa = src->alpha;
+ dp = dst->samples + (unsigned int)((y - dst->y) * dst->stride + (x - dst->x) * dst->n);
+ da = dst->alpha;
- assert(src->n == dst->n);
+ n -= sa;
+ assert(n == dst->n - da);
if (!isolated)
{
- unsigned char *hp = shape->samples + (unsigned int)((y - shape->y) * shape->w + (x - shape->x));
+ unsigned char *hp = shape->samples + (unsigned int)((y - shape->y) * shape->stride + (x - shape->x));
while (h--)
{
- if (n == 4 && blendmode >= FZ_BLEND_HUE)
- fz_blend_nonseparable_nonisolated(dp, sp, w, blendmode, hp, alpha);
+ if (n == 3 && blendmode >= FZ_BLEND_HUE)
+ if (da)
+ if (sa)
+ fz_blend_nonseparable_nonisolated(dp, 1, sp, 1, w, blendmode, hp, alpha);
+ else
+ fz_blend_nonseparable_nonisolated(dp, 1, sp, 0, w, blendmode, hp, alpha);
+ else
+ if (sa)
+ fz_blend_nonseparable_nonisolated(dp, 0, sp, 1, w, blendmode, hp, alpha);
+ else
+ fz_blend_nonseparable_nonisolated(dp, 0, sp, 0, w, blendmode, hp, alpha);
else
- fz_blend_separable_nonisolated(dp, sp, n, w, blendmode, hp, alpha);
- sp += src->w * n;
- dp += dst->w * n;
- hp += shape->w;
+ if (da)
+ if (sa)
+ fz_blend_separable_nonisolated(dp, 1, sp, 1, n, w, blendmode, hp, alpha);
+ else
+ fz_blend_separable_nonisolated(dp, 1, sp, 0, n, w, blendmode, hp, alpha);
+ else
+ if (sa)
+ fz_blend_separable_nonisolated(dp, 0, sp, 1, n, w, blendmode, hp, alpha);
+ else
+ fz_blend_separable_nonisolated(dp, 0, sp, 0, n, w, blendmode, hp, alpha);
+ sp += src->stride;
+ dp += dst->stride;
+ hp += shape->stride;
}
}
else
{
while (h--)
{
- if (n == 4 && blendmode >= FZ_BLEND_HUE)
- fz_blend_nonseparable(dp, sp, w, blendmode);
+ if (n == 3 && blendmode >= FZ_BLEND_HUE)
+ if (da)
+ if (sa)
+ fz_blend_nonseparable(dp, 1, sp, 1, w, blendmode);
+ else
+ fz_blend_nonseparable(dp, 1, sp, 0, w, blendmode);
+ else
+ if (sa)
+ fz_blend_nonseparable(dp, 0, sp, 1, w, blendmode);
+ else
+ fz_blend_nonseparable(dp, 0, sp, 0, w, blendmode);
else
- fz_blend_separable(dp, sp, n, w, blendmode);
- sp += src->w * n;
- dp += dst->w * n;
+ if (da)
+ if (sa)
+ fz_blend_separable(dp, 1, sp, 1, n, w, blendmode);
+ else
+ fz_blend_separable(dp, 1, sp, 0, n, w, blendmode);
+ else
+ if (sa)
+ fz_blend_separable(dp, 0, sp, 1, n, w, blendmode);
+ else
+ fz_blend_separable(dp, 0, sp, 0, n, w, blendmode);
+ sp += src->stride;
+ dp += dst->stride;
}
}
}
diff --git a/source/fitz/draw-device.c b/source/fitz/draw-device.c
index 5b512c44..516e05bc 100644
--- a/source/fitz/draw-device.c
+++ b/source/fitz/draw-device.c
@@ -162,7 +162,7 @@ fz_knockout_begin(fz_context *ctx, fz_draw_device *dev)
fz_pixmap_bbox(ctx, state->dest, &bbox);
fz_intersect_irect(&bbox, &state->scissor);
- dest = fz_new_pixmap_with_bbox(ctx, state->dest->colorspace, &bbox);
+ dest = fz_new_pixmap_with_bbox(ctx, state->dest->colorspace, &bbox, state->dest->alpha || isolated);
if (isolated)
{
@@ -193,7 +193,7 @@ fz_knockout_begin(fz_context *ctx, fz_draw_device *dev)
}
else
{
- shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, shape);
}
#ifdef DUMP_GROUP_BLENDS
@@ -276,13 +276,10 @@ fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
unsigned char colorbv[FZ_MAX_COLORS + 1];
float colorfv[FZ_MAX_COLORS];
fz_irect bbox;
- int i;
+ int i, n;
fz_draw_state *state = &dev->stack[dev->top];
fz_colorspace *model = state->dest->colorspace;
- if (model == NULL)
- model = fz_device_gray(ctx);
-
if (flatness < 0.001f)
flatness = 0.001f;
@@ -298,8 +295,9 @@ fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
+ n = model ? model->n : 0;
fz_convert_color(ctx, model, colorfv, colorspace, color);
- for (i = 0; i < model->n; i++)
+ for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
colorbv[i] = alpha * 255;
@@ -331,14 +329,11 @@ fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const
unsigned char colorbv[FZ_MAX_COLORS + 1];
float colorfv[FZ_MAX_COLORS];
fz_irect bbox;
- int i;
+ int i, n;
float aa_level = 2.0f/(fz_graphics_aa_level(ctx)+2);
fz_draw_state *state = &dev->stack[dev->top];
fz_colorspace *model = state->dest->colorspace;
- if (model == NULL)
- model = fz_device_gray(ctx);
-
if (linewidth * expansion < aa_level)
linewidth = aa_level / expansion;
if (flatness < 0.001f)
@@ -359,11 +354,19 @@ fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
+ n = model ? model->n : 0;
fz_convert_color(ctx, model, colorfv, colorspace, color);
- for (i = 0; i < model->n; i++)
+ for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
colorbv[i] = alpha * 255;
+#ifdef DUMP_GROUP_BLENDS
+ dump_spaces(dev->top, "");
+ fz_dump_blend(ctx, state->dest, "Before stroke ");
+ if (state->shape)
+ fz_dump_blend(ctx, state->shape, "/");
+ printf("\n");
+#endif
fz_scan_convert(ctx, gel, 0, &bbox, state->dest, colorbv);
if (state->shape)
{
@@ -377,6 +380,13 @@ fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const
colorbv[0] = 255;
fz_scan_convert(ctx, gel, 0, &bbox, state->shape, colorbv);
}
+#ifdef DUMP_GROUP_BLENDS
+ dump_spaces(dev->top, "");
+ fz_dump_blend(ctx, state->dest, "After stroke ");
+ if (state->shape)
+ fz_dump_blend(ctx, state->shape, "/");
+ printf("\n");
+#endif
if (state->blendmode & FZ_BLEND_KNOCKOUT)
fz_knockout_end(ctx, dev);
@@ -424,13 +434,20 @@ fz_draw_clip_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
fz_try(ctx)
{
- state[1].mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, state[1].mask);
- state[1].dest = fz_new_pixmap_with_bbox(ctx, model, &bbox);
- fz_clear_pixmap(ctx, state[1].dest);
+ /* When there is no alpha in the current destination (state[0].dest->alpha == 0)
+ * we have a choice. We can either create the new destination WITH alpha, or
+ * we can copy the old pixmap contents in. We opt for the latter here, but
+ * may want to revisit this decision in future. */
+ state[1].dest = fz_new_pixmap_with_bbox(ctx, model, &bbox, state[0].dest->alpha);
+ if (state[0].dest->alpha)
+ fz_clear_pixmap(ctx, state[1].dest);
+ else
+ fz_copy_pixmap_rect(ctx, state[1].dest, state[0].dest, &bbox);
if (state[1].shape)
{
- state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, state[1].shape);
}
@@ -487,13 +504,20 @@ fz_draw_clip_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path,
fz_try(ctx)
{
- state[1].mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, state[1].mask);
- state[1].dest = fz_new_pixmap_with_bbox(ctx, model, &bbox);
- fz_clear_pixmap(ctx, state[1].dest);
+ /* When there is no alpha in the current destination (state[0].dest->alpha == 0)
+ * we have a choice. We can either create the new destination WITH alpha, or
+ * we can copy the old pixmap contents in. We opt for the latter here, but
+ * may want to revisit this decision in future. */
+ state[1].dest = fz_new_pixmap_with_bbox(ctx, model, &bbox, state[0].dest->alpha);
+ if (state[0].dest->alpha)
+ fz_clear_pixmap(ctx, state[1].dest);
+ else
+ fz_copy_pixmap_rect(ctx, state[1].dest, state[0].dest, &bbox);
if (state->shape)
{
- state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, state[1].shape);
}
@@ -537,24 +561,25 @@ draw_glyph(unsigned char *colorbv, fz_pixmap *dst, fz_glyph *glyph,
skip_x = x - glyph->x - xorig;
skip_y = y - glyph->y - yorig;
- dp = dst->samples + (unsigned int)(((y - dst->y) * dst->w + (x - dst->x)) * dst->n);
-
msk = glyph->pixmap;
+ dp = dst->samples + (unsigned int)((y - dst->y) * dst->stride + (x - dst->x) * dst->n);
if (msk == NULL)
{
fz_paint_glyph(colorbv, dst, dp, glyph, w, h, skip_x, skip_y);
}
else
{
- unsigned char *mp = msk->samples + skip_y * msk->w + skip_x;
+ unsigned char *mp = msk->samples + skip_y * msk->stride + skip_x;
+ int da = dst->alpha;
+
while (h--)
{
if (dst->colorspace)
- fz_paint_span_with_color(dp, mp, dst->n, w, colorbv);
+ fz_paint_span_with_color(dp, mp, dst->n, w, colorbv, da);
else
- fz_paint_span(dp, mp, 1, w, 255);
- dp += dst->w * dst->n;
- mp += msk->w;
+ fz_paint_span(dp, da, mp, 1, 0, w, 255);
+ dp += dst->stride;
+ mp += msk->stride;
}
}
}
@@ -570,13 +595,14 @@ fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
unsigned char shapebv;
float colorfv[FZ_MAX_COLORS];
fz_text_span *span;
- int i;
+ int i, n;
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
+ n = model ? model->n : 0;
fz_convert_color(ctx, model, colorfv, colorspace, color);
- for (i = 0; i < model->n; i++)
+ for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
colorbv[i] = alpha * 255;
shapebv = 255;
@@ -599,7 +625,7 @@ fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
tm.f = span->items[i].y;
fz_concat(&trm, &tm, ctm);
- glyph = fz_render_glyph(ctx, span->font, gid, &trm, model, &state->scissor);
+ glyph = fz_render_glyph(ctx, span->font, gid, &trm, model, &state->scissor, state->dest->alpha);
if (glyph)
{
fz_pixmap *pixmap = glyph->pixmap;
@@ -651,13 +677,14 @@ fz_draw_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text, const
unsigned char colorbv[FZ_MAX_COLORS + 1];
float colorfv[FZ_MAX_COLORS];
fz_text_span *span;
- int i;
+ int i, n;
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
+ n = model ? model->n : 0;
fz_convert_color(ctx, model, colorfv, colorspace, color);
- for (i = 0; i < model->n; i++)
+ for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
colorbv[i] = alpha * 255;
@@ -738,13 +765,20 @@ fz_draw_clip_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
fz_try(ctx)
{
- mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, mask);
- dest = fz_new_pixmap_with_bbox(ctx, model, &bbox);
- fz_clear_pixmap(ctx, dest);
+ /* When there is no alpha in the current destination (state[0].dest->alpha == 0)
+ * we have a choice. We can either create the new destination WITH alpha, or
+ * we can copy the old pixmap contents in. We opt for the latter here, but
+ * may want to revisit this decision in future. */
+ dest = fz_new_pixmap_with_bbox(ctx, model, &bbox, state[0].dest->alpha);
+ if (state[0].dest->alpha)
+ fz_clear_pixmap(ctx, dest);
+ else
+ fz_copy_pixmap_rect(ctx, dest, state[0].dest, &bbox);
if (state->shape)
{
- shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, shape);
}
else
@@ -775,7 +809,7 @@ fz_draw_clip_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
tm.f = span->items[i].y;
fz_concat(&trm, &tm, ctm);
- glyph = fz_render_glyph(ctx, span->font, gid, &trm, model, &state->scissor);
+ glyph = fz_render_glyph(ctx, span->font, gid, &trm, model, &state->scissor, state[1].dest->alpha);
if (glyph)
{
int x = (int)trm.e;
@@ -853,13 +887,20 @@ fz_draw_clip_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text,
fz_try(ctx)
{
- state[1].mask = mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].mask = mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, mask);
- state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, &bbox);
- fz_clear_pixmap(ctx, dest);
+ /* When there is no alpha in the current destination (state[0].dest->alpha == 0)
+ * we have a choice. We can either create the new destination WITH alpha, or
+ * we can copy the old pixmap contents in. We opt for the latter here, but
+ * may want to revisit this decision in future. */
+ state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, &bbox, state[0].dest->alpha);
+ if (state[0].dest->alpha)
+ fz_clear_pixmap(ctx, state[1].dest);
+ else
+ fz_copy_pixmap_rect(ctx, state[1].dest, state[0].dest, &bbox);
if (state->shape)
{
- state[1].shape = shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].shape = shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, shape);
}
else
@@ -963,12 +1004,6 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
if (fz_is_empty_irect(&bbox))
return;
- if (!model)
- {
- fz_warn(ctx, "cannot render shading directly to an alpha mask");
- return;
- }
-
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
@@ -977,11 +1012,14 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
if (alpha < 1)
{
- dest = fz_new_pixmap_with_bbox(ctx, state->dest->colorspace, &bbox);
- fz_clear_pixmap(ctx, dest);
+ dest = fz_new_pixmap_with_bbox(ctx, state->dest->colorspace, &bbox, state->dest->alpha);
+ if (state->dest->alpha)
+ fz_clear_pixmap(ctx, dest);
+ else
+ fz_copy_pixmap_rect(ctx, dest, state[0].dest, &bbox);
if (shape)
{
- shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, shape);
}
}
@@ -990,15 +1028,16 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
{
unsigned char *s;
int x, y, n, i;
+ n = model ? model->n : 0;
fz_convert_color(ctx, model, colorfv, shade->colorspace, shade->background);
- for (i = 0; i < model->n; i++)
+ for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
colorbv[i] = 255;
n = dest->n;
for (y = scissor.y0; y < scissor.y1; y++)
{
- s = dest->samples + (unsigned int)(((scissor.x0 - dest->x) + (y - dest->y) * dest->w) * dest->n);
+ s = dest->samples + (unsigned int)((y - dest->y) * dest->stride + (scissor.x0 - dest->x) * n);
for (x = scissor.x0; x < scissor.x1; x++)
{
for (i = 0; i < n; i++)
@@ -1009,7 +1048,7 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
{
for (y = scissor.y0; y < scissor.y1; y++)
{
- s = shape->samples + (unsigned int)((scissor.x0 - shape->x) + (y - shape->y) * shape->w);
+ s = shape->samples + (unsigned int)((y - shape->y) * shape->stride + (scissor.x0 - shape->x));
for (x = scissor.x0; x < scissor.x1; x++)
{
*s++ = 255;
@@ -1022,6 +1061,14 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
if (shape)
fz_clear_pixmap_rect_with_value(ctx, shape, 255, &bbox);
+#ifdef DUMP_GROUP_BLENDS
+ dump_spaces(dev->top, "");
+ fz_dump_blend(ctx, dest, "Shade ");
+ if (shape)
+ fz_dump_blend(ctx, shape, "/");
+ printf("\n");
+#endif
+
if (alpha < 1)
{
fz_paint_pixmap(state->dest, dest, alpha * 255);
@@ -1122,12 +1169,6 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
fz_var(scaled);
- if (!model)
- {
- fz_warn(ctx, "cannot render image directly to an alpha mask");
- return;
- }
-
if (image->w == 0 || image->h == 0)
return;
@@ -1170,7 +1211,7 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
orig_pixmap = pixmap;
/* convert images with more components (cmyk->rgb) before scaling */
- /* convert images with fewer components (gray->rgb after scaling */
+ /* convert images with fewer components (gray->rgb) after scaling */
/* convert images with expensive colorspace transforms after scaling */
fz_try(ctx)
@@ -1186,7 +1227,7 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
{
fz_irect bbox;
fz_pixmap_bbox(ctx, pixmap, &bbox);
- converted = fz_new_pixmap_with_bbox(ctx, model, &bbox);
+ converted = fz_new_pixmap_with_bbox(ctx, model, &bbox, pixmap->alpha);
fz_convert_pixmap(ctx, converted, pixmap);
pixmap = converted;
}
@@ -1218,7 +1259,7 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
{
fz_irect bbox;
fz_pixmap_bbox(ctx, pixmap, &bbox);
- converted = fz_new_pixmap_with_bbox(ctx, model, &bbox);
+ converted = fz_new_pixmap_with_bbox(ctx, model, &bbox, pixmap->alpha);
fz_convert_pixmap(ctx, converted, pixmap);
pixmap = converted;
}
@@ -1252,7 +1293,7 @@ fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
fz_pixmap *pixmap;
fz_pixmap *orig_pixmap;
int dx, dy;
- int i;
+ int i, n;
fz_draw_state *state = &dev->stack[dev->top];
fz_colorspace *model = state->dest->colorspace;
fz_irect clip;
@@ -1325,8 +1366,9 @@ fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
pixmap = scaled;
}
+ n = model ? model->n : 0;
fz_convert_color(ctx, model, colorfv, colorspace, color);
- for (i = 0; i < model->n; i++)
+ for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
colorbv[i] = alpha * 255;
@@ -1404,14 +1446,21 @@ fz_draw_clip_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
pixmap = fz_get_pixmap_from_image(ctx, image, NULL, &local_ctm, &dx, &dy);
orig_pixmap = pixmap;
- state[1].mask = mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].mask = mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, mask);
- state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, &bbox);
- fz_clear_pixmap(ctx, dest);
+ /* When there is no alpha in the current destination (state[0].dest->alpha == 0)
+ * we have a choice. We can either create the new destination WITH alpha, or
+ * we can copy the old pixmap contents in. We opt for the latter here, but
+ * may want to revisit this decision in future. */
+ state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, &bbox, state[0].dest->alpha);
+ if (state[0].dest->alpha)
+ fz_clear_pixmap(ctx, state[1].dest);
+ else
+ fz_copy_pixmap_rect(ctx, state[1].dest, state[0].dest, &bbox);
if (state->shape)
{
- state[1].shape = shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].shape = shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, shape);
}
@@ -1433,7 +1482,21 @@ fz_draw_clip_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
if (scaled)
pixmap = scaled;
}
+#ifdef DUMP_GROUP_BLENDS
+ dump_spaces(dev->top, "");
+ fz_dump_blend(ctx, pixmap, "Plotting imagemask ");
+ fz_dump_blend(ctx, mask, "/");
+ fz_dump_blend(ctx, state[1].dest, " onto ");
+ if (state[1].shape)
+ fz_dump_blend(ctx, state[1].shape, "/");
+#endif
fz_paint_image(mask, &bbox, state->shape, pixmap, &local_ctm, 255, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES), devp->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED);
+#ifdef DUMP_GROUP_BLENDS
+ fz_dump_blend(ctx, state[1].dest, " to get ");
+ if (state[1].shape)
+ fz_dump_blend(ctx, state[1].shape, "/");
+ printf("\n");
+#endif
}
fz_always(ctx)
{
@@ -1517,7 +1580,13 @@ fz_draw_begin_mask(fz_context *ctx, fz_device *devp, const fz_rect *rect, int lu
fz_try(ctx)
{
- state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, fz_device_gray(ctx), &bbox);
+ /* If luminosity, then we generate a mask from the greyscale value of the shapes.
+ * If !luminosity, then we generate a mask from the alpha value of the shapes.
+ */
+ if (luminosity)
+ state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, fz_device_gray(ctx), &bbox, 0);
+ else
+ state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
if (state->shape)
{
/* FIXME: If we ever want to support AIS true, then
@@ -1547,7 +1616,8 @@ fz_draw_begin_mask(fz_context *ctx, fz_device *devp, const fz_rect *rect, int lu
}
#ifdef DUMP_GROUP_BLENDS
- dump_spaces(dev->top-1, "Mask begin\n");
+ dump_spaces(dev->top-1, "Mask begin");
+ printf("%s\n", luminosity ? "(luminosity)" : "");
#endif
state[1].scissor = bbox;
state[1].luminosity = luminosity;
@@ -1578,7 +1648,10 @@ fz_draw_end_mask(fz_context *ctx, fz_device *devp)
luminosity = state[1].luminosity;
#ifdef DUMP_GROUP_BLENDS
- dump_spaces(dev->top-1, "Mask -> Clip\n");
+ dump_spaces(dev->top-1, "Mask -> Clip: ");
+ fz_dump_blend(ctx, state[1].dest, "Mask ");
+ if (state[1].shape)
+ fz_dump_blend(ctx, state[1].shape, "/");
#endif
fz_try(ctx)
{
@@ -1594,10 +1667,18 @@ fz_draw_end_mask(fz_context *ctx, fz_device *devp)
fz_drop_pixmap(ctx, state[1].shape);
state[1].shape = NULL;
+#ifdef DUMP_GROUP_BLENDS
+ fz_dump_blend(ctx, temp, "-> Clip ");
+ printf("\n");
+#endif
+
/* create new dest scratch buffer */
fz_pixmap_bbox(ctx, temp, &bbox);
- dest = fz_new_pixmap_with_bbox(ctx, state->dest->colorspace, &bbox);
- fz_clear_pixmap(ctx, dest);
+ dest = fz_new_pixmap_with_bbox(ctx, state->dest->colorspace, &bbox, state->dest->alpha);
+ if (state->dest->alpha)
+ fz_clear_pixmap(ctx, dest);
+ else
+ fz_copy_pixmap_rect(ctx, dest, state->dest, &bbox);
/* push soft mask as clip mask */
state[1].dest = dest;
@@ -1606,7 +1687,7 @@ fz_draw_end_mask(fz_context *ctx, fz_device *devp)
* clip mask when we pop. So create a new shape now. */
if (state[0].shape)
{
- state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, state[1].shape);
}
state[1].scissor = bbox;
@@ -1635,13 +1716,13 @@ fz_draw_begin_group(fz_context *ctx, fz_device *devp, const fz_rect *rect, int i
fz_try(ctx)
{
- state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, &bbox);
-
#ifndef ATTEMPT_KNOCKOUT_AND_ISOLATED
knockout = 0;
isolated = 1;
#endif
+ state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, &bbox, state[0].dest->alpha || isolated);
+
if (isolated)
{
fz_clear_pixmap(ctx, dest);
@@ -1659,7 +1740,7 @@ fz_draw_begin_group(fz_context *ctx, fz_device *devp, const fz_rect *rect, int i
}
else
{
- state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, state[1].shape);
}
@@ -1902,12 +1983,13 @@ fz_draw_begin_tile(fz_context *ctx, fz_device *devp, const fz_rect *area, const
fz_try(ctx)
{
- state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, &bbox);
+ /* Patterns can be transparent, so we need to have an alpha here. */
+ state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, &bbox, 1);
fz_clear_pixmap(ctx, dest);
shape = state[0].shape;
if (shape)
{
- state[1].shape = shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].shape = shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, shape);
}
state[1].blendmode |= FZ_BLEND_ISOLATED;
diff --git a/source/fitz/draw-edge.c b/source/fitz/draw-edge.c
index 6c104ff2..abf02a8c 100644
--- a/source/fitz/draw-edge.c
+++ b/source/fitz/draw-edge.c
@@ -836,11 +836,11 @@ static inline void
blit_aa(fz_pixmap *dst, int x, int y, unsigned char *mp, int w, unsigned char *color)
{
unsigned char *dp;
- dp = dst->samples + (unsigned int)(( (y - dst->y) * dst->w + (x - dst->x) ) * dst->n);
+ dp = dst->samples + (unsigned int)((y - dst->y) * dst->stride + (x - dst->x) * dst->n);
if (color)
- fz_paint_span_with_color(dp, mp, dst->n, w, color);
+ fz_paint_span_with_color(dp, mp, dst->n, w, color, dst->alpha);
else
- fz_paint_span(dp, mp, 1, w, 255);
+ fz_paint_span(dp, dst->alpha, mp, 1, 0, w, 255);
}
static void
@@ -1031,15 +1031,16 @@ static inline void
blit_sharp(int x0, int x1, int y, const fz_irect *clip, fz_pixmap *dst, unsigned char *color)
{
unsigned char *dp;
+ int da = dst->alpha;
x0 = fz_clampi(x0, dst->x, dst->x + dst->w);
x1 = fz_clampi(x1, dst->x, dst->x + dst->w);
if (x0 < x1)
{
- dp = dst->samples + (unsigned int)(( (y - dst->y) * dst->w + (x0 - dst->x) ) * dst->n);
+ dp = dst->samples + (unsigned int)((y - dst->y) * dst->stride + (x0 - dst->x) * dst->n);
if (color)
- fz_paint_solid_color(dp, dst->n, x1 - x0, color);
+ fz_paint_solid_color(dp, dst->n, x1 - x0, color, da);
else
- fz_paint_solid_alpha(dp, x1 - x0, 255);
+ memset(dp, 255, x1-x0);
}
}
diff --git a/source/fitz/draw-glyph.c b/source/fitz/draw-glyph.c
index 691e426d..98f9252b 100644
--- a/source/fitz/draw-glyph.c
+++ b/source/fitz/draw-glyph.c
@@ -185,7 +185,7 @@ fz_render_stroked_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix *trm,
(void)fz_subpixel_adjust(ctx, trm, &subpix_trm, &qe, &qf);
return fz_render_ft_stroked_glyph(ctx, font, gid, &subpix_trm, ctm, stroke);
}
- return fz_render_glyph(ctx, font, gid, trm, NULL, scissor);
+ return fz_render_glyph(ctx, font, gid, trm, NULL, scissor, 1);
}
fz_pixmap *
@@ -201,7 +201,7 @@ fz_render_stroked_glyph_pixmap(fz_context *ctx, fz_font *font, int gid, fz_matri
(void)fz_subpixel_adjust(ctx, trm, &subpix_trm, &qe, &qf);
return fz_render_ft_stroked_glyph_pixmap(ctx, font, gid, &subpix_trm, ctm, stroke);
}
- return fz_render_glyph_pixmap(ctx, font, gid, trm, NULL, scissor);
+ return fz_render_glyph_pixmap(ctx, font, gid, trm, scissor);
}
static unsigned do_hash(unsigned char *s, int len)
@@ -241,7 +241,7 @@ move_to_front(fz_glyph_cache *cache, fz_glyph_cache_entry *entry)
}
fz_glyph *
-fz_render_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix *ctm, fz_colorspace *model, const fz_irect *scissor)
+fz_render_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix *ctm, fz_colorspace *model, const fz_irect *scissor, int alpha)
{
fz_glyph_cache *cache;
fz_glyph_key key;
@@ -407,7 +407,7 @@ unlock_and_return_val:
}
fz_pixmap *
-fz_render_glyph_pixmap(fz_context *ctx, fz_font *font, int gid, fz_matrix *ctm, fz_colorspace *model, const fz_irect *scissor)
+fz_render_glyph_pixmap(fz_context *ctx, fz_font *font, int gid, fz_matrix *ctm, const fz_irect *scissor)
{
fz_pixmap *val;
unsigned char qe, qf;
@@ -432,7 +432,7 @@ fz_render_glyph_pixmap(fz_context *ctx, fz_font *font, int gid, fz_matrix *ctm,
}
else if (font->t3procs)
{
- val = fz_render_t3_glyph_pixmap(ctx, font, gid, &subpix_ctm, model, scissor);
+ val = fz_render_t3_glyph_pixmap(ctx, font, gid, &subpix_ctm, NULL, scissor);
}
else
{
diff --git a/source/fitz/draw-imp.h b/source/fitz/draw-imp.h
index 18580585..0eef8156 100644
--- a/source/fitz/draw-imp.h
+++ b/source/fitz/draw-imp.h
@@ -29,11 +29,10 @@ fz_irect *fz_bound_path_accurate(fz_context *ctx, fz_irect *bbox, const fz_irect
* Plotting functions.
*/
-void fz_paint_solid_alpha(unsigned char * restrict dp, int w, int alpha);
-void fz_paint_solid_color(unsigned char * restrict dp, int n, int w, unsigned char *color);
+void fz_paint_solid_color(unsigned char * restrict dp, int n, int w, unsigned char *color, int da);
-void fz_paint_span(unsigned char * restrict dp, unsigned char * restrict sp, int n, int w, int alpha);
-void fz_paint_span_with_color(unsigned char * restrict dp, unsigned char * restrict mp, int n, int w, unsigned char *color);
+void fz_paint_span(unsigned char * restrict dp, int da, unsigned char * restrict sp, int sa, int n, int w, int alpha);
+void fz_paint_span_with_color(unsigned char * restrict dp, unsigned char * restrict mp, int n, int w, unsigned char *color, int da);
void fz_paint_image(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz_pixmap *img, const fz_matrix *ctm, int alpha, int lerp_allowed, int gridfit_as_tiled);
void fz_paint_image_with_color(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz_pixmap *img, const fz_matrix *ctm, unsigned char *colorbv, int lerp_allowed, int gridfit_as_tiled);
diff --git a/source/fitz/draw-mesh.c b/source/fitz/draw-mesh.c
index 00483f51..c4e54643 100644
--- a/source/fitz/draw-mesh.c
+++ b/source/fitz/draw-mesh.c
@@ -9,7 +9,7 @@ static void paint_scan(fz_pixmap *restrict pix, int y, int fx0, int fx1, int cx0
int c[MAXN], dc[MAXN];
int k, w;
float div, mul;
- int x0, x1;
+ int x0, x1, pa;
/* Ensure that fx0 is left edge, and fx1 is right */
if (fx0 > fx1)
@@ -41,7 +41,8 @@ static void paint_scan(fz_pixmap *restrict pix, int y, int fx0, int fx1, int cx0
c[k] = v0[k] + dc[k] * mul;
}
- p = pix->samples + ((x0 - pix->x) + (y - pix->y) * pix->w) * pix->n;
+ p = pix->samples + ((x0 - pix->x) * pix->n) + ((y - pix->y) * pix->stride);
+ pa = pix->alpha;
while (w--)
{
for (k = 0; k < n; k++)
@@ -49,7 +50,8 @@ static void paint_scan(fz_pixmap *restrict pix, int y, int fx0, int fx1, int cx0
*p++ = c[k]>>16;
c[k] += dc[k];
}
- *p++ = 255;
+ if (pa)
+ *p++ = 255;
}
}
@@ -205,7 +207,7 @@ fz_paint_shade(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_pixmap
fz_pixmap *conv = NULL;
float color[FZ_MAX_COLORS];
struct paint_tri_data ptd = { 0 };
- int i, k;
+ int i, k, n;
fz_matrix local_ctm;
fz_var(temp);
@@ -218,16 +220,19 @@ fz_paint_shade(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_pixmap
if (shade->use_function)
{
fz_color_converter cc;
+ n = dest->colorspace ? dest->colorspace->n : 0;
fz_lookup_color_converter(ctx, &cc, dest->colorspace, shade->colorspace);
for (i = 0; i < 256; i++)
{
cc.convert(ctx, &cc, color, shade->function[i]);
- for (k = 0; k < dest->colorspace->n; k++)
+ for (k = 0; k < n; k++)
clut[i][k] = color[k] * 255;
clut[i][k] = shade->function[i][shade->colorspace->n] * 255;
}
- conv = fz_new_pixmap_with_bbox(ctx, dest->colorspace, bbox);
- temp = fz_new_pixmap_with_bbox(ctx, fz_device_gray(ctx), bbox);
+ /* We need to use alpha = 1 here, because the shade might not fill
+ * the bbox. */
+ conv = fz_new_pixmap_with_bbox(ctx, dest->colorspace, bbox, 1);
+ temp = fz_new_pixmap_with_bbox(ctx, fz_device_gray(ctx), bbox, 1);
fz_clear_pixmap(ctx, temp);
}
else
@@ -246,14 +251,25 @@ fz_paint_shade(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_pixmap
{
unsigned char *s = temp->samples;
unsigned char *d = conv->samples;
- int len = temp->w * temp->h;
- while (len--)
+ int da = conv->alpha;
+ int sa = temp->alpha;
+ int hh = temp->h;
+ while (hh--)
{
- int v = *s++;
- int a = fz_mul255(*s++, clut[v][conv->n - 1]);
- for (k = 0; k < conv->n - 1; k++)
- *d++ = fz_mul255(clut[v][k], a);
- *d++ = a;
+ int len = temp->w;
+ while (len--)
+ {
+ int v = *s++;
+ int a = (da ? clut[v][conv->n - 1] : 255);
+ if (sa)
+ a = fz_mul255(*s++, a);
+ for (k = 0; k < conv->n - da; k++)
+ *d++ = fz_mul255(clut[v][k], a);
+ if (da)
+ *d++ = a;
+ }
+ d += conv->stride - conv->w * conv->n;
+ s += temp->stride - temp->w * temp->n;
}
fz_paint_pixmap(dest, conv, 255);
fz_drop_pixmap(ctx, conv);
diff --git a/source/fitz/draw-paint.c b/source/fitz/draw-paint.c
index acd4c0cb..17f50724 100644
--- a/source/fitz/draw-paint.c
+++ b/source/fitz/draw-paint.c
@@ -75,19 +75,8 @@ typedef unsigned char byte;
/* These are used by the non-aa scan converter */
-void
-fz_paint_solid_alpha(byte * restrict dp, int w, int alpha)
-{
- int t = FZ_EXPAND(255 - alpha);
- while (w--)
- {
- *dp = alpha + FZ_COMBINE(*dp, t);
- dp ++;
- }
-}
-
static inline void
-fz_paint_solid_color_2(byte * restrict dp, int w, byte *color)
+fz_paint_solid_color_2_da(byte * restrict dp, int w, byte *color)
{
int sa = FZ_EXPAND(color[1]);
if (sa == 0)
@@ -119,7 +108,7 @@ static inline int isbigendian(void)
}
static inline void
-fz_paint_solid_color_4(byte * restrict dp, int w, byte *color)
+fz_paint_solid_color_4_da(byte * restrict dp, int w, byte *color)
{
unsigned int rgba = *(int *)color;
int sa = FZ_EXPAND(color[3]);
@@ -158,7 +147,7 @@ fz_paint_solid_color_4(byte * restrict dp, int w, byte *color)
}
static inline void
-fz_paint_solid_color_5(byte * restrict dp, int w, byte *color)
+fz_paint_solid_color_5_da(byte * restrict dp, int w, byte *color)
{
int sa = FZ_EXPAND(color[4]);
if (sa == 0)
@@ -236,10 +225,10 @@ fz_paint_solid_color_5(byte * restrict dp, int w, byte *color)
}
static inline void
-fz_paint_solid_color_N(byte * restrict dp, int n, int w, byte *color)
+fz_paint_solid_color_N(byte * restrict dp, int n, int w, byte *color, int da)
{
int k;
- int n1 = n - 1;
+ int n1 = n - da;
int sa = FZ_EXPAND(color[n1]);
if (sa == 0)
return;
@@ -249,7 +238,8 @@ fz_paint_solid_color_N(byte * restrict dp, int n, int w, byte *color)
{
for (k = 0; k < n1; k++)
dp[k] = color[k];
- dp[k] = 255;
+ if (da)
+ dp[k] = 255;
dp += n;
}
}
@@ -259,28 +249,42 @@ fz_paint_solid_color_N(byte * restrict dp, int n, int w, byte *color)
{
for (k = 0; k < n1; k++)
dp[k] = FZ_BLEND(color[k], dp[k], sa);
- dp[k] = FZ_BLEND(255, dp[k], sa);
+ if (da)
+ dp[k] = FZ_BLEND(255, dp[k], sa);
dp += n;
}
}
}
void
-fz_paint_solid_color(byte * restrict dp, int n, int w, byte *color)
+fz_paint_solid_color(byte * restrict dp, int n, int w, byte *color, int da)
{
- switch (n)
+ if (da)
{
- case 2: fz_paint_solid_color_2(dp, w, color); break;
- case 4: fz_paint_solid_color_4(dp, w, color); break;
- case 5: fz_paint_solid_color_5(dp, w, color); break;
- default: fz_paint_solid_color_N(dp, n, w, color); break;
+ switch (n)
+ {
+ case 2: fz_paint_solid_color_2_da(dp, w, color); break;
+ case 4: fz_paint_solid_color_4_da(dp, w, color); break;
+ case 5: fz_paint_solid_color_5_da(dp, w, color); break;
+ default: fz_paint_solid_color_N(dp, n, w, color, 1); break;
+ }
+ }
+ else
+ {
+ switch (n)
+ {
+ case 1: fz_paint_solid_color_N(dp, 1, w, color, 0); break;
+ case 3: fz_paint_solid_color_N(dp, 3, w, color, 0); break;
+ case 4: fz_paint_solid_color_N(dp, 4, w, color, 0); break;
+ default: fz_paint_solid_color_N(dp, n, w, color, 0); break;
+ }
}
}
/* Blend a non-premultiplied color in mask over destination */
static inline void
-fz_paint_span_with_color_2(byte * restrict dp, byte * restrict mp, int w, byte *color)
+fz_paint_span_with_color_2_da(byte * restrict dp, byte * restrict mp, int w, byte *color)
{
int sa = FZ_EXPAND(color[1]);
int g = color[0];
@@ -327,7 +331,7 @@ fz_paint_span_with_color_2(byte * restrict dp, byte * restrict mp, int w, byte *
}
static inline void
-fz_paint_span_with_color_4(byte * restrict dp, byte * restrict mp, int w, byte *color)
+fz_paint_span_with_color_4_da(byte * restrict dp, byte * restrict mp, int w, byte *color)
{
unsigned int rgba = *((unsigned int *)color);
unsigned int mask, rb, ga;
@@ -391,7 +395,7 @@ fz_paint_span_with_color_4(byte * restrict dp, byte * restrict mp, int w, byte *
}
static inline void
-fz_paint_span_with_color_5(byte * restrict dp, byte * restrict mp, int w, byte *color)
+fz_paint_span_with_color_5_da(byte * restrict dp, byte * restrict mp, int w, byte *color)
{
int sa = FZ_EXPAND(color[4]);
int c = color[0];
@@ -450,10 +454,10 @@ fz_paint_span_with_color_5(byte * restrict dp, byte * restrict mp, int w, byte *
}
static inline void
-fz_paint_span_with_color_N(byte * restrict dp, byte * restrict mp, int n, int w, byte *color)
+fz_paint_span_with_color_N(byte * restrict dp, byte * restrict mp, int n, int w, byte *color, int da)
{
int k;
- int n1 = n - 1;
+ int n1 = n - da;
int sa = FZ_EXPAND(color[n1]);
if (sa == 0)
return;
@@ -470,13 +474,15 @@ fz_paint_span_with_color_N(byte * restrict dp, byte * restrict mp, int n, int w,
{
for (k = 0; k < n1; k++)
dp[k] = color[k];
- dp[k] = 255;
+ if (da)
+ dp[k] = 255;
}
else
{
for (k = 0; k < n1; k++)
dp[k] = FZ_BLEND(color[k], dp[k], ma);
- dp[k] = FZ_BLEND(255, dp[k], ma);
+ if (da)
+ dp[k] = FZ_BLEND(255, dp[k], ma);
}
dp += n;
}
@@ -489,21 +495,35 @@ fz_paint_span_with_color_N(byte * restrict dp, byte * restrict mp, int n, int w,
ma = FZ_COMBINE(FZ_EXPAND(ma), sa);
for (k = 0; k < n1; k++)
dp[k] = FZ_BLEND(color[k], dp[k], ma);
- dp[k] = FZ_BLEND(255, dp[k], ma);
+ if (da)
+ dp[k] = FZ_BLEND(255, dp[k], ma);
dp += n;
}
}
}
void
-fz_paint_span_with_color(byte * restrict dp, byte * restrict mp, int n, int w, byte *color)
+fz_paint_span_with_color(byte * restrict dp, byte * restrict mp, int n, int w, byte *color, int da)
{
- switch (n)
+ if (da)
+ {
+ switch (n)
+ {
+ case 2: fz_paint_span_with_color_2_da(dp, mp, w, color); break;
+ case 4: fz_paint_span_with_color_4_da(dp, mp, w, color); break;
+ case 5: fz_paint_span_with_color_5_da(dp, mp, w, color); break;
+ default: fz_paint_span_with_color_N(dp, mp, n, w, color, 1); break;
+ }
+ }
+ else
{
- case 2: fz_paint_span_with_color_2(dp, mp, w, color); break;
- case 4: fz_paint_span_with_color_4(dp, mp, w, color); break;
- case 5: fz_paint_span_with_color_5(dp, mp, w, color); break;
- default: fz_paint_span_with_color_N(dp, mp, n, w, color); break;
+ switch (n)
+ {
+ case 1: fz_paint_span_with_color_N(dp, mp, 1, w, color, 0); break;
+ case 3: fz_paint_span_with_color_N(dp, mp, 3, w, color, 0); break;
+ case 4: fz_paint_span_with_color_N(dp, mp, 4, w, color, 0); break;
+ default: fz_paint_span_with_color_N(dp, mp, n, w, color, 0); break;
+ }
}
}
@@ -511,7 +531,7 @@ fz_paint_span_with_color(byte * restrict dp, byte * restrict mp, int n, int w, b
/* FIXME: There is potential for SWAR optimisation here */
static inline void
-fz_paint_span_with_mask_2(byte * restrict dp, byte * restrict sp, byte * restrict mp, int w)
+fz_paint_span_with_mask_1(byte * restrict dp, int da, byte * restrict sp, int sa, byte * restrict mp, int w)
{
while (w--)
{
@@ -520,42 +540,65 @@ fz_paint_span_with_mask_2(byte * restrict dp, byte * restrict sp, byte * restric
ma = FZ_EXPAND(ma);
if (ma == 0)
{
- dp += 2;
- sp += 2;
+ dp += 1 + da;
+ sp += 1 + sa;
}
else if (ma == 256)
{
- masa = 255 - sp[1];
+ masa = (sa ? 255 - sp[1] : 0);
if (masa == 0)
{
*dp++ = *sp++;
- *dp++ = *sp++;
+ if (da)
+ *dp++ = (sa ? *sp++ : 255);
}
else
{
masa = FZ_EXPAND(masa);
*dp = *sp + FZ_COMBINE(*dp, masa);
sp++; dp++;
- *dp = *sp + FZ_COMBINE(*dp, masa);
- sp++; dp++;
+ if (da)
+ {
+ *dp = (sa ? *sp : 255) + FZ_COMBINE(*dp, masa);
+ dp++;
+ }
+ if (sa)
+ sp++;
}
}
else
{
- masa = FZ_COMBINE(sp[1], ma);
- masa = 255 - masa;
- masa = FZ_EXPAND(masa);
- *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
- sp++; dp++;
- *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
- sp++; dp++;
+ if (sa)
+ {
+ masa = FZ_COMBINE(sp[1], ma);
+ masa = 255 - masa;
+ masa = FZ_EXPAND(masa);
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ sp++; dp++;
+ if (da)
+ {
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ dp++;
+ }
+ sp++;
+ }
+ else
+ {
+ *dp = FZ_BLEND(*sp, *dp, ma);
+ sp++; dp++;
+ if (da)
+ {
+ *dp = FZ_BLEND(255, *dp, ma);
+ dp++;
+ }
+ }
}
}
}
/* FIXME: There is potential for SWAR optimisation here */
static inline void
-fz_paint_span_with_mask_4(byte * restrict dp, byte * restrict sp, byte * restrict mp, int w)
+fz_paint_span_with_mask_3(byte * restrict dp, int da, byte * restrict sp, int sa, byte * restrict mp, int w)
{
while (w--)
{
@@ -564,16 +607,29 @@ fz_paint_span_with_mask_4(byte * restrict dp, byte * restrict sp, byte * restric
ma = FZ_EXPAND(ma);
if (ma == 0)
{
- dp += 4;
- sp += 4;
+ dp += 3 + da;
+ sp += 3 + sa;
}
else if (ma == 256)
{
- masa = 255 - sp[3];
+ masa = (sa ? 255 - sp[3] : 0);
if (masa == 0)
{
- *(int*)dp = *(int *)sp;
- sp += 4; dp += 4;
+ if (da && sa)
+ {
+ *(int*)dp = *(int *)sp;
+ sp += 4; dp += 4;
+ }
+ else
+ {
+ *dp++ = *sp++;
+ *dp++ = *sp++;
+ *dp++ = *sp++;
+ if (da)
+ *dp++ = (sa ? *sp : 255);
+ if (sa)
+ sp++;
+ }
}
else
{
@@ -584,31 +640,57 @@ fz_paint_span_with_mask_4(byte * restrict dp, byte * restrict sp, byte * restric
sp++; dp++;
*dp = *sp + FZ_COMBINE(*dp, masa);
sp++; dp++;
- *dp = *sp + FZ_COMBINE(*dp, masa);
- sp++; dp++;
+ if (da)
+ {
+ *dp = (sa ? *sp : 255) + FZ_COMBINE(*dp, masa);
+ dp++;
+ }
+ if (sa)
+ sp++;
}
}
else
{
/* FIXME: There is potential for SWAR optimisation here */
- masa = FZ_COMBINE(sp[3], ma);
- masa = 255 - masa;
- masa = FZ_EXPAND(masa);
- *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
- sp++; dp++;
- *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
- sp++; dp++;
- *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
- sp++; dp++;
- *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
- sp++; dp++;
+ if (sa)
+ {
+ masa = FZ_COMBINE(sp[3], ma);
+ masa = 255 - masa;
+ masa = FZ_EXPAND(masa);
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ sp++; dp++;
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ sp++; dp++;
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ sp++; dp++;
+ if (da)
+ {
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ dp++;
+ }
+ sp++;
+ }
+ else
+ {
+ *dp = FZ_BLEND(*sp, *dp, ma);
+ sp++; dp++;
+ *dp = FZ_BLEND(*sp, *dp, ma);
+ sp++; dp++;
+ *dp = FZ_BLEND(*sp, *dp, ma);
+ sp++; dp++;
+ if (da)
+ {
+ *dp = FZ_BLEND(255, *dp, ma);
+ dp++;
+ }
+ }
}
}
}
/* FIXME: There is potential for SWAR optimisation here */
static inline void
-fz_paint_span_with_mask_5(byte * restrict dp, byte * restrict sp, byte * restrict mp, int w)
+fz_paint_span_with_mask_4(byte * restrict dp, int da, byte * restrict sp, int sa, byte * restrict mp, int w)
{
while (w--)
{
@@ -617,19 +699,22 @@ fz_paint_span_with_mask_5(byte * restrict dp, byte * restrict sp, byte * restric
ma = FZ_EXPAND(ma);
if (ma == 0)
{
- dp += 5;
- sp += 5;
+ dp += 4 + da;
+ sp += 4 + sa;
}
else if (ma == 256)
{
- masa = 255 - sp[4];
+ masa = (sa ? 255 - sp[4] : 0);
if (masa == 0)
{
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
- *dp++ = *sp++;
+ if (da)
+ *dp++ = (sa ? *sp : 255);
+ if (sa)
+ sp++;
}
else
{
@@ -642,31 +727,59 @@ fz_paint_span_with_mask_5(byte * restrict dp, byte * restrict sp, byte * restric
sp++; dp++;
*dp = *sp + FZ_COMBINE(*dp, masa);
sp++; dp++;
- *dp = *sp + FZ_COMBINE(*dp, masa);
- sp++; dp++;
+ if (da)
+ {
+ *dp = (sa ? *sp : 255) + FZ_COMBINE(*dp, masa);
+ dp++;
+ }
+ if (sa)
+ sp++;
}
}
else
{
- masa = FZ_COMBINE(sp[4], ma);
- masa = 255 - masa;
- masa = FZ_EXPAND(masa);
- *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
- sp++; dp++;
- *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
- sp++; dp++;
- *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
- sp++; dp++;
- *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
- sp++; dp++;
- *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
- sp++; dp++;
+ if (sa)
+ {
+ masa = FZ_COMBINE(sp[4], ma);
+ masa = 255 - masa;
+ masa = FZ_EXPAND(masa);
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ sp++; dp++;
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ sp++; dp++;
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ sp++; dp++;
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ sp++; dp++;
+ if (da)
+ {
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ dp++;
+ }
+ sp++;
+ }
+ else
+ {
+ *dp = FZ_BLEND(*sp, *dp, ma);
+ sp++; dp++;
+ *dp = FZ_BLEND(*sp, *dp, ma);
+ sp++; dp++;
+ *dp = FZ_BLEND(*sp, *dp, ma);
+ sp++; dp++;
+ *dp = FZ_BLEND(*sp, *dp, ma);
+ sp++; dp++;
+ if (da)
+ {
+ *dp = FZ_BLEND(255, *dp, ma);
+ dp++;
+ }
+ }
}
}
}
static inline void
-fz_paint_span_with_mask_N(byte * restrict dp, byte * restrict sp, byte * restrict mp, int n, int w)
+fz_paint_span_with_mask_N(byte * restrict dp, int da, byte * restrict sp, int sa, byte * restrict mp, int n, int w)
{
while (w--)
{
@@ -674,19 +787,23 @@ fz_paint_span_with_mask_N(byte * restrict dp, byte * restrict sp, byte * restric
ma = FZ_EXPAND(ma);
if (ma == 0)
{
- dp += n;
- sp += n;
+ dp += n + da;
+ sp += n + sa;
}
else if (ma == 256)
{
int k = n;
- int masa = 255 - sp[n-1];
+ int masa = (sa ? 255 - sp[n] : 0);
if (masa == 0)
{
while (k--)
{
*dp++ = *sp++;
}
+ if (da)
+ *dp++ = (sa ? *sp : 255);
+ if (sa)
+ sp++;
}
else
{
@@ -696,78 +813,158 @@ fz_paint_span_with_mask_N(byte * restrict dp, byte * restrict sp, byte * restric
*dp = *sp + FZ_COMBINE(*dp, masa);
sp++; dp++;
}
+ if (da)
+ {
+ *dp = (sa ? *sp : 255) + FZ_COMBINE(*dp, masa);
+ dp++;
+ }
+ if (sa)
+ sp++;
}
}
else
{
int k = n;
- int masa = FZ_COMBINE(sp[n-1], ma);
- masa = 255-masa;
- masa = FZ_EXPAND(masa);
- while (k--)
+ if (sa)
{
- *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
- sp++; dp++;
+ int masa;
+ masa = FZ_COMBINE(sp[n], ma);
+ masa = 255-masa;
+ masa = FZ_EXPAND(masa);
+ while (k--)
+ {
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ sp++; dp++;
+ }
+ if (da)
+ {
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ dp++;
+ }
+ sp++;
+ }
+ else
+ {
+ while (k--)
+ {
+ *dp = FZ_BLEND(*sp, *dp, ma);
+ sp++; dp++;
+ }
+ if (da)
+ {
+ *dp = FZ_BLEND(255, *dp, ma);
+ dp++;
+ }
}
}
}
}
static void
-fz_paint_span_with_mask(byte * restrict dp, byte * restrict sp, byte * restrict mp, int n, int w)
+fz_paint_span_with_mask(byte * restrict dp, int da, byte * restrict sp, int sa, byte * restrict mp, int n, int w)
{
- switch (n)
+ if (da)
+ {
+ if (sa)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_span_with_mask_1(dp, 1, sp, 1, mp, w); break;
+ case 3: fz_paint_span_with_mask_3(dp, 1, sp, 1, mp, w); break;
+ case 4: fz_paint_span_with_mask_4(dp, 1, sp, 1, mp, w); break;
+ default: fz_paint_span_with_mask_N(dp, 1, sp, 1, mp, n, w); break;
+ }
+ }
+ else
+ {
+ switch (n)
+ {
+ case 1: fz_paint_span_with_mask_1(dp, 1, sp, 0, mp, w); break;
+ case 3: fz_paint_span_with_mask_3(dp, 1, sp, 0, mp, w); break;
+ case 4: fz_paint_span_with_mask_4(dp, 1, sp, 0, mp, w); break;
+ default: fz_paint_span_with_mask_N(dp, 1, sp, 0, mp, n, w); break;
+ }
+ }
+ }
+ else
{
- case 2: fz_paint_span_with_mask_2(dp, sp, mp, w); break;
- case 4: fz_paint_span_with_mask_4(dp, sp, mp, w); break;
- case 5: fz_paint_span_with_mask_5(dp, sp, mp, w); break;
- default: fz_paint_span_with_mask_N(dp, sp, mp, n, w); break;
+ if (sa)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_span_with_mask_1(dp, 0, sp, 1, mp, w); break;
+ case 3: fz_paint_span_with_mask_3(dp, 0, sp, 1, mp, w); break;
+ case 4: fz_paint_span_with_mask_4(dp, 0, sp, 1, mp, w); break;
+ default: fz_paint_span_with_mask_N(dp, 0, sp, 1, mp, n, w); break;
+ }
+ }
+ else
+ {
+ switch (n)
+ {
+ case 1: fz_paint_span_with_mask_1(dp, 0, sp, 0, mp, w); break;
+ case 3: fz_paint_span_with_mask_3(dp, 0, sp, 0, mp, w); break;
+ case 4: fz_paint_span_with_mask_4(dp, 0, sp, 0, mp, w); break;
+ default: fz_paint_span_with_mask_N(dp, 0, sp, 0, mp, n, w); break;
+ }
+ }
}
}
/* Blend source in constant alpha over destination */
static inline void
-fz_paint_span_2_with_alpha(byte * restrict dp, byte * restrict sp, int w, int alpha)
+fz_paint_span_1_with_alpha(byte * restrict dp, int da, byte * restrict sp, int sa, int w, int alpha)
{
- alpha = FZ_EXPAND(alpha);
+ if (sa)
+ alpha = FZ_EXPAND(alpha);
while (w--)
{
- int masa = FZ_COMBINE(sp[1], alpha);
- *dp = FZ_BLEND(*sp, *dp, masa);
- dp++; sp++;
+ int masa = (sa ? FZ_COMBINE(sp[1], alpha) : alpha);
*dp = FZ_BLEND(*sp, *dp, masa);
dp++; sp++;
+ if (da)
+ {
+ *dp = FZ_BLEND((sa ? *sp : 255), *dp, masa);
+ dp++;
+ }
+ if (sa)
+ sp++;
}
}
static inline void
-fz_paint_span_4_with_alpha(byte * restrict dp, byte * restrict sp, int w, int alpha)
+fz_paint_span_3_with_alpha(byte * restrict dp, int da, byte * restrict sp, int sa, int w, int alpha)
{
- alpha = FZ_EXPAND(alpha);
+ if (sa)
+ alpha = FZ_EXPAND(alpha);
while (w--)
{
- int masa = FZ_COMBINE(sp[3], alpha);
- *dp = FZ_BLEND(*sp, *dp, masa);
- sp++; dp++;
+ int masa = (sa ? FZ_COMBINE(sp[3], alpha) : alpha);
*dp = FZ_BLEND(*sp, *dp, masa);
sp++; dp++;
*dp = FZ_BLEND(*sp, *dp, masa);
sp++; dp++;
*dp = FZ_BLEND(*sp, *dp, masa);
sp++; dp++;
+ if (da)
+ {
+ *dp = FZ_BLEND((sa ? *sp : 255), *dp, masa);
+ dp++;
+ }
+ if (sa)
+ sp++;
}
}
static inline void
-fz_paint_span_5_with_alpha(byte * restrict dp, byte * restrict sp, int w, int alpha)
+fz_paint_span_4_with_alpha(byte * restrict dp, int da, byte * restrict sp, int sa, int w, int alpha)
{
- alpha = FZ_EXPAND(alpha);
+ if (sa)
+ alpha = FZ_EXPAND(alpha);
while (w--)
{
- int masa = FZ_COMBINE(sp[4], alpha);
- *dp = FZ_BLEND(*sp, *dp, masa);
- sp++; dp++;
+ int masa = (sa ? FZ_COMBINE(sp[4], alpha) : alpha);
*dp = FZ_BLEND(*sp, *dp, masa);
sp++; dp++;
*dp = FZ_BLEND(*sp, *dp, masa);
@@ -776,29 +973,44 @@ fz_paint_span_5_with_alpha(byte * restrict dp, byte * restrict sp, int w, int al
sp++; dp++;
*dp = FZ_BLEND(*sp, *dp, masa);
sp++; dp++;
+ if (da)
+ {
+ *dp = FZ_BLEND((sa ? *sp : 255), *dp, masa);
+ dp++;
+ }
+ if (sa)
+ sp++;
}
}
static inline void
-fz_paint_span_N_with_alpha(byte * restrict dp, byte * restrict sp, int n, int w, int alpha)
+fz_paint_span_N_with_alpha(byte * restrict dp, int da, byte * restrict sp, int sa, int n1, int w, int alpha)
{
- alpha = FZ_EXPAND(alpha);
+ if (sa)
+ alpha = FZ_EXPAND(alpha);
while (w--)
{
- int masa = FZ_COMBINE(sp[n-1], alpha);
- int k = n;
+ int masa = (sa ? FZ_COMBINE(sp[n1], alpha) : alpha);
+ int k = n1;
while (k--)
{
*dp = FZ_BLEND(*sp++, *dp, masa);
dp++;
}
+ if (da)
+ {
+ *dp = FZ_BLEND((sa ? *sp : 255), *dp, masa);
+ dp++;
+ }
+ if (sa)
+ sp++;
}
}
/* Blend source over destination */
static inline void
-fz_paint_span_1(byte * restrict dp, byte * restrict sp, int w)
+fz_paint_span_1_dasa(byte * restrict dp, byte * restrict sp, int w)
{
while (w--)
{
@@ -809,14 +1021,14 @@ fz_paint_span_1(byte * restrict dp, byte * restrict sp, int w)
}
static inline void
-fz_paint_span_2(byte * restrict dp, byte * restrict sp, int w)
+fz_paint_span_1(byte * restrict dp, int da, byte * restrict sp, int sa, int w)
{
while (w--)
{
- int t = FZ_EXPAND(sp[1]);
+ int t = (sa ? FZ_EXPAND(sp[1]): 256);
if (t == 0)
{
- dp += 2; sp += 2;
+ dp += 1 + da; sp += 1 + sa;
}
else
{
@@ -824,36 +1036,53 @@ fz_paint_span_2(byte * restrict dp, byte * restrict sp, int w)
if (t == 0)
{
*dp++ = *sp++;
- *dp++ = *sp++;
+ if (da)
+ *dp++ = (sa ? *sp : 255);
+ if (sa)
+ sp++;
}
else
{
*dp = *sp++ + FZ_COMBINE(*dp, t);
dp++;
- *dp = *sp++ + FZ_COMBINE(*dp, t);
- dp++;
+ if (da)
+ {
+ *dp = (sa ? *sp + FZ_COMBINE(*dp, t) : 255);
+ dp++;
+ }
+ if (sa)
+ sp++;
}
}
}
}
static inline void
-fz_paint_span_4(byte * restrict dp, byte * restrict sp, int w)
+fz_paint_span_3(byte * restrict dp, int da, byte * restrict sp, int sa, int w)
{
while (w--)
{
- int t = FZ_EXPAND(sp[3]);
+ int t = (sa ? FZ_EXPAND(sp[3]) : 256);
if (t == 0)
{
- dp += 4; sp += 4;
+ dp += 3 + da; sp += 3 + sa;
}
else
{
t = 256 - t;
if (t == 0)
{
- *(int *)dp = *(int *)sp;
- dp += 4; sp += 4;
+ if (da && sa)
+ *(int *)dp = *(int *)sp;
+ else
+ {
+ dp[0] = sp[0];
+ dp[1] = sp[1];
+ dp[2] = sp[2];
+ if (da)
+ dp[3] = (sa ? sp[3] : 255);
+ }
+ dp += 3+da; sp += 3+sa;
}
else
{
@@ -863,22 +1092,27 @@ fz_paint_span_4(byte * restrict dp, byte * restrict sp, int w)
dp++;
*dp = *sp++ + FZ_COMBINE(*dp, t);
dp++;
- *dp = *sp++ + FZ_COMBINE(*dp, t);
- dp++;
+ if (da)
+ {
+ *dp = (sa ? *sp + FZ_COMBINE(*dp, t) : 255);
+ dp++;
+ }
+ if (sa)
+ sp++;
}
}
}
}
static inline void
-fz_paint_span_5(byte * restrict dp, byte * restrict sp, int w)
+fz_paint_span_4(byte * restrict dp, int da, byte * restrict sp, int sa, int w)
{
while (w--)
{
- int t = FZ_EXPAND(sp[4]);
+ int t = (sa ? FZ_EXPAND(sp[4]) : 256);
if (t == 0)
{
- dp += 5; sp += 5;
+ dp += 4+da; sp += 4+sa;
}
else
{
@@ -889,8 +1123,9 @@ fz_paint_span_5(byte * restrict dp, byte * restrict sp, int w)
dp[1] = sp[1];
dp[2] = sp[2];
dp[3] = sp[3];
- dp[4] = sp[4];
- dp += 5; sp += 5;
+ if (da)
+ dp[4] = (sa ? sp[4] : 255);
+ dp += 4+da; sp += 4 + sa;
}
else
{
@@ -902,69 +1137,163 @@ fz_paint_span_5(byte * restrict dp, byte * restrict sp, int w)
dp++;
*dp = *sp++ + FZ_COMBINE(*dp, t);
dp++;
- *dp = *sp++ + FZ_COMBINE(*dp, t);
- dp++;
+ if (da)
+ {
+ *dp = (sa ? *sp + FZ_COMBINE(*dp, t) : 255);
+ dp++;
+ }
+ if (sa)
+ sp++;
}
}
}
}
static inline void
-fz_paint_span_N(byte * restrict dp, byte * restrict sp, int n, int w)
+fz_paint_span_N(byte * restrict dp, int da, byte * restrict sp, int sa, int n1, int w)
{
while (w--)
{
- int t = FZ_EXPAND(sp[n-1]);
+ int t = (sa ? FZ_EXPAND(sp[n1]) : 256);
if (t == 0)
{
- dp += n; sp += n;
+ dp += n1 + da; sp += n1 + sa;
}
else
{
t = 256 - t;
if (t == 0)
{
- int k = n;
+ int k = n1;
while (k--)
{
*dp++ = *sp++;
}
+ if (da)
+ *dp++ = (sa ? *sp : 255);
+ if (sa)
+ sp++;
}
else
{
- int k = n;
+ int k = n1;
while (k--)
{
*dp = *sp++ + FZ_COMBINE(*dp, t);
dp++;
}
+ if (da)
+ {
+ *dp = (sa ? *sp + FZ_COMBINE(*dp, t) : 255);
+ dp++;
+ }
+ if (sa)
+ sp++;
}
}
}
}
void
-fz_paint_span(byte * restrict dp, byte * restrict sp, int n, int w, int alpha)
+fz_paint_span(byte * restrict dp, int da, byte * restrict sp, int sa, int n, int w, int alpha)
{
- if (alpha == 255)
+ if (da)
{
- switch (n)
+ if (sa)
{
- case 1: fz_paint_span_1(dp, sp, w); break;
- case 2: fz_paint_span_2(dp, sp, w); break;
- case 4: fz_paint_span_4(dp, sp, w); break;
- case 5: fz_paint_span_5(dp, sp, w); break;
- default: fz_paint_span_N(dp, sp, n, w); break;
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 0: fz_paint_span_1_dasa(dp, sp, w); break;
+ case 1: fz_paint_span_1(dp, 1, sp, 1, w); break;
+ case 3: fz_paint_span_3(dp, 1, sp, 1, w); break;
+ case 4: fz_paint_span_4(dp, 1, sp, 1, w); break;
+ default: fz_paint_span_N(dp, 1, sp, 1, n, w); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_span_1_with_alpha(dp, 1, sp, 1, w, alpha); break;
+ case 3: fz_paint_span_3_with_alpha(dp, 1, sp, 1, w, alpha); break;
+ case 4: fz_paint_span_4_with_alpha(dp, 1, sp, 1, w, alpha); break;
+ default: fz_paint_span_N_with_alpha(dp, 1, sp, 1, n, w, alpha); break;
+ }
+ }
+ }
+ else
+ {
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_span_1(dp, 1, sp, 0, w); break;
+ case 3: fz_paint_span_3(dp, 1, sp, 0, w); break;
+ case 4: fz_paint_span_4(dp, 1, sp, 0, w); break;
+ default: fz_paint_span_N(dp, 1, sp, 0, n, w); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_span_1_with_alpha(dp, 1, sp, 0, w, alpha); break;
+ case 3: fz_paint_span_3_with_alpha(dp, 1, sp, 0, w, alpha); break;
+ case 4: fz_paint_span_4_with_alpha(dp, 1, sp, 0, w, alpha); break;
+ default: fz_paint_span_N_with_alpha(dp, 1, sp, 0, n, w, alpha); break;
+ }
+ }
}
}
- else if (alpha > 0)
+ else
{
- switch (n)
+ if (sa)
+ {
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_span_1(dp, 0, sp, 1, w); break;
+ case 3: fz_paint_span_3(dp, 0, sp, 1, w); break;
+ case 4: fz_paint_span_4(dp, 0, sp, 1, w); break;
+ default: fz_paint_span_N(dp, 0, sp, 1, n, w); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_span_1_with_alpha(dp, 0, sp, 1, w, alpha); break;
+ case 3: fz_paint_span_3_with_alpha(dp, 0, sp, 1, w, alpha); break;
+ case 4: fz_paint_span_4_with_alpha(dp, 0, sp, 1, w, alpha); break;
+ default: fz_paint_span_N_with_alpha(dp, 0, sp, 1, n, w, alpha); break;
+ }
+ }
+ }
+ else
{
- case 2: fz_paint_span_2_with_alpha(dp, sp, w, alpha); break;
- case 4: fz_paint_span_4_with_alpha(dp, sp, w, alpha); break;
- case 5: fz_paint_span_5_with_alpha(dp, sp, w, alpha); break;
- default: fz_paint_span_N_with_alpha(dp, sp, n, w, alpha); break;
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_span_1(dp, 0, sp, 0, w); break;
+ case 3: fz_paint_span_3(dp, 0, sp, 0, w); break;
+ case 4: fz_paint_span_4(dp, 0, sp, 0, w); break;
+ default: fz_paint_span_N(dp, 0, sp, 0, n, w); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_span_1_with_alpha(dp, 0, sp, 0, w, alpha); break;
+ case 3: fz_paint_span_3_with_alpha(dp, 0, sp, 0, w, alpha); break;
+ case 4: fz_paint_span_4_with_alpha(dp, 0, sp, 0, w, alpha); break;
+ default: fz_paint_span_N_with_alpha(dp, 0 ,sp, 0, n, w, alpha); break;
+ }
+ }
}
}
}
@@ -977,10 +1306,10 @@ void
fz_paint_pixmap_with_bbox(fz_pixmap *dst, fz_pixmap *src, int alpha, fz_irect bbox)
{
unsigned char *sp, *dp;
- int x, y, w, h, n;
+ int x, y, w, h, n, da, sa;
fz_irect bbox2;
- assert(dst->n == src->n);
+ assert(dst->n - dst->alpha == src->n - src->alpha);
fz_pixmap_bbox_no_ctx(dst, &bbox2);
fz_intersect_irect(&bbox, &bbox2);
@@ -995,14 +1324,17 @@ fz_paint_pixmap_with_bbox(fz_pixmap *dst, fz_pixmap *src, int alpha, fz_irect bb
return;
n = src->n;
- sp = src->samples + (unsigned int)(((y - src->y) * src->w + (x - src->x)) * src->n);
- dp = dst->samples + (unsigned int)(((y - dst->y) * dst->w + (x - dst->x)) * dst->n);
+ sp = src->samples + (unsigned int)((y - src->y) * src->stride + (x - src->x) * src->n);
+ sa = src->alpha;
+ dp = dst->samples + (unsigned int)((y - dst->y) * dst->stride + (x - dst->x) * dst->n);
+ da = dst->alpha;
+ n -= sa;
while (h--)
{
- fz_paint_span(dp, sp, n, w, alpha);
- sp += src->w * n;
- dp += dst->w * n;
+ fz_paint_span(dp, da, sp, sa, n, w, alpha);
+ sp += src->stride;
+ dp += dst->stride;
}
}
@@ -1012,9 +1344,9 @@ fz_paint_pixmap(fz_pixmap *dst, fz_pixmap *src, int alpha)
unsigned char *sp, *dp;
fz_irect bbox;
fz_irect bbox2;
- int x, y, w, h, n;
+ int x, y, w, h, n, da, sa;
- assert(dst->n == src->n);
+ assert(dst->n - dst->alpha == src->n - src->alpha);
fz_pixmap_bbox_no_ctx(dst, &bbox);
fz_pixmap_bbox_no_ctx(src, &bbox2);
@@ -1028,14 +1360,17 @@ fz_paint_pixmap(fz_pixmap *dst, fz_pixmap *src, int alpha)
return;
n = src->n;
- sp = src->samples + (unsigned int)(((y - src->y) * src->w + (x - src->x)) * src->n);
- dp = dst->samples + (unsigned int)(((y - dst->y) * dst->w + (x - dst->x)) * dst->n);
+ sp = src->samples + (unsigned int)((y - src->y) * src->stride + (x - src->x) * src->n);
+ sa = src->alpha;
+ dp = dst->samples + (unsigned int)((y - dst->y) * dst->stride + (x - dst->x) * dst->n);
+ da = dst->alpha;
+ n -= sa;
while (h--)
{
- fz_paint_span(dp, sp, n, w, alpha);
- sp += src->w * n;
- dp += dst->w * n;
+ fz_paint_span(dp, da, sp, sa, n, w, alpha);
+ sp += src->stride;
+ dp += dst->stride;
}
}
@@ -1044,7 +1379,7 @@ fz_paint_pixmap_with_mask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *msk)
{
unsigned char *sp, *dp, *mp;
fz_irect bbox, bbox2;
- int x, y, w, h, n;
+ int x, y, w, h, n, sa, da;
assert(dst->n == src->n);
assert(msk->n == 1);
@@ -1063,21 +1398,24 @@ fz_paint_pixmap_with_mask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *msk)
return;
n = src->n;
- sp = src->samples + (unsigned int)(((y - src->y) * src->w + (x - src->x)) * src->n);
- mp = msk->samples + (unsigned int)(((y - msk->y) * msk->w + (x - msk->x)) * msk->n);
- dp = dst->samples + (unsigned int)(((y - dst->y) * dst->w + (x - dst->x)) * dst->n);
+ sp = src->samples + (unsigned int)((y - src->y) * src->stride + (x - src->x) * src->n);
+ sa = src->alpha;
+ mp = msk->samples + (unsigned int)((y - msk->y) * msk->stride + (x - msk->x) * msk->n);
+ dp = dst->samples + (unsigned int)((y - dst->y) * dst->stride + (x - dst->x) * dst->n);
+ da = dst->alpha;
+ n -= sa;
while (h--)
{
- fz_paint_span_with_mask(dp, sp, mp, n, w);
- sp += src->w * n;
- dp += dst->w * n;
- mp += msk->w;
+ fz_paint_span_with_mask(dp, da, sp, sa, mp, n, w);
+ sp += src->stride;
+ dp += dst->stride;
+ mp += msk->stride;
}
}
static inline void
-fz_paint_glyph_mask(int span, unsigned char *dp, fz_glyph *glyph, int w, int h, int skip_x, int skip_y)
+fz_paint_glyph_mask(int span, unsigned char *dp, int da, fz_glyph *glyph, int w, int h, int skip_x, int skip_y)
{
while (h--)
{
@@ -1205,82 +1543,163 @@ intermediate_run:
}
}
-#define N 2
+#define DA
+#define N 1
#include "paint-glyph.h"
+#define DA
+#define N 3
+#include "paint-glyph.h"
+
+#define DA
#define N 4
#include "paint-glyph.h"
-#define N 5
+#define DA
#include "paint-glyph.h"
+#define DA
+#define ALPHA
+#define N 1
#include "paint-glyph.h"
+#define DA
#define ALPHA
-#define N 2
+#define N 3
#include "paint-glyph.h"
+#define DA
#define ALPHA
#define N 4
#include "paint-glyph.h"
+#define DA
#define ALPHA
-#define N 5
+#include "paint-glyph.h"
+
+#define N 1
+#include "paint-glyph.h"
+
+#define N 3
+#include "paint-glyph.h"
+
+#define N 4
+#include "paint-glyph.h"
+
+#include "paint-glyph.h"
+
+#define ALPHA
+#define N 1
+#include "paint-glyph.h"
+
+#define ALPHA
+#define N 3
+#include "paint-glyph.h"
+
+#define ALPHA
+#define N 4
#include "paint-glyph.h"
#define ALPHA
#include "paint-glyph.h"
static inline void
-fz_paint_glyph_alpha(unsigned char *colorbv, int n, int span, unsigned char *dp, fz_glyph *glyph, int w, int h, int skip_x, int skip_y)
+fz_paint_glyph_alpha(unsigned char *colorbv, int n, int span, unsigned char *dp, int da, fz_glyph *glyph, int w, int h, int skip_x, int skip_y)
{
- switch (n)
+ if (da)
{
- case 2:
- fz_paint_glyph_alpha_2(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
- break;
- case 4:
- fz_paint_glyph_alpha_4(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
- break;
- case 5:
- fz_paint_glyph_alpha_5(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
- break;
- default:
- fz_paint_glyph_alpha_N(colorbv, n, span, dp, glyph, w, h, skip_x, skip_y);
- break;
+ switch (n)
+ {
+ case 1:
+ fz_paint_glyph_alpha_1_da(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ case 3:
+ fz_paint_glyph_alpha_3_da(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ case 4:
+ fz_paint_glyph_alpha_4_da(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ default:
+ fz_paint_glyph_alpha_N_da(colorbv, n, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ }
+ }
+ else
+ {
+ switch (n)
+ {
+ case 1:
+ fz_paint_glyph_alpha_1(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ case 3:
+ fz_paint_glyph_alpha_3(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ case 4:
+ fz_paint_glyph_alpha_4(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ default:
+ fz_paint_glyph_alpha_N(colorbv, n, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ }
}
}
static inline void
-fz_paint_glyph_solid(unsigned char *colorbv, int n, int span, unsigned char *dp, fz_glyph *glyph, int w, int h, int skip_x, int skip_y)
+fz_paint_glyph_solid(unsigned char *colorbv, int n, int span, unsigned char *dp, int da, fz_glyph *glyph, int w, int h, int skip_x, int skip_y)
{
- switch (n)
+ if (da)
{
- case 2:
- fz_paint_glyph_solid_2(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
- break;
- case 4:
- fz_paint_glyph_solid_4(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
- break;
- case 5:
- fz_paint_glyph_solid_5(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
- break;
- default:
- fz_paint_glyph_solid_N(colorbv, n, span, dp, glyph, w, h, skip_x, skip_y);
- break;
+ switch (n)
+ {
+ case 1:
+ fz_paint_glyph_solid_1_da(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ case 3:
+ fz_paint_glyph_solid_3_da(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ case 4:
+ fz_paint_glyph_solid_4_da(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ default:
+ fz_paint_glyph_solid_N_da(colorbv, n, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ }
+ }
+ else
+ {
+ switch (n)
+ {
+ case 1:
+ fz_paint_glyph_solid_1(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ case 3:
+ fz_paint_glyph_solid_3(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ case 4:
+ fz_paint_glyph_solid_4(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ default:
+ fz_paint_glyph_solid_N(colorbv, n, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ }
}
}
void
fz_paint_glyph(unsigned char *colorbv, fz_pixmap *dst, unsigned char *dp, fz_glyph *glyph, int w, int h, int skip_x, int skip_y)
{
+ int n = dst->n - dst->alpha;
if (dst->colorspace)
{
- if (colorbv[dst->n-1] == 255)
- fz_paint_glyph_solid(colorbv, dst->n, dst->w * dst->n, dp, glyph, w, h, skip_x, skip_y);
- else if (colorbv[dst->n-1] != 0)
- fz_paint_glyph_alpha(colorbv, dst->n, dst->w * dst->n, dp, glyph, w, h, skip_x, skip_y);
+ assert(n > 0);
+ if (colorbv[n] == 255)
+ fz_paint_glyph_solid(colorbv, n, dst->stride, dp, dst->alpha, glyph, w, h, skip_x, skip_y);
+ else if (colorbv[n] != 0)
+ fz_paint_glyph_alpha(colorbv, n, dst->stride, dp, dst->alpha, glyph, w, h, skip_x, skip_y);
}
else
- fz_paint_glyph_mask(dst->w, dp, glyph, w, h, skip_x, skip_y);
+ {
+ assert(dst->alpha && dst->n == 1 && dst->colorspace == NULL);
+ fz_paint_glyph_mask(dst->stride, dp, dst->alpha, glyph, w, h, skip_x, skip_y);
+ }
}
diff --git a/source/fitz/draw-scale-simple.c b/source/fitz/draw-scale-simple.c
index cf9251e7..0f267743 100644
--- a/source/fitz/draw-scale-simple.c
+++ b/source/fitz/draw-scale-simple.c
@@ -1027,21 +1027,29 @@ scale_row_from_temp(unsigned char *dst, unsigned char *src, fz_weights *weights,
#ifdef SINGLE_PIXEL_SPECIALS
static void
-duplicate_single_pixel(unsigned char *dst, unsigned char *src, int n, int w, int h)
+duplicate_single_pixel(unsigned char *dst, unsigned char *src, int n, int w, int h, int stride)
{
int i;
+ w *= n;
for (i = n; i > 0; i--)
*dst++ = *src++;
- for (i = (w*h-1)*n; i > 0; i--)
+ for (i = w-n; i > 0; i--)
{
*dst = dst[-n];
dst++;
}
+ dst -= w;
+ h--;
+ while (h--)
+ {
+ memcpy(dst+stride, dst, w);
+ dst += stride;
+ }
}
static void
-scale_single_row(unsigned char *dst, unsigned char *src, fz_weights *weights, int src_w, int h)
+scale_single_row(unsigned char *dst, int dstride, unsigned char *src, fz_weights *weights, int src_w, int h)
{
int *contrib = &weights->index[weights->index[0]];
int min, len, i, j, n;
@@ -1072,7 +1080,7 @@ scale_single_row(unsigned char *dst, unsigned char *src, fz_weights *weights, in
}
dst -= 2*n;
}
- dst += n * (weights->count+1);
+ dst += n + dstride;
}
else
{
@@ -1093,18 +1101,19 @@ scale_single_row(unsigned char *dst, unsigned char *src, fz_weights *weights, in
tmp[j] = 128;
}
}
+ dst += dstride - weights->count * n;
}
/* And then duplicate it h times */
n *= weights->count;
while (--h > 0)
{
- memcpy(dst, dst-n, n);
- dst += n;
+ memcpy(dst, dst-dstride, n);
+ dst += dstride;
}
}
static void
-scale_single_col(unsigned char *dst, unsigned char *src, fz_weights *weights, int src_w, int n, int w, int flip_y)
+scale_single_col(unsigned char *dst, int dstride, unsigned char *src, int sstride, fz_weights *weights, int src_w, int n, int w, int flip_y)
{
int *contrib = &weights->index[weights->index[0]];
int min, len, i, j;
@@ -1114,18 +1123,18 @@ scale_single_col(unsigned char *dst, unsigned char *src, fz_weights *weights, in
tmp[j] = 128;
if (flip_y)
{
- src_w = (src_w-1)*n;
- w = (w-1)*n;
+ src_w = (src_w-1)*sstride;
for (i=weights->count; i > 0; i--)
{
/* Scale the next pixel in the column */
min = *contrib++;
len = *contrib++;
- min = src_w-min*n;
+ min = src_w-min*sstride;
while (len-- > 0)
{
for (j = 0; j < n; j++)
- tmp[j] += src[src_w-min+j] * *contrib;
+ tmp[j] += src[min+j] * *contrib;
+ min -= sstride;
contrib++;
}
for (j = 0; j < n; j++)
@@ -1134,26 +1143,27 @@ scale_single_col(unsigned char *dst, unsigned char *src, fz_weights *weights, in
tmp[j] = 128;
}
/* And then duplicate it across the row */
- for (j = w; j > 0; j--)
+ for (j = (w-1)*n; j > 0; j--)
{
*dst = dst[-n];
dst++;
}
+ dst += dstride - w*n;
}
}
else
{
- w = (w-1)*n;
for (i=weights->count; i > 0; i--)
{
/* Scale the next pixel in the column */
min = *contrib++;
len = *contrib++;
- min *= n;
+ min *= sstride;
while (len-- > 0)
{
for (j = 0; j < n; j++)
- tmp[j] += src[min++] * *contrib;
+ tmp[j] += src[min+j] * *contrib;
+ min += sstride;
contrib++;
}
for (j = 0; j < n; j++)
@@ -1162,11 +1172,12 @@ scale_single_col(unsigned char *dst, unsigned char *src, fz_weights *weights, in
tmp[j] = 128;
}
/* And then duplicate it across the row */
- for (j = w; j > 0; j--)
+ for (j = (w-1)*n; j > 0; j--)
{
*dst = dst[-n];
dst++;
}
+ dst += dstride - w*n;
}
}
}
@@ -1284,6 +1295,8 @@ fz_scale_pixmap_cached(fz_context *ctx, const fz_pixmap *src, float x, float y,
dst_h_int = (int)ceilf(y + h);
}
+ fz_valgrind_pixmap(src);
+
/* Step 0: Calculate the patch */
patch.x0 = 0;
patch.y0 = 0;
@@ -1352,7 +1365,7 @@ fz_scale_pixmap_cached(fz_context *ctx, const fz_pixmap *src, float x, float y,
#endif /* SINGLE_PIXEL_SPECIALS */
contrib_rows = make_weights(ctx, src->h, y, h, filter, 1, dst_h_int, patch.y0, patch.y1, src->n, flip_y, cache_y);
- output = fz_new_pixmap(ctx, src->colorspace, patch.x1 - patch.x0, patch.y1 - patch.y0);
+ output = fz_new_pixmap(ctx, src->colorspace, patch.x1 - patch.x0, patch.y1 - patch.y0, src->alpha);
}
fz_catch(ctx)
{
@@ -1373,18 +1386,21 @@ fz_scale_pixmap_cached(fz_context *ctx, const fz_pixmap *src, float x, float y,
if (!contrib_cols)
{
/* Only 1 pixel in the entire image! */
- duplicate_single_pixel(output->samples, src->samples, src->n, patch.x1-patch.x0, patch.y1-patch.y0);
+ duplicate_single_pixel(output->samples, src->samples, src->n, patch.x1-patch.x0, patch.y1-patch.y0, output->stride);
+ fz_valgrind_pixmap(output);
}
else
{
/* Scale the row once, then copy it. */
- scale_single_row(output->samples, src->samples, contrib_cols, src->w, patch.y1-patch.y0);
+ scale_single_row(output->samples, output->stride, src->samples, contrib_cols, src->w, patch.y1-patch.y0);
+ fz_valgrind_pixmap(output);
}
}
else if (!contrib_cols)
{
/* Only 1 source pixel wide. Scale the col and duplicate. */
- scale_single_col(output->samples, src->samples, contrib_rows, src->h, src->n, patch.x1-patch.x0, flip_y);
+ scale_single_col(output->samples, output->stride, src->samples, src->stride, contrib_rows, src->h, src->n, patch.x1-patch.x0, flip_y);
+ fz_valgrind_pixmap(output);
}
else
#endif /* SINGLE_PIXEL_SPECIALS */
@@ -1438,13 +1454,15 @@ fz_scale_pixmap_cached(fz_context *ctx, const fz_pixmap *src, float x, float y,
{
/* Scale another row */
assert(max_row < src->h);
- (*row_scale)(&temp[temp_span*(max_row % temp_rows)], &src->samples[(flip_y ? (src->h-1-max_row): max_row)*src->w*src->n], contrib_cols);
+ (*row_scale)(&temp[temp_span*(max_row % temp_rows)], &src->samples[(flip_y ? (src->h-1-max_row): max_row)*src->stride], contrib_cols);
max_row++;
}
- scale_row_from_temp(&output->samples[row*output->w*output->n], temp, contrib_rows, temp_span, row);
+ scale_row_from_temp(&output->samples[row*output->stride], temp, contrib_rows, temp_span, row);
}
fz_free(ctx, temp);
+
+ fz_valgrind_pixmap(output);
}
cleanup:
@@ -1452,6 +1470,7 @@ cleanup:
fz_free(ctx, contrib_rows);
if (!cache_x)
fz_free(ctx, contrib_cols);
+
return output;
}
diff --git a/source/fitz/draw-unpack.c b/source/fitz/draw-unpack.c
index d21e7303..8ac76bdc 100644
--- a/source/fitz/draw-unpack.c
+++ b/source/fitz/draw-unpack.c
@@ -72,7 +72,7 @@ fz_unpack_tile(fz_context *ctx, fz_pixmap *dst, unsigned char * restrict src, in
for (y = 0; y < dst->h; y++)
{
unsigned char *sp = src + (unsigned int)(y * stride);
- unsigned char *dp = dst->samples + (unsigned int)(y * dst->w * dst->n);
+ unsigned char *dp = dst->samples + (unsigned int)(y * dst->stride);
/* Specialized loops */
@@ -177,10 +177,12 @@ fz_decode_indexed_tile(fz_context *ctx, fz_pixmap *pix, const float *decode, int
int add[FZ_MAX_COLORS];
int mul[FZ_MAX_COLORS];
unsigned char *p = pix->samples;
- int len = pix->w * pix->h;
+ int stride = pix->stride - pix->w * pix->n;
+ int len;
int n = pix->n - 1;
int needed;
int k;
+ int h;
needed = 0;
for (k = 0; k < n; k++)
@@ -195,14 +197,20 @@ fz_decode_indexed_tile(fz_context *ctx, fz_pixmap *pix, const float *decode, int
if (!needed)
return;
- while (len--)
+ h = pix->h;
+ while (h--)
{
- for (k = 0; k < n; k++)
+ len = pix->w;
+ while (len--)
{
- int value = (add[k] + (((p[k] << 8) * mul[k]) >> 8)) >> 8;
- p[k] = fz_clampi(value, 0, 255);
+ for (k = 0; k < n; k++)
+ {
+ int value = (add[k] + (((p[k] << 8) * mul[k]) >> 8)) >> 8;
+ p[k] = fz_clampi(value, 0, 255);
+ }
+ p += n + 1;
}
- p += n + 1;
+ p += stride;
}
}
@@ -212,10 +220,12 @@ fz_decode_tile(fz_context *ctx, fz_pixmap *pix, const float *decode)
int add[FZ_MAX_COLORS];
int mul[FZ_MAX_COLORS];
unsigned char *p = pix->samples;
- int len = pix->w * pix->h;
+ int stride = pix->stride - pix->w * pix->n;
+ int len;
int n = fz_maxi(1, pix->n - 1);
int needed;
int k;
+ int h;
needed = 0;
for (k = 0; k < n; k++)
@@ -230,13 +240,19 @@ fz_decode_tile(fz_context *ctx, fz_pixmap *pix, const float *decode)
if (!needed)
return;
- while (len--)
+ h = pix->h;
+ while (h--)
{
- for (k = 0; k < n; k++)
+ len = pix->w;
+ while (len--)
{
- int value = add[k] + fz_mul255(p[k], mul[k]);
- p[k] = fz_clampi(value, 0, 255);
+ for (k = 0; k < n; k++)
+ {
+ int value = add[k] + fz_mul255(p[k], mul[k]);
+ p[k] = fz_clampi(value, 0, 255);
+ }
+ p += pix->n;
}
- p += pix->n;
+ p += stride;
}
}
diff --git a/source/fitz/font.c b/source/fitz/font.c
index e67f64dc..07476235 100644
--- a/source/fitz/font.c
+++ b/source/fitz/font.c
@@ -1241,7 +1241,8 @@ fz_render_t3_glyph_pixmap(fz_context *ctx, fz_font *font, int gid, const fz_matr
fz_irect_from_rect(&bbox, &bounds);
fz_intersect_irect(&bbox, scissor);
- glyph = fz_new_pixmap_with_bbox(ctx, model ? model : fz_device_gray(ctx), &bbox);
+ /* Glyphs must always have alpha */
+ glyph = fz_new_pixmap_with_bbox(ctx, model, &bbox, 1);
fz_clear_pixmap(ctx, glyph);
dev = fz_new_draw_device_type3(ctx, glyph);
diff --git a/source/fitz/glyph.c b/source/fitz/glyph.c
index 180b7421..b76d2f76 100644
--- a/source/fitz/glyph.c
+++ b/source/fitz/glyph.c
@@ -145,7 +145,7 @@ fz_new_glyph_from_pixmap(fz_context *ctx, fz_pixmap *pix)
glyph->pixmap = fz_keep_pixmap(ctx, pix);
}
else
- glyph = fz_new_glyph_from_8bpp_data(ctx, pix->x, pix->y, pix->w, pix->h, pix->samples, pix->w);
+ glyph = fz_new_glyph_from_8bpp_data(ctx, pix->x, pix->y, pix->w, pix->h, pix->samples, pix->stride);
}
fz_always(ctx)
{
diff --git a/source/fitz/halftone.c b/source/fitz/halftone.c
index 707084c4..60e3c182 100644
--- a/source/fitz/halftone.c
+++ b/source/fitz/halftone.c
@@ -68,7 +68,7 @@ fz_halftone *fz_default_halftone(fz_context *ctx, int num_comps)
{
int i;
for (i = 0; i < num_comps; i++)
- ht->comp[i] = fz_new_pixmap_with_data(ctx, NULL, 16, 16, mono_ht);
+ ht->comp[i] = fz_new_pixmap_with_data(ctx, NULL, 16, 16, 1, 16, mono_ht);
}
fz_catch(ctx)
{
@@ -285,21 +285,21 @@ static void do_threshold_1(const unsigned char * restrict ht_line, const unsigne
h = 0;
if (pixmap[0] < ht_line[0])
h |= 0x80;
- if (pixmap[2] < ht_line[1])
+ if (pixmap[1] < ht_line[1])
h |= 0x40;
- if (pixmap[4] < ht_line[2])
+ if (pixmap[2] < ht_line[2])
h |= 0x20;
- if (pixmap[6] < ht_line[3])
+ if (pixmap[3] < ht_line[3])
h |= 0x10;
- if (pixmap[8] < ht_line[4])
+ if (pixmap[4] < ht_line[4])
h |= 0x08;
- if (pixmap[10] < ht_line[5])
+ if (pixmap[5] < ht_line[5])
h |= 0x04;
- if (pixmap[12] < ht_line[6])
+ if (pixmap[6] < ht_line[6])
h |= 0x02;
- if (pixmap[14] < ht_line[7])
+ if (pixmap[7] < ht_line[7])
h |= 0x01;
- pixmap += 16; /* Skip the alpha */
+ pixmap += 8;
ht_line += 8;
l -= 8;
if (l == 0)
@@ -315,17 +315,17 @@ static void do_threshold_1(const unsigned char * restrict ht_line, const unsigne
h = 0;
if (pixmap[0] < ht_line[0])
h |= 0x80;
- if (w > -6 && pixmap[2] < ht_line[1])
+ if (w > -6 && pixmap[1] < ht_line[1])
h |= 0x40;
- if (w > -5 && pixmap[4] < ht_line[2])
+ if (w > -5 && pixmap[2] < ht_line[2])
h |= 0x20;
- if (w > -4 && pixmap[6] < ht_line[3])
+ if (w > -4 && pixmap[3] < ht_line[3])
h |= 0x10;
- if (w > -3 && pixmap[8] < ht_line[4])
+ if (w > -3 && pixmap[4] < ht_line[4])
h |= 0x08;
- if (w > -2 && pixmap[10] < ht_line[5])
+ if (w > -2 && pixmap[5] < ht_line[5])
h |= 0x04;
- if (w > -1 && pixmap[12] < ht_line[6])
+ if (w > -1 && pixmap[6] < ht_line[6])
h |= 0x02;
*out++ = h;
}
@@ -541,13 +541,13 @@ static void do_threshold_4(const unsigned char * restrict ht_line, const unsigne
h |= 0x20;
if (pixmap[3] >= ht_line[3])
h |= 0x10;
- if (pixmap[5] >= ht_line[4])
+ if (pixmap[4] >= ht_line[4])
h |= 0x08;
- if (pixmap[6] >= ht_line[5])
+ if (pixmap[5] >= ht_line[5])
h |= 0x04;
- if (pixmap[7] >= ht_line[6])
+ if (pixmap[6] >= ht_line[6])
h |= 0x02;
- if (pixmap[8] >= ht_line[7])
+ if (pixmap[7] >= ht_line[7])
h |= 0x01;
*out++ = h;
l -= 2;
@@ -556,7 +556,7 @@ static void do_threshold_4(const unsigned char * restrict ht_line, const unsigne
l = ht_len;
ht_line -= ht_len<<2;
}
- pixmap += 10;
+ pixmap += 8;
ht_line += 8;
w -= 2;
}
@@ -609,11 +609,13 @@ fz_bitmap *fz_new_bitmap_from_pixmap_band(fz_context *ctx, fz_pixmap *pix, fz_ha
if (!pix)
return NULL;
+ assert(pix->alpha == 0);
+
fz_var(ht_line);
fz_var(out);
band *= bandheight;
- n = pix->n-1; /* Remove alpha */
+ n = pix->n;
switch(n)
{
@@ -659,7 +661,7 @@ fz_bitmap *fz_new_bitmap_from_pixmap_band(fz_context *ctx, fz_pixmap *pix, fz_ha
y = pix->y + band;
w = pix->w;
ostride = out->stride;
- pstride = pix->w * pix->n;
+ pstride = pix->stride;
while (h--)
{
make_ht_line(ht_line, ht, x, y++, lcm);
diff --git a/source/fitz/image.c b/source/fitz/image.c
index d8fcdc20..bd6e0b62 100644
--- a/source/fitz/image.c
+++ b/source/fitz/image.c
@@ -95,18 +95,25 @@ static void
fz_mask_color_key(fz_pixmap *pix, int n, const int *colorkey)
{
unsigned char *p = pix->samples;
- int len = pix->w * pix->h;
+ int w;
int k, t;
- while (len--)
+ int h = pix->h;
+ int stride = pix->stride - pix->w * pix->n;
+ while (h--)
{
- t = 1;
- for (k = 0; k < n; k++)
- if (p[k] < colorkey[k * 2] || p[k] > colorkey[k * 2 + 1])
- t = 0;
- if (t)
- for (k = 0; k < pix->n; k++)
- p[k] = 0;
- p += pix->n;
+ w = pix->w;
+ while (w--)
+ {
+ t = 1;
+ for (k = 0; k < n; k++)
+ if (p[k] < colorkey[k * 2] || p[k] > colorkey[k * 2 + 1])
+ t = 0;
+ if (t)
+ for (k = 0; k < pix->n; k++)
+ p[k] = 0;
+ p += pix->n;
+ }
+ p += stride;
}
}
@@ -114,9 +121,13 @@ static void
fz_unblend_masked_tile(fz_context *ctx, fz_pixmap *tile, fz_image *image)
{
fz_pixmap *mask = fz_get_pixmap_from_image(ctx, image->mask, NULL, NULL, NULL, NULL);
- unsigned char *s = mask->samples, *end = s + mask->w * mask->h;
+ unsigned char *s = mask->samples;
unsigned char *d = tile->samples;
+ int n = tile->n;
int k;
+ int sstride = mask->stride - mask->w * mask->n;
+ int dstride = tile->stride - tile->w * tile->n;
+ int h = mask->h;
if (tile->w != mask->w || tile->h != mask->h)
{
@@ -125,14 +136,22 @@ fz_unblend_masked_tile(fz_context *ctx, fz_pixmap *tile, fz_image *image)
return;
}
- for (; s < end; s++, d += tile->n)
+ while (h--)
{
- if (*s == 0)
- for (k = 0; k < image->n; k++)
- d[k] = image->colorkey[k];
- else
- for (k = 0; k < image->n; k++)
- d[k] = fz_clampi(image->colorkey[k] + (d[k] - image->colorkey[k]) * 255 / *s, 0, 255);
+ int w = mask->w;
+ while (w--)
+ {
+ if (*s == 0)
+ for (k = 0; k < image->n; k++)
+ d[k] = image->colorkey[k];
+ else
+ for (k = 0; k < image->n; k++)
+ d[k] = fz_clampi(image->colorkey[k] + (d[k] - image->colorkey[k]) * 255 / *s, 0, 255);
+ s++;
+ d += n;
+ }
+ s += sstride;
+ d += dstride;
}
fz_drop_pixmap(ctx, mask);
@@ -179,7 +198,7 @@ fz_decomp_image_from_stream(fz_context *ctx, fz_stream *stm, fz_compressed_image
fz_try(ctx)
{
- tile = fz_new_pixmap(ctx, image->colorspace, w, h);
+ tile = fz_new_pixmap(ctx, image->colorspace, w, h, 1);
tile->interpolate = image->interpolate;
stride = (w * image->n * image->bpc + 7) / 8;
@@ -982,13 +1001,13 @@ display_list_image_get_pixmap(fz_context *ctx, fz_image *image_, fz_irect *subar
int r = (subarea->x1 * w + image->super.w - 1) / image->super.w;
int b = (subarea->y1 * h + image->super.h - 1) / image->super.h;
- pix = fz_new_pixmap(ctx, image->super.colorspace, r-l, b-t);
+ pix = fz_new_pixmap(ctx, image->super.colorspace, r-l, b-t, 0);
pix->x = l;
pix->y = t;
}
else
{
- pix = fz_new_pixmap(ctx, image->super.colorspace, w, h);
+ pix = fz_new_pixmap(ctx, image->super.colorspace, w, h, 0);
}
/* If we render the displaylist into pix with the image matrix, we'll get a unit
diff --git a/source/fitz/load-bmp.c b/source/fitz/load-bmp.c
index 433b9dd1..a15ec093 100644
--- a/source/fitz/load-bmp.c
+++ b/source/fitz/load-bmp.c
@@ -697,7 +697,7 @@ bmp_read_bitmap(fz_context *ctx, struct info *info, unsigned char *p, unsigned c
}
fz_try(ctx)
- pix = fz_new_pixmap(ctx, fz_device_rgb(ctx), width, height);
+ pix = fz_new_pixmap(ctx, fz_device_rgb(ctx), width, height, 1);
fz_catch(ctx)
{
fz_free(ctx, decompressed);
@@ -705,7 +705,7 @@ bmp_read_bitmap(fz_context *ctx, struct info *info, unsigned char *p, unsigned c
}
ddp = pix->samples;
- dstride = width * 4;
+ dstride = pix->stride;
if (!info->topdown)
{
ddp = pix->samples + (height - 1) * dstride;
diff --git a/source/fitz/load-gif.c b/source/fitz/load-gif.c
index 02c153f0..d31dee09 100644
--- a/source/fitz/load-gif.c
+++ b/source/fitz/load-gif.c
@@ -401,7 +401,7 @@ gif_read_image(fz_context *ctx, struct info *info, unsigned char *p, int total,
if (only_metadata)
return NULL;
- pix = fz_new_pixmap(ctx, fz_device_rgb(ctx), info->width, info->height);
+ pix = fz_new_pixmap(ctx, fz_device_rgb(ctx), info->width, info->height, 1);
fz_try(ctx)
{
diff --git a/source/fitz/load-jpeg.c b/source/fitz/load-jpeg.c
index 29db9bcf..6aac519c 100644
--- a/source/fitz/load-jpeg.c
+++ b/source/fitz/load-jpeg.c
@@ -223,7 +223,7 @@ fz_load_jpeg(fz_context *ctx, unsigned char *rbuf, int rlen)
unsigned char *row[1], *sp, *dp;
fz_colorspace *colorspace;
unsigned int x;
- int k;
+ int k, stride;
fz_pixmap *image = NULL;
fz_var(image);
@@ -266,7 +266,7 @@ fz_load_jpeg(fz_context *ctx, unsigned char *rbuf, int rlen)
else
fz_throw(ctx, FZ_ERROR_GENERIC, "bad number of components in jpeg: %d", cinfo.num_components);
- image = fz_new_pixmap(ctx, colorspace, cinfo.output_width, cinfo.output_height);
+ image = fz_new_pixmap(ctx, colorspace, cinfo.output_width, cinfo.output_height, 1);
if (extract_exif_resolution(cinfo.marker_list, &image->xres, &image->yres))
/* XPS prefers EXIF resolution to JFIF density */;
@@ -290,6 +290,7 @@ fz_load_jpeg(fz_context *ctx, unsigned char *rbuf, int rlen)
row[0] = fz_malloc(ctx, cinfo.output_components * cinfo.output_width);
dp = image->samples;
+ stride = image->stride - image->w * image->n;
while (cinfo.output_scanline < cinfo.output_height)
{
jpeg_read_scanlines(&cinfo, row, 1);
@@ -300,6 +301,7 @@ fz_load_jpeg(fz_context *ctx, unsigned char *rbuf, int rlen)
*dp++ = *sp++;
*dp++ = 255;
}
+ dp += stride;
}
}
fz_always(ctx)
diff --git a/source/fitz/load-jpx.c b/source/fitz/load-jpx.c
index 3ea7775c..6a8c36c0 100644
--- a/source/fitz/load-jpx.c
+++ b/source/fitz/load-jpx.c
@@ -83,7 +83,7 @@ fz_load_jpx(fz_context *ctx, unsigned char *data, int size, fz_colorspace *defcs
unsigned char *p;
OPJ_CODEC_FORMAT format;
int a, n, w, h, depth, sgnd;
- int x, y, k, v;
+ int x, y, k, v, stride;
stream_block sb;
if (size < 2)
@@ -204,7 +204,7 @@ fz_load_jpx(fz_context *ctx, unsigned char *data, int size, fz_colorspace *defcs
fz_try(ctx)
{
- img = fz_new_pixmap(ctx, colorspace, w, h);
+ img = fz_new_pixmap(ctx, colorspace, w, h, 1);
}
fz_catch(ctx)
{
@@ -213,6 +213,7 @@ fz_load_jpx(fz_context *ctx, unsigned char *data, int size, fz_colorspace *defcs
}
p = img->samples;
+ stride = img->stride - w * (n + 1);
for (y = 0; y < h; y++)
{
for (x = 0; x < w; x++)
@@ -231,6 +232,7 @@ fz_load_jpx(fz_context *ctx, unsigned char *data, int size, fz_colorspace *defcs
if (!a)
*p++ = 255;
}
+ p += stride;
}
opj_image_destroy(jpx);
@@ -239,7 +241,7 @@ fz_load_jpx(fz_context *ctx, unsigned char *data, int size, fz_colorspace *defcs
{
if (n == 4)
{
- fz_pixmap *tmp = fz_new_pixmap(ctx, fz_device_rgb(ctx), w, h);
+ fz_pixmap *tmp = fz_new_pixmap(ctx, fz_device_rgb(ctx), w, h, 1);
fz_convert_pixmap(ctx, tmp, img);
fz_drop_pixmap(ctx, img);
img = tmp;
diff --git a/source/fitz/load-png.c b/source/fitz/load-png.c
index 33979d4c..21e6e94e 100644
--- a/source/fitz/load-png.c
+++ b/source/fitz/load-png.c
@@ -500,10 +500,12 @@ png_read_image(fz_context *ctx, struct info *info, unsigned char *p, unsigned in
static fz_pixmap *
png_expand_palette(fz_context *ctx, struct info *info, fz_pixmap *src)
{
- fz_pixmap *dst = fz_new_pixmap(ctx, fz_device_rgb(ctx), src->w, src->h);
+ fz_pixmap *dst = fz_new_pixmap(ctx, fz_device_rgb(ctx), src->w, src->h, 1);
unsigned char *sp = src->samples;
unsigned char *dp = dst->samples;
unsigned int x, y;
+ int dstride = dst->stride - dst->w * dst->n;
+ int sstride = src->stride - src->w * src->n;
dst->xres = src->xres;
dst->yres = src->yres;
@@ -519,6 +521,8 @@ png_expand_palette(fz_context *ctx, struct info *info, fz_pixmap *src)
*dp++ = info->palette[v + 3];
sp += 2;
}
+ sp += sstride;
+ dp += dstride;
}
fz_drop_pixmap(ctx, src);
@@ -536,7 +540,7 @@ png_mask_transparency(struct info *info, fz_pixmap *dst)
for (y = 0; y < info->height; y++)
{
unsigned char *sp = info->samples + (unsigned int)(y * stride);
- unsigned char *dp = dst->samples + (unsigned int)(y * dst->w * dst->n);
+ unsigned char *dp = dst->samples + (unsigned int)(y * dst->stride);
for (x = 0; x < info->width; x++)
{
t = 1;
@@ -568,7 +572,7 @@ fz_load_png(fz_context *ctx, unsigned char *p, int total)
fz_try(ctx)
{
- image = fz_new_pixmap(ctx, colorspace, png.width, png.height);
+ image = fz_new_pixmap(ctx, colorspace, png.width, png.height, 1);
}
fz_catch(ctx)
{
diff --git a/source/fitz/load-tiff.c b/source/fitz/load-tiff.c
index 2002c61a..f7661a8d 100644
--- a/source/fitz/load-tiff.c
+++ b/source/fitz/load-tiff.c
@@ -849,7 +849,7 @@ fz_load_tiff_subimage(fz_context *ctx, unsigned char *buf, int len, int subimage
fz_swap_tiff_byte_order(tiff.samples, tiff.imagewidth * tiff.imagelength * tiff.samplesperpixel);
/* Expand into fz_pixmap struct */
- image = fz_new_pixmap(ctx, tiff.colorspace, tiff.imagewidth, tiff.imagelength);
+ image = fz_new_pixmap(ctx, tiff.colorspace, tiff.imagewidth, tiff.imagelength, 1);
image->xres = tiff.xresolution;
image->yres = tiff.yresolution;
@@ -861,7 +861,7 @@ fz_load_tiff_subimage(fz_context *ctx, unsigned char *buf, int len, int subimage
/* CMYK is a subtractive colorspace, we want additive for premul alpha */
if (image->n == 5)
{
- fz_pixmap *rgb = fz_new_pixmap(ctx, fz_device_rgb(ctx), image->w, image->h);
+ fz_pixmap *rgb = fz_new_pixmap(ctx, fz_device_rgb(ctx), image->w, image->h, 1);
fz_convert_pixmap(ctx, rgb, image);
rgb->xres = image->xres;
rgb->yres = image->yres;
diff --git a/source/fitz/output-cbz.c b/source/fitz/output-cbz.c
index d9aff180..4c6d0ca0 100644
--- a/source/fitz/output-cbz.c
+++ b/source/fitz/output-cbz.c
@@ -30,7 +30,7 @@ cbz_begin_page(fz_context *ctx, fz_document_writer *wri_, const fz_rect *mediabo
fz_transform_rect(&bbox, ctm);
fz_round_rect(&ibbox, &bbox);
- wri->pixmap = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), &ibbox);
+ wri->pixmap = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), &ibbox, 1);
fz_clear_pixmap_with_value(ctx, wri->pixmap, 0xFF);
return fz_new_draw_device(ctx, wri->pixmap);
diff --git a/source/fitz/output-pcl.c b/source/fitz/output-pcl.c
index e37cce85..6d0a24a6 100644
--- a/source/fitz/output-pcl.c
+++ b/source/fitz/output-pcl.c
@@ -687,7 +687,7 @@ fz_write_pixmap_as_pcl(fz_context *ctx, fz_output *out, const fz_pixmap *pixmap,
pcoc = fz_write_color_pcl_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->xres, pixmap->yres, 0, pcl);
fz_try(ctx)
- fz_write_color_pcl_band(ctx, out, pcoc, pixmap->w, pixmap->h, pixmap->n, 0, 0, pixmap->samples);
+ fz_write_color_pcl_band(ctx, out, pcoc, pixmap->w, pixmap->h, pixmap->n, pixmap->stride, 0, 0, pixmap->samples);
fz_always(ctx)
fz_write_color_pcl_trailer(ctx, out, pcoc);
fz_catch(ctx)
@@ -777,7 +777,7 @@ fz_color_pcl_output_context *fz_write_color_pcl_header(fz_context *ctx, fz_outpu
return pcoc;
}
-void fz_write_color_pcl_band(fz_context *ctx, fz_output *out, fz_color_pcl_output_context *pcoc, int w, int h, int n, int band, int bandheight, unsigned char *sp)
+void fz_write_color_pcl_band(fz_context *ctx, fz_output *out, fz_color_pcl_output_context *pcoc, int w, int h, int n, int stride, int band, int bandheight, unsigned char *sp)
{
int y, ss, ds, seed_valid, fill;
unsigned char *prev;
@@ -839,14 +839,14 @@ void fz_write_color_pcl_band(fz_context *ctx, fz_output *out, fz_color_pcl_outpu
if (seed_valid && fill + 5 <= 32767 && memcmp(curr, prev, ds) == 0)
{
int count = 1;
- sp += ss;
+ sp += stride;
y++;
while (count < 32767 && y < h)
{
- if (memcmp(sp-ss, sp, ss) != 0)
+ if (memcmp(sp-stride, sp, ss) != 0)
break;
count++;
- sp += ss;
+ sp += stride;
y++;
}
comp[fill++] = 5; /* Duplicate row */
@@ -900,7 +900,7 @@ void fz_write_color_pcl_band(fz_context *ctx, fz_output *out, fz_color_pcl_outpu
/* curr becomes prev */
tmp = prev; prev = curr; curr = tmp;
- sp += ss;
+ sp += stride;
y++;
}
}
diff --git a/source/fitz/output-ps.c b/source/fitz/output-ps.c
index e80a3f00..1c4f5103 100644
--- a/source/fitz/output-ps.c
+++ b/source/fitz/output-ps.c
@@ -128,7 +128,7 @@ void fz_write_pixmap_as_ps(fz_context *ctx, fz_output *out, const fz_pixmap *pix
fz_try(ctx)
{
- fz_write_ps_band(ctx, out, psoc, pixmap->w, pixmap->h, pixmap->n, 0, 0, pixmap->samples);
+ fz_write_ps_band(ctx, out, psoc, pixmap->w, pixmap->h, pixmap->n, pixmap->stride, 0, 0, pixmap->samples);
}
fz_always(ctx)
{
@@ -153,7 +153,7 @@ void fz_save_pixmap_as_ps(fz_context *ctx, fz_pixmap *pixmap, char *filename, in
fz_rethrow(ctx);
}
-void fz_write_ps_band(fz_context *ctx, fz_output *out, fz_ps_output_context *psoc, int w, int h, int n, int band, int bandheight, unsigned char *samples)
+void fz_write_ps_band(fz_context *ctx, fz_output *out, fz_ps_output_context *psoc, int w, int h, int n, int stride, int band, int bandheight, unsigned char *samples)
{
int x, y, i, err;
int required_input;
@@ -185,12 +185,15 @@ void fz_write_ps_band(fz_context *ctx, fz_output *out, fz_ps_output_context *pso
o = psoc->input;
for (y = 0; y < bandheight; y++)
+ {
for (x = 0; x < w; x++)
{
for (i = n-1; i > 0; i--)
*o++ = *samples++;
samples++;
}
+ samples += stride - w*n;
+ }
psoc->stream.next_in = (Bytef*)psoc->input;
psoc->stream.avail_in = required_input;
diff --git a/source/fitz/output-pwg.c b/source/fitz/output-pwg.c
index 9302009e..50e25a13 100644
--- a/source/fitz/output-pwg.c
+++ b/source/fitz/output-pwg.c
@@ -91,7 +91,7 @@ void
fz_write_pixmap_as_pwg_page(fz_context *ctx, fz_output *out, const fz_pixmap *pixmap, const fz_pwg_options *pwg)
{
unsigned char *sp;
- int y, x, sn, dn, ss;
+ int y, x, sn, dn, ss, ss2;
if (!out || !pixmap)
return;
@@ -109,17 +109,18 @@ fz_write_pixmap_as_pwg_page(fz_context *ctx, fz_output *out, const fz_pixmap *pi
/* Now output the actual bitmap, using a packbits like compression */
sp = pixmap->samples;
ss = pixmap->w * sn;
+ ss2 = pixmap->stride;
y = 0;
while (y < pixmap->h)
{
int yrep;
- assert(sp == pixmap->samples + y * ss);
+ assert(sp == pixmap->samples + y * ss2);
/* Count the number of times this line is repeated */
for (yrep = 1; yrep < 256 && y+yrep < pixmap->h; yrep++)
{
- if (memcmp(sp, sp + yrep * ss, ss) != 0)
+ if (memcmp(sp, sp + yrep * ss2, ss) != 0)
break;
}
fz_write_byte(ctx, out, yrep-1);
@@ -130,7 +131,7 @@ fz_write_pixmap_as_pwg_page(fz_context *ctx, fz_output *out, const fz_pixmap *pi
{
int d;
- assert(sp == pixmap->samples + y * ss + x * sn);
+ assert(sp == pixmap->samples + y * ss2 + x * sn);
/* How far do we have to look to find a repeated value? */
for (d = 1; d < 128 && x+d < pixmap->w; d++)
@@ -169,7 +170,7 @@ fz_write_pixmap_as_pwg_page(fz_context *ctx, fz_output *out, const fz_pixmap *pi
}
/* Move to the next line */
- sp += ss*(yrep-1);
+ sp += ss2*(yrep-1);
y += yrep;
}
}
diff --git a/source/fitz/paint-glyph.h b/source/fitz/paint-glyph.h
index 42b58b97..824adaf2 100644
--- a/source/fitz/paint-glyph.h
+++ b/source/fitz/paint-glyph.h
@@ -9,25 +9,38 @@
#define NAME solid
#endif
-#define FUNCTION_NAMER(NAME,N) fz_paint_glyph_##NAME##_##N
-#define FUNCTION_NAME(NAME,N) FUNCTION_NAMER(NAME,N)
+#ifdef DA
+#define NAME2 _da
+#else
+#define NAME2
+#endif
+
+#define FUNCTION_NAMER(NAME,N,NAME2) fz_paint_glyph_##NAME##_##N##NAME2
+#define FUNCTION_NAME(NAME,N,NAME2) FUNCTION_NAMER(NAME,N,NAME2)
static inline void
-FUNCTION_NAME(NAME,N)(const unsigned char * restrict colorbv,
+FUNCTION_NAME(NAME,N,NAME2)(const unsigned char * restrict colorbv,
#ifndef N
- int n,
+ const int n1,
#endif
int span, unsigned char * restrict dp, const fz_glyph * restrict glyph, int w, int h, int skip_x, int skip_y)
{
#ifdef N
- const int n = N;
+ const int n1 = N;
+#endif
+#ifdef DA
+ const int n = n1 + 1;
+#else
+ const int n = n1;
#endif
#ifdef ALPHA
- int sa = FZ_EXPAND(colorbv[n-1]);
+ int sa = FZ_EXPAND(colorbv[n1]);
#else
-#if defined(N) && N == 2
+#if defined(N) && N == 1 && defined(DA)
const uint16_t color = *(const uint16_t *)colorbv;
-#elif defined(N) && N == 4
+#elif defined(N) && N == 3 && defined(DA)
+ const uint32_t color = *(const uint32_t *)colorbv;
+#elif defined(N) && N == 4 && !defined(DA)
const uint32_t color = *(const uint32_t *)colorbv;
#endif
#endif
@@ -120,42 +133,68 @@ solid_run:
do
{
#ifdef ALPHA
-#if defined(N) && N == 2
+#if defined(N) && N == 1
ddp[0] = FZ_BLEND(colorbv[0], ddp[0], sa);
+#ifdef DA
ddp[1] = FZ_BLEND(0xFF, ddp[1], sa);
ddp += 2;
-#elif defined(N) && N == 4
+#else
+ ddp++;
+#endif
+#elif defined(N) && N == 3
ddp[0] = FZ_BLEND(colorbv[0], ddp[0], sa);
ddp[1] = FZ_BLEND(colorbv[1], ddp[1], sa);
ddp[2] = FZ_BLEND(colorbv[2], ddp[2], sa);
+#ifdef DA
ddp[3] = FZ_BLEND(0xFF, ddp[3], sa);
ddp += 4;
-#elif defined(N) && N == 5
+#else
+ ddp += 3;
+#endif
+#elif defined(N) && N == 4
ddp[0] = FZ_BLEND(colorbv[0], ddp[0], sa);
ddp[1] = FZ_BLEND(colorbv[1], ddp[1], sa);
ddp[2] = FZ_BLEND(colorbv[2], ddp[2], sa);
ddp[3] = FZ_BLEND(colorbv[3], ddp[3], sa);
+#ifdef DA
ddp[4] = FZ_BLEND(0xFF, ddp[4], sa);
ddp += 5;
#else
+ ddp += 4;
+#endif
+#else
int k = 0;
do
{
*ddp = FZ_BLEND(colorbv[k++], *ddp, sa);
ddp++;
}
- while (k != n-1);
+ while (k != n);
+#ifdef DA
*ddp = FZ_BLEND(0xFF, *ddp, sa);
ddp++;
#endif
+#endif
#else
-#if defined(N) && N == 2
+#if defined(N) && N == 1
+#ifdef DA
*(uint16_t *)ddp = color;
ddp += 2;
-#elif defined(N) && N == 4
+#else
+ *ddp++ = colorbv[0];
+#endif
+#elif defined(N) && N == 3
+#ifdef DA
*(uint32_t *)ddp = color;
ddp += 4;
-#elif defined(N) && N == 5
+#else
+ ddp[0] = colorbv[0];
+ ddp[1] = colorbv[1];
+ ddp[2] = colorbv[2];
+ ddp += 3;
+#endif
+#elif defined(N) && N == 4
+#ifdef DA
ddp[0] = colorbv[0];
ddp[1] = colorbv[1];
ddp[2] = colorbv[2];
@@ -163,6 +202,10 @@ solid_run:
ddp[4] = colorbv[4];
ddp += 5;
#else
+ *(uint32_t *)ddp = color;
+ ddp += 4;
+#endif
+#else
int k = 0;
do
{
@@ -192,33 +235,47 @@ intermediate_run:
a = FZ_EXPAND(a);
#endif
(void)k;
-#if defined(N) && N == 2
+#if defined(N) && N == 1
ddp[0] = FZ_BLEND(colorbv[0], ddp[0], a);
+#ifdef DA
ddp[1] = FZ_BLEND(0xFF, ddp[1], a);
ddp += 2;
-#elif defined(N) && N == 4
+#else
+ ddp++;
+#endif
+#elif defined(N) && N == 3
ddp[0] = FZ_BLEND(colorbv[0], ddp[0], a);
ddp[1] = FZ_BLEND(colorbv[1], ddp[1], a);
ddp[2] = FZ_BLEND(colorbv[2], ddp[2], a);
+#ifdef DA
ddp[3] = FZ_BLEND(0xFF, ddp[3], a);
ddp += 4;
-#elif defined(N) && N == 5
+#else
+ ddp += 3;
+#endif
+#elif defined(N) && N == 4
ddp[0] = FZ_BLEND(colorbv[0], ddp[0], a);
ddp[1] = FZ_BLEND(colorbv[1], ddp[1], a);
ddp[2] = FZ_BLEND(colorbv[2], ddp[2], a);
ddp[3] = FZ_BLEND(colorbv[3], ddp[3], a);
+#ifdef DA
ddp[4] = FZ_BLEND(0xFF, ddp[4], a);
ddp += 5;
#else
+ ddp += 4;
+#endif
+#else
do
{
*ddp = FZ_BLEND(colorbv[k++], *ddp, a);
ddp++;
}
- while (k != n-1);
+ while (k != n1);
+#ifdef DA
*ddp = FZ_BLEND(0xFF, *ddp, a);
ddp++;
#endif
+#endif
}
while (--len);
break;
@@ -233,6 +290,8 @@ intermediate_run:
#undef NAME
#undef ALPHA
+#undef NAME2
+#undef DA
#undef N
#undef FUNCTION_NAMER
#undef FUNCTION_NAME
diff --git a/source/fitz/pixmap.c b/source/fitz/pixmap.c
index fca6f733..e0d24265 100644
--- a/source/fitz/pixmap.c
+++ b/source/fitz/pixmap.c
@@ -25,29 +25,41 @@ fz_drop_pixmap_imp(fz_context *ctx, fz_storable *pix_)
}
fz_pixmap *
-fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h, unsigned char *samples)
+fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h, int alpha, int stride, unsigned char *samples)
{
fz_pixmap *pix;
+ int n;
if (w < 0 || h < 0)
fz_throw(ctx, FZ_ERROR_GENERIC, "Illegal dimensions for pixmap %d %d", w, h);
+ n = alpha + (colorspace ? colorspace->n : 0);
+ if (stride < n*w && stride > -n*w)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Illegal stride for pixmap (n=%d w=%d, stride=%d)", n, w, stride);
+ if (samples == NULL && stride < n*w)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Illegal -ve stride for pixmap without data");
+
pix = fz_malloc_struct(ctx, fz_pixmap);
FZ_INIT_STORABLE(pix, 1, fz_drop_pixmap_imp);
pix->x = 0;
pix->y = 0;
pix->w = w;
pix->h = h;
+ pix->alpha = alpha = !!alpha;
pix->interpolate = 1;
pix->xres = 96;
pix->yres = 96;
pix->colorspace = NULL;
- pix->n = 1;
+ pix->n = n;
+ pix->stride = stride;
if (colorspace)
{
pix->colorspace = fz_keep_colorspace(ctx, colorspace);
- pix->n = 1 + colorspace->n;
+ }
+ else
+ {
+ assert(alpha);
}
pix->samples = samples;
@@ -59,9 +71,9 @@ fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h
{
fz_try(ctx)
{
- if (pix->w + pix->n - 1 > INT_MAX / pix->n)
+ if (pix->stride - 1 > INT_MAX / pix->n)
fz_throw(ctx, FZ_ERROR_GENERIC, "overly wide image");
- pix->samples = fz_malloc_array(ctx, pix->h, pix->w * pix->n);
+ pix->samples = fz_malloc_array(ctx, pix->h, pix->stride);
}
fz_catch(ctx)
{
@@ -77,25 +89,28 @@ fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h
}
fz_pixmap *
-fz_new_pixmap(fz_context *ctx, fz_colorspace *colorspace, int w, int h)
+fz_new_pixmap(fz_context *ctx, fz_colorspace *colorspace, int w, int h, int alpha)
{
- return fz_new_pixmap_with_data(ctx, colorspace, w, h, NULL);
+ int stride = ((colorspace ? colorspace->n : 0) + alpha) * w;
+ return fz_new_pixmap_with_data(ctx, colorspace, w, h, alpha, stride, NULL);
}
fz_pixmap *
-fz_new_pixmap_with_bbox(fz_context *ctx, fz_colorspace *colorspace, const fz_irect *r)
+fz_new_pixmap_with_bbox(fz_context *ctx, fz_colorspace *colorspace, const fz_irect *r, int alpha)
{
fz_pixmap *pixmap;
- pixmap = fz_new_pixmap(ctx, colorspace, r->x1 - r->x0, r->y1 - r->y0);
+ pixmap = fz_new_pixmap(ctx, colorspace, r->x1 - r->x0, r->y1 - r->y0, alpha);
pixmap->x = r->x0;
pixmap->y = r->y0;
return pixmap;
}
fz_pixmap *
-fz_new_pixmap_with_bbox_and_data(fz_context *ctx, fz_colorspace *colorspace, const fz_irect *r, unsigned char *samples)
+fz_new_pixmap_with_bbox_and_data(fz_context *ctx, fz_colorspace *colorspace, const fz_irect *r, int alpha, unsigned char *samples)
{
- fz_pixmap *pixmap = fz_new_pixmap_with_data(ctx, colorspace, r->x1 - r->x0, r->y1 - r->y0, samples);
+ int w = r->x1 - r->x0;
+ int stride = ((colorspace ? colorspace->n : 0) + alpha) * w;
+ fz_pixmap *pixmap = fz_new_pixmap_with_data(ctx, colorspace, w, r->y1 - r->y0, alpha, stride, samples);
pixmap->x = r->x0;
pixmap->y = r->y0;
return pixmap;
@@ -160,9 +175,15 @@ fz_pixmap_components(fz_context *ctx, fz_pixmap *pix)
}
int
+fz_pixmap_colorants(fz_context *ctx, fz_pixmap *pix)
+{
+ return pix->n - pix->alpha;
+}
+
+int
fz_pixmap_stride(fz_context *ctx, fz_pixmap *pix)
{
- return pix->w * pix->n;
+ return pix->stride;
}
unsigned char *
@@ -173,12 +194,6 @@ fz_pixmap_samples(fz_context *ctx, fz_pixmap *pix)
return pix->samples;
}
-void
-fz_clear_pixmap(fz_context *ctx, fz_pixmap *pix)
-{
- memset(pix->samples, 0, (unsigned int)(pix->w * pix->h * pix->n));
-}
-
/*
The slowest routine in most CMYK rendering profiles.
We therefore spend some effort to improve it. Rather than
@@ -238,87 +253,202 @@ clear_cmyk_bitmap(unsigned char *samples, int c, int value)
}
#else
static void
-clear_cmyk_bitmap(unsigned char *samples, int c, int value)
+clear_cmyk_bitmap(unsigned char *samples, int w, int h, int stride, int value, int alpha)
{
- union
- {
- uint8_t bytes[20];
- uint32_t words[5];
- } d;
uint32_t *s = (uint32_t *)(void *)samples;
uint8_t *t;
- d.words[0] = 0;
- d.words[1] = 0;
- d.words[2] = 0;
- d.words[3] = 0;
- d.words[4] = 0;
- d.bytes[3] = value;
- d.bytes[4] = 255;
- d.bytes[8] = value;
- d.bytes[9] = 255;
- d.bytes[13] = value;
- d.bytes[14] = 255;
- d.bytes[18] = value;
- d.bytes[19] = 255;
-
- c -= 3;
+ if (alpha)
{
- const int a0 = d.words[0];
- const int a1 = d.words[1];
- const int a2 = d.words[2];
- const int a3 = d.words[3];
- const int a4 = d.words[4];
- while (c > 0)
+ int c = w;
+ stride -= w*5;
+ if (stride == 0)
+ {
+ /* We can do it all fast (except for maybe a few stragglers) */
+ union
+ {
+ uint8_t bytes[20];
+ uint32_t words[5];
+ } d;
+
+ c *= h;
+ h = 1;
+
+ d.words[0] = 0;
+ d.words[1] = 0;
+ d.words[2] = 0;
+ d.words[3] = 0;
+ d.words[4] = 0;
+ d.bytes[3] = value;
+ d.bytes[4] = 255;
+ d.bytes[8] = value;
+ d.bytes[9] = 255;
+ d.bytes[13] = value;
+ d.bytes[14] = 255;
+ d.bytes[18] = value;
+ d.bytes[19] = 255;
+
+ c -= 3;
+ {
+ const uint32_t a0 = d.words[0];
+ const uint32_t a1 = d.words[1];
+ const uint32_t a2 = d.words[2];
+ const uint32_t a3 = d.words[3];
+ const uint32_t a4 = d.words[4];
+ while (c > 0)
+ {
+ *s++ = a0;
+ *s++ = a1;
+ *s++ = a2;
+ *s++ = a3;
+ *s++ = a4;
+ c -= 4;
+ }
+ }
+ c += 3;
+ }
+ t = (unsigned char *)s;
+ w = c;
+ while (h--)
{
- *s++ = a0;
- *s++ = a1;
- *s++ = a2;
- *s++ = a3;
- *s++ = a4;
- c -= 4;
+ c = w;
+ while (c > 0)
+ {
+ *t++ = 0;
+ *t++ = 0;
+ *t++ = 0;
+ *t++ = value;
+ *t++ = 255;
+ c--;
+ }
+ t += stride;
}
}
- c += 3;
- t = (unsigned char *)s;
- while (c > 0)
+ else
{
- *t++ = 0;
- *t++ = 0;
- *t++ = 0;
- *t++ = value;
- *t++ = 255;
- c--;
+ stride -= w*4;
+ if ((stride & 3)== 0)
+ {
+ /* We can do it all fast */
+ union
+ {
+ uint8_t bytes[4];
+ uint32_t word;
+ } d;
+
+ d.word = 0;
+ d.bytes[3] = value;
+ w *= h;
+
+ {
+ const uint32_t a0 = d.word;
+ while (w > 0)
+ {
+ *s++ = a0;
+ w--;
+ }
+ s += (stride>>2);
+ }
+ }
+ else
+ {
+ t = (unsigned char *)s;
+ while (h--)
+ {
+ int c = w;
+ while (c > 0)
+ {
+ *t++ = 0;
+ *t++ = 0;
+ *t++ = 0;
+ *t++ = value;
+ c--;
+ }
+ t += stride;
+ }
+ }
}
}
#endif
void
+fz_clear_pixmap(fz_context *ctx, fz_pixmap *pix)
+{
+ int stride = pix->w * pix->n;
+ int h = pix->h;
+ unsigned char *s = pix->samples;
+ if (stride == pix->stride)
+ {
+ stride *= h;
+ h = 1;
+ }
+ if (pix->alpha)
+ {
+ while (h--)
+ {
+ memset(s, 0, (unsigned int)stride);
+ s += pix->stride;
+ }
+ }
+ else
+ {
+ /* FIXME: Not right for CMYK or other subtractive spaces */
+ while (h--)
+ {
+ memset(s, 0xff, (unsigned int)stride);
+ s += pix->stride;
+ }
+ }
+}
+
+void
fz_clear_pixmap_with_value(fz_context *ctx, fz_pixmap *pix, int value)
{
+ unsigned char *s;
+ int w, h, n, stride, len;
+ int alpha = pix->alpha;
+
/* CMYK needs special handling (and potentially any other subtractive colorspaces) */
if (pix->colorspace && pix->colorspace->n == 4)
{
- clear_cmyk_bitmap(pix->samples, pix->w * pix->h, 255-value);
+ clear_cmyk_bitmap(pix->samples, pix->w, pix->h, pix->stride, 255-value, pix->alpha);
return;
}
- if (value == 255)
+ w = pix->w;
+ h = pix->h;
+ n = pix->n;
+ stride = pix->stride;
+ len = w * n;
+
+ s = pix->samples;
+ if (value == 255 || !alpha)
{
- memset(pix->samples, 255, (unsigned int)(pix->w * pix->h * pix->n));
+ if (stride == len)
+ {
+ len *= h;
+ h = 1;
+ }
+ while (h--)
+ {
+ memset(s, value, (unsigned int)len);
+ s += stride;
+ }
}
else
{
int k, x, y;
- unsigned char *s = pix->samples;
+ stride -= len;
for (y = 0; y < pix->h; y++)
{
for (x = 0; x < pix->w; x++)
{
for (k = 0; k < pix->n - 1; k++)
*s++ = value;
- *s++ = 255;
+ if (alpha)
+ *s++ = 255;
}
+ s += stride;
}
}
}
@@ -339,9 +469,9 @@ fz_copy_pixmap_rect(fz_context *ctx, fz_pixmap *dest, fz_pixmap *src, const fz_i
if (w <= 0 || y <= 0)
return;
- srcspan = src->w * src->n;
+ srcspan = src->stride;
srcp = src->samples + (unsigned int)(srcspan * (local_b.y0 - src->y) + src->n * (local_b.x0 - src->x));
- destspan = dest->w * dest->n;
+ destspan = dest->stride;
destp = dest->samples + (unsigned int)(destspan * (local_b.y0 - dest->y) + dest->n * (local_b.x0 - dest->x));
if (src->n == dest->n)
@@ -376,6 +506,10 @@ fz_copy_pixmap_rect(fz_context *ctx, fz_pixmap *dest, fz_pixmap *src, const fz_i
}
while (--y);
}
+ else if (src->n == 1 + src->alpha && dest->n == 3 + dest->alpha)
+ {
+ assert("FIXME" == NULL);
+ }
else if (src->n == 4 && dest->n == 2)
{
/* Copy, and convert from rgb+alpha to grey+alpha */
@@ -397,6 +531,10 @@ fz_copy_pixmap_rect(fz_context *ctx, fz_pixmap *dest, fz_pixmap *src, const fz_i
}
while (--y);
}
+ else if (src->n == 3 + src->alpha && dest->n == 1 + dest->alpha)
+ {
+ assert("FIXME" == NULL);
+ }
else
{
/* FIXME: Crap conversion */
@@ -439,7 +577,7 @@ fz_clear_pixmap_rect_with_value(fz_context *ctx, fz_pixmap *dest, int value, con
if (w <= 0 || y <= 0)
return;
- destspan = dest->w * dest->n;
+ destspan = dest->stride;
destp = dest->samples + (unsigned int)(destspan * (local_b.y0 - dest->y) + dest->n * (local_b.x0 - dest->x));
/* CMYK needs special handling (and potentially any other subtractive colorspaces) */
@@ -495,6 +633,7 @@ fz_premultiply_pixmap(fz_context *ctx, fz_pixmap *pix)
unsigned char *s = pix->samples;
unsigned char a;
int k, x, y;
+ int stride = pix->stride - pix->w * pix->n;
for (y = 0; y < pix->h; y++)
{
@@ -505,6 +644,7 @@ fz_premultiply_pixmap(fz_context *ctx, fz_pixmap *pix)
s[k] = fz_mul255(s[k], a);
s += pix->n;
}
+ s += stride;
}
}
@@ -514,6 +654,7 @@ fz_unmultiply_pixmap(fz_context *ctx, fz_pixmap *pix)
unsigned char *s = pix->samples;
int a, inva;
int k, x, y;
+ int stride = pix->stride - pix->w * pix->n;
for (y = 0; y < pix->h; y++)
{
@@ -525,6 +666,7 @@ fz_unmultiply_pixmap(fz_context *ctx, fz_pixmap *pix)
s[k] = (s[k] * inva) >> 8;
s += pix->n;
}
+ s += stride;
}
}
@@ -533,22 +675,28 @@ fz_alpha_from_gray(fz_context *ctx, fz_pixmap *gray, int luminosity)
{
fz_pixmap *alpha;
unsigned char *sp, *dp;
- int len;
+ int w, h, sstride, dstride;
fz_irect bbox;
- assert(gray->n == 2);
+ assert(gray->n == 1);
- alpha = fz_new_pixmap_with_bbox(ctx, NULL, fz_pixmap_bbox(ctx, gray, &bbox));
+ alpha = fz_new_pixmap_with_bbox(ctx, NULL, fz_pixmap_bbox(ctx, gray, &bbox), 1);
dp = alpha->samples;
+ dstride = alpha->stride - alpha->w;
sp = gray->samples;
- if (!luminosity)
- sp ++;
+ sstride = gray->stride - gray->w;
- len = gray->w * gray->h;
- while (len--)
+ h = gray->h;
+ while (h--)
{
- *dp++ = sp[0];
- sp += 2;
+ w = gray->w;
+ while (w--)
+ {
+ *dp++ = sp[0];
+ sp++;
+ }
+ sp += sstride;
+ dp += dstride;
}
return alpha;
@@ -577,26 +725,30 @@ fz_tint_pixmap(fz_context *ctx, fz_pixmap *pix, int r, int g, int b)
if (pix->n == 4)
{
- for (x = 0; x < pix->w; x++)
+ assert(pix->alpha);
+ for (y = 0; y < pix->h; y++)
{
- for (y = 0; y < pix->h; y++)
+ for (x = 0; x < pix->w; x++)
{
s[0] = fz_mul255(s[0], r);
s[1] = fz_mul255(s[1], g);
s[2] = fz_mul255(s[2], b);
s += 4;
}
+ s += pix->stride - pix->w * 4;
}
}
else if (pix->n == 2)
{
- for (x = 0; x < pix->w; x++)
+ assert(pix->alpha);
+ for (y = 0; y < pix->h; y++)
{
- for (y = 0; y < pix->h; y++)
+ for (x = 0; x < pix->w; x++)
{
*s = fz_mul255(*s, g);
s += 2;
}
+ s += pix->stride - pix->w * 2;
}
}
}
@@ -615,6 +767,7 @@ fz_invert_pixmap(fz_context *ctx, fz_pixmap *pix)
s[k] = 255 - s[k];
s += pix->n;
}
+ s += pix->stride - pix->w * pix->n;
}
}
@@ -630,7 +783,7 @@ void fz_invert_pixmap_rect(fz_context *ctx, fz_pixmap *image, const fz_irect *re
for (y = y0; y < y1; y++)
{
- p = image->samples + (unsigned int)((y * image->w + x0) * image->n);
+ p = image->samples + (unsigned int)((y * image->stride) + (x0 * image->n));
for (x = x0; x < x1; x++)
{
for (n = image->n; n > 1; n--, p++)
@@ -658,6 +811,7 @@ fz_gamma_pixmap(fz_context *ctx, fz_pixmap *pix, float gamma)
s[k] = gamma_map[s[k]];
s += pix->n;
}
+ s += pix->stride - pix->w * pix->n;
}
}
@@ -668,19 +822,19 @@ fz_gamma_pixmap(fz_context *ctx, fz_pixmap *pix, float gamma)
void
fz_write_pnm_header(fz_context *ctx, fz_output *out, int w, int h, int n)
{
- if (n != 1 && n != 2 && n != 4)
+ if (n < 1 || n > 4)
fz_throw(ctx, FZ_ERROR_GENERIC, "pixmap must be grayscale or rgb to write as pnm");
if (n == 1 || n == 2)
fz_printf(ctx, out, "P5\n");
- if (n == 4)
+ if (n == 3 || n == 4)
fz_printf(ctx, out, "P6\n");
fz_printf(ctx, out, "%d %d\n", w, h);
fz_printf(ctx, out, "255\n");
}
void
-fz_write_pnm_band(fz_context *ctx, fz_output *out, int w, int h, int n, int band, int bandheight, unsigned char *p)
+fz_write_pnm_band(fz_context *ctx, fz_output *out, int w, int h, int n, int stride, int band, int bandheight, unsigned char *p)
{
char buffer[2*3*4*5*6]; /* Buffer must be a multiple of 2 and 3 at least. */
int len;
@@ -694,58 +848,63 @@ fz_write_pnm_band(fz_context *ctx, fz_output *out, int w, int h, int n, int band
end = h;
end -= start;
- len = w * end;
-
/* Tests show that writing single bytes out at a time
* is appallingly slow. We get a huge improvement
* by collating stuff into buffers first. */
- while (len)
+ while (end--)
{
- int num_written = len;
-
- switch (n)
- {
- case 1:
- /* No collation required */
- fz_write(ctx, out, p, num_written);
- break;
- case 2:
+ len = w;
+ while (len)
{
- char *o = buffer;
- int count;
+ int num_written = len;
- if (num_written > sizeof(buffer))
- num_written = sizeof(buffer);
-
- for (count = num_written; count; count--)
+ switch (n)
{
- *o++ = *p;
- p += 2;
- }
- fz_write(ctx, out, buffer, num_written);
- break;
- }
- case 4:
- {
- char *o = buffer;
- int count;
+ case 1:
+ /* No collation required */
+ fz_write(ctx, out, p, num_written);
+ p += num_written;
+ break;
+ case 2:
+ {
+ char *o = buffer;
+ int count;
- if (num_written > sizeof(buffer)/3)
- num_written = sizeof(buffer)/3;
+ if (num_written > sizeof(buffer))
+ num_written = sizeof(buffer);
- for (count = num_written; count; count--)
+ for (count = num_written; count; count--)
+ {
+ *o++ = *p;
+ p += 2;
+ }
+ fz_write(ctx, out, buffer, num_written);
+ break;
+ }
+ case 3:
+ case 4:
{
- *o++ = p[0];
- *o++ = p[1];
- *o++ = p[2];
- p += 4;
+ char *o = buffer;
+ int count;
+
+ if (num_written > sizeof(buffer)/3)
+ num_written = sizeof(buffer)/3;
+
+ for (count = num_written; count; count--)
+ {
+ *o++ = p[0];
+ *o++ = p[1];
+ *o++ = p[2];
+ p += n;
+ }
+ fz_write(ctx, out, buffer, num_written * 3);
+ break;
}
- fz_write(ctx, out, buffer, num_written * 3);
- break;
- }
+ }
+ len -= num_written;
}
- len -= num_written;
+ p += stride - w*n;
}
}
@@ -753,7 +912,7 @@ void
fz_write_pixmap_as_pnm(fz_context *ctx, fz_output *out, fz_pixmap *pixmap)
{
fz_write_pnm_header(ctx, out, pixmap->w, pixmap->h, pixmap->n);
- fz_write_pnm_band(ctx, out, pixmap->w, pixmap->h, pixmap->n, 0, pixmap->h, pixmap->samples);
+ fz_write_pnm_band(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->stride, 0, pixmap->h, pixmap->samples);
}
void
@@ -761,7 +920,7 @@ fz_save_pixmap_as_pnm(fz_context *ctx, fz_pixmap *pixmap, char *filename)
{
fz_output *out = fz_new_output_with_path(ctx, filename, 0);
fz_write_pnm_header(ctx, out, pixmap->w, pixmap->h, pixmap->n);
- fz_write_pnm_band(ctx, out, pixmap->w, pixmap->h, pixmap->n, 0, pixmap->h, pixmap->samples);
+ fz_write_pnm_band(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->stride, 0, pixmap->h, pixmap->samples);
fz_drop_output(ctx, out);
}
@@ -792,7 +951,7 @@ fz_write_pam_header(fz_context *ctx, fz_output *out, int w, int h, int n, int sa
}
void
-fz_write_pam_band(fz_context *ctx, fz_output *out, int w, int h, int n, int band, int bandheight, unsigned char *sp, int savealpha)
+fz_write_pam_band(fz_context *ctx, fz_output *out, int w, int h, int n, int stride, int band, int bandheight, unsigned char *sp, int savealpha)
{
int y, x;
int start = band * bandheight;
@@ -817,6 +976,7 @@ fz_write_pam_band(fz_context *ctx, fz_output *out, int w, int h, int n, int band
fz_write(ctx, out, sp, dn);
sp += sn;
}
+ sp += stride - w*n;
}
}
@@ -824,7 +984,7 @@ void
fz_write_pixmap_as_pam(fz_context *ctx, fz_output *out, fz_pixmap *pixmap, int savealpha)
{
fz_write_pam_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, savealpha);
- fz_write_pam_band(ctx, out, pixmap->w, pixmap->h, pixmap->n, 0, pixmap->h, pixmap->samples, savealpha);
+ fz_write_pam_band(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->stride, 0, pixmap->h, pixmap->samples, savealpha);
}
void
@@ -834,7 +994,7 @@ fz_save_pixmap_as_pam(fz_context *ctx, fz_pixmap *pixmap, char *filename, int sa
fz_try(ctx)
{
fz_write_pam_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, savealpha);
- fz_write_pam_band(ctx, out, pixmap->w, pixmap->h, pixmap->n, 0, pixmap->h, pixmap->samples, savealpha);
+ fz_write_pam_band(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->stride, 0, pixmap->h, pixmap->samples, savealpha);
}
fz_always(ctx)
fz_drop_output(ctx, out);
@@ -878,8 +1038,8 @@ fz_save_pixmap_as_png(fz_context *ctx, fz_pixmap *pixmap, const char *filename,
fz_try(ctx)
{
- poc = fz_write_png_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, savealpha);
- fz_write_png_band(ctx, out, poc, pixmap->w, pixmap->h, pixmap->n, 0, pixmap->h, pixmap->samples, savealpha);
+ poc = fz_write_png_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, savealpha);
+ fz_write_png_band(ctx, out, poc, pixmap->stride, 0, pixmap->h, pixmap->samples);
}
fz_always(ctx)
{
@@ -900,11 +1060,11 @@ fz_write_pixmap_as_png(fz_context *ctx, fz_output *out, const fz_pixmap *pixmap,
if (!out)
return;
- poc = fz_write_png_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, savealpha);
+ poc = fz_write_png_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, savealpha);
fz_try(ctx)
{
- fz_write_png_band(ctx, out, poc, pixmap->w, pixmap->h, pixmap->n, 0, pixmap->h, pixmap->samples, savealpha);
+ fz_write_png_band(ctx, out, poc, pixmap->stride, 0, pixmap->h, pixmap->samples);
}
fz_always(ctx)
{
@@ -922,10 +1082,15 @@ struct fz_png_output_context_s
unsigned char *cdata;
uLong usize, csize;
z_stream stream;
+ int w;
+ int h;
+ int n;
+ int alpha;
+ int savealpha;
};
fz_png_output_context *
-fz_write_png_header(fz_context *ctx, fz_output *out, int w, int h, int n, int savealpha)
+fz_write_png_header(fz_context *ctx, fz_output *out, int w, int h, int n, int alpha, int savealpha)
{
static const unsigned char pngsig[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
unsigned char head[13];
@@ -935,23 +1100,29 @@ fz_write_png_header(fz_context *ctx, fz_output *out, int w, int h, int n, int sa
if (!out)
return NULL;
- if (n != 1 && n != 2 && n != 4)
- fz_throw(ctx, FZ_ERROR_GENERIC, "pixmap must be grayscale or rgb to write as png");
-
- poc = fz_malloc_struct(ctx, fz_png_output_context);
-
- if (!savealpha && n > 1)
- n--;
+ /* Treat alpha only as greyscale */
+ if (n == 1 && alpha)
+ alpha = 0;
- switch (n)
+ switch (n - alpha)
{
+ case 1: color = (alpha ? 4 : 0); break; /* 0 = Greyscale, 4 = Greyscale + Alpha */
+ case 3: color = (alpha ? 6 : 2); break; /* 2 = RGB, 6 = RGBA */
default:
- case 1: color = 0; break;
- case 2: color = 4; break;
- case 3: color = 2; break;
- case 4: color = 6; break;
+ fz_throw(ctx, FZ_ERROR_GENERIC, "pixmap must be grayscale or rgb to write as png");
}
+ /* If we have no alpha, save no alpha */
+ if (!alpha)
+ savealpha = 0;
+
+ poc = fz_malloc_struct(ctx, fz_png_output_context);
+ poc->w = w;
+ poc->h = h;
+ poc->n = n;
+ poc->alpha = alpha;
+ poc->savealpha = savealpha;
+
big32(head+0, w);
big32(head+4, h);
head[8] = 8; /* depth */
@@ -967,16 +1138,20 @@ fz_write_png_header(fz_context *ctx, fz_output *out, int w, int h, int n, int sa
}
void
-fz_write_png_band(fz_context *ctx, fz_output *out, fz_png_output_context *poc, int w, int h, int n, int band, int bandheight, unsigned char *sp, int savealpha)
+fz_write_png_band(fz_context *ctx, fz_output *out, fz_png_output_context *poc, int stride, int band, int bandheight, unsigned char *sp)
{
unsigned char *dp;
int y, x, k, sn, dn, err, finalband;
+ int w, h, n, alpha, savealpha;
if (!out || !sp || !poc)
return;
- if (n != 1 && n != 2 && n != 4)
- fz_throw(ctx, FZ_ERROR_GENERIC, "pixmap must be grayscale or rgb to write as png");
+ w = poc->w;
+ h = poc->h;
+ n = poc->n;
+ alpha = poc->alpha;
+ savealpha = poc->savealpha;
band *= bandheight;
finalband = (band+bandheight >= h);
@@ -984,9 +1159,7 @@ fz_write_png_band(fz_context *ctx, fz_output *out, fz_png_output_context *poc, i
bandheight = h - band;
sn = n;
- dn = n;
- if (!savealpha && dn > 1)
- dn--;
+ dn = n - alpha + savealpha;
if (poc->udata == NULL)
{
@@ -1015,6 +1188,7 @@ fz_write_png_band(fz_context *ctx, fz_output *out, fz_png_output_context *poc, i
}
dp = poc->udata;
+ stride -= w*sn;
for (y = 0; y < bandheight; y++)
{
*dp++ = 1; /* sub prediction filter */
@@ -1030,6 +1204,7 @@ fz_write_png_band(fz_context *ctx, fz_output *out, fz_png_output_context *poc, i
sp += sn;
dp += dn;
}
+ sp += stride;
}
poc->stream.next_in = (Bytef*)poc->udata;
@@ -1099,7 +1274,7 @@ png_from_pixmap(fz_context *ctx, fz_pixmap *pix, int drop)
{
if (pix->colorspace && pix->colorspace != fz_device_gray(ctx) && pix->colorspace != fz_device_rgb(ctx))
{
- pix2 = fz_new_pixmap(ctx, fz_device_rgb(ctx), pix->w, pix->h);
+ pix2 = fz_new_pixmap(ctx, fz_device_rgb(ctx), pix->w, pix->h, 1);
fz_convert_pixmap(ctx, pix2, pix);
if (drop)
fz_drop_pixmap(ctx, pix);
@@ -1231,12 +1406,17 @@ fz_pixmap_size(fz_context *ctx, fz_pixmap * pix)
fz_pixmap *
fz_new_pixmap_from_8bpp_data(fz_context *ctx, int x, int y, int w, int h, unsigned char *sp, int span)
{
- fz_pixmap *pixmap = fz_new_pixmap(ctx, NULL, w, h);
+ fz_pixmap *pixmap = fz_new_pixmap(ctx, NULL, w, h, 1);
+ int stride = pixmap->stride;
+ unsigned char *s = pixmap->samples;
pixmap->x = x;
pixmap->y = y;
for (y = 0; y < h; y++)
- memcpy(pixmap->samples + y * w, sp + y * span, w);
+ {
+ memcpy(s, sp + y * span, w);
+ s += stride;
+ }
return pixmap;
}
@@ -1244,7 +1424,8 @@ fz_new_pixmap_from_8bpp_data(fz_context *ctx, int x, int y, int w, int h, unsign
fz_pixmap *
fz_new_pixmap_from_1bpp_data(fz_context *ctx, int x, int y, int w, int h, unsigned char *sp, int span)
{
- fz_pixmap *pixmap = fz_new_pixmap(ctx, NULL, w, h);
+ fz_pixmap *pixmap = fz_new_pixmap(ctx, NULL, w, h, 1);
+ int stride = pixmap->stride - pixmap->w;
pixmap->x = x;
pixmap->y = y;
@@ -1261,6 +1442,7 @@ fz_new_pixmap_from_1bpp_data(fz_context *ctx, int x, int y, int w, int h, unsign
if (bit == 0)
bit = 0x80, in++;
}
+ out += stride;
}
return pixmap;
@@ -1458,6 +1640,9 @@ fz_subsample_pixmap(fz_context *ctx, fz_pixmap *tile, int factor)
if (!tile)
return;
+
+ assert(tile->stride >= tile->w * tile->n);
+
s = d = tile->samples;
f = 1<<factor;
w = tile->w;
@@ -1465,11 +1650,11 @@ fz_subsample_pixmap(fz_context *ctx, fz_pixmap *tile, int factor)
n = tile->n;
dst_w = (w + f-1)>>factor;
dst_h = (h + f-1)>>factor;
- fwd = w*n;
+ fwd = tile->stride;
back = f*fwd-n;
back2 = f*n-1;
fwd2 = (f-1)*n;
- fwd3 = (f-1)*fwd;
+ fwd3 = (f-1)*fwd + tile->stride - w * n;
factor *= 2;
#ifdef ARCH_ARM
{
@@ -1583,6 +1768,7 @@ fz_subsample_pixmap(fz_context *ctx, fz_pixmap *tile, int factor)
#endif
tile->w = dst_w;
tile->h = dst_h;
+ tile->stride = dst_w * n;
tile->samples = fz_resize_array(ctx, tile->samples, dst_w * n, dst_h);
}
@@ -1600,6 +1786,43 @@ fz_md5_pixmap(fz_context *ctx, fz_pixmap *pix, unsigned char digest[16])
fz_md5_init(&md5);
if (pix)
- fz_md5_update(&md5, pix->samples, pix->w * pix->h * pix->n);
+ {
+ unsigned char *s = pix->samples;
+ int h = pix->h;
+ int ss = pix->stride;
+ int len = pix->w * pix->n;
+ while (h--)
+ {
+ fz_md5_update(&md5, s, len);
+ s += ss;
+ }
+ }
fz_md5_final(&md5, digest);
}
+
+#ifdef HAVE_VALGRIND
+int fz_valgrind_pixmap(const fz_pixmap *pix)
+{
+ int w, h, n, total;
+ int ww, hh, nn;
+ int stride;
+ const unsigned char *p = pix->samples;
+
+ if (pix == NULL)
+ return;
+
+ total = 0;
+ ww = pix->w;
+ hh = pix->h;
+ nn = pix->n;
+ stride = pix->stride - ww*nn;
+ for (h = 0; h < hh; h++)
+ {
+ for (w = 0; w < ww; w++)
+ for (n = 0; n < nn; n++)
+ if (*p++) total ++;
+ p += stride;
+ }
+ return total;
+}
+#endif /* HAVE_VALGRIND */
diff --git a/source/fitz/svg-device.c b/source/fitz/svg-device.c
index 97a1acca..acc2c5bc 100644
--- a/source/fitz/svg-device.c
+++ b/source/fitz/svg-device.c
@@ -776,7 +776,7 @@ svg_dev_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_ma
fz_round_rect(&bbox, fz_intersect_rect(fz_bound_shade(ctx, shade, ctm, &rect), &dev->container[dev->container_len-1].scissor));
if (fz_is_empty_irect(&bbox))
return;
- pix = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), &bbox);
+ pix = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), &bbox, 1);
fz_clear_pixmap(ctx, pix);
fz_try(ctx)
diff --git a/source/fitz/test-device.c b/source/fitz/test-device.c
index c0fb95f9..15e6a3ff 100644
--- a/source/fitz/test-device.c
+++ b/source/fitz/test-device.c
@@ -127,7 +127,7 @@ fz_test_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_ma
fz_test_device *t = (fz_test_device*)dev;
fz_pixmap *pix;
- unsigned int count, i, k;
+ unsigned int count, i, k, h, sa, ss;
unsigned char *s;
fz_compressed_buffer *buffer;
@@ -177,6 +177,9 @@ fz_test_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_ma
{
*t->is_color = 1;
dev->hints |= FZ_IGNORE_IMAGE;
+ fz_drop_stream(ctx, stream);
+ fz_fin_cached_color_converter(ctx, &cc);
+ fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
break;
}
}
@@ -190,23 +193,30 @@ fz_test_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_ma
if (pix == NULL) /* Should never happen really, but... */
return;
- count = (unsigned int)pix->w * (unsigned int)pix->h;
+ count = pix->w;
+ h = pix->h;
s = pix->samples;
+ sa = pix->alpha;
+ ss = pix->stride - pix->w * pix->n;
if (pix->colorspace == fz_device_rgb(ctx))
{
int threshold_u8 = t->threshold * 255;
- for (i = 0; i < count; i++)
+ while (h--)
{
- if (s[3] != 0 && is_rgb_color_u8(threshold_u8, s[0], s[1], s[2]))
+ for (i = 0; i < count; i++)
{
- *t->is_color = 1;
- dev->hints |= FZ_IGNORE_IMAGE;
- fz_drop_pixmap(ctx, pix);
- fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
- break;
+ if ((!sa || s[3] != 0) && is_rgb_color_u8(threshold_u8, s[0], s[1], s[2]))
+ {
+ *t->is_color = 1;
+ dev->hints |= FZ_IGNORE_IMAGE;
+ fz_drop_pixmap(ctx, pix);
+ fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
+ break;
+ }
+ s += 3 + sa;
}
- s += 4;
+ s += ss;
}
}
else
@@ -215,26 +225,31 @@ fz_test_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_ma
unsigned int n = (unsigned int)pix->n-1;
fz_init_cached_color_converter(ctx, &cc, fz_device_rgb(ctx), pix->colorspace);
- for (i = 0; i < count; i++)
+ while (h--)
{
- float cs[FZ_MAX_COLORS];
- float ds[FZ_MAX_COLORS];
+ for (i = 0; i < count; i++)
+ {
+ float cs[FZ_MAX_COLORS];
+ float ds[FZ_MAX_COLORS];
- for (k = 0; k < n; k++)
- cs[k] = (*s++) / 255.0f;
- if (*s++ == 0)
- continue;
+ for (k = 0; k < n; k++)
+ cs[k] = (*s++) / 255.0f;
+ if (sa && *s++ == 0)
+ continue;
- cc.convert(ctx, &cc, ds, cs);
+ cc.convert(ctx, &cc, ds, cs);
- if (is_rgb_color(t->threshold, ds[0], ds[1], ds[2]))
- {
- *t->is_color = 1;
- dev->hints |= FZ_IGNORE_IMAGE;
- fz_drop_pixmap(ctx, pix);
- fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
- break;
+ if (is_rgb_color(t->threshold, ds[0], ds[1], ds[2]))
+ {
+ *t->is_color = 1;
+ dev->hints |= FZ_IGNORE_IMAGE;
+ fz_fin_cached_color_converter(ctx, &cc);
+ fz_drop_pixmap(ctx, pix);
+ fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
+ break;
+ }
}
+ s += ss;
}
fz_fin_cached_color_converter(ctx, &cc);
}
diff --git a/source/fitz/transition.c b/source/fitz/transition.c
index b4da6192..ec7d3f19 100644
--- a/source/fitz/transition.c
+++ b/source/fitz/transition.c
@@ -1,22 +1,40 @@
#include "mupdf/fitz.h"
+/*
+ FIXME: Currently transitions only work with alpha. Our app only
+ uses alpha.
+*/
+
static int
-fade(fz_pixmap *tpix, fz_pixmap *opix, fz_pixmap *npix, int time)
+fade(fz_pixmap *tpix, const fz_pixmap *opix, const fz_pixmap *npix, int time)
{
unsigned char *t, *o, *n;
int size;
+ int h;
+ int tstride, ostride, nstride;
if (!tpix || !opix || !npix || tpix->w != opix->w || opix->w != npix->w || tpix->h != opix->h || opix->h != npix->h || tpix->n != opix->n || opix->n != npix->n)
return 0;
- size = tpix->w * tpix->h * tpix->n;
+ h = tpix->h;
+ size = tpix->w * tpix->n;
+ ostride = opix->stride - size;
+ nstride = npix->stride - size;
+ tstride = tpix->stride - size;
t = tpix->samples;
o = opix->samples;
n = npix->samples;
- while (size-- > 0)
+ while (h--)
{
- int op = *o++;
- int np = *n++;
- *t++ = ((op<<8) + ((np-op) * time) + 0x80)>>8;
+ int ww = size;
+ while (ww-- > 0)
+ {
+ int op = *o++;
+ int np = *n++;
+ *t++ = ((op<<8) + ((np-op) * time) + 0x80)>>8;
+ }
+ o += ostride;
+ n += nstride;
+ t += tstride;
}
return 1;
}
@@ -25,22 +43,26 @@ static int
blind_horiz(fz_pixmap *tpix, fz_pixmap *opix, fz_pixmap *npix, int time)
{
unsigned char *t, *o, *n;
- int blind_height, span, position, y;
+ int blind_height, size, position, y;
+ int tstride, ostride, nstride;
if (!tpix || !opix || !npix || tpix->w != opix->w || opix->w != npix->w || tpix->h != opix->h || opix->h != npix->h || tpix->n != opix->n || opix->n != npix->n)
return 0;
- span = tpix->w * tpix->n;
+ size = tpix->w * tpix->n;
blind_height = (tpix->h+7) / 8;
position = blind_height * time / 256;
+ ostride = opix->stride;
+ nstride = npix->stride;
+ tstride = tpix->stride;
t = tpix->samples;
o = opix->samples;
n = npix->samples;
for (y = 0; y < tpix->h; y++)
{
- memcpy(t, ((y % blind_height) <= position ? n : o), span);
- t += span;
- o += span;
- n += span;
+ memcpy(t, ((y % blind_height) <= position ? n : o), size);
+ t += tstride;
+ o += ostride;
+ n += nstride;
}
return 1;
}
@@ -49,15 +71,19 @@ static int
blind_vertical(fz_pixmap *tpix, fz_pixmap *opix, fz_pixmap *npix, int time)
{
unsigned char *t, *o, *n;
- int blind_width, span, position, y;
+ int blind_width, size, position, y;
+ int tstride, ostride, nstride;
if (!tpix || !opix || !npix || tpix->w != opix->w || opix->w != npix->w || tpix->h != opix->h || opix->h != npix->h || tpix->n != opix->n || opix->n != npix->n)
return 0;
- span = tpix->w * tpix->n;
+ size = tpix->w * tpix->n;
blind_width = (tpix->w+7) / 8;
position = blind_width * time / 256;
blind_width *= tpix->n;
position *= tpix->n;
+ ostride = opix->stride - size;
+ nstride = npix->stride - size;
+ tstride = tpix->stride - size;
t = tpix->samples;
o = opix->samples;
n = npix->samples;
@@ -65,7 +91,7 @@ blind_vertical(fz_pixmap *tpix, fz_pixmap *opix, fz_pixmap *npix, int time)
{
int w, x;
x = 0;
- while ((w = span - x) > 0)
+ while ((w = size - x) > 0)
{
int p;
if (w > blind_width)
@@ -80,6 +106,9 @@ blind_vertical(fz_pixmap *tpix, fz_pixmap *opix, fz_pixmap *npix, int time)
o += w;
n += w;
}
+ o += ostride;
+ n += nstride;
+ t += tstride;
}
return 1;
}
@@ -88,28 +117,32 @@ static int
wipe_tb(fz_pixmap *tpix, fz_pixmap *opix, fz_pixmap *npix, int time)
{
unsigned char *t, *o, *n;
- int span, position, y;
+ int size, position, y;
+ int tstride, ostride, nstride;
if (!tpix || !opix || !npix || tpix->w != opix->w || opix->w != npix->w || tpix->h != opix->h || opix->h != npix->h || tpix->n != opix->n || opix->n != npix->n)
return 0;
- span = tpix->w * tpix->n;
+ size = tpix->w * tpix->n;
position = tpix->h * time / 256;
+ ostride = opix->stride;
+ nstride = npix->stride;
+ tstride = tpix->stride;
t = tpix->samples;
o = opix->samples;
n = npix->samples;
for (y = 0; y < position; y++)
{
- memcpy(t, n, span);
- t += span;
- o += span;
- n += span;
+ memcpy(t, n, size);
+ t += tstride;
+ o += ostride;
+ n += nstride;
}
for (; y < tpix->h; y++)
{
- memcpy(t, o, span);
- t += span;
- o += span;
- n += span;
+ memcpy(t, o, size);
+ t += tstride;
+ o += ostride;
+ n += nstride;
}
return 1;
}
@@ -118,23 +151,27 @@ static int
wipe_lr(fz_pixmap *tpix, fz_pixmap *opix, fz_pixmap *npix, int time)
{
unsigned char *t, *o, *n;
- int span, position, y;
+ int size, position, y;
+ int tstride, ostride, nstride;
if (!tpix || !opix || !npix || tpix->w != opix->w || opix->w != npix->w || tpix->h != opix->h || opix->h != npix->h || tpix->n != opix->n || opix->n != npix->n)
return 0;
- span = tpix->w * tpix->n;
+ size = tpix->w * tpix->n;
position = tpix->w * time / 256;
position *= tpix->n;
+ ostride = opix->stride;
+ nstride = npix->stride;
+ tstride = tpix->stride;
t = tpix->samples;
o = opix->samples + position;
n = npix->samples;
for (y = 0; y < tpix->h; y++)
{
memcpy(t, n, position);
- memcpy(t+position, o, span-position);
- t += span;
- o += span;
- n += span;
+ memcpy(t+position, o, size-position);
+ t += tstride;
+ o += ostride;
+ n += nstride;
}
return 1;
}
diff --git a/source/fitz/util.c b/source/fitz/util.c
index 0d782ba8..01e52e91 100644
--- a/source/fitz/util.c
+++ b/source/fitz/util.c
@@ -43,7 +43,7 @@ fz_new_display_list_from_page_number(fz_context *ctx, fz_document *doc, int numb
}
fz_pixmap *
-fz_new_pixmap_from_display_list(fz_context *ctx, fz_display_list *list, const fz_matrix *ctm, fz_colorspace *cs, int background)
+fz_new_pixmap_from_display_list(fz_context *ctx, fz_display_list *list, const fz_matrix *ctm, fz_colorspace *cs, int alpha)
{
fz_rect rect;
fz_irect irect;
@@ -54,11 +54,11 @@ fz_new_pixmap_from_display_list(fz_context *ctx, fz_display_list *list, const fz
fz_transform_rect(&rect, ctm);
fz_round_rect(&irect, &rect);
- pix = fz_new_pixmap_with_bbox(ctx, cs, &irect);
- if (background)
- fz_clear_pixmap_with_value(ctx, pix, 0xFF);
- else
+ pix = fz_new_pixmap_with_bbox(ctx, cs, &irect, alpha);
+ if (alpha)
fz_clear_pixmap(ctx, pix);
+ else
+ fz_clear_pixmap_with_value(ctx, pix, 0xFF);
fz_try(ctx)
{
@@ -90,7 +90,7 @@ fz_new_pixmap_from_page_contents(fz_context *ctx, fz_page *page, const fz_matrix
fz_transform_rect(&rect, ctm);
fz_round_rect(&irect, &rect);
- pix = fz_new_pixmap_with_bbox(ctx, cs, &irect);
+ pix = fz_new_pixmap_with_bbox(ctx, cs, &irect, 0);
fz_clear_pixmap_with_value(ctx, pix, 0xFF);
fz_try(ctx)
@@ -123,7 +123,7 @@ fz_new_pixmap_from_annot(fz_context *ctx, fz_annot *annot, const fz_matrix *ctm,
fz_transform_rect(&rect, ctm);
fz_round_rect(&irect, &rect);
- pix = fz_new_pixmap_with_bbox(ctx, cs, &irect);
+ pix = fz_new_pixmap_with_bbox(ctx, cs, &irect, 1);
fz_clear_pixmap(ctx, pix);
fz_try(ctx)
@@ -156,7 +156,7 @@ fz_new_pixmap_from_page(fz_context *ctx, fz_page *page, const fz_matrix *ctm, fz
fz_transform_rect(&rect, ctm);
fz_round_rect(&irect, &rect);
- pix = fz_new_pixmap_with_bbox(ctx, cs, &irect);
+ pix = fz_new_pixmap_with_bbox(ctx, cs, &irect, 0);
fz_clear_pixmap_with_value(ctx, pix, 0xFF);
fz_try(ctx)
diff --git a/source/pdf/pdf-image.c b/source/pdf/pdf-image.c
index 51bb4583..3bba27ad 100644
--- a/source/pdf/pdf-image.c
+++ b/source/pdf/pdf-image.c
@@ -40,12 +40,13 @@ pdf_load_image_imp(fz_context *ctx, pdf_document *doc, pdf_obj *rdb, pdf_obj *di
fz_pixmap_image *cimg = (fz_pixmap_image *)image;
fz_pixmap *mask_pixmap;
fz_pixmap *tile = fz_pixmap_image_tile(ctx, cimg);
- if (image->n != 2)
+ if (tile->n != 1)
{
fz_pixmap *gray;
fz_irect bbox;
- fz_warn(ctx, "soft mask should be grayscale");
- gray = fz_new_pixmap_with_bbox(ctx, fz_device_gray(ctx), fz_pixmap_bbox(ctx, tile, &bbox));
+ if (tile->n != 2)
+ fz_warn(ctx, "soft mask should be grayscale");
+ gray = fz_new_pixmap_with_bbox(ctx, fz_device_gray(ctx), fz_pixmap_bbox(ctx, tile, &bbox), 0);
fz_convert_pixmap(ctx, gray, tile);
fz_drop_pixmap(ctx, tile);
tile = gray;
@@ -323,32 +324,44 @@ pdf_add_image(fz_context *ctx, pdf_document *doc, fz_image *image, int mask)
else
{
unsigned int size;
- int n;
+ int n, h;
+ unsigned char *d, *s;
/* Currently, set to maintain resolution; should we consider
* subsampling here according to desired output res? */
pixmap = fz_get_pixmap_from_image(ctx, image, NULL, NULL, NULL, NULL);
colorspace = pixmap->colorspace; /* May be different to image->colorspace! */
- n = (pixmap->n == 1 ? 1 : pixmap->n - 1);
- size = image->w * image->h * n;
+ n = (pixmap->n == 1 ? 1 : pixmap->n - pixmap->alpha);
+ d = buffer->data;
+ s = pixmap->samples;
+ h = image->h;
+ size = image->w * n;
buffer = fz_new_buffer(ctx, size);
buffer->len = size;
- if (pixmap->n == 1)
+ if (pixmap->alpha == 0 || n == 1)
{
- memcpy(buffer->data, pixmap->samples, size);
+ while (h--)
+ {
+ memcpy(d, s, size);
+ d += size;
+ s += pixmap->stride;
+ }
}
else
{
/* Need to remove the alpha plane */
- unsigned char *d = buffer->data;
- unsigned char *s = pixmap->samples;
int mod = n;
- while (size--)
+ int stride = pixmap->stride - pixmap->w * pixmap->n;
+ while (h--)
{
- *d++ = *s++;
- mod--;
- if (mod == 0)
- s++, mod = n;
+ while (size--)
+ {
+ *d++ = *s++;
+ mod--;
+ if (mod == 0)
+ s++, mod = n;
+ }
+ s += stride;
}
}
}
diff --git a/source/pdf/pdf-resources.c b/source/pdf/pdf-resources.c
index 212c57df..b66c0a23 100644
--- a/source/pdf/pdf-resources.c
+++ b/source/pdf/pdf-resources.c
@@ -27,10 +27,18 @@ res_image_get_md5(fz_context *ctx, fz_image *image, unsigned char *digest)
{
fz_pixmap *pixmap;
fz_md5 state;
+ int h;
+ unsigned char *d;
pixmap = fz_get_pixmap_from_image(ctx, image, NULL, NULL, 0, 0);
fz_md5_init(&state);
- fz_md5_update(&state, pixmap->samples, pixmap->w * pixmap->h * pixmap->n);
+ d = pixmap->samples;
+ h = pixmap->h;
+ while (h--)
+ {
+ fz_md5_update(&state, d, pixmap->w * pixmap->n);
+ d += pixmap->stride;
+ }
fz_md5_final(&state, digest);
fz_drop_pixmap(ctx, pixmap);
}
diff --git a/source/tools/mudraw.c b/source/tools/mudraw.c
index a58912a9..b1ab97e9 100644
--- a/source/tools/mudraw.c
+++ b/source/tools/mudraw.c
@@ -363,6 +363,7 @@ static int lowmemory = 0;
static int errored = 0;
static fz_stext_sheet *sheet = NULL;
static fz_colorspace *colorspace;
+static int alpha;
static char *filename;
static int files = 0;
static int num_workers = 0;
@@ -835,7 +836,7 @@ static void dodrawpage(fz_context *ctx, fz_page *page, fz_display_list *list, in
workers[band].tbounds = tbounds;
memset(&workers[band].cookie, 0, sizeof(fz_cookie));
workers[band].list = list;
- workers[band].pix = fz_new_pixmap_with_bbox(ctx, colorspace, &band_ibounds);
+ workers[band].pix = fz_new_pixmap_with_bbox(ctx, colorspace, &band_ibounds, alpha);
fz_pixmap_set_resolution(workers[band].pix, resolution);
DEBUG_THREADS(("Worker %d, Pre-triggering band %d\n", band, band));
SEMAPHORE_TRIGGER(workers[band].start);
@@ -845,7 +846,7 @@ static void dodrawpage(fz_context *ctx, fz_page *page, fz_display_list *list, in
}
else
{
- pix = fz_new_pixmap_with_bbox(ctx, colorspace, &band_ibounds);
+ pix = fz_new_pixmap_with_bbox(ctx, colorspace, &band_ibounds, alpha);
fz_pixmap_set_resolution(pix, resolution);
}
@@ -857,7 +858,7 @@ static void dodrawpage(fz_context *ctx, fz_page *page, fz_display_list *list, in
else if (output_format == OUT_PAM)
fz_write_pam_header(ctx, out, pix->w, totalheight, pix->n, savealpha);
else if (output_format == OUT_PNG)
- poc = fz_write_png_header(ctx, out, pix->w, totalheight, pix->n, savealpha);
+ poc = fz_write_png_header(ctx, out, pix->w, totalheight, pix->n, pix->alpha, savealpha);
else if (output_format == OUT_PBM)
fz_write_pbm_header(ctx, out, pix->w, totalheight);
else if (output_format == OUT_PKM)
@@ -889,11 +890,11 @@ static void dodrawpage(fz_context *ctx, fz_page *page, fz_display_list *list, in
if (output)
{
if (output_format == OUT_PGM || output_format == OUT_PPM || output_format == OUT_PNM)
- fz_write_pnm_band(ctx, out, pix->w, totalheight, pix->n, band, drawheight, pix->samples);
+ fz_write_pnm_band(ctx, out, pix->w, totalheight, pix->n, pix->stride, band, drawheight, pix->samples);
else if (output_format == OUT_PAM)
- fz_write_pam_band(ctx, out, pix->w, totalheight, pix->n, band, drawheight, pix->samples, savealpha);
+ fz_write_pam_band(ctx, out, pix->w, totalheight, pix->n, pix->stride, band, drawheight, pix->samples, savealpha);
else if (output_format == OUT_PNG)
- fz_write_png_band(ctx, out, poc, pix->w, totalheight, pix->n, band, drawheight, pix->samples, savealpha);
+ fz_write_png_band(ctx, out, poc, pix->stride, band, drawheight, pix->samples);
else if (output_format == OUT_PWG)
fz_write_pixmap_as_pwg(ctx, out, pix, NULL);
else if (output_format == OUT_PCL)
@@ -905,10 +906,10 @@ static void dodrawpage(fz_context *ctx, fz_page *page, fz_display_list *list, in
fz_drop_bitmap(ctx, bit);
}
else
- fz_write_color_pcl_band(ctx, out, pccoc, pix->w, totalheight, pix->n, band, drawheight, pix->samples);
+ fz_write_color_pcl_band(ctx, out, pccoc, pix->w, totalheight, pix->n, pix->stride, band, drawheight, pix->samples);
}
else if (output_format == OUT_PS)
- fz_write_ps_band(ctx, out, psoc, pix->w, totalheight, pix->n, band, drawheight, pix->samples);
+ fz_write_ps_band(ctx, out, psoc, pix->w, totalheight, pix->n, pix->stride, band, drawheight, pix->samples);
else if (output_format == OUT_PBM) {
fz_bitmap *bit = fz_new_bitmap_from_pixmap_band(ctx, pix, NULL, band, bandheight);
fz_write_pbm_band(ctx, out, bit);
@@ -1537,20 +1538,24 @@ int mudraw_main(int argc, char **argv)
}
}
+ alpha = 1;
switch (out_cs)
{
case CS_MONO:
case CS_GRAY:
case CS_GRAY_ALPHA:
colorspace = fz_device_gray(ctx);
+ alpha = (out_cs == CS_GRAY_ALPHA);
break;
case CS_RGB:
case CS_RGB_ALPHA:
colorspace = fz_device_rgb(ctx);
+ alpha = (out_cs == CS_RGB_ALPHA);
break;
case CS_CMYK:
case CS_CMYK_ALPHA:
colorspace = fz_device_cmyk(ctx);
+ alpha = (out_cs == CS_CMYK_ALPHA);
break;
default:
fprintf(stderr, "Unknown colorspace!\n");
diff --git a/source/tools/murun.c b/source/tools/murun.c
index b8a7d991..e069bf0d 100644
--- a/source/tools/murun.c
+++ b/source/tools/murun.c
@@ -1748,10 +1748,11 @@ static void ffi_new_Pixmap(js_State *J)
fz_context *ctx = js_getcontext(J);
fz_colorspace *colorspace = js_touserdata(J, 1, "fz_colorspace");
fz_irect bounds = ffi_toirect(J, 2);
+ int alpha = js_toboolean(J, 3);
fz_pixmap *pixmap;
fz_try(ctx)
- pixmap = fz_new_pixmap_with_bbox(ctx, colorspace, &bounds);
+ pixmap = fz_new_pixmap_with_bbox(ctx, colorspace, &bounds, alpha);
fz_catch(ctx)
rethrow(J);
@@ -2260,11 +2261,11 @@ static void ffi_DisplayList_toPixmap(js_State *J)
fz_display_list *list = js_touserdata(J, 0, "fz_display_list");
fz_matrix ctm = ffi_tomatrix(J, 1);
fz_colorspace *colorspace = js_touserdata(J, 2, "fz_colorspace");
- int solid = js_isdefined(J, 3) ? js_toboolean(J, 3) : 1;
+ int alpha = js_isdefined(J, 3) ? js_toboolean(J, 3) : 0;
fz_pixmap *pixmap;
fz_try(ctx)
- pixmap = fz_new_pixmap_from_display_list(ctx, list, &ctm, colorspace, solid);
+ pixmap = fz_new_pixmap_from_display_list(ctx, list, &ctm, colorspace, alpha);
fz_catch(ctx)
rethrow(J);
@@ -3301,7 +3302,7 @@ int murun_main(int argc, char **argv)
jsB_propcon(J, "fz_buffer", "Buffer", ffi_new_Buffer, 1);
jsB_propcon(J, "fz_document", "Document", ffi_new_Document, 1);
- jsB_propcon(J, "fz_pixmap", "Pixmap", ffi_new_Pixmap, 2);
+ jsB_propcon(J, "fz_pixmap", "Pixmap", ffi_new_Pixmap, 3);
jsB_propcon(J, "fz_image", "Image", ffi_new_Image, 1);
jsB_propcon(J, "fz_font", "Font", ffi_new_Font, 2);
jsB_propcon(J, "fz_text", "Text", ffi_new_Text, 0);
diff --git a/source/tools/pdfextract.c b/source/tools/pdfextract.c
index 3f79137a..b784fda1 100644
--- a/source/tools/pdfextract.c
+++ b/source/tools/pdfextract.c
@@ -39,7 +39,7 @@ static void writepixmap(fz_context *ctx, fz_pixmap *pix, char *file, int rgb)
if (rgb && pix->colorspace && pix->colorspace != fz_device_rgb(ctx))
{
fz_irect bbox;
- converted = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), fz_pixmap_bbox(ctx, pix, &bbox));
+ converted = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), fz_pixmap_bbox(ctx, pix, &bbox), 1);
fz_convert_pixmap(ctx, converted, pix);
pix = converted;
}