summaryrefslogtreecommitdiff
path: root/render
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2004-11-24 03:47:04 +0100
committerTor Andersson <tor@ghostscript.com>2004-11-24 03:47:04 +0100
commitb48de7618e25bc2cef9d9db4f9b49e1d546e438a (patch)
tree5f365a90a0bd355073e7d5d1f69e66d2f82b4446 /render
parente092458f4403f1424d8fd1f5ec194880a05c3362 (diff)
downloadmupdf-b48de7618e25bc2cef9d9db4f9b49e1d546e438a.tar.xz
rewrite of render loop part 3
Diffstat (limited to 'render')
-rw-r--r--render/pixmap.c117
-rw-r--r--render/rastnone.c385
-rw-r--r--render/rastport.c448
-rw-r--r--render/render.c427
4 files changed, 729 insertions, 648 deletions
diff --git a/render/pixmap.c b/render/pixmap.c
index 21f36ee0..c024a025 100644
--- a/render/pixmap.c
+++ b/render/pixmap.c
@@ -33,6 +33,17 @@ fz_newpixmapwithrect(fz_pixmap **pixp, fz_irect r, int n)
r.max.y - r.min.y, n);
}
+fz_error *
+fz_newpixmapcopy(fz_pixmap **pixp, fz_pixmap *old)
+{
+ fz_error *error;
+ error = fz_newpixmap(pixp, old->x, old->y, old->w, old->h, old->n);
+ if (error)
+ return error;
+ memcpy((*pixp)->samples, old->samples, old->w * old->h * old->n);
+ return nil;
+}
+
void
fz_droppixmap(fz_pixmap *pix)
{
@@ -47,112 +58,6 @@ fz_clearpixmap(fz_pixmap *pix)
}
void
-fz_blendover(fz_pixmap *src, fz_pixmap *dst)
-{
- int x, y, k;
- fz_irect sr, dr, rect;
- unsigned char *s;
- unsigned char *d;
-
- assert(dst->n == src->n || src->n == 1);
-
- sr.min.x = src->x;
- sr.min.y = src->y;
- sr.max.x = src->x + src->w;
- sr.max.y = src->y + src->h;
-
- dr.min.x = dst->x;
- dr.min.y = dst->y;
- dr.max.x = dst->x + dst->w;
- dr.max.y = dst->y + dst->h;
-
- rect = fz_intersectirects(sr, dr);
-
- if (dst->n == src->n)
- {
- for (y = rect.min.y; y < rect.max.y; y++)
- {
- s = src->samples + ((rect.min.x - src->x) + (y - src->y) * src->w) * src->n;
- d = dst->samples + ((rect.min.x - dst->x) + (y - dst->y) * dst->w) * dst->n;
- for (x = rect.min.x; x < rect.max.x; x++)
- {
- int sa = s[0];
- int ssa = 255 - sa;
-
- for (k = 0; k < dst->n; k++)
- d[k] = s[k] + fz_mul255(d[k], ssa);
-
- s += src->n;
- d += dst->n;
- }
- }
- }
- else if (src->n == 1)
- {
- for (y = rect.min.y; y < rect.max.y; y++)
- {
- s = src->samples + ((rect.min.x - src->x) + (y - src->y) * src->w) * src->n;
- d = dst->samples + ((rect.min.x - dst->x) + (y - dst->y) * dst->w) * dst->n;
- for (x = rect.min.x; x < rect.max.x; x++)
- {
- int sa = s[0];
- int ssa = 255 - sa;
-
- d[0] = s[0] + fz_mul255(d[0], ssa);
- for (k = 1; k < dst->n; k++)
- d[k] = 0 + fz_mul255(d[k], ssa);
-
- s += src->n;
- d += dst->n;
- }
- }
- }
-}
-
-void
-fz_blendmask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *msk)
-{
- unsigned char *d;
- unsigned char *s;
- unsigned char *m;
- fz_irect sr, dr, mr, rect;
- int x, y, k;
-
- assert(src->n == dst->n);
-
- sr.min.x = src->x;
- sr.min.y = src->y;
- sr.max.x = src->x + src->w;
- sr.max.y = src->y + src->h;
-
- dr.min.x = dst->x;
- dr.min.y = dst->y;
- dr.max.x = dst->x + dst->w;
- dr.max.y = dst->y + dst->h;
-
- mr.min.x = msk->x;
- mr.min.y = msk->y;
- mr.max.x = msk->x + msk->w;
- mr.max.y = msk->y + msk->h;
-
- rect = fz_intersectirects(sr, dr);
- rect = fz_intersectirects(rect, mr);
-
- for (y = rect.min.y; y < rect.max.y; y++)
- {
- s = src->samples + ((rect.min.x - src->x) + (y - src->y) * src->w) * src->n;
- d = dst->samples + ((rect.min.x - dst->x) + (y - dst->y) * dst->w) * dst->n;
- m = msk->samples + ((rect.min.x - msk->x) + (y - msk->y) * msk->w) * msk->n;
- for (x = rect.min.x; x < rect.max.x; x++)
- {
- for (k = 0; k < dst->n; k++)
- *d++ = fz_mul255(*s++, *m);
- m += msk->n;
- }
- }
-}
-
-void
fz_gammapixmap(fz_pixmap *pix, float gamma)
{
unsigned char table[255];
diff --git a/render/rastnone.c b/render/rastnone.c
deleted file mode 100644
index 2af45882..00000000
--- a/render/rastnone.c
+++ /dev/null
@@ -1,385 +0,0 @@
-#include <fitz.h>
-
-/* XXX: half of these funcs are totally wrong. fix! */
-
-typedef unsigned char byte;
-
-/*
- * Mask -- blit one span (clipped and adjusted)
- *
- * mask_g
- * mask_i1
- * mask_o1
- * mask_i1o1
- * mask_o4w3
- * mask_i1o4w3
- */
-
-static void mask_g(int n, byte *src, byte *pix)
-{
- memcpy(pix, src, n);
-}
-
-static void mask_i1(int n, byte *src, byte *dst)
-{
- while (n--)
- {
- dst[0] = fz_mul255(src[0], dst[0]);
- src++;
- dst++;
- }
-}
-
-static void mask_o1(int n, byte *src, byte *dst)
-{
- while (n--)
- {
- dst[0] = src[0] + fz_mul255(dst[0], 255 - src[0]);
- src++;
- dst++;
- }
-}
-
-static void mask_i1o1(int n, byte *src, byte *msk, byte *dst)
-{
- while (n--)
- {
- byte sa = fz_mul255(src[0], msk[0]);
- dst[0] = sa + fz_mul255(dst[0], 255 - sa);
- src++;
- msk++;
- dst++;
- }
-}
-
-static void mask_o4w3(int n, byte *src, byte *dst, byte *rgb)
-{
- 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;
- }
-}
-
-static void mask_i1o4w3(int n, byte *src, byte *msk, byte *dst, byte *rgb)
-{
- byte sa, ssa;
- while (n--)
- {
- sa = fz_mul255(src[0], msk[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 ++;
- msk ++;
- dst += 4;
- }
-}
-
-/*
- * Image -- blit entire image
- *
- * img1_g
- * img1_i1
- * img1_o1
- * img1_i1o1
- * img1_o4w3
- * img1_i1o4w3
- *
- * img4_g
- * img4_o4
- * img4_i1o4
- */
-
-#define lerpmsk(a,b,t) (a + (((b - a) * t) >> 16))
-
-static inline byte getmsk(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 samplemsk(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 = getmsk(s, w, h, ui, vi);
- int b = getmsk(s, w, h, ui+1, vi);
- int c = getmsk(s, w, h, ui, vi+1);
- int d = getmsk(s, w, h, ui+1, vi+1);
- int ab = lerpmsk(a, b, ud);
- int cd = lerpmsk(c, d, ud);
- return lerpmsk(ab, cd, vd);
-}
-
-static inline void lerpargb(byte *dst, byte *a, byte *b, int t)
-{
- dst[0] = lerpmsk(a[0], b[0], t);
- dst[1] = lerpmsk(a[1], b[1], t);
- dst[2] = lerpmsk(a[2], b[2], t);
- dst[3] = lerpmsk(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);
-}
-
-#define PSRC byte *src, int w, int h, int nx0, int ny
-#define PDST byte *dst0, int dstw
-#define PMSK byte *msk0, int mskw
-#define PCTM int u0, int v0, int fa, int fb, int fc, int fd
-
-#if 0
-static void example(PSRC, PDST, PMSK, PCTM)
-{
- while (ny--)
- {
- byte *dst = dst0;
- byte *msk = msk0;
- int u = u0;
- int v = v0;
- int nx = nx0;
- while (nx--)
- {
- // dst[0] = ... msk[0] ... sample(s, w, h, u, v);
- dst ++;
- msk ++;
- u += fa;
- v += fb;
- }
- u0 += fc;
- v0 += fd;
- dst0 += dstw;
- msk0 += mskw;
- }
-}
-#endif
-
-#define BEGLOOP \
- while (ny--) \
- { \
- byte *dst = dst0; \
- int u = u0; \
- int v = v0; \
- int nx = nx0; \
- while (nx--)
-
-#define ENDLOOP \
- u0 += fc; \
- v0 += fd; \
- dst0 += dstw; \
- }
-
-#define BEGLOOPM \
- while (ny--) \
- { \
- byte *dst = dst0; \
- byte *msk = msk0; \
- int u = u0; \
- int v = v0; \
- int nx = nx0; \
- while (nx--)
-
-#define ENDLOOPM \
- u0 += fc; \
- v0 += fd; \
- dst0 += dstw; \
- msk0 += mskw; \
- }
-
-static void img1_g(PSRC, PDST, PCTM)
-{
- BEGLOOP
- {
- dst[0] = samplemsk(src, w, h, u, v);
- dst ++;
- u += fa;
- v += fb;
- }
- ENDLOOP
-}
-
-static void img1_i1(PSRC, PDST, PCTM)
-{
- BEGLOOP
- {
- dst[0] = fz_mul255(dst[0], samplemsk(src, w, h, u, v));
- dst ++;
- u += fa;
- v += fb;
- }
- ENDLOOP
-}
-
-static void img1_o1(PSRC, PDST, PCTM)
-{
- BEGLOOP
- {
- byte sa = samplemsk(src, w, h, u, v);
- dst[0] = sa + fz_mul255(dst[0], 255 - sa);
- dst ++;
- u += fa;
- v += fb;
- }
- ENDLOOP
-}
-
-static void img1_i1o1(PSRC, PDST, PMSK, PCTM)
-{
- BEGLOOPM
- {
- byte sa = fz_mul255(msk[0], samplemsk(src, w, h, u, v));
- dst[0] = sa + fz_mul255(dst[0], 255 - sa);
- dst ++;
- msk ++;
- u += fa;
- v += fb;
- }
- ENDLOOPM
-}
-
-static void img1_o4w3(PSRC, PDST, PCTM, byte *rgb)
-{
- BEGLOOP
- {
- byte sa = samplemsk(src, w, h, u, v);
- byte 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);
- dst += 4;
- u += fa;
- v += fb;
- }
- ENDLOOP
-}
-
-static void img1_i1o4w3(PSRC, PDST, PMSK, PCTM, byte *rgb)
-{
- BEGLOOPM
- {
- byte sa = fz_mul255(msk[0], samplemsk(src, w, h, u, v));
- byte 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);
- dst += 4;
- msk ++;
- u += fa;
- v += fb;
- }
- ENDLOOPM
-}
-
-static void img4_g(PSRC, PDST, PCTM)
-{
- BEGLOOP
- {
- sampleargb(src, w, h, u, v, dst);
- dst += 4;
- u += fa;
- v += fb;
- }
- ENDLOOP
-}
-
-static void img4_o4(PSRC, PDST, PCTM)
-{
- byte argb[4];
- BEGLOOP
- {
- sampleargb(src, w, h, u, v, argb);
- byte sa = argb[0];
- byte ssa = 255 - sa;
- dst[0] = sa + fz_mul255(dst[0], ssa);
- dst[1] = argb[1] + fz_mul255(dst[1], ssa);
- dst[2] = argb[2] + fz_mul255(dst[2], ssa);
- dst[3] = argb[3] + fz_mul255(dst[3], ssa);
- dst += 4;
- u += fa;
- v += fb;
- }
- ENDLOOP
-}
-
-static void img4_i1o4(PSRC, PDST, PMSK, PCTM)
-{
- byte argb[4];
- BEGLOOPM
- {
- sampleargb(src, w, h, u, v, argb);
- byte sa = fz_mul255(msk[0], argb[0]);
- byte ssa = 255 - sa;
- dst[0] = argb[0] + fz_mul255(dst[0], ssa);
- dst[1] = argb[1] + fz_mul255((short)dst[1] - argb[1], ssa);
- dst[2] = argb[2] + fz_mul255((short)dst[2] - argb[2], ssa);
- dst[3] = argb[3] + fz_mul255((short)dst[3] - argb[3], ssa);
- dst += 4;
- msk ++;
- u += fa;
- v += fb;
- }
- ENDLOOPM
-}
-
-/*
- *
- */
-
-void
-fz_defaultrastfuncs(fz_rastfuncs *tab)
-{
- tab->mask_g = mask_g;
- tab->mask_i1 = mask_i1;
- tab->mask_o1 = mask_o1;
- tab->mask_i1o1 = mask_i1o1;
- tab->mask_o4w3 = mask_o4w3;
- tab->mask_i1o4w3 = mask_i1o4w3;
-
- tab->img1_g = img1_g;
- tab->img1_i1 = img1_i1;
- tab->img1_o1 = img1_o1;
- tab->img1_i1o1 = img1_i1o1;
- tab->img1_o4w3 = img1_o4w3;
- tab->img1_i1o4w3 = img1_i1o4w3;
-
- tab->img4_g = img4_g;
- tab->img4_o4 = img4_o4;
- tab->img4_i1o4 = img4_i1o4;
-}
-
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;
+}
+
diff --git a/render/render.c b/render/render.c
index 6aee9c8a..b92c8fe0 100644
--- a/render/render.c
+++ b/render/render.c
@@ -1,8 +1,9 @@
#include <fitz.h>
+#define DEBUG(args...) printf(args)
+
#define FNONE 0
#define FOVER 1
-#define FMASK 2
#define FRGB 4
static fz_error *rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm);
@@ -38,7 +39,6 @@ fz_newrenderer(fz_renderer **gcp, fz_colorspace *pcm, int maskonly, int gcmem)
fz_defaultrastfuncs(&gc->rast);
gc->dest = nil;
- gc->mask = nil;
gc->over = nil;
gc->rgb[0] = 0;
gc->rgb[1] = 0;
@@ -61,7 +61,6 @@ void
fz_droprenderer(fz_renderer *gc)
{
if (gc->dest) fz_droppixmap(gc->dest);
- if (gc->mask) fz_droppixmap(gc->mask);
if (gc->over) fz_droppixmap(gc->over);
if (gc->model) fz_dropcolorspace(gc->model);
@@ -79,14 +78,14 @@ static fz_error *
rendertransform(fz_renderer *gc, fz_transformnode *transform, fz_matrix ctm)
{
fz_error *error;
-//printf("transform [%g %g %g %g %g %g]\n",
-//transform->m.a, transform->m.b,
-//transform->m.c, transform->m.d,
-//transform->m.e, transform->m.f);
-//puts("{");
+DEBUG("transform [%g %g %g %g %g %g]\n",
+transform->m.a, transform->m.b,
+transform->m.c, transform->m.d,
+transform->m.e, transform->m.f);
+DEBUG("{\n");
ctm = fz_concat(transform->m, ctm);
error = rendernode(gc, transform->super.first, ctm);
-//puts("}");
+DEBUG("}\n");
return error;
}
@@ -112,14 +111,21 @@ rendercolor(fz_renderer *gc, fz_colornode *color, fz_matrix ctm)
gc->rgb[1] = rgb[1] * 255;
gc->rgb[2] = rgb[2] * 255;
-printf("color %s [%d %d %d]\n", color->cs->name, gc->rgb[0], gc->rgb[1], gc->rgb[2]);
-
- error = fz_newpixmapwithrect(&gc->dest, gc->clip, 4);
- if (error)
- return error;
+DEBUG("color %s [%d %d %d];\n", color->cs->name, gc->rgb[0], gc->rgb[1], gc->rgb[2]);
- p = gc->dest->samples;
- n = gc->dest->w * gc->dest->h;
+ if (gc->flag == FOVER)
+ {
+ p = gc->over->samples;
+ n = gc->over->w * gc->over->h;
+ }
+ else
+ {
+ error = fz_newpixmapwithrect(&gc->dest, gc->clip, 4);
+ if (error)
+ return error;
+ p = gc->dest->samples;
+ n = gc->dest->w * gc->dest->h;
+ }
while (n--)
{
@@ -144,7 +150,6 @@ struct spandata
fz_rastfuncs *rast;
int x, n;
fz_pixmap *dst;
- fz_pixmap *msk;
unsigned char *rgb;
int flag;
};
@@ -154,28 +159,24 @@ static void spanfunc(int y, int x, int n, unsigned char *path, void *userdata)
struct spandata *user = userdata;
fz_rastfuncs *rast = user->rast;
fz_pixmap *dst = user->dst;
- fz_pixmap *msk = user->msk;
- unsigned char *d;
- unsigned char *m = nil;
+ unsigned char *dstp;
path += user->x;
+ x += user->x;
- d = dst->samples + ( (y - dst->y) * dst->w + (x - dst->x) ) * dst->n;
- if (msk)
- m = msk->samples + ( (y - msk->y) * msk->w + (x - msk->x) ) * msk->n;
+ dstp = dst->samples + ( (y - dst->y) * dst->w + (x - dst->x) ) * dst->n;
switch (user->flag)
{
case FNONE:
- rast->mask_g(user->n, path, d); break;
+ assert(dst->n == 1);
+ rast->msk_1c1(path, dstp, user->n); break;
case FOVER:
- rast->mask_o1(user->n, path, d); break;
- case FOVER | FMASK:
- rast->mask_i1o1(user->n, path, m, d); break;
+ assert(dst->n == 1);
+ rast->msk_1o1(path, dstp, user->n); break;
case FOVER | FRGB:
- rast->mask_o4w3(user->n, path, d, user->rgb); break;
- case FOVER | FMASK | FRGB:
- rast->mask_i1o4w3(user->n, path, m, d, user->rgb); break;
+ assert(dst->n == 4);
+ rast->msk_w3i1o4(user->rgb, path, dstp, user->n); break;
default:
assert(!"impossible flag in path span function");
}
@@ -213,33 +214,28 @@ renderpath(fz_renderer *gc, fz_pathnode *path, fz_matrix ctm)
gbox = fz_boundgel(gc->gel);
clip = fz_intersectirects(gc->clip, gbox);
- if (clip.max.x <= clip.min.x)
- return nil;
- if (clip.max.y <= clip.min.y)
+ if (fz_isemptyrect(clip))
return nil;
-//printf("path clip[%d %d %d %d]\n", clip.min.x, clip.min.y, clip.max.x, clip.max.y);
+DEBUG("path %s;\n", path->paint == FZ_STROKE ? "stroke" : "fill");
user.rast = &gc->rast;
user.x = clip.min.x - gbox.min.x;
user.n = clip.max.x - clip.min.x;
user.flag = gc->flag;
+ user.rgb = gc->rgb;
- if (gc->flag == FNONE)
+ if (gc->flag & FOVER)
+ {
+ user.dst = gc->over;
+ }
+ else
{
error = fz_newpixmapwithrect(&gc->dest, clip, 1);
if (error)
return error;
fz_clearpixmap(gc->dest);
user.dst = gc->dest;
- user.msk = nil;
- user.rgb = gc->rgb;
- }
- else
- {
- user.dst = gc->over;
- user.msk = gc->mask;
- user.rgb = gc->rgb;
}
error = fz_scanconvert(gc->gel, gc->ael, path->paint == FZ_EOFILL,
@@ -259,6 +255,8 @@ static void drawglyph(fz_renderer *gc, fz_pixmap *dst, fz_glyph *src, int xorig,
unsigned char *dp, *sp;
int w, h;
+ int dx0 = dst->x;
+ int dy0 = dst->y;
int dx1 = dst->x + dst->w;
int dy1 = dst->y + dst->h;
@@ -272,14 +270,12 @@ static void drawglyph(fz_renderer *gc, fz_pixmap *dst, fz_glyph *src, int xorig,
int sx1 = src->w;
int sy1 = src->h;
- if (x1 < dst->x || x0 >= dx1) return;
- if (y1 < dst->y || y0 >= dy1) return;
-
- if (x0 < dst->x) { sx0 += dst->x - x0; x0 = dst->x; }
- if (y0 < dst->y) { sy0 += dst->y - y0; y0 = dst->y; }
-
- if (x1 >= dx1) { sx1 -= dx1 - x1; x1 = dx1; }
- if (y1 >= dy1) { sy1 -= dy1 - y1; y1 = dy1; }
+ if (x1 < dx0 || x0 >= dx1) return;
+ if (y1 < dy0 || y0 >= dy1) return;
+ if (x0 < dx0) { sx0 += dx0 - x0; x0 = dx0; }
+ if (y0 < dy0) { sy0 += dy0 - y0; y0 = dy0; }
+ if (x1 >= dx1) { sx1 += dx1 - x1; x1 = dx1; }
+ if (y1 >= dy1) { sy1 += dy1 - y1; y1 = dy1; }
sp = src->samples + (sy0 * src->w + sx0);
dp = dst->samples + ((y0 - dst->y) * dst->w + (x0 - dst->x)) * dst->n;
@@ -290,29 +286,32 @@ static void drawglyph(fz_renderer *gc, fz_pixmap *dst, fz_glyph *src, int xorig,
switch (gc->flag)
{
case FNONE:
+ assert(dst->n == 1);
while (h--)
{
- gc->rast.mask_g(w, sp, dp);
+ gc->rast.msk_1c1(sp, dp, w);
sp += src->w;
- dp += dst->w * dst->n;
+ dp += dst->w;
}
break;
case FOVER:
+ assert(dst->n == 1);
while (h--)
{
- gc->rast.mask_o1(w, sp, dp);
+ gc->rast.msk_1o1(sp, dp, w);
sp += src->w;
- dp += dst->w * dst->n;
+ dp += dst->w;
}
break;
case FOVER | FRGB:
+ assert(dst->n == 4);
while (h--)
{
- gc->rast.mask_o4w3(w, sp, dp, gc->rgb);
+ gc->rast.msk_w3i1o4(gc->rgb, sp, dp, w);
sp += src->w;
- dp += dst->w * dst->n;
+ dp += dst->w * 4;
}
break;
@@ -334,14 +333,11 @@ rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm)
tbox = fz_roundrect(fz_boundnode((fz_node*)text, ctm));
clip = fz_intersectirects(gc->clip, tbox);
-//printf("text %s n=%d [%g %g %g %g] clip[%d %d %d %d]\n",
-//text->font->name, text->len,
-//text->trm.a, text->trm.b, text->trm.c, text->trm.d,
-//clip.min.x, clip.min.y, clip.max.x, clip.max.y);
+DEBUG("text %s n=%d [%g %g %g %g];\n",
+text->font->name, text->len,
+text->trm.a, text->trm.b, text->trm.c, text->trm.d);
- if (clip.max.x <= clip.min.x)
- return nil;
- if (clip.max.y <= clip.min.y)
+ if (fz_isemptyrect(clip))
return nil;
clip.min.x ++;
@@ -349,7 +345,7 @@ rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm)
clip.max.x ++;
clip.max.y ++;
- if (gc->flag == FNONE)
+ if (!(gc->flag & FOVER))
{
error = fz_newpixmapwithrect(&gc->dest, clip, 1);
if (error)
@@ -374,7 +370,7 @@ rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm)
if (error)
return error;
- if (gc->flag == FNONE)
+ if (!(gc->flag & FOVER))
drawglyph(gc, gc->dest, &glyph, x, y);
else
drawglyph(gc, gc->over, &glyph, x, y);
@@ -423,19 +419,17 @@ renderimage(fz_renderer *gc, fz_imagenode *node, fz_matrix ctm)
int x0, y0;
int w, h;
-printf("renderimage %dx%d %d+%d %s\n", image->w, image->h, image->n, image->a, image->cs?image->cs->name:"(nil)");
+DEBUG("image %dx%d %d+%d %s\n{\n", image->w, image->h, image->n, image->a, image->cs?image->cs->name:"(nil)");
bbox = fz_roundrect(fz_boundnode((fz_node*)node, ctm));
clip = fz_intersectirects(gc->clip, bbox);
- if (clip.max.x <= clip.min.x)
- return nil;
- if (clip.max.y <= clip.min.y)
+ if (fz_isemptyrect(clip))
return nil;
calcimagescale(ctm, image->w, image->h, &dx, &dy);
-printf(" load image\n");
+DEBUG(" load image\n");
error = fz_newpixmap(&tile, 0, 0, image->w, image->h, image->n + 1);
if (error)
return error;
@@ -446,7 +440,7 @@ printf(" load image\n");
if (dx != 1 || dy != 1)
{
-printf(" scale image 1/%d 1/%d\n", dx, dy);
+DEBUG(" scale image 1/%d 1/%d\n", dx, dy);
fz_pixmap *temp;
error = fz_scalepixmap(&temp, tile, dx, dy);
if (error)
@@ -458,7 +452,7 @@ printf(" scale image 1/%d 1/%d\n", dx, dy);
if (image->cs && image->cs != gc->model)
{
fz_pixmap *temp;
-printf(" convert from %s to %s\n", image->cs->name, gc->model->name);
+DEBUG(" convert from %s to %s\n", image->cs->name, gc->model->name);
error = fz_newpixmap(&temp, tile->x, tile->y, tile->w, tile->h, gc->model->n + 1);
if (error)
goto cleanup;
@@ -486,11 +480,15 @@ printf(" convert from %s to %s\n", image->cs->name, gc->model->name);
fc = invmat.c * 65536;
fd = invmat.d * 65536;
+#define PSRC tile->samples, tile->w, tile->h
+#define PDST(p) p->samples + ((y0-p->y) * p->w + (x0-p->x)) * p->n, p->w * p->n
+#define PCTM u0, v0, fa, fb, fc, fd, w, h
+
switch (gc->flag)
{
case FNONE:
{
-printf(" fnone %d x %d\n", w, h);
+DEBUG(" fnone %d x %d\n", w, h);
if (image->cs)
error = fz_newpixmapwithrect(&gc->dest, clip, gc->model->n + 1);
else
@@ -499,50 +497,33 @@ printf(" fnone %d x %d\n", w, h);
goto cleanup;
if (image->cs)
- gc->rast.img4_g(
- tile->samples, tile->w, tile->h, w, h,
- gc->dest->samples, gc->dest->w * gc->dest->n,
- u0, v0, fa, fb, fc, fd);
+ gc->rast.img_4c4(PSRC, PDST(gc->dest), PCTM);
else
- gc->rast.img1_g(
- tile->samples, tile->w, tile->h, w, h,
- gc->dest->samples, gc->dest->w * gc->dest->n,
- u0, v0, fa, fb, fc, fd);
+ gc->rast.img_1c1(PSRC, PDST(gc->dest), PCTM);
}
break;
case FOVER:
{
-printf(" fover %d x %d\n", w, h);
+DEBUG(" fover %d x %d\n", w, h);
if (image->cs)
- gc->rast.img4_o4(
- tile->samples, tile->w, tile->h, w, h,
- gc->over->samples + ((y0 - gc->over->y) * gc->over->w + (x0 - gc->over->x)) * 4,
- gc->over->w * gc->over->n,
- u0, v0, fa, fb, fc, fd);
+ gc->rast.img_4o4(PSRC, PDST(gc->over), PCTM);
else
- gc->rast.img1_o1(
- tile->samples, tile->w, tile->h, w, h,
- gc->over->samples + ((y0 - gc->over->y) * gc->over->w + (x0 - gc->over->x)),
- gc->over->w * gc->over->n,
- u0, v0, fa, fb, fc, fd);
+ gc->rast.img_1o1(PSRC, PDST(gc->over), PCTM);
}
break;
case FOVER | FRGB:
- {
-printf(" fover+rgb %d x %d\n", w, h);
- gc->rast.img1_o4w3(
- tile->samples, tile->w, tile->h, w, h,
- gc->over->samples + ((y0 - gc->over->y) * gc->over->w + (x0 - gc->over->x)) * 4,
- gc->over->w * gc->over->n,
- u0, v0, fa, fb, fc, fd, gc->rgb);
- }
+DEBUG(" fover+rgb %d x %d\n", w, h);
+ gc->rast.img_w3i1o4(gc->rgb, PSRC, PDST(gc->over), PCTM);
break;
+
default:
assert(!"impossible flag in image span function");
}
+DEBUG("}\n");
+
fz_droppixmap(tile);
return nil;
@@ -555,24 +536,119 @@ cleanup:
* Over, Mask and Blend
*/
+static void
+blendover(fz_renderer *gc, fz_pixmap *src, fz_pixmap *dst)
+{
+ unsigned char *sp, *dp;
+ fz_irect sr, dr;
+ int x, y, w, h;
+
+ sr.min.x = src->x;
+ sr.min.y = src->y;
+ sr.max.x = src->x + src->w;
+ sr.max.y = src->y + src->h;
+
+ dr.min.x = dst->x;
+ dr.min.y = dst->y;
+ dr.max.x = dst->x + dst->w;
+ dr.max.y = dst->y + dst->h;
+
+ dr = fz_intersectirects(sr, dr);
+ x = dr.min.x;
+ y = dr.min.y;
+ w = dr.max.x - dr.min.x;
+ h = dr.max.y - dr.min.y;
+
+ 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;
+
+ if (src->n == 1 && dst->n == 1)
+ gc->rast.duff_1o1(sp, src->w, dp, dst->w, w, h);
+ else if (src->n == 4 && dst->n == 4)
+ gc->rast.duff_4o4(sp, src->w * 4, dp, dst->w * 4, w, h);
+ else if (src->n == dst->n)
+ gc->rast.duff_NoN(sp, src->w * src->n, src->n, dp, dst->w * dst->n, w, h);
+ else
+ assert(!"blendover src and dst mismatch");
+}
+
+static void
+blendmask(fz_renderer *gc, fz_pixmap *src, fz_pixmap *msk, fz_pixmap *dst, int over)
+{
+ unsigned char *sp, *dp, *mp;
+ fz_irect sr, dr, mr;
+ int x, y, w, h;
+
+ sr.min.x = src->x;
+ sr.min.y = src->y;
+ sr.max.x = src->x + src->w;
+ sr.max.y = src->y + src->h;
+
+ dr.min.x = dst->x;
+ dr.min.y = dst->y;
+ dr.max.x = dst->x + dst->w;
+ dr.max.y = dst->y + dst->h;
+
+ mr.min.x = msk->x;
+ mr.min.y = msk->y;
+ mr.max.x = msk->x + msk->w;
+ mr.max.y = msk->y + msk->h;
+
+ dr = fz_intersectirects(sr, dr);
+ dr = fz_intersectirects(dr, mr);
+ x = dr.min.x;
+ y = dr.min.y;
+ w = dr.max.x - dr.min.x;
+ h = dr.max.y - dr.min.y;
+
+ sp = src->samples + ((y - src->y) * src->w + (x - src->x)) * src->n;
+ mp = msk->samples + ((y - msk->y) * msk->w + (x - msk->x)) * msk->n;
+ dp = dst->samples + ((y - dst->y) * dst->w + (x - dst->x)) * dst->n;
+
+ if (over)
+ {
+ if (src->n == 1 && msk->n == 1 && dst->n == 1)
+ gc->rast.duff_1i1o1(sp, src->w, mp, msk->w, dp, dst->w, w, h);
+ else if (src->n == 4 && msk->n == 1 && dst->n == 4)
+ gc->rast.duff_4i1o4(sp, src->w * 4, mp, msk->w, dp, dst->w * 4, w, h);
+ else if (src->n == dst->n)
+ gc->rast.duff_NiMoN(sp, src->w * src->n, src->n, mp, msk->w * msk->n, msk->n, dp, dst->w * dst->n, w, h);
+ else
+ assert(!"blendmaskover src and msk and dst mismatch");
+ }
+ else
+ {
+ if (src->n == 1 && msk->n == 1 && dst->n == 1)
+ gc->rast.duff_1i1c1(sp, src->w, mp, msk->w, dp, dst->w, w, h);
+ else if (src->n == 4 && msk->n == 1 && dst->n == 4)
+ gc->rast.duff_4i1c4(sp, src->w * 4, mp, msk->w, dp, dst->w * 4, w, h);
+ else if (src->n == dst->n)
+ gc->rast.duff_NiMcN(sp, src->w * src->n, src->n, mp, msk->w * msk->n, msk->n, dp, dst->w * dst->n, w, h);
+ else
+ assert(!"blendmask src and msk and dst mismatch");
+ }
+}
+
static fz_error *
renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm)
{
fz_error *error;
fz_node *child;
- int cluster = 0;;
-
-//printf("over\n{\n");
+ int cluster = 0;
if (!gc->over)
{
-//printf(" alloc dest!\n");
- error = fz_newpixmapwithrect(&gc->over, gc->clip, gc->maskonly ? 1 : 4);
+DEBUG("over cluster %d\n{\n", gc->maskonly ? 1 : 4);
+ cluster = 1;
+ if (gc->maskonly)
+ error = fz_newpixmapwithrect(&gc->over, gc->clip, 1);
+ else
+ error = fz_newpixmapwithrect(&gc->over, gc->clip, 4);
if (error)
return error;
fz_clearpixmap(gc->over);
- cluster = 1;
}
+else DEBUG("over\n{\n");
for (child = over->super.first; child; child = child->next)
{
@@ -581,7 +657,7 @@ renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm)
return error;
if (gc->dest)
{
- fz_blendover(gc->dest, gc->over);
+ blendover(gc, gc->dest, gc->over);
fz_droppixmap(gc->dest);
gc->dest = nil;
}
@@ -593,7 +669,7 @@ renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm)
gc->over = nil;
}
-//printf("}\n");
+DEBUG("}\n");
return nil;
}
@@ -602,12 +678,13 @@ static fz_error *
rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm)
{
fz_error *error;
+ int oldmaskonly;
fz_pixmap *oldover;
- fz_pixmap *oldmask;
fz_irect oldclip;
- fz_irect newclip;
- fz_pixmap *shapepix;
- fz_pixmap *colorpix;
+ fz_irect bbox;
+ fz_irect clip;
+ fz_pixmap *shapepix = nil;
+ fz_pixmap *colorpix = nil;
fz_node *shape;
fz_node *color;
float rgb[3];
@@ -628,7 +705,7 @@ rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm)
gc->rgb[2] = rgb[2] * 255;
gc->flag |= FRGB;
- /* we know these handle FOVER | FRGB */
+ /* we know these can handle the FRGB shortcut */
if (fz_ispathnode(shape))
return renderpath(gc, (fz_pathnode*)shape, ctm);
if (fz_istextnode(shape))
@@ -640,50 +717,77 @@ rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm)
oldclip = gc->clip;
oldover = gc->over;
- oldmask = gc->mask;
- newclip = fz_roundrect(fz_boundnode(shape, ctm));
- newclip = fz_intersectirects(newclip, gc->clip);
+ bbox = fz_roundrect(fz_boundnode(shape, ctm));
+ clip = fz_intersectirects(bbox, gc->clip);
+ bbox = fz_roundrect(fz_boundnode(color, ctm));
+ clip = fz_intersectirects(bbox, clip);
- gc->clip = newclip;
- gc->over = nil;
- gc->mask = nil;
+ if (fz_isemptyrect(clip))
+ return nil;
-printf("mask\n{\n");
+DEBUG("mask [%d %d %d %d]\n{\n", clip.min.x, clip.min.y, clip.max.x, clip.max.y);
- error = rendernode(gc, color, ctm);
- if (error)
- return error;
- colorpix = gc->dest;
- gc->dest = nil;
+{
+fz_irect sbox = fz_roundrect(fz_boundnode(shape, ctm));
+fz_irect cbox = fz_roundrect(fz_boundnode(color, ctm));
+if (cbox.min.x >= sbox.min.x && cbox.max.x <= sbox.max.x)
+if (cbox.min.y >= sbox.min.y && cbox.max.y <= sbox.max.y)
+DEBUG("potentially useless mask\n");
+}
+
+ gc->clip = clip;
+ gc->over = nil;
+
+ oldmaskonly = gc->maskonly;
+ gc->maskonly = 1;
error = rendernode(gc, shape, ctm);
if (error)
- return error;
+ goto cleanup;
shapepix = gc->dest;
gc->dest = nil;
- if (colorpix && shapepix)
- {
- error = fz_newpixmapwithrect(&gc->dest, gc->clip, colorpix->n);
- if (error)
- return error;
+ gc->maskonly = oldmaskonly;
- fz_clearpixmap(gc->dest);
+ error = rendernode(gc, color, ctm);
+ if (error)
+ goto cleanup;
+ colorpix = gc->dest;
+ gc->dest = nil;
- fz_blendmask(gc->dest, colorpix, shapepix);
+ gc->clip = oldclip;
+ gc->over = oldover;
+
+ if (shapepix && colorpix)
+ {
+ if (gc->over)
+ {
+ blendmask(gc, colorpix, shapepix, gc->over, 1);
+ }
+ else
+ {
+ clip.min.x = MAX(colorpix->x, shapepix->x);
+ clip.min.y = MAX(colorpix->y, shapepix->y);
+ clip.max.x = MIN(colorpix->x+colorpix->w, shapepix->x+shapepix->w);
+ clip.max.y = MIN(colorpix->y+colorpix->h, shapepix->y+shapepix->h);
+ error = fz_newpixmapwithrect(&gc->dest, clip, colorpix->n);
+ if (error)
+ goto cleanup;
+ blendmask(gc, colorpix, shapepix, gc->dest, 0);
+ }
}
+DEBUG("}\n");
+
if (shapepix) fz_droppixmap(shapepix);
if (colorpix) fz_droppixmap(colorpix);
-
- gc->over = oldover;
- gc->mask = oldmask;
- gc->clip = oldclip;
-
-printf("}\n");
-
return nil;
+
+cleanup:
+ if (shapepix) fz_droppixmap(shapepix);
+ if (colorpix) fz_droppixmap(colorpix);
+ return error;
}
/*
@@ -697,8 +801,8 @@ rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm)
return nil;
gc->flag = FNONE;
- if (gc->over) gc->flag |= FOVER;
- if (gc->mask) gc->flag |= FMASK;
+ if (gc->over)
+ gc->flag |= FOVER;
switch (node->kind)
{
@@ -718,6 +822,8 @@ rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm)
return renderimage(gc, (fz_imagenode*)node, ctm);
case FZ_NLINK:
return rendernode(gc, ((fz_linknode*)node)->tree->root, ctm);
+ case FZ_NMETA:
+ return rendernode(gc, node->first, ctm);
}
return nil;
@@ -731,33 +837,40 @@ fz_rendertree(fz_pixmap **outp,
fz_error *error;
gc->clip = bbox;
+ gc->over = nil;
- if (white)
- {
- assert(gc->maskonly == 0);
-
+ if (gc->maskonly)
+ error = fz_newpixmapwithrect(&gc->over, bbox, 1);
+ else
error = fz_newpixmapwithrect(&gc->over, bbox, 4);
- if (error)
- return error;
+ if (error)
+ return error;
+ if (white)
memset(gc->over->samples, 0xff, gc->over->w * gc->over->h * gc->over->n);
- }
+ else
+ memset(gc->over->samples, 0x00, gc->over->w * gc->over->h * gc->over->n);
+
+DEBUG("tree %d [%d %d %d %d]\n{\n",
+gc->maskonly ? 1 : 4,
+bbox.min.x, bbox.min.y, bbox.max.x, bbox.max.y);
error = rendernode(gc, tree->root, ctm);
if (error)
return error;
- if (white)
- {
- *outp = gc->over;
- gc->over = nil;
- }
- else
+DEBUG("}\n");
+
+ if (gc->dest)
{
- *outp = gc->dest;
+ blendover(gc, gc->dest, gc->over);
+ fz_droppixmap(gc->dest);
gc->dest = nil;
}
+ *outp = gc->over;
+ gc->over = nil;
+
return nil;
}