diff options
author | Tor Andersson <tor@ghostscript.com> | 2010-07-14 02:51:01 +0200 |
---|---|---|
committer | Tor Andersson <tor@ghostscript.com> | 2010-07-14 02:51:01 +0200 |
commit | b8fa3eabea0fc29a1937d661565cda0caf79ce50 (patch) | |
tree | 2a6d14905ea660155a8d0d5b5de294375f0f006f /draw | |
parent | 48f6f0e2cd05182613b78322c2b924635caf3f55 (diff) | |
download | mupdf-b8fa3eabea0fc29a1937d661565cda0caf79ce50.tar.xz |
Add transparency group/mask device calls and implement basic blend modes when drawing primitive objects.
Diffstat (limited to 'draw')
-rw-r--r-- | draw/blendmodes.c | 133 |
1 files changed, 97 insertions, 36 deletions
diff --git a/draw/blendmodes.c b/draw/blendmodes.c index f86fa1ef..9dde35d1 100644 --- a/draw/blendmodes.c +++ b/draw/blendmodes.c @@ -8,49 +8,43 @@ Only the actual blend routines are here, not the node rendering logic which live These are slow. */ - /* These functions apply to a single component, 0-255 range typically */ -static int +static inline int fz_screen_byte(int bd, int s) { return bd + s - fz_mul255(bd, s); } - -static int +static inline int fz_hardlight_byte(int bd, int s) { int s2 = s << 1; if (s <= 127) return fz_mul255(bd, s2); else - return fz_screen_byte(bd, s2); + return fz_screen_byte(bd, s2 - 1); } - -static int +static inline int fz_overlay_byte(int bd, int s) { return fz_hardlight_byte(s, bd); // note swapped order } - -static int +static inline int fz_darken_byte(int bd, int s) { return MIN(bd, s); } - -static int +static inline int fz_lighten_byte(int bd, int s) { return MAX(bd, s); } - -static int +static inline int fz_colordodge_byte(int bd, int s) { if (s < 255) @@ -59,8 +53,7 @@ fz_colordodge_byte(int bd, int s) return 255; } - -static int +static inline int fz_colorburn_byte(int bd, int s) { if (s > 0) @@ -69,8 +62,7 @@ fz_colorburn_byte(int bd, int s) return 0; } - -static int +static inline int fz_softlight_byte(int bd, int s) { /* review this */ @@ -87,32 +79,27 @@ fz_softlight_byte(int bd, int s) } } - -static int +static inline int fz_difference_byte(int bd, int s) { return ABS(bd - s); } - -static int +static inline int fz_exclusion_byte(int bd, int s) { return bd + s - (fz_mul255(bd, s)<<1); } - /* Non-separable blend modes */ - -static int +static inline int lum(int r, int g, int b) { /* 0.3, 0.59, 0.11 in 16.16 fixed point */ return (19662 * r + 38666 * g + 7208 * b) >> 16; } - static void clipcolor(int r, int g, int b, int *dr, int *dg, int *db) { @@ -131,7 +118,6 @@ clipcolor(int r, int g, int b, int *dr, int *dg, int *db) } } - static void setlum(int r, int g, int b, int l, int *dr, int *dg, int *db) { @@ -139,14 +125,12 @@ setlum(int r, int g, int b, int l, int *dr, int *dg, int *db) clipcolor(r + d, g + d, b + d, dr, dg, db); } - -static int +static inline int sat(int r, int g, int b) { return MAX(MAX(r, g), b) - MIN(MIN(r, g), b); } - static void setsat(int r, int g, int b, int s, int *dr, int *dg, int *db) { @@ -176,7 +160,6 @@ setsat(int r, int g, int b, int s, int *dr, int *dg, int *db) *db = b; } - static void fz_hue_rgb(int *bdr, int *bdg, int *bdb, int sr, int sg, int sb) { @@ -185,7 +168,6 @@ fz_hue_rgb(int *bdr, int *bdg, int *bdb, int sr, int sg, int sb) setlum(tr, tg, tb, lum(*bdr, *bdg, *bdb), bdr, bdg, bdb); } - static void fz_saturation_rgb(int *bdr, int *bdg, int *bdb, int sr, int sg, int sb) { @@ -194,21 +176,100 @@ fz_saturation_rgb(int *bdr, int *bdg, int *bdb, int sr, int sg, int sb) setlum(tr, tg, tb, lum(*bdr, *bdg, *bdb), bdr, bdg, bdb); } - static void fz_color_rgb(int *bdr, int *bdg, int *bdb, int sr, int sg, int sb) { setlum(sr, sg, sb, lum(*bdr, *bdg, *bdb), bdr, bdg, bdb); } - static void fz_luminosity_rgb(int *bdr, int *bdg, int *bdb, int sr, int sg, int sb) { setlum(*bdr, *bdg, *bdb, lum(sr, sg, sb), bdr, bdg, bdb); } +/* + * + */ + +void +fz_blend_nxn(byte * restrict sp, int sw, int sn, + byte * restrict dp, int dw, + int w0, int h, fz_blendmode blendmode) +{ + int k; + + sw -= w0*sn; + dw -= w0*sn; + while (h--) + { + int w = w0; + while (w--) + { + int sa = sp[sn-1]; + int da = dp[sn-1]; + int ta = 255 - sa; + int tb = 255 - da; + int tc = fz_mul255(sa, da); + for (k = 0; k < sn; k++) + { + int r, bd, s; + if (da) + bd = dp[k] * 255 / da; + if (sa) + s = sp[k] * 255 / sa; + switch (blendmode) + { + default: + case FZ_BMULTIPLY: r = fz_mul255(bd, s); break; + case FZ_BSCREEN: r = fz_screen_byte(bd, s); break; + case FZ_BOVERLAY: r = fz_overlay_byte(bd, s); break; + case FZ_BDARKEN: r = fz_darken_byte(bd, s); break; + case FZ_BLIGHTEN: r = fz_lighten_byte(bd, s); break; + case FZ_BCOLORDODGE: r = fz_colordodge_byte(bd, s); break; + case FZ_BCOLORBURN: r = fz_colorburn_byte(bd, s); break; + case FZ_BHARDLIGHT: r = fz_hardlight_byte(bd, s); break; + case FZ_BSOFTLIGHT: r = fz_softlight_byte(bd, s); break; + case FZ_BDIFFERENCE: r = fz_difference_byte(bd, s); break; + case FZ_BEXCLUSION: r = fz_exclusion_byte(bd, s); break; + } + dp[k] = fz_mul255(ta, dp[k]) + fz_mul255(tb, sp[k]) + fz_mul255(tc, r); + } + sp += sn; + dp += sn; + } + sp += sw; + dp += dw; + } +} + +void +fz_blendpixmaps(fz_pixmap *src, fz_pixmap *dst, fz_blendmode blendmode) +{ + unsigned char *sp, *dp; + fz_bbox sr, dr; + int x, y, w, h; + + 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; -//fz_separable_blend(, fz_blendkind mode) -//{ - //} + 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; + + 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; + + fz_blend_nxn(sp, src->w * src->n, src->n, dp, dst->w * dst->n, w, h, blendmode); +} |