summaryrefslogtreecommitdiff
path: root/draw
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2010-07-21 15:28:37 +0000
committerTor Andersson <tor@ghostscript.com>2010-07-21 15:28:37 +0000
commit869cd3ece49149ae9badee5f0c96d5561fbbed53 (patch)
tree0757e704bd4086a214cc0019c748f82709eac998 /draw
parentf80091ed41a318c328b76cc307ec715807173085 (diff)
downloadmupdf-869cd3ece49149ae9badee5f0c96d5561fbbed53.tar.xz
Reorganize pixmap blending functions.
Diffstat (limited to 'draw')
-rw-r--r--draw/blendmodes.c99
-rw-r--r--draw/meshdraw.c46
-rw-r--r--draw/porterduff.c287
3 files changed, 219 insertions, 213 deletions
diff --git a/draw/blendmodes.c b/draw/blendmodes.c
index 455ff7b4..3f80d4f9 100644
--- a/draw/blendmodes.c
+++ b/draw/blendmodes.c
@@ -131,12 +131,15 @@ fz_luminosity_rgb(int *rd, int *gd, int *bd, int rb, int gb, int bb, int rs, int
if ((r | g | b) & 0x100)
{
y = (rs * 77 + gs * 151 + bs * 28 + 0x80) >> 8;
- if (delta > 0) {
+ if (delta > 0)
+ {
int max;
max = r > g ? r : g;
max = b > max ? b : max;
scale = ((255 - y) << 16) / (max - y);
- } else {
+ }
+ else
+ {
int min;
min = r < g ? r : g;
min = b < min ? b : min;
@@ -165,7 +168,8 @@ fz_saturation_rgb(int *rd, int *gd, int *bd, int rb, int gb, int bb, int rs, int
minb = minb < bb ? minb : bb;
maxb = rb > gb ? rb : gb;
maxb = maxb > bb ? maxb : bb;
- if (minb == maxb) {
+ if (minb == maxb)
+ {
/* backdrop has zero saturation, avoid divide by 0 */
*rd = gb;
*gd = gb;
@@ -184,7 +188,8 @@ fz_saturation_rgb(int *rd, int *gd, int *bd, int rb, int gb, int bb, int rs, int
g = y + ((((gb - y) * scale) + 0x8000) >> 16);
b = y + ((((bb - y) * scale) + 0x8000) >> 16);
- if ((r | g | b) & 0x100) {
+ if ((r | g | b) & 0x100)
+ {
int scalemin, scalemax;
int min, max;
@@ -228,10 +233,10 @@ fz_hue_rgb(int *rr, int *rg, int *rb, int br, int bg, int bb, int sr, int sg, in
fz_saturation_rgb(rr, rg, rb, tr, tg, tb, br, bg, bb);
}
-/* Blending functions */
+/* Blending loops */
-static void
-fz_blendseparable(byte * restrict sp, byte * restrict bp, int n, int w, fz_blendmode blendmode)
+void
+fz_blendseparable(byte * restrict bp, byte * restrict sp, int n, int w, fz_blendmode blendmode)
{
int k;
int n1 = n - 1;
@@ -241,16 +246,16 @@ fz_blendseparable(byte * restrict sp, byte * restrict bp, int n, int w, fz_blend
int ba = bp[n1];
int saba = fz_mul255(sa, ba);
+ /* ugh, division to get non-premul components */
+ int invsa = sa ? 255 * 256 / sa : 0;
+ int invba = ba ? 255 * 256 / ba : 0;
+
for (k = 0; k < n1; k++)
{
- int sc = sp[k];
- int bc = bp[k];
+ int sc = (sp[k] * invsa) >> 8;
+ int bc = (bp[k] * invba) >> 8;
int rc;
- /* ugh, division to get non-premul components */
- if (sa) sc = sc * 255 / sa;
- if (ba) bc = bc * 255 / ba;
-
switch (blendmode)
{
default:
@@ -278,36 +283,28 @@ fz_blendseparable(byte * restrict sp, byte * restrict bp, int n, int w, fz_blend
}
}
-static void
-fz_blendnonseparable(byte * restrict sp, byte * restrict bp, int w, fz_blendmode blendmode)
+void
+fz_blendnonseparable(byte * restrict bp, byte * restrict sp, int w, fz_blendmode blendmode)
{
while (w--)
{
- int rr, rg, rb, saba;
+ int rr, rg, rb;
- int sr = sp[0];
- int sg = sp[1];
- int sb = sp[2];
int sa = sp[3];
-
- int br = bp[0];
- int bg = bp[1];
- int bb = bp[2];
int ba = bp[3];
-
- saba = fz_mul255(sa, ba);
+ int saba = fz_mul255(sa, ba);
/* ugh, division to get non-premul components */
- if (sa) {
- sr = sr * 255 / sa;
- sg = sg * 255 / sa;
- sb = sb * 255 / sa;
- }
- if (ba) {
- br = br * 255 / ba;
- bg = bg * 255 / ba;
- bb = bb * 255 / ba;
- }
+ int invsa = sa ? 255 * 256 / sa : 0;
+ int invba = ba ? 255 * 256 / ba : 0;
+
+ int sr = (sp[0] * invsa) >> 8;
+ int sg = (sp[1] * invsa) >> 8;
+ int sb = (sp[2] * invsa) >> 8;
+
+ int br = (bp[0] * invba) >> 8;
+ int bg = (bp[1] * invba) >> 8;
+ int bb = (bp[2] * invba) >> 8;
switch (blendmode)
{
@@ -337,40 +334,32 @@ fz_blendnonseparable(byte * restrict sp, byte * restrict bp, int w, fz_blendmode
}
void
-fz_blendpixmaps(fz_pixmap *src, fz_pixmap *dst, fz_blendmode blendmode)
+fz_blendpixmapswithmode(fz_pixmap *dst, fz_pixmap *src, fz_blendmode blendmode)
{
unsigned char *sp, *dp;
- fz_bbox sr, dr;
+ fz_bbox bbox;
int x, y, w, h, n;
- assert(src->n == dst->n);
-
- sr.x0 = src->x;
- sr.y0 = src->y;
- sr.x1 = src->x + src->w;
- sr.y1 = src->y + src->h;
+ bbox = fz_boundpixmap(dst);
+ bbox = fz_intersectbbox(bbox, fz_boundpixmap(src));
- dr.x0 = dst->x;
- dr.y0 = dst->y;
- dr.x1 = dst->x + dst->w;
- dr.y1 = dst->y + dst->h;
-
- dr = fz_intersectbbox(sr, dr);
- x = dr.x0;
- y = dr.y0;
- w = dr.x1 - dr.x0;
- h = dr.y1 - dr.y0;
+ x = bbox.x0;
+ y = bbox.y0;
+ w = bbox.x1 - bbox.x0;
+ h = bbox.y1 - bbox.y0;
n = src->n;
sp = src->samples + ((y - src->y) * src->w + (x - src->x)) * n;
dp = dst->samples + ((y - dst->y) * dst->w + (x - dst->x)) * n;
+ assert(src->n == dst->n);
+
while (h--)
{
if (n == 4 && blendmode >= FZ_BHUE)
- fz_blendnonseparable(sp, dp, w, blendmode);
+ fz_blendnonseparable(dp, sp, w, blendmode);
else
- fz_blendseparable(sp, dp, n, w, blendmode);
+ fz_blendseparable(dp, sp, n, w, blendmode);
sp += src->w * n;
dp += dst->w * n;
}
diff --git a/draw/meshdraw.c b/draw/meshdraw.c
index d71174d6..4fbdab70 100644
--- a/draw/meshdraw.c
+++ b/draw/meshdraw.c
@@ -314,20 +314,26 @@ void
fz_rendershade(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox)
{
unsigned char clut[256][FZ_MAXCOLORS];
- fz_pixmap *temp;
+ fz_pixmap *temp, *conv;
float color[FZ_MAXCOLORS];
float tri[3][MAXN];
fz_point p;
float *mesh;
int ntris;
int i, j, k;
- int x, y;
ctm = fz_concat(shade->matrix, ctm);
mesh = shade->mesh;
if (shade->usefunction)
{
+ for (i = 0; i < 256; i++)
+ {
+ fz_convertcolor(shade->cs, shade->function[i], dest->colorspace, color);
+ for (k = 0; k < dest->colorspace->n; k++)
+ clut[i][k] = color[k] * 255;
+ }
+ conv = fz_newpixmapwithrect(dest->colorspace, bbox);
temp = fz_newpixmapwithrect(fz_devicegray, bbox);
fz_clearpixmap(temp, 0);
ntris = shade->meshlen / 9;
@@ -362,34 +368,18 @@ fz_rendershade(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox)
if (shade->usefunction)
{
- unsigned char *s, *d;
- unsigned char sa, ssa, sc;
-
- for (i = 0; i < 256; i++)
+ unsigned char *s = temp->samples;
+ unsigned char *d = conv->samples;
+ int len = temp->w * temp->h;
+ while (len--)
{
- fz_convertcolor(shade->cs, shade->function[i], dest->colorspace, color);
- for (k = 0; k < dest->colorspace->n; k++)
- clut[i][k] = color[k] * 255;
- }
-
- /* duff_non with lookup table for colors */
- for (y = bbox.y0; y < bbox.y1; y++)
- {
- s = temp->samples + ((bbox.x0 - temp->x) + (y - temp->y) * temp->w) * temp->n;
- d = dest->samples + ((bbox.x0 - dest->x) + (y - dest->y) * dest->w) * dest->n;
- for (x = bbox.x0; x < bbox.x1; x++)
- {
- sc = s[0];
- sa = s[1];
- ssa = 255 - s[1];
- for (k = 0; k < dest->colorspace->n; k++)
- d[k] = fz_mul255(clut[sc][k], sa) + fz_mul255(d[k], ssa);
- d[k] = sa + fz_mul255(d[k], ssa);
- s += 2;
- d += dest->n;
- }
+ int v = *s++;
+ for (k = 0; k < conv->n - 1; k++)
+ *d++ = clut[v][k];
+ *d++ = *s++;
}
-
+ fz_blendpixmaps(dest, conv);
+ fz_droppixmap(conv);
fz_droppixmap(temp);
}
}
diff --git a/draw/porterduff.c b/draw/porterduff.c
index 40f900e0..99e00e05 100644
--- a/draw/porterduff.c
+++ b/draw/porterduff.c
@@ -73,124 +73,7 @@ and stick to using the premultiplied form.
typedef unsigned char byte;
/*
- * Blend pixmap regions
- */
-
-/* dst = src in msk over dst */
-static void
-duff_ni1on(byte * restrict sp, int sw, int sn, byte * restrict mp, int mw, byte * restrict dp, int dw, int w0, int h)
-{
- int k;
-
- sw -= w0*sn;
- mw -= w0;
- dw -= w0*sn;
- while (h--)
- {
- int w = w0;
- while (w--)
- {
- int ma = mp[0];
- int ssa = 255 - fz_mul255(sp[sn-1], ma);
- for (k = 0; k < sn; k++)
- {
- dp[k] = fz_mul255(sp[k], ma) + fz_mul255(dp[k], ssa);
- }
- sp += sn;
- mp ++;
- dp += sn;
- }
- sp += sw;
- mp += mw;
- dp += dw;
- }
-}
-
-static void
-duff_1i1o1(byte * restrict sp, int sw, byte * restrict mp, int mw, byte * restrict dp, int dw, int w0, int h)
-{
- /* duff_nimon(sp0, sw, 1, mp0, mw, 1, dp0, dw, w0, h); */
-
- sw -= w0;
- dw -= w0;
- mw -= w0;
- while (h--)
- {
- int w = w0;
- while (w--)
- {
- byte ma = mp[0];
- byte sa = fz_mul255(sp[0], ma);
- byte ssa = 255 - sa;
- dp[0] = sa + fz_mul255(dp[0], ssa);
- sp ++;
- mp ++;
- dp ++;
- }
- sp += sw;
- mp += mw;
- dp += dw;
- }
-}
-
-static void
-duff_2i1o2(byte * restrict sp, int sw, byte * restrict mp, int mw, byte * restrict dp, int dw, int w0, int h)
-{
-
- /* duff_nimon(sp, sw, 2, mp, mw, 1, dp, dw, w0, h); */
- sw -= w0<<1;
- dw -= w0<<1;
- mw -= w0;
- while (h--)
- {
- int w = w0;
- while (w--)
- {
- byte ma = mp[0];
- byte ssa = 255 - fz_mul255(sp[1], ma);
- dp[0] = fz_mul255(sp[0], ma) + fz_mul255(dp[0], ssa);
- dp[1] = fz_mul255(sp[1], ma) + fz_mul255(dp[1], ssa);
- sp += 2;
- mp += 1;
- dp += 2;
- }
- sp += sw;
- mp += mw;
- dp += dw;
- }
-}
-
-static void
-duff_4i1o4(byte * restrict sp, int sw, byte * restrict mp, int mw, byte * restrict dp, int dw, int w0, int h)
-{
- /* duff_nimon(sp, sw, 4, mp, mw, 1, dp, dw, w0, h); */
-
- sw -= w0<<2;
- dw -= w0<<2;
- mw -= w0;
- while (h--)
- {
- int w = w0;
- while (w--)
- {
- byte ma = mp[0];
- byte ssa = 255 - fz_mul255(sp[3], ma);
- dp[0] = fz_mul255(sp[0], ma) + fz_mul255(dp[0], ssa);
- dp[1] = fz_mul255(sp[1], ma) + fz_mul255(dp[1], ssa);
- dp[2] = fz_mul255(sp[2], ma) + fz_mul255(dp[2], ssa);
- dp[3] = fz_mul255(sp[3], ma) + fz_mul255(dp[3], ssa);
- sp += 4;
- mp += 1;
- dp += 4;
- }
- sp += sw;
- mp += mw;
- dp += dw;
- }
-}
-
-/*
- * Path masks
+ * Path drawing (the source colors are not premultiplied)
*/
static void
@@ -243,8 +126,12 @@ path_w4i1o4(byte *rgba, byte * restrict src, byte cov, int len, byte * restrict
}
}
+void (*fz_path_1o1)(byte*restrict,byte,int,byte*restrict) = path_1o1;
+void (*fz_path_w2i1o2)(byte*,byte*restrict,byte,int,byte*restrict) = path_w2i1o2;
+void (*fz_path_w4i1o4)(byte*,byte*restrict,byte,int,byte*restrict) = path_w4i1o4;
+
/*
- * Text masks
+ * Text drawing (the source colors are not premultiplied)
*/
static void
@@ -319,19 +206,159 @@ text_w4i1o4(byte *rgba, byte * restrict src, int srcw, byte * restrict dst, int
}
}
+void (*fz_text_1o1)(byte*restrict,int,byte*restrict,int,int,int) = text_1o1;
+void (*fz_text_w2i1o2)(byte*,byte*restrict,int,byte*restrict,int,int,int) = text_w2i1o2;
+void (*fz_text_w4i1o4)(byte*,byte*restrict,int,byte*restrict,int,int,int) = text_w4i1o4;
+
/*
- * ... and the function pointers
+ * Pixmap blending
*/
-void (*fz_duff_ni1on)(byte*restrict,int,int,byte*restrict,int,byte*restrict,int,int,int) = duff_ni1on;
-void (*fz_duff_1i1o1)(byte*restrict,int,byte*restrict,int,byte*restrict,int,int,int) = duff_1i1o1;
-void (*fz_duff_2i1o2)(byte*restrict,int,byte*restrict,int,byte*restrict,int,int,int) = duff_2i1o2;
-void (*fz_duff_4i1o4)(byte*restrict,int,byte*restrict,int,byte*restrict,int,int,int) = duff_4i1o4;
+void
+fz_blendwithmask(byte * restrict dp, byte * restrict sp, byte * restrict mp, int n, int w)
+{
+ int k;
-void (*fz_path_1o1)(byte*restrict,byte,int,byte*restrict) = path_1o1;
-void (*fz_path_w2i1o2)(byte*,byte*restrict,byte,int,byte*restrict) = path_w2i1o2;
-void (*fz_path_w4i1o4)(byte*,byte*restrict,byte,int,byte*restrict) = path_w4i1o4;
+ switch (n)
+ {
+ case 2:
+ while (w--)
+ {
+ int ma = *mp++;
+ int masa = fz_mul255(sp[1], ma);
+ int t = 255 - masa;
+ dp[0] = fz_mul255(sp[0], ma) + fz_mul255(dp[0], t);
+ sp += 2;
+ dp += 2;
+ }
+ break;
+ case 4:
+ while (w--)
+ {
+ int ma = *mp++;
+ int masa = fz_mul255(sp[3], ma);
+ int t = 255 - masa;
+ dp[0] = fz_mul255(sp[0], ma) + fz_mul255(dp[0], t);
+ dp[1] = fz_mul255(sp[1], ma) + fz_mul255(dp[1], t);
+ dp[2] = fz_mul255(sp[2], ma) + fz_mul255(dp[2], t);
+ dp[3] = fz_mul255(sp[3], ma) + fz_mul255(dp[3], t);
+ sp += 4;
+ dp += 4;
+ }
+ break;
+ default:
+ while (w--)
+ {
+ int ma = *mp++;
+ int masa = fz_mul255(sp[n-1], ma);
+ int t = 255 - masa;
+ for (k = 0; k < n; k++)
+ dp[k] = fz_mul255(sp[k], ma) + fz_mul255(dp[k], t);
+ sp += n;
+ dp += n;
+ }
+ }
+}
-void (*fz_text_1o1)(byte*restrict,int,byte*restrict,int,int,int) = text_1o1;
-void (*fz_text_w2i1o2)(byte*,byte*restrict,int,byte*restrict,int,int,int) = text_w2i1o2;
-void (*fz_text_w4i1o4)(byte*,byte*restrict,int,byte*restrict,int,int,int) = text_w4i1o4;
+void
+fz_blendwithalpha(byte * restrict dp, byte * restrict sp, int ma, int n, int w)
+{
+ int k;
+
+ while (w--)
+ {
+ int masa = fz_mul255(sp[n-1], ma);
+ int t = 255 - masa;
+ for (k = 0; k < n; k++)
+ dp[k] = fz_mul255(sp[k], ma) + fz_mul255(dp[k], t);
+ sp += n;
+ dp += n;
+ }
+}
+
+void
+fz_blendnormal(byte * restrict dp, byte * restrict sp, int n, int w)
+{
+ int k;
+
+ while (w--)
+ {
+ int t = 255 - sp[n-1];
+ for (k = 0; k < n; k++)
+ dp[k] = sp[k] + fz_mul255(dp[k], t);
+ sp += n;
+ dp += n;
+ }
+}
+
+void
+fz_blendpixmapswithmask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *msk)
+{
+ unsigned char *sp, *dp, *mp;
+ fz_bbox bbox;
+ int x, y, w, h, n;
+
+ bbox = fz_boundpixmap(dst);
+ bbox = fz_intersectbbox(bbox, fz_boundpixmap(src));
+ bbox = fz_intersectbbox(bbox, fz_boundpixmap(msk));
+
+ x = bbox.x0;
+ y = bbox.y0;
+ w = bbox.x1 - bbox.x0;
+ h = bbox.y1 - bbox.y0;
+
+ n = src->n;
+ sp = src->samples + ((y - src->y) * src->w + (x - src->x)) * src->n;
+ mp = msk->samples + ((y - msk->y) * msk->w + (x - msk->x)) * msk->n;
+ dp = dst->samples + ((y - dst->y) * dst->w + (x - dst->x)) * dst->n;
+
+ assert(dst->n == src->n);
+ assert(msk->n == 1);
+
+ while (h--)
+ {
+ fz_blendwithmask(dp, sp, mp, n, w);
+ sp += src->w * n;
+ dp += dst->w * n;
+ mp += msk->w;
+ }
+}
+
+void
+fz_blendpixmapswithalpha(fz_pixmap *dst, fz_pixmap *src, float alpha)
+{
+ unsigned char *sp, *dp;
+ fz_bbox bbox;
+ int x, y, w, h, n, a;
+
+ bbox = fz_boundpixmap(dst);
+ bbox = fz_intersectbbox(bbox, fz_boundpixmap(src));
+
+ x = bbox.x0;
+ y = bbox.y0;
+ w = bbox.x1 - bbox.x0;
+ h = bbox.y1 - bbox.y0;
+
+ a = alpha * 255;
+ n = src->n;
+ sp = src->samples + ((y - src->y) * src->w + (x - src->x)) * src->n;
+ dp = dst->samples + ((y - dst->y) * dst->w + (x - dst->x)) * dst->n;
+
+ assert(dst->n == src->n);
+
+ while (h--)
+ {
+ if (a == 255)
+ fz_blendnormal(dp, sp, n, w);
+ else
+ fz_blendwithalpha(dp, sp, a, n, w);
+ sp += src->w * n;
+ dp += dst->w * n;
+ }
+}
+
+void
+fz_blendpixmaps(fz_pixmap *dst, fz_pixmap *src)
+{
+ fz_blendpixmapswithalpha(dst, src, 1);
+}