diff options
-rw-r--r-- | draw/draw_blend.c | 84 | ||||
-rw-r--r-- | draw/draw_device.c | 2 |
2 files changed, 71 insertions, 15 deletions
diff --git a/draw/draw_blend.c b/draw/draw_blend.c index 20ad8a28..2f72ec9c 100644 --- a/draw/draw_blend.c +++ b/draw/draw_blend.c @@ -335,22 +335,57 @@ fz_blend_separable_nonisolated(byte * restrict bp, byte * restrict sp, int n, in { int k; int n1 = n - 1; + + if (alpha == 255 && blendmode == 0) + { + /* In this case, the uncompositing and the recompositing + * cancel one another out, and it's just a simple copy. */ + /* FIXME: Maybe we can avoid using the shape plane entirely + * and just copy? */ + while (w--) + { + int ha = fz_mul255(*hp++, alpha); /* ha = shape_alpha */ + /* If ha == 0 then leave everything unchanged */ + if (ha != 0) + { + for (k = 0; k < n; k++) + { + bp[k] = sp[k]; + } + } + + sp += n; + bp += n; + } + return; + } while (w--) { - int ha = fz_mul255(*hp++, alpha); /* ha = shape_alpha */ - /* If ha == 0 then leave everything unchanged */ - if (ha != 0) + int ha = *hp++; + int haa = fz_mul255(ha, alpha); /* ha = shape_alpha */ + /* If haa == 0 then leave everything unchanged */ + if (haa != 0) { int sa = sp[n1]; int ba = bp[n1]; - int baha = fz_mul255(ba, ha); + int baha = fz_mul255(ba, haa); /* ugh, division to get non-premul components */ int invsa = sa ? 255 * 256 / sa : 0; int invba = ba ? 255 * 256 / ba : 0; /* Calculate result_alpha */ - int ra = bp[n1] = ba - baha + ha; + int ra = bp[n1] = ba - baha + haa; + + /* Because we are a non-isolated group, we need to + * 'uncomposite' before we blend (recomposite). + * We assume that normal blending has been done inside + * the group, so: ra.rc = (1-ha).bc + ha.sc + * A bit of rearrangement, and that gives us that: + * sc = (ra.rc - bc)/ha + bc + * Now, the result of the blend was stored in src, so: + */ + int invha = ha ? 255 * 256 / ha : 0; if (ra != 0) for (k = 0; k < n1; k++) { @@ -358,6 +393,11 @@ fz_blend_separable_nonisolated(byte * restrict bp, byte * restrict sp, int n, in int bc = (bp[k] * invba) >> 8; int rc; + /* Uncomposite */ + sc = (((sc-bc)*invha)>>8) + bc; + if (sc < 0) sc = 0; + if (sc > 255) sc = 255; + switch (blendmode) { default: @@ -374,7 +414,7 @@ fz_blend_separable_nonisolated(byte * restrict bp, byte * restrict sp, int n, in case FZ_BLEND_DIFFERENCE: rc = fz_difference_byte(bc, sc); break; case FZ_BLEND_EXCLUSION: rc = fz_exclusion_byte(bc, sc); break; } - rc = fz_mul255(255 - ha, bc) + fz_mul255(255 - ba, sc) + fz_mul255(baha, rc); + rc = fz_mul255(255 - haa, bc) + fz_mul255(fz_mul255(255 - ba, sc), haa) + fz_mul255(baha, rc); if (rc < 0) rc = 0; if (rc > 255) rc = 255; bp[k] = fz_mul255(rc, ra); @@ -391,18 +431,29 @@ fz_blend_nonseparable_nonisolated(byte * restrict bp, byte * restrict sp, int w, { while (w--) { - int ha = fz_mul255(*hp++, alpha); - if (ha != 0) + int ha = *hp++; + int haa = fz_mul255(ha, alpha); + if (haa != 0) { int sa = sp[3]; int ba = bp[3]; - int baha = fz_mul255(ba, ha); + int baha = fz_mul255(ba, haa); /* Calculate result_alpha */ - int ra = bp[3] = ba - baha + ha; - + int ra = bp[3] = ba - baha + haa; if (ra != 0) { + /* Because we are a non-isolated group, we + * need to 'uncomposite' before we blend + * (recomposite). We assume that normal + * blending has been done inside the group, + * so: ra.rc = (1-ha).bc + ha.sc + * A bit of rearrangement, and that gives us + * that: sc = (ra.rc - bc)/ha + bc + * Now, the result of the blend was stored in + * src, so: */ + int invha = ha ? 255 * 256 / ha : 0; + int rr, rg, rb; /* ugh, division to get non-premul components */ @@ -417,6 +468,11 @@ fz_blend_nonseparable_nonisolated(byte * restrict bp, byte * restrict sp, int w, int bg = (bp[1] * invba) >> 8; int bb = (bp[2] * invba) >> 8; + /* Uncomposite */ + sr = (((sr-br)*invha)>>8) + br; + sg = (((sg-bg)*invha)>>8) + bg; + sb = (((sb-bb)*invha)>>8) + bb; + switch (blendmode) { default: @@ -434,9 +490,9 @@ fz_blend_nonseparable_nonisolated(byte * restrict bp, byte * restrict sp, int w, break; } - rr = fz_mul255(255 - ha, bp[0]) + fz_mul255(255 - ba, sp[0]) + fz_mul255(baha, rr); - rg = fz_mul255(255 - ha, bp[1]) + fz_mul255(255 - ba, sp[1]) + fz_mul255(baha, rg); - rb = fz_mul255(255 - ha, bp[2]) + fz_mul255(255 - ba, sp[2]) + fz_mul255(baha, rb); + rr = fz_mul255(255 - haa, bp[0]) + fz_mul255(fz_mul255(255 - ba, sr), haa) + fz_mul255(baha, rr); + rg = fz_mul255(255 - haa, bp[1]) + fz_mul255(fz_mul255(255 - ba, sg), haa) + fz_mul255(baha, rg); + rb = fz_mul255(255 - haa, bp[2]) + fz_mul255(fz_mul255(255 - ba, sb), haa) + fz_mul255(baha, rb); bp[0] = fz_mul255(ra, rr); bp[1] = fz_mul255(ra, rg); bp[2] = fz_mul255(ra, rb); diff --git a/draw/draw_device.c b/draw/draw_device.c index f3ced47d..3c1f8114 100644 --- a/draw/draw_device.c +++ b/draw/draw_device.c @@ -134,7 +134,7 @@ static void fz_knockout_begin(void *user) dev->stack[dev->top].dest = dev->dest; dev->stack[dev->top].shape = dev->shape; #ifdef DUMP_GROUP_BLENDS - dump_spaces(dev->top, "Knockout begin"); + dump_spaces(dev->top, "Knockout begin\n"); #endif dev->top++; |