diff options
-rw-r--r-- | draw/draw_blend.c | 69 |
1 files changed, 50 insertions, 19 deletions
diff --git a/draw/draw_blend.c b/draw/draw_blend.c index 6775e79d..a4cdbf19 100644 --- a/draw/draw_blend.c +++ b/draw/draw_blend.c @@ -364,37 +364,64 @@ fz_blend_separable_nonisolated(byte * restrict bp, byte * restrict sp, int n, in int ha = *hp++; int haa = fz_mul255(ha, alpha); /* ha = shape_alpha */ /* If haa == 0 then leave everything unchanged */ - if (haa != 0) + while (haa != 0) /* Use while, so we can break out */ { - int sa = sp[n1]; - int ba = bp[n1]; - int baha = fz_mul255(ba, haa); + int sa, ba, bahaa, ra, invsa, invba, invha, invra; + sa = sp[n1]; + if (sa == 0) + break; /* No change! */ + invsa = sa ? 255 * 256 / sa : 0; + ba = bp[n1]; + if (ba == 0) + { + /* Just copy pixels (allowing for change in + * premultiplied alphas) */ + for (k = 0; k < n1; k++) + { + bp[k] = fz_mul255((sp[k] * invsa) >> 8, haa); + } + bp[n1] = haa; + break; + } + bahaa = 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 + haa; + invba = ba ? 255 * 256 / ba : 0; + /* Calculate result_alpha - a combination of the + * background alpha, and 'shape' */ + ra = bp[n1] = ba - bahaa + haa; + if (ra == 0) + break; /* 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 + * the group, so: 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: + * sc = (rc - bc)/ha + bc + * Now, the result of the blend (rc) was stored in src, so + * we actually want to calculate: + * sc = (sc-bc)/ha + bc */ - int invha = ha ? 255 * 256 / ha : 0; + invha = ha ? 255 * 256 / ha : 0; + invra = ra ? 255 * 256 / ra : 0; + + /* sa = the final alpha to blend with - this + * is calculated from the shape + alpha, + * divided by ra. */ + sa = (haa*invra + 128)>>8; + if (sa < 0) sa = 0; + if (sa > 255) sa = 255; - if (ra != 0) for (k = 0; k < n1; k++) + for (k = 0; k < n1; k++) { - int sc = (sp[k] * invsa) >> 8; - int bc = (bp[k] * invba) >> 8; + /* Read pixels (and convert to non-premultiplied form) */ + int sc = (sp[k] * invsa + 128) >> 8; + int bc = (bp[k] * invba + 128) >> 8; int rc; - /* Uncomposite */ - sc = (((sc-bc)*invha)>>8) + bc; + /* Uncomposite (see above) */ + sc = (((sc-bc) * invha + 128)>>8) + bc; if (sc < 0) sc = 0; if (sc > 255) sc = 255; @@ -414,11 +441,15 @@ 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 - haa, bc) + fz_mul255(fz_mul255(255 - ba, sc), haa) + fz_mul255(baha, rc); + /* Composition formula, as given in pdf_reference17.pdf: + * rc = ( 1 - (ha/ra)) * bc + (ha/ra) * ((1-ba)*sc + ba * rc) + */ + 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); } + break; } sp += n; |