summaryrefslogtreecommitdiff
path: root/draw/draw_blend.c
diff options
context:
space:
mode:
authorRobin Watts <Robin.Watts@artifex.com>2011-07-13 20:31:56 +0100
committerRobin Watts <robin.watts@artifex.com>2011-07-13 21:03:28 +0100
commit6913145eefde0e5c4cde9573d8d2cb2a35fd605d (patch)
treef79dc7269f4f562bdb168b572a37367e806e0190 /draw/draw_blend.c
parent2c4bbbfdc7413a68cad395c3c61ff8e62dceb18b (diff)
downloadmupdf-6913145eefde0e5c4cde9573d8d2cb2a35fd605d.tar.xz
Non-isolated group support, and fix Bug 692336.
Firstly, this takes on some of Zenikos patch to correct the clip stack handling that was broken by the fix to bug 692287 (in commit 2c3bbbf). This bug should now be solved. We add a new 'shape' field to the draw device structure (and clip stack). When we are inside non-isolated groups, this is set to be a pixmap where we accumulate the 'shape' of the objects drawn. When we come to blend back, if we are blending a non-isolated group back, we have to use a different blending function that takes account of the shape. Various internal groups (the page group, and groups used to force blending) are set to be isolated to avoid carrying shape planes around when this is not required. All our rendering code now has to know how to maintain the shape plane as well as doing the basic rendering.
Diffstat (limited to 'draw/draw_blend.c')
-rw-r--r--draw/draw_blend.c174
1 files changed, 143 insertions, 31 deletions
diff --git a/draw/draw_blend.c b/draw/draw_blend.c
index ef9d8c7c..0634f944 100644
--- a/draw/draw_blend.c
+++ b/draw/draw_blend.c
@@ -4,29 +4,6 @@
typedef unsigned char byte;
-enum
-{
- /* PDF 1.4 -- standard separable */
- FZ_BLEND_NORMAL,
- FZ_BLEND_MULTIPLY,
- FZ_BLEND_SCREEN,
- FZ_BLEND_OVERLAY,
- FZ_BLEND_DARKEN,
- FZ_BLEND_LIGHTEN,
- FZ_BLEND_COLOR_DODGE,
- FZ_BLEND_COLOR_BURN,
- FZ_BLEND_HARD_LIGHT,
- FZ_BLEND_SOFT_LIGHT,
- FZ_BLEND_DIFFERENCE,
- FZ_BLEND_EXCLUSION,
-
- /* PDF 1.4 -- standard non-separable */
- FZ_BLEND_HUE,
- FZ_BLEND_SATURATION,
- FZ_BLEND_COLOR,
- FZ_BLEND_LUMINOSITY,
-};
-
static const char *fz_blendmode_names[] =
{
"Normal",
@@ -354,7 +331,124 @@ fz_blend_nonseparable(byte * restrict bp, byte * restrict sp, int w, int blendmo
}
void
-fz_blend_pixmap(fz_pixmap *dst, fz_pixmap *src, int alpha, int blendmode)
+fz_blend_separable_isolated(byte * restrict bp, byte * restrict sp, int n, int w, int blendmode, byte * restrict hp)
+{
+ int k;
+ int n1 = n - 1;
+ while (w--)
+ {
+ int ha = *hp++; /* ha = shape_alpha */
+ /* If ha == 0 then leave everything unchanged */
+ if (ha != 0)
+ {
+ int sa = sp[n1];
+ int ba = bp[n1];
+ int baha = fz_mul255(ba, ha);
+
+ /* 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;
+
+ if (ra != 0) for (k = 0; k < n1; k++)
+ {
+ int sc = (sp[k] * invsa) >> 8;
+ int bc = (bp[k] * invba) >> 8;
+ int rc;
+
+ switch (blendmode)
+ {
+ default:
+ case FZ_BLEND_NORMAL: rc = sc; break;
+ case FZ_BLEND_MULTIPLY: rc = fz_mul255(bc, sc); break;
+ case FZ_BLEND_SCREEN: rc = fz_screen_byte(bc, sc); break;
+ case FZ_BLEND_OVERLAY: rc = fz_overlay_byte(bc, sc); break;
+ case FZ_BLEND_DARKEN: rc = fz_darken_byte(bc, sc); break;
+ case FZ_BLEND_LIGHTEN: rc = fz_lighten_byte(bc, sc); break;
+ case FZ_BLEND_COLOR_DODGE: rc = fz_color_dodge_byte(bc, sc); break;
+ case FZ_BLEND_COLOR_BURN: rc = fz_color_burn_byte(bc, sc); break;
+ case FZ_BLEND_HARD_LIGHT: rc = fz_hard_light_byte(bc, sc); break;
+ case FZ_BLEND_SOFT_LIGHT: rc = fz_soft_light_byte(bc, sc); break;
+ 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);
+ bp[k] = fz_mul255(rc, ra);
+ }
+ }
+
+ sp += n;
+ bp += n;
+ }
+}
+
+void
+fz_blend_nonseparable_isolated(byte * restrict bp, byte * restrict sp, int w, int blendmode, byte * restrict hp)
+{
+ while (w--)
+ {
+ int ha = *hp++;
+ if (ha != 0)
+ {
+ int sa = sp[3];
+ int ba = bp[3];
+ int baha = fz_mul255(ba, ha);
+
+ /* Calculate result_alpha */
+ int ra = bp[3] = ba - baha + ha;
+
+ if (ra != 0)
+ {
+ int rr, rg, rb;
+
+ /* ugh, division to get non-premul components */
+ 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)
+ {
+ default:
+ case FZ_BLEND_HUE:
+ fz_hue_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb);
+ break;
+ case FZ_BLEND_SATURATION:
+ fz_saturation_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb);
+ break;
+ case FZ_BLEND_COLOR:
+ fz_color_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb);
+ break;
+ case FZ_BLEND_LUMINOSITY:
+ fz_luminosity_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb);
+ 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);
+ bp[0] = fz_mul255(ra, rr);
+ bp[1] = fz_mul255(ra, rg);
+ bp[2] = fz_mul255(ra, rb);
+ }
+ }
+
+ sp += 4;
+ bp += 4;
+ }
+}
+
+void
+fz_blend_pixmap(fz_pixmap *dst, fz_pixmap *src, int alpha, int blendmode, int isolated, fz_pixmap *shape)
{
unsigned char *sp, *dp;
fz_bbox bbox;
@@ -386,13 +480,31 @@ fz_blend_pixmap(fz_pixmap *dst, fz_pixmap *src, int alpha, int blendmode)
assert(src->n == dst->n);
- while (h--)
+ if (!isolated)
{
- if (n == 4 && blendmode >= FZ_BLEND_HUE)
- fz_blend_nonseparable(dp, sp, w, blendmode);
- else
- fz_blend_separable(dp, sp, n, w, blendmode);
- sp += src->w * n;
- dp += dst->w * n;
+ unsigned char *hp = shape->samples + (y - shape->y) * shape->w + (x - shape->x);
+
+ while (h--)
+ {
+ if (n == 4 && blendmode >= FZ_BLEND_HUE)
+ fz_blend_nonseparable_isolated(dp, sp, w, blendmode, hp);
+ else
+ fz_blend_separable_isolated(dp, sp, n, w, blendmode, hp);
+ sp += src->w * n;
+ dp += dst->w * n;
+ hp += shape->w;
+ }
+ }
+ else
+ {
+ while (h--)
+ {
+ if (n == 4 && blendmode >= FZ_BLEND_HUE)
+ fz_blend_nonseparable(dp, sp, w, blendmode);
+ else
+ fz_blend_separable(dp, sp, n, w, blendmode);
+ sp += src->w * n;
+ dp += dst->w * n;
+ }
}
}