diff options
Diffstat (limited to 'source')
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; } |