#include "fitz.h" typedef unsigned char byte; /* PDF 1.4 blend modes, except Normal and Multiply which are Over and In respectively. Only the actual blend routines are here, not the node rendering logic which lives in render.c. These are slow. */ /* These functions apply to a single component, 0-255 range typically */ static int fz_screen_byte(int bd, int s) { return bd + s - fz_mul255(bd, s); } static 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); } static int fz_overlay_byte(int bd, int s) { return fz_hardlight_byte(s, bd); // note swapped order } static int fz_darken_byte(int bd, int s) { return MIN(bd, s); } static int fz_lighten_byte(int bd, int s) { return MAX(bd, s); } static int fz_colordodge_byte(int bd, int s) { if (s < 255) return MIN(255, 255 * bd / (255 - s)); else return 255; } static int fz_colorburn_byte(int bd, int s) { if (s > 0) return 255 - MIN(255, 255 * (255 - bd) / s); else return 0; } static int fz_softlight_byte(int bd, int s) { /* review this */ if (s < 128) { return bd - fz_mul255(fz_mul255((255 - (s<<1)), bd), 255 - bd); } else { int dbd; if (bd < 64) dbd = fz_mul255(fz_mul255((bd << 4) - 12, bd) + 4, bd); else dbd = (int)sqrtf(255.0f * bd); return bd + fz_mul255(((s<<1) - 255), (dbd - bd)); } } static int fz_difference_byte(int bd, int s) { return ABS(bd - s); } static int fz_exclusion_byte(int bd, int s) { return bd + s - (fz_mul255(bd, s)<<1); } /* Non-separable blend modes */ static 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) { int l = lum(r, g, b); int n = MIN(MIN(r, g), b); int x = MAX(MAX(r, g), b); if (n < 0) { *dr = l + 255 * (r - l) / (l - n); *dg = l + 255 * (g - l) / (l - n); *db = l + 255 * (b - l) / (l - n); } else { *dr = l + 255 * (255 - l) / (x - l); *dg = l + 255 * (255 - l) / (x - l); *db = l + 255 * (255 - l) / (x - l); } } static void setlum(int r, int g, int b, int l, int *dr, int *dg, int *db) { int d = 255 - lum(r, g, b); clipcolor(r + d, g + d, b + d, dr, dg, db); } static 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) { int *m[3]; /* min, med, max */ int *t; m[0] = &r; m[1] = &g; m[2] = &b; #define SWAP(a, b) (t = a, a = b, b = t) if (*m[0] > *m[1]) SWAP(m[0], m[1]); if (*m[0] > *m[2]) SWAP(m[0], m[2]); if (*m[1] > *m[2]) SWAP(m[1], m[2]); if (*m[2] > *m[0]) { *m[1] = (*m[1] - *m[0]) * s / (*m[2] - *m[0]); *m[2] = s; } else { *m[1] = 0; *m[2] = 0; } *dr = r; *dg = g; *db = b; } static void fz_hue_rgb(int *bdr, int *bdg, int *bdb, int sr, int sg, int sb) { int tr, tg, tb; setsat(sr, sg, sb, sat(*bdr, *bdg, *bdb), &tr, &tg, &tb); 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) { int tr, tg, tb; setsat(*bdr, *bdg, *bdb, sat(sr, sg, sb), &tr, &tg, &tb); 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); } //fz_separable_blend(, fz_blendkind mode) //{ //}