summaryrefslogtreecommitdiff
path: root/draw/porterduff.c
diff options
context:
space:
mode:
Diffstat (limited to 'draw/porterduff.c')
-rw-r--r--draw/porterduff.c328
1 files changed, 211 insertions, 117 deletions
diff --git a/draw/porterduff.c b/draw/porterduff.c
index e5070a5d..59a4f4d4 100644
--- a/draw/porterduff.c
+++ b/draw/porterduff.c
@@ -72,131 +72,172 @@ and stick to using the premultiplied form.
typedef unsigned char byte;
-/* Blend source alpha over destination alpha */
+/* Blend a non-premultiplied color in mask over destination */
-void
-fz_blendmasks(byte * restrict dp, byte * restrict sp, int w)
+static inline void
+fz_paintspancolor2(byte * restrict dp, byte * restrict mp, int w, byte *color)
{
+ int sa = FZ_EXPAND(color[1]);
+ int g = color[0];
while (w--)
{
- dp[0] = sp[0] + fz_mul255(dp[0], 255 - sp[0]);
- sp++;
- dp++;
+ int ma = *mp++;
+ int masa = FZ_COMBINE(FZ_EXPAND(ma), sa);
+ dp[0] = FZ_BLEND(g, dp[0], masa);
+ dp[1] = FZ_BLEND(255, dp[1], masa);
+ dp += 2;
}
}
-/* Blend a non-premultiplied color in mask over destination */
+static inline void
+fz_paintspancolor4(byte * restrict dp, byte * restrict mp, int w, byte *color)
+{
+ int sa = FZ_EXPAND(color[3]);
+ int r = color[0];
+ int g = color[1];
+ int b = color[2];
+ while (w--)
+ {
+ int ma = *mp++;
+ int masa = FZ_COMBINE(FZ_EXPAND(ma), sa);
+ dp[0] = FZ_BLEND(r, dp[0], masa);
+ dp[1] = FZ_BLEND(g, dp[1], masa);
+ dp[2] = FZ_BLEND(b, dp[2], masa);
+ dp[3] = FZ_BLEND(255, dp[3], masa);
+ dp += 4;
+ }
+}
-void
-fz_blendwithcolormask(byte * restrict dp, byte * restrict sp, byte * restrict mp, int n, int w)
+static inline void
+fz_paintspancolorN(byte * restrict dp, byte * restrict mp, int n, int w, byte *color)
{
- int sa, r, g, b, k;
+ int sa = FZ_EXPAND(color[n-1]);
+ int k;
+ while (w--)
+ {
+ int ma = *mp++;
+ int masa = FZ_COMBINE(FZ_EXPAND(ma), sa);
+ for (k = 0; k < n - 1; k++)
+ dp[k] = FZ_BLEND(color[k], dp[k], masa);
+ dp[k] = FZ_BLEND(255, dp[k], masa);
+ dp += n;
+ }
+}
+void
+fz_paintspancolor(byte * restrict dp, byte * restrict mp, int n, int w, byte *color)
+{
switch (n)
{
- case 2:
- sa = FZ_EXPAND(sp[1]);
- g = sp[0];
- while (w--)
- {
- int ma = *mp++;
- int masa = FZ_COMBINE(FZ_EXPAND(ma), sa);
- dp[0] = FZ_BLEND(g, dp[0], masa);
- dp[1] = FZ_BLEND(255, dp[1], masa);
- dp += 2;
- }
- break;
- case 4:
- sa = FZ_EXPAND(sp[3]);
- r = sp[0];
- g = sp[1];
- b = sp[2];
- while (w--)
- {
- int ma = *mp++;
- int masa = FZ_COMBINE(FZ_EXPAND(ma), sa);
- dp[0] = FZ_BLEND(r, dp[0], masa);
- dp[1] = FZ_BLEND(g, dp[1], masa);
- dp[2] = FZ_BLEND(b, dp[2], masa);
- dp[3] = FZ_BLEND(255, dp[3], masa);
- dp += 4;
- }
- break;
- default:
- sa = FZ_EXPAND(sp[n-1]);
- while (w--)
- {
- int ma = *mp++;
- int masa = FZ_COMBINE(FZ_EXPAND(ma), sa);
- for (k = 0; k < n - 1; k++)
- dp[k] = FZ_BLEND(sp[k], dp[k], masa);
- dp[k] = FZ_BLEND(255, dp[k], masa);
- dp += n;
- }
+ case 2: fz_paintspancolor2(dp, mp, w, color); break;
+ case 4: fz_paintspancolor4(dp, mp, w, color); break;
+ default: fz_paintspancolorN(dp, mp, n, w, color); break;
}
}
/* Blend source in mask over destination */
-void
-fz_blendwithmask(byte * restrict dp, byte * restrict sp, byte * restrict mp, int n, int w)
+static inline void
+fz_paintspanmask2(byte * restrict dp, byte * restrict sp, byte * restrict mp, int w)
+{
+ while (w--)
+ {
+ int ma = *mp++;
+ int masa = fz_mul255(sp[1], ma);
+ int t = 255 - masa;
+ dp[0] = fz_mul255(sp[0], ma) + fz_mul255(dp[0], t);
+ dp[1] = fz_mul255(sp[1], ma) + fz_mul255(dp[1], t);
+ sp += 2;
+ dp += 2;
+ }
+}
+
+static inline void
+fz_paintspanmask4(byte * restrict dp, byte * restrict sp, byte * restrict mp, int w)
+{
+ while (w--)
+ {
+ int ma = *mp++;
+ int masa = fz_mul255(sp[3], ma);
+ int t = 255 - masa;
+ dp[0] = fz_mul255(sp[0], ma) + fz_mul255(dp[0], t);
+ dp[1] = fz_mul255(sp[1], ma) + fz_mul255(dp[1], t);
+ dp[2] = fz_mul255(sp[2], ma) + fz_mul255(dp[2], t);
+ dp[3] = fz_mul255(sp[3], ma) + fz_mul255(dp[3], t);
+ sp += 4;
+ dp += 4;
+ }
+}
+
+static inline void
+fz_paintspanmaskN(byte * restrict dp, byte * restrict sp, byte * restrict mp, int n, int w)
{
int k;
+ while (w--)
+ {
+ int ma = *mp++;
+ int masa = fz_mul255(sp[n-1], ma);
+ int t = 255 - masa;
+ for (k = 0; k < n; k++)
+ dp[k] = fz_mul255(sp[k], ma) + fz_mul255(dp[k], t);
+ sp += n;
+ dp += n;
+ }
+}
+void
+fz_paintspanmask(byte * restrict dp, byte * restrict sp, byte * restrict mp, int n, int w)
+{
switch (n)
{
- case 2:
- while (w--)
- {
- int ma = *mp++;
- int masa = fz_mul255(sp[1], ma);
- int t = 255 - masa;
- dp[0] = fz_mul255(sp[0], ma) + fz_mul255(dp[0], t);
- sp += 2;
- dp += 2;
- }
- break;
- case 4:
- while (w--)
- {
- int ma = *mp++;
- int masa = fz_mul255(sp[3], ma);
- int t = 255 - masa;
- dp[0] = fz_mul255(sp[0], ma) + fz_mul255(dp[0], t);
- dp[1] = fz_mul255(sp[1], ma) + fz_mul255(dp[1], t);
- dp[2] = fz_mul255(sp[2], ma) + fz_mul255(dp[2], t);
- dp[3] = fz_mul255(sp[3], ma) + fz_mul255(dp[3], t);
- sp += 4;
- dp += 4;
- }
- break;
- default:
- while (w--)
- {
- int ma = *mp++;
- int masa = fz_mul255(sp[n-1], ma);
- int t = 255 - masa;
- for (k = 0; k < n; k++)
- dp[k] = fz_mul255(sp[k], ma) + fz_mul255(dp[k], t);
- sp += n;
- dp += n;
- }
+ case 2: fz_paintspanmask2(dp, sp, mp, w); break;
+ case 4: fz_paintspanmask4(dp, sp, mp, w); break;
+ default: fz_paintspanmaskN(dp, sp, mp, n, w); break;
}
}
-/* Blend source in (constant) alpha over destination */
+/* Blend source in constant alpha over destination */
-void
-fz_blendwithalpha(byte * restrict dp, byte * restrict sp, int ma, int n, int w)
+static inline void
+fz_paintspan2alpha(byte * restrict dp, byte * restrict sp, int w, int alpha)
{
- int k;
+ while (w--)
+ {
+ int masa = fz_mul255(sp[1], alpha);
+ int t = 255 - masa;
+ dp[0] = fz_mul255(sp[0], masa) + fz_mul255(dp[0], t);
+ dp[1] = fz_mul255(sp[1], masa) + fz_mul255(dp[1], t);
+ sp += 2;
+ dp += 2;
+ }
+}
+static inline void
+fz_paintspan4alpha(byte * restrict dp, byte * restrict sp, int w, int alpha)
+{
while (w--)
{
- int masa = fz_mul255(sp[n-1], ma);
+ int masa = fz_mul255(sp[3], alpha);
+ int t = 255 - masa;
+ dp[0] = fz_mul255(sp[0], masa) + fz_mul255(dp[0], t);
+ dp[1] = fz_mul255(sp[1], masa) + fz_mul255(dp[1], t);
+ dp[2] = fz_mul255(sp[2], masa) + fz_mul255(dp[2], t);
+ dp[3] = fz_mul255(sp[3], masa) + fz_mul255(dp[3], t);
+ sp += 4;
+ dp += 4;
+ }
+}
+
+static inline void
+fz_paintspanNalpha(byte * restrict dp, byte * restrict sp, int n, int w, int alpha)
+{
+ int k;
+ while (w--)
+ {
+ int masa = fz_mul255(sp[n-1], alpha);
int t = 255 - masa;
for (k = 0; k < n; k++)
- dp[k] = fz_mul255(sp[k], ma) + fz_mul255(dp[k], t);
+ dp[k] = fz_mul255(sp[k], masa) + fz_mul255(dp[k], t);
sp += n;
dp += n;
}
@@ -204,11 +245,50 @@ fz_blendwithalpha(byte * restrict dp, byte * restrict sp, int ma, int n, int w)
/* Blend source over destination */
-void
-fz_blendnormal(byte * restrict dp, byte * restrict sp, int n, int w)
+static inline void
+fz_paintspan1(byte * restrict dp, byte * restrict sp, int w)
{
- int k;
+ while (w--)
+ {
+ int t = 255 - sp[0];
+ dp[0] = sp[0] + fz_mul255(dp[0], t);
+ sp ++;
+ dp ++;
+ }
+}
+static inline void
+fz_paintspan2(byte * restrict dp, byte * restrict sp, int w)
+{
+ while (w--)
+ {
+ int t = 255 - sp[1];
+ dp[0] = sp[0] + fz_mul255(dp[0], t);
+ dp[1] = sp[1] + fz_mul255(dp[1], t);
+ sp += 2;
+ dp += 2;
+ }
+}
+
+static inline void
+fz_paintspan4(byte * restrict dp, byte * restrict sp, int w)
+{
+ while (w--)
+ {
+ int t = 255 - sp[3];
+ dp[0] = sp[0] + fz_mul255(dp[0], t);
+ dp[1] = sp[1] + fz_mul255(dp[1], t);
+ dp[2] = sp[2] + fz_mul255(dp[2], t);
+ dp[3] = sp[3] + fz_mul255(dp[3], t);
+ sp += 4;
+ dp += 4;
+ }
+}
+
+static inline void
+fz_paintspanN(byte * restrict dp, byte * restrict sp, int n, int w)
+{
+ int k;
while (w--)
{
int t = 255 - sp[n-1];
@@ -219,23 +299,45 @@ fz_blendnormal(byte * restrict dp, byte * restrict sp, int n, int w)
}
}
+void
+fz_paintspan(byte * restrict dp, byte * restrict sp, int n, int w, int alpha)
+{
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 1: fz_paintspan1(dp, sp, w); break;
+ case 2: fz_paintspan2(dp, sp, w); break;
+ case 4: fz_paintspan4(dp, sp, w); break;
+ default: fz_paintspanN(dp, sp, n, w); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 2: fz_paintspan2alpha(dp, sp, w, alpha); break;
+ case 4: fz_paintspan4alpha(dp, sp, w, alpha); break;
+ default: fz_paintspanNalpha(dp, sp, n, w, alpha); break;
+ }
+ }
+}
+
/*
* Pixmap blending functions
*/
void
-fz_blendpixmapswithmask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *msk)
+fz_paintpixmap(fz_pixmap *dst, fz_pixmap *src, int alpha)
{
- unsigned char *sp, *dp, *mp;
+ unsigned char *sp, *dp;
fz_bbox bbox;
int x, y, w, h, n;
assert(dst->n == src->n);
- assert(msk->n == 1);
bbox = fz_boundpixmap(dst);
bbox = fz_intersectbbox(bbox, fz_boundpixmap(src));
- bbox = fz_intersectbbox(bbox, fz_boundpixmap(msk));
x = bbox.x0;
y = bbox.y0;
@@ -244,53 +346,45 @@ fz_blendpixmapswithmask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *msk)
n = src->n;
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;
while (h--)
{
- fz_blendwithmask(dp, sp, mp, n, w);
+ fz_paintspan(dp, sp, n, w, alpha);
sp += src->w * n;
dp += dst->w * n;
- mp += msk->w;
}
}
void
-fz_blendpixmapswithalpha(fz_pixmap *dst, fz_pixmap *src, float alpha)
+fz_paintpixmapmask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *msk)
{
- unsigned char *sp, *dp;
+ unsigned char *sp, *dp, *mp;
fz_bbox bbox;
- int x, y, w, h, n, a;
+ int x, y, w, h, n;
assert(dst->n == src->n);
+ assert(msk->n == 1);
bbox = fz_boundpixmap(dst);
bbox = fz_intersectbbox(bbox, fz_boundpixmap(src));
+ bbox = fz_intersectbbox(bbox, fz_boundpixmap(msk));
x = bbox.x0;
y = bbox.y0;
w = bbox.x1 - bbox.x0;
h = bbox.y1 - bbox.y0;
- a = alpha * 255;
n = src->n;
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;
while (h--)
{
- if (a == 255)
- fz_blendnormal(dp, sp, n, w);
- else
- fz_blendwithalpha(dp, sp, a, n, w);
+ fz_paintspanmask(dp, sp, mp, n, w);
sp += src->w * n;
dp += dst->w * n;
+ mp += msk->w;
}
}
-
-void
-fz_blendpixmaps(fz_pixmap *dst, fz_pixmap *src)
-{
- fz_blendpixmapswithalpha(dst, src, 1);
-}