diff options
Diffstat (limited to 'render/rastport.c')
-rw-r--r-- | render/rastport.c | 448 |
1 files changed, 448 insertions, 0 deletions
diff --git a/render/rastport.c b/render/rastport.c new file mode 100644 index 00000000..0daf3458 --- /dev/null +++ b/render/rastport.c @@ -0,0 +1,448 @@ +#include <fitz.h> + +/* XXX: half of these funcs are totally wrong. fix! */ + +typedef unsigned char byte; + +/* + * General Porter-Duff compositing -- blit image regions + * + * duff_NoN + * duff_NiM + * duff_NiMoN + */ + +/* dst = src over dst */ +static void +duff_NoN(byte *sp0, int sw, int sn, byte *dp0, int dw, int w0, int h) +{ + int k; + while (h--) + { + byte *sp = sp0; + byte *dp = dp0; + int w = w0; + while (w--) + { + byte sa = sp[0]; + byte ssa = 255 - sa; + for (k = 0; k < sn; k++) + { + dp[k] = sp[k] + fz_mul255(dp[k], ssa); + } + sp += sn; + dp += sn; + } + sp0 += sw; + dp0 += dw; + } +} + +/* dst = src in msk */ +static void +duff_NiMcN(byte *sp0, int sw, int sn, byte *mp0, int mw, int mn, byte *dp0, int dw, int w0, int h) +{ + int k; + while (h--) + { + byte *sp = sp0; + byte *mp = mp0; + byte *dp = dp0; + int w = w0; + while (w--) + { + byte ma = mp[0]; + for (k = 0; k < sn; k++) + dp[k] = fz_mul255(sp[k], ma); + sp += sn; + mp += mn; + dp += sn; + } + sp0 += sw; + mp0 += mw; + dp0 += dw; + } +} + +/* dst = src in msk over dst */ +static void +duff_NiMoN(byte *sp0, int sw, int sn, byte *mp0, int mw, int mn, byte *dp0, int dw, int w0, int h) +{ + int k; + while (h--) + { + byte *sp = sp0; + byte *mp = mp0; + byte *dp = dp0; + int w = w0; + while (w--) + { + byte ma = mp[0]; + byte sa = fz_mul255(sp[0], ma); + byte ssa = 255 - sa; + for (k = 0; k < sn; k++) + { + dp[k] = fz_mul255(sp[k], ma) + fz_mul255(dp[k], ssa); + } + sp += sn; + mp += mn; + dp += sn; + } + sp0 += sw; + mp0 += mw; + dp0 += dw; + } +} + +static void duff_1o1(byte *sp0, int sw, byte *dp0, int dw, int w0, int h) +{ + duff_NoN(sp0, sw, 1, dp0, dw, w0, h); +} + +static void duff_4o4(byte *sp0, int sw, byte *dp0, int dw, int w0, int h) +{ + duff_NoN(sp0, sw, 4, dp0, dw, w0, h); +} + +static void duff_1i1c1(byte *sp0, int sw, byte *mp0, int mw, byte *dp0, int dw, int w0, int h) +{ + duff_NiMcN(sp0, sw, 1, mp0, mw, 1, dp0, dw, w0, h); +} + +static void duff_4i1c4(byte *sp0, int sw, byte *mp0, int mw, byte *dp0, int dw, int w0, int h) +{ + duff_NiMcN(sp0, sw, 4, mp0, mw, 1, dp0, dw, w0, h); +} + +static void duff_1i1o1(byte *sp0, int sw, byte *mp0, int mw, byte *dp0, int dw, int w0, int h) +{ + duff_NiMoN(sp0, sw, 1, mp0, mw, 1, dp0, dw, w0, h); +} + +static void duff_4i1o4(byte *sp0, int sw, byte *mp0, int mw, byte *dp0, int dw, int w0, int h) +{ + duff_NiMoN(sp0, sw, 4, mp0, mw, 1, dp0, dw, w0, h); +} + +/* + * Mask -- blit one scanline of mask + * + * msk_1c1 + * msk_1o1 + * msk_1i1c1 + * msk_1i1o1 + * msk_w3i1o4 + * msk_w3i1i1o4 + */ + +static void msk_1c1(byte *src, byte *dst, int w) +{ + memcpy(dst, src, w); +} + +static void msk_1o1(byte *src, byte *dst, int w) +{ + while (w--) + { + dst[0] = src[0] + fz_mul255(dst[0], 255 - src[0]); + src++; + dst++; + } +} + +static void msk_w3i1o4(byte *rgb, byte *src, byte *dst, int n) +{ + byte sa, ssa; + while (n--) + { + sa = src[0]; + ssa = 255 - sa; + dst[0] = sa + fz_mul255(dst[0], ssa); + dst[1] = rgb[0] + fz_mul255((short)dst[1] - rgb[0], ssa); + dst[2] = rgb[1] + fz_mul255((short)dst[2] - rgb[1], ssa); + dst[3] = rgb[2] + fz_mul255((short)dst[3] - rgb[2], ssa); + src ++; + dst += 4; + } +} + +/* + * Image -- draw transformed image + * + */ + +#define lerp(a,b,t) (a + (((b - a) * t) >> 16)) + +static inline byte getcomp(byte *s, int w, int h, int u, int v, int n, int k) +{ + if (u < 0 || u >= w) return 0; + if (v < 0 || v >= h) return 0; + return s[(w * v + u) * n + k]; +} + +static inline int samplecomp(byte *s, int w, int h, int u, int v, int n, int k) +{ + int ui = u >> 16; + int vi = v >> 16; + int ud = u & 0xFFFF; + int vd = v & 0xFFFF; + int a = getcomp(s, w, h, ui, vi, n, k); + int b = getcomp(s, w, h, ui+1, vi, n, k); + int c = getcomp(s, w, h, ui, vi+1, n, k); + int d = getcomp(s, w, h, ui+1, vi+1, n, k); + int ab = lerp(a, b, ud); + int cd = lerp(c, d, ud); + return lerp(ab, cd, vd); +} + +static inline byte getmask(byte *s, int w, int h, int u, int v) +{ + if (u < 0 || u >= w) return 0; + if (v < 0 || v >= h) return 0; + return s[w * v + u]; +} + +static inline int samplemask(byte *s, int w, int h, int u, int v) +{ + int ui = u >> 16; + int vi = v >> 16; + int ud = u & 0xFFFF; + int vd = v & 0xFFFF; + int a = getmask(s, w, h, ui, vi); + int b = getmask(s, w, h, ui+1, vi); + int c = getmask(s, w, h, ui, vi+1); + int d = getmask(s, w, h, ui+1, vi+1); + int ab = lerp(a, b, ud); + int cd = lerp(c, d, ud); + return lerp(ab, cd, vd); +} + +static inline void lerpargb(byte *dst, byte *a, byte *b, int t) +{ + dst[0] = lerp(a[0], b[0], t); + dst[1] = lerp(a[1], b[1], t); + dst[2] = lerp(a[2], b[2], t); + dst[3] = lerp(a[3], b[3], t); +} + +static inline byte *getargb(byte *s, int w, int h, int u, int v) +{ + static byte zero[4] = { 0, 0, 0, 0 }; + if (u < 0 || u >= w) return zero; + if (v < 0 || v >= h) return zero; + return s + ((w * v + u) << 2); +} + +static inline void sampleargb(byte *s, int w, int h, int u, int v, byte *abcd) +{ + byte ab[4]; + byte cd[4]; + int ui = u >> 16; + int vi = v >> 16; + int ud = u & 0xFFFF; + int vd = v & 0xFFFF; + byte *a = getargb(s, w, h, ui, vi); + byte *b = getargb(s, w, h, ui+1, vi); + byte *c = getargb(s, w, h, ui, vi+1); + byte *d = getargb(s, w, h, ui+1, vi+1); + lerpargb(ab, a, b, ud); + lerpargb(cd, c, d, ud); + lerpargb(abcd, ab, cd, vd); +} + +/* + * img_NcN + * img_1c1 + * img_4c4 + * img_1o1 + * img_4o4 + * img_1i1c1 + * img_1i1o1 + * img_4i1c4 + * img_4i1o4 + * img_w3i1o4 + * img_w3i1i1o4 + */ + +static void img_NcN(FZ_PSRC, int srcn, FZ_PDST, FZ_PCTM) +{ + int k; + while (h--) + { + byte *dstp = dst0; + int u = u0; + int v = v0; + int w = w0; + while (w--) + { + for (k = 0; k < srcn; k++) + { + dstp[k] = samplecomp(src, srcw, srch, u, v, srcn, k); + dstp += srcn; + u += fa; + v += fb; + } + } + dst0 += dstw; + u0 += fc; + v0 += fd; + } +} + +static void img_1c1(FZ_PSRC, FZ_PDST, FZ_PCTM) +{ + while (h--) + { + byte *dstp = dst0; + int u = u0; + int v = v0; + int w = w0; + while (w--) + { + dstp[0] = samplemask(src, srcw, srch, u, v); + dstp ++; + u += fa; + v += fb; + } + dst0 += dstw; + u0 += fc; + v0 += fd; + } +} + +static void img_4c4(FZ_PSRC, FZ_PDST, FZ_PCTM) +{ + while (h--) + { + byte *dstp = dst0; + int u = u0; + int v = v0; + int w = w0; + while (w--) + { + sampleargb(src, srcw, srch, u, v, dstp); + dstp += 4; + u += fa; + v += fb; + } + dst0 += dstw; + u0 += fc; + v0 += fd; + } +} + +static void img_1o1(FZ_PSRC, FZ_PDST, FZ_PCTM) +{ + byte srca; + while (h--) + { + byte *dstp = dst0; + int u = u0; + int v = v0; + int w = w0; + while (w--) + { + srca = samplemask(src, srcw, srch, u, v); + dstp[0] = srca + fz_mul255(dstp[0], 255 - srca); + dstp ++; + u += fa; + v += fb; + } + dst0 += dstw; + u0 += fc; + v0 += fd; + } +} + +static void img_4o4(FZ_PSRC, FZ_PDST, FZ_PCTM) +{ + byte argb[4]; + while (h--) + { + byte *dstp = dst0; + int u = u0; + int v = v0; + int w = w0; + while (w--) + { + sampleargb(src, srcw, srch, u, v, argb); + byte ssa = 255 - argb[0]; + dstp[0] = argb[0] + fz_mul255(dstp[0], ssa); + dstp[1] = argb[1] + fz_mul255((short)dstp[1] - argb[1], ssa); + dstp[2] = argb[2] + fz_mul255((short)dstp[2] - argb[2], ssa); + dstp[3] = argb[3] + fz_mul255((short)dstp[3] - argb[3], ssa); + dstp += 4; + u += fa; + v += fb; + } + dst0 += dstw; + u0 += fc; + v0 += fd; + } +} + +static void img_w3i1o4(byte *rgb, FZ_PSRC, FZ_PDST, FZ_PCTM) +{ + byte sa, ssa; + while (h--) + { + byte *dstp = dst0; + int u = u0; + int v = v0; + int w = w0; + while (w--) + { + sa = samplemask(src, srcw, srch, u, v); + ssa = 255 - sa; + dstp[0] = sa + fz_mul255(dstp[0], ssa); + dstp[1] = rgb[0] + fz_mul255((short)dstp[1] - rgb[0], ssa); + dstp[2] = rgb[1] + fz_mul255((short)dstp[2] - rgb[1], ssa); + dstp[3] = rgb[2] + fz_mul255((short)dstp[3] - rgb[2], ssa); + dstp += 4; + u += fa; + v += fb; + } + dst0 += dstw; + u0 += fc; + v0 += fd; + } +} + +/* + * Fill in the big fat vtable + */ + +static fz_rastfuncs deftab = +{ + duff_NoN, + duff_NiMcN, + duff_NiMoN, + duff_1o1, + duff_4o4, + duff_1i1c1, + duff_4i1c4, + duff_1i1o1, + duff_4i1o4, + + msk_1c1, + msk_1o1, + msk_w3i1o4, + + nil, + nil, + nil, + + img_NcN, + img_1c1, + img_4c4, + img_1o1, + img_4o4, + img_w3i1o4 +}; + +void +fz_defaultrastfuncs(fz_rastfuncs *tab) +{ + *tab = deftab; +} + |