summaryrefslogtreecommitdiff
path: root/base/gsroprun.c
diff options
context:
space:
mode:
authorChris Liddell <chris.liddell@artifex.com>2013-07-23 16:24:19 +0100
committerChris Liddell <chris.liddell@artifex.com>2015-07-20 18:21:17 +0100
commit6948650efd3fb9e2a70b8cf16aca57e9d0b7eb0a (patch)
tree5c2a1c671c1d4521f8a770d1e69e3d4342718030 /base/gsroprun.c
parent7fd9e0be26e67c36f87733bc89ea07dc26d9f839 (diff)
downloadghostpdl-6948650efd3fb9e2a70b8cf16aca57e9d0b7eb0a.tar.gz
Commit of build_consolidation branch
Squashed into one commit (see branch for details of the evolution of the branch). This brings gpcl6 and gxps into the Ghostscript build system, and a shared set of graphics library object files for all the interpreters. Also, brings the same configuration options to the pcl and xps products as we have for Ghostscript.
Diffstat (limited to 'base/gsroprun.c')
-rw-r--r--base/gsroprun.c1879
1 files changed, 1879 insertions, 0 deletions
diff --git a/base/gsroprun.c b/base/gsroprun.c
new file mode 100644
index 000000000..25a210b5b
--- /dev/null
+++ b/base/gsroprun.c
@@ -0,0 +1,1879 @@
+/* Copyright (C) 2001-2012 Artifex Software, Inc.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied,
+ modified or distributed except as expressly authorized under the terms
+ of the license contained in the file LICENSE in this distribution.
+
+ Refer to licensing information at http://www.artifex.com or contact
+ Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
+ CA 94903, U.S.A., +1(415)492-9861, for further information.
+*/
+
+
+/* Runs of RasterOps */
+#include "std.h"
+#include "stdpre.h"
+#include "gsropt.h"
+#include "arch.h"
+#include "gp.h"
+
+/* Enable the following define to use 'template'd code (code formed by
+ * repeated #inclusion of a header file to generate differen versions).
+ * This code should be faster as it uses native ints where possible.
+ * Eventually this should be the only type of code left in here and we can
+ * remove this define. */
+#define USE_TEMPLATES
+
+/* Enable the following define to disable all rops (at least, all the ones
+ * done using the rop run mechanism. For debugging only. */
+#undef DISABLE_ROPS
+
+/* A hack. Define this, and we will update the rop usage within a file. */
+#undef RECORD_ROP_USAGE
+
+/* Values used for defines used when including 'template' headers. */
+#define MAYBE 0
+#define YES 1
+
+#ifdef RECORD_ROP_USAGE
+#define MAX (1024<<7)
+static int usage[MAX*3];
+
+static int inited = 0;
+
+static void write_usage(void)
+{
+ int i;
+ for (i = 0; i < MAX; i++)
+ if (usage[3*i] != 0) {
+ int depth = ((i>>4)&3)<<3;
+ if (depth == 0) depth = 1;
+ if (i & (1<<6))
+ (fprintf)(stderr, "ROP: rop=%x ", i>>7);
+ else
+ (fprintf)(stderr, "ROP: rop=ANY ");
+ (fprintf)(stderr, "depth=%d flags=%d gets=%d inits=%d pixels=%d\n",
+ depth, i&15, usage[3*i], usage[3*i+1], usage[3*i+2]);
+ }
+#ifdef RECORD_BINARY
+ FILE *out = gp_fopen("ropusage2.tmp", "wb");
+ if (!out)
+ return;
+ fwrite(usage, sizeof(int), (1024<<7), out);
+ fclose(out);
+#endif
+}
+
+static void record(int rop)
+{
+ if (inited == 0) {
+#ifdef RECORD_BINARY
+ FILE *in = gp_fopen("ropusage2.tmp", "r");
+ if (!in)
+ memset(usage, 0, MAX*sizeof(int));
+ else {
+ fread(usage, sizeof(int), MAX, in);
+ fclose(in);
+ }
+#endif
+ memset(usage, 0, MAX*3*sizeof(int));
+ atexit(write_usage);
+ inited = 1;
+ }
+
+ usage[3*rop]++;
+}
+
+static void unrecord(int rop)
+{
+ usage[3*rop]--;
+}
+#endif
+
+#define get24(ptr)\
+ (((rop_operand)(ptr)[0] << 16) | ((rop_operand)(ptr)[1] << 8) | (ptr)[2])
+#define put24(ptr, pixel)\
+ (ptr)[0] = (byte)((pixel) >> 16),\
+ (ptr)[1] = (byte)((uint)(pixel) >> 8),\
+ (ptr)[2] = (byte)(pixel)
+
+/* Rop specific code */
+/* Rop 0x55 = Invert dep=1 (all cases) */
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME invert_rop_run1
+#define SPECIFIC_ROP 0x55
+#define SPECIFIC_CODE(O,D,S,T) do { O = ~D; } while (0)
+#define S_CONST
+#define T_CONST
+#include "gsroprun1.h"
+#else
+static void invert_rop_run1(rop_run_op *op, byte *d, int len)
+{
+ byte lmask, rmask;
+
+ len = len * op->depth + op->dpos;
+ /* lmask = the set of bits to alter in the output bitmap on the left
+ * hand edge of the run. rmask = the set of bits NOT to alter in the
+ * output bitmap on the right hand edge of the run. */
+ lmask = 255>>(7 & op->dpos);
+ rmask = 255>>(7 & len);
+
+ len -= 8;
+ if (len < 0) {
+ /* Short case - starts and ends in the same byte */
+ lmask &= ~rmask; /* Combined mask = bits to alter */
+ *d = (*d & ~lmask) | ((~*d) & lmask);
+ return;
+ }
+ if (lmask != 0xFF) {
+ *d = (*d & ~lmask) | ((~*d) & lmask);
+ d++;
+ len -= 8;
+ }
+ if (len >= 0) {
+ /* Simple middle case (complete destination bytes). */
+ do {
+ *d = ~*d;
+ d++;
+ len -= 8;
+ } while (len >= 0);
+ }
+ if (rmask != 0xFF) {
+ /* Unaligned right hand case */
+ *d = ((~*d) & ~rmask) | (*d & rmask);
+ }
+}
+#endif
+
+/* Rop 0x55 = Invert dep=8 (all cases) */
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME invert_rop_run8
+#define SPECIFIC_ROP 0x55
+#define SPECIFIC_CODE(O,D,S,T) do { O = ~D; } while (0)
+#define S_CONST
+#define T_CONST
+#include "gsroprun8.h"
+#else
+static void invert_rop_run8(rop_run_op *op, byte *d, int len)
+{
+ do {
+ *d = ~*d;
+ d++;
+ }
+ while (--len);
+}
+#endif
+
+/* Rop 0x55 = Invert dep=24 (all cases) */
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME invert_rop_run24
+#define SPECIFIC_ROP 0x55
+#define SPECIFIC_CODE(O,D,S,T) do { O = ~D; } while (0)
+#define S_CONST
+#define T_CONST
+#include "gsroprun24.h"
+#else
+static void invert_rop_run24(rop_run_op *op, byte *d, int len)
+{
+ do
+ {
+ *d = ~*d;
+ d++;
+ *d = ~*d;
+ d++;
+ *d = ~*d;
+ d++;
+ }
+ while (--len);
+}
+#endif
+
+/* Rop 0x0f = ~t */
+
+/* 0x0F = ~t dep=1 s_constant */
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME notT_rop_run1_const_s
+#define SPECIFIC_ROP 0x0F
+#define SPECIFIC_CODE(O,D,S,T) do { O = ~T; } while (0)
+#define S_CONST
+#include "gsroprun1.h"
+#else
+static void notT_rop_run1_const_s(rop_run_op *op, byte *d, int len)
+{
+ byte lmask, rmask;
+ const byte *t = op->t.b.ptr;
+ byte T;
+ int t_skew;
+
+ len = len * op->depth + op->dpos;
+ /* lmask = the set of bits to alter in the output bitmap on the left
+ * hand edge of the run. rmask = the set of bits NOT to alter in the
+ * output bitmap on the right hand edge of the run. */
+ lmask = 255>>(7 & op->dpos);
+ rmask = 255>>(7 & len);
+
+ /* Note #1: This mirrors what the original code did, but I think it has
+ * the risk of moving s and t back beyond officially allocated space. We
+ * may be saved by the fact that all blocks have a word or two in front
+ * of them due to the allocator. If we ever get valgrind properly marking
+ * allocated blocks as readable etc, then this may throw some spurious
+ * errors. RJW. */
+ t_skew = op->t.b.pos - op->dpos;
+ if (t_skew < 0) {
+ t_skew += 8;
+ t--;
+ }
+
+ len -= 8;
+ if (len < 0) {
+ /* Short case - starts and ends in the same byte */
+ lmask &= ~rmask; /* Combined mask = bits to alter */
+ T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
+ *d = (*d & ~lmask) | (~T & lmask);
+ return;
+ }
+ if (lmask != 0xFF) {
+ /* Unaligned left hand case */
+ T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
+ t++;
+ *d = (*d & ~lmask) | (~T & lmask);
+ d++;
+ len -= 8;
+ }
+ if (len >= 0) {
+ /* Simple middle case (complete destination bytes). */
+ if (t_skew == 0) {
+ do {
+ *d++ = ~*t++;
+ len -= 8;
+ } while (len >= 0);
+ } else {
+ do {
+ T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
+ t++;
+ *d++ = ~T;
+ len -= 8;
+ } while (len >= 0);
+ }
+ }
+ if (rmask != 0xFF) {
+ /* Unaligned right hand case */
+ T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
+ *d = (~T & ~rmask) | (*d & rmask);
+ }
+}
+#endif
+
+/* Rop 0xEE = d|s */
+
+/* 0xEE = d|s dep=1 t_constant */
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME dors_rop_run1_const_t
+#define SPECIFIC_ROP 0xEE
+#define SPECIFIC_CODE(O,D,S,T) do { O = D|S; } while (0)
+#define T_CONST
+#include "gsroprun1.h"
+#else
+static void dors_rop_run1_const_t(rop_run_op *op, byte *d, int len)
+{
+ byte lmask, rmask;
+ const byte *s = op->s.b.ptr;
+ byte S, D;
+ int s_skew;
+
+ len = len * op->depth + op->dpos;
+ /* lmask = the set of bits to alter in the output bitmap on the left
+ * hand edge of the run. rmask = the set of bits NOT to alter in the
+ * output bitmap on the right hand edge of the run. */
+ lmask = 255>>(7 & op->dpos);
+ rmask = 255>>(7 & len);
+
+ /* Note #1: This mirrors what the original code did, but I think it has
+ * the risk of moving s and t back beyond officially allocated space. We
+ * may be saved by the fact that all blocks have a word or two in front
+ * of them due to the allocator. If we ever get valgrind properly marking
+ * allocated blocks as readable etc, then this may throw some spurious
+ * errors. RJW. */
+ s_skew = op->s.b.pos - op->dpos;
+ if (s_skew < 0) {
+ s_skew += 8;
+ s--;
+ }
+
+ len -= 8;
+ if (len < 0) {
+ /* Short case - starts and ends in the same byte */
+ lmask &= ~rmask; /* Combined mask = bits to alter */
+ S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
+ D = *d | S;
+ *d = (*d & ~lmask) | (D & lmask);
+ return;
+ }
+ if (lmask != 0xFF) {
+ /* Unaligned left hand case */
+ S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
+ s++;
+ D = *d | S;
+ *d = (*d & ~lmask) | (D & lmask);
+ d++;
+ len -= 8;
+ }
+ if (len >= 0) {
+ /* Simple middle case (complete destination bytes). */
+ if (s_skew == 0) {
+ do {
+ *d++ |= *s++;
+ len -= 8;
+ } while (len >= 0);
+ } else {
+ do {
+ S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
+ s++;
+ *d |= S;
+ d++;
+ len -= 8;
+ } while (len >= 0);
+ }
+ }
+ if (rmask != 0xFF) {
+ /* Unaligned right hand case */
+ S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
+ D = *d | S;
+ *d = (D & ~rmask) | (*d & rmask);
+ }
+}
+#endif
+
+/* Rop 0xfa = d|t */
+
+/* 0xFA = d|t dep=1 s_constant */
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME dort_rop_run1_const_s
+#define SPECIFIC_ROP 0xFA
+#define SPECIFIC_CODE(O,D,S,T) do { O = D|T; } while (0)
+#define S_CONST
+#include "gsroprun1.h"
+#else
+static void dort_rop_run1_const_s(rop_run_op *op, byte *d, int len)
+{
+ byte lmask, rmask;
+ const byte *t = op->t.b.ptr;
+ byte T, D;
+ int t_skew;
+
+ len = len * op->depth + op->dpos;
+ /* lmask = the set of bits to alter in the output bitmap on the left
+ * hand edge of the run. rmask = the set of bits NOT to alter in the
+ * output bitmap on the right hand edge of the run. */
+ lmask = 255>>(7 & op->dpos);
+ rmask = 255>>(7 & len);
+
+ /* Note #1: This mirrors what the original code did, but I think it has
+ * the risk of moving s and t back beyond officially allocated space. We
+ * may be saved by the fact that all blocks have a word or two in front
+ * of them due to the allocator. If we ever get valgrind properly marking
+ * allocated blocks as readable etc, then this may throw some spurious
+ * errors. RJW. */
+ t_skew = op->t.b.pos - op->dpos;
+ if (t_skew < 0) {
+ t_skew += 8;
+ t--;
+ }
+
+ len -= 8;
+ if (len < 0) {
+ /* Short case - starts and ends in the same byte */
+ lmask &= ~rmask; /* Combined mask = bits to alter */
+ T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
+ D = *d | T;
+ *d = (*d & ~lmask) | (D & lmask);
+ return;
+ }
+ if (lmask != 0xFF) {
+ /* Unaligned left hand case */
+ T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
+ t++;
+ D = *d | T;
+ *d = (*d & ~lmask) | (D & lmask);
+ d++;
+ len -= 8;
+ }
+ if (len >= 0) {
+ /* Simple middle case (complete destination bytes). */
+ if (t_skew == 0) {
+ do {
+ *d++ |= *t++;
+ len -= 8;
+ } while (len >= 0);
+ } else {
+ do {
+ T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
+ t++;
+ *d |= T;
+ d++;
+ len -= 8;
+ } while (len >= 0);
+ }
+ }
+ if (rmask != 0xFF) {
+ /* Unaligned right hand case */
+ T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
+ D = *d | T;
+ *d = (D & ~rmask) | (*d & rmask);
+ }
+}
+#endif
+
+/* Rop 0x66 = d^s (and 0x5A = d^t) */
+
+/* 0x5A = d^t dep=1 s_constant */
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME xor_rop_run1_const_s
+#define SPECIFIC_ROP 0x5A
+#define SPECIFIC_CODE(O,D,S,T) do { O = D^T; } while (0)
+#define S_CONST
+#include "gsroprun1.h"
+#else
+static void xor_rop_run1_const_s(rop_run_op *op, byte *d, int len)
+{
+ byte lmask, rmask;
+ const byte *t = op->t.b.ptr;
+ byte T, D;
+ int t_skew;
+
+ len = len * op->depth + op->dpos;
+ /* lmask = the set of bits to alter in the output bitmap on the left
+ * hand edge of the run. rmask = the set of bits NOT to alter in the
+ * output bitmap on the right hand edge of the run. */
+ lmask = 255>>(7 & op->dpos);
+ rmask = 255>>(7 & len);
+
+ /* Note #1: This mirrors what the original code did, but I think it has
+ * the risk of moving s and t back beyond officially allocated space. We
+ * may be saved by the fact that all blocks have a word or two in front
+ * of them due to the allocator. If we ever get valgrind properly marking
+ * allocated blocks as readable etc, then this may throw some spurious
+ * errors. RJW. */
+ t_skew = op->t.b.pos - op->dpos;
+ if (t_skew < 0) {
+ t_skew += 8;
+ t--;
+ }
+
+ len -= 8;
+ if (len < 0) {
+ /* Short case - starts and ends in the same byte */
+ lmask &= ~rmask; /* Combined mask = bits to alter */
+ T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
+ D = *d ^ T;
+ *d = (*d & ~lmask) | (D & lmask);
+ return;
+ }
+ if (lmask != 0xFF) {
+ /* Unaligned left hand case */
+ T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
+ t++;
+ D = *d ^ T;
+ *d = (*d & ~lmask) | (D & lmask);
+ d++;
+ len -= 8;
+ }
+ if (len >= 0) {
+ /* Simple middle case (complete destination bytes). */
+ if (t_skew == 0) {
+ do {
+ *d++ ^= *t++;
+ len -= 8;
+ } while (len >= 0);
+ } else {
+ do {
+ T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
+ t++;
+ *d = *d ^ T;
+ d++;
+ len -= 8;
+ } while (len >= 0);
+ }
+ }
+ if (rmask != 0xFF) {
+ /* Unaligned right hand case */
+ T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
+ D = *d ^ T;
+ *d = (D & ~rmask) | (*d & rmask);
+ }
+}
+#endif
+
+/* rop = 0x66 = d^s dep=8 s_constant t_constant */
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME xor_rop_run8_const_st
+#define SPECIFIC_ROP 0x66
+#define SPECIFIC_CODE(O,D,S,T) do { O = D^S; } while (0)
+#define S_CONST
+#define T_CONST
+#include "gsroprun8.h"
+#else
+static void xor_rop_run8_const_st(rop_run_op *op, byte *d, int len)
+{
+ const byte S = op->s.c;
+ if (S == 0)
+ return;
+ do {
+ *d ^= S;
+ d++;
+ }
+ while (--len);
+}
+#endif
+
+/* rop = 0x66 = d^s dep=24 s_constant t_constant */
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME xor_rop_run24_const_st
+#define SPECIFIC_ROP 0x66
+#define SPECIFIC_CODE(O,D,S,T) do { O = D^S; } while (0)
+#define S_CONST
+#define T_CONST
+#include "gsroprun24.h"
+#else
+static void xor_rop_run24_const_st(rop_run_op *op, byte *d, int len)
+{
+ rop_operand S = op->s.c;
+ if (S == 0)
+ return;
+ do
+ {
+ rop_operand D = get24(d) ^ S;
+ put24(d, D);
+ d += 3;
+ }
+ while (--len);
+}
+#endif
+
+/* rop = 0xFC = s | t dep=24 s_constant t_constant */
+#ifdef USE_TEMPLATES
+/* FIXME: Not optimal; introduce 'PRE' code to combine S and T. */
+#define TEMPLATE_NAME sort_rop_run24_const_st
+#define SPECIFIC_ROP 0x66
+#define SPECIFIC_CODE(O,D,S,T) do { O = S|T; } while (0)
+#define S_CONST
+#define T_CONST
+#include "gsroprun24.h"
+#else
+static void sort_rop_run24_const_st(rop_run_op *op, byte *d, int len)
+{
+ rop_operand SorT = op->s.c | op->t.c;
+ do
+ {
+ put24(d, SorT);
+ d += 3;
+ }
+ while (--len);
+}
+#endif
+
+/* rop = 0xAA = d dep=? s_constant t_constant */
+static void nop_rop_const_st(rop_run_op *op, byte *d, int len)
+{
+}
+
+/* rop = 0xF0 = t dep=1 s_constant */
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME sett_rop_run1_const_s
+#define SPECIFIC_ROP 0xF0
+#define SPECIFIC_CODE(O,D,S,T) do { O = T; } while (0)
+#define S_CONST
+#include "gsroprun1.h"
+#else
+static void sett_rop_run1_const_s(rop_run_op *op, byte *d, int len)
+{
+ rop_proc proc = rop_proc_table[op->rop];
+ byte lmask, rmask;
+ byte T, D;
+ const byte *t = op->t.b.ptr;
+ int t_skew;
+
+ len = len*op->depth + op->dpos;
+ /* lmask = the set of bits to alter in the output bitmap on the left
+ * hand edge of the run. rmask = the set of bits NOT to alter in the
+ * output bitmap on the right hand edge of the run. */
+ lmask = 255>>(7 & op->dpos);
+ rmask = 255>>(7 & len);
+
+ /* See note #1 above. RJW. */
+ t_skew = op->t.b.pos - op->dpos;
+ if (t_skew < 0) {
+ t_skew += 8;
+ t--;
+ }
+
+ len -= 8;
+ if (len < 0) {
+ /* Short case - starts and ends in the same byte */
+ lmask &= ~rmask; /* Combined mask = bits to alter */
+ T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
+ D = proc(*d, 0, T);
+ *d = (*d & ~lmask) | (D & lmask);
+ return;
+ }
+ if (lmask != 0xFF) {
+ /* Unaligned left hand case */
+ T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
+ t++;
+ D = proc(*d, 0, T);
+ *d = (*d & ~lmask) | (D & lmask);
+ d++;
+ len -= 8;
+ }
+ if (len >= 0) {
+ /* Simple middle case (complete destination bytes). */
+ if (t_skew == 0) {
+ do {
+ *d = proc(*d, 0, *t++);
+ d++;
+ len -= 8;
+ } while (len >= 0);
+ } else {
+ do {
+ T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
+ t++;
+ *d = proc(*d, 0, T);
+ d++;
+ len -= 8;
+ } while (len >= 0);
+ }
+ }
+ if (rmask != 0xFF) {
+ /* Unaligned right hand case */
+ T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
+ D = proc(*d, 0, T);
+ *d = (D & ~rmask) | (*d & rmask);
+ }
+}
+#endif
+
+/* rop = 0xCC = s dep=1 t_constant */
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME sets_rop_run1_const_t
+#define SPECIFIC_ROP 0xCC
+#define SPECIFIC_CODE(O,D,S,T) do { O = S; } while (0)
+#define T_CONST
+#include "gsroprun1.h"
+#else
+static void sets_rop_run1_const_s(rop_run_op *op, byte *d, int len)
+{
+ rop_proc proc = rop_proc_table[op->rop];
+ byte lmask, rmask;
+ byte S, D;
+ const byte *s = op->s.b.ptr;
+ int s_skew;
+
+ len = len*op->depth + op->dpos;
+ /* lmask = the set of bits to alter in the output bitmap on the left
+ * hand edge of the run. rmask = the set of bits NOT to alter in the
+ * output bitmap on the right hand edge of the run. */
+ lmask = 255>>(7 & op->dpos);
+ rmask = 255>>(7 & len);
+
+ /* See note #1 above. RJW. */
+ s_skew = op->s.b.pos - op->dpos;
+ if (s_skew < 0) {
+ s_skew += 8;
+ s--;
+ }
+
+ len -= 8;
+ if (len < 0) {
+ /* Short case - starts and ends in the same byte */
+ lmask &= ~rmask; /* Combined mask = bits to alter */
+ S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
+ D = proc(*d, 0, S);
+ *d = (*d & ~lmask) | (D & lmask);
+ return;
+ }
+ if (lmask != 0xFF) {
+ /* Unaligned left hand case */
+ S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
+ s++;
+ D = proc(*d, 0, S);
+ *d = (*d & ~lmask) | (D & lmask);
+ d++;
+ len -= 8;
+ }
+ if (len >= 0) {
+ /* Simple middle case (complete destination bytes). */
+ if (s_skew == 0) {
+ do {
+ *d = proc(*d, 0, *s++);
+ d++;
+ len -= 8;
+ } while (len >= 0);
+ } else {
+ do {
+ S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
+ s++;
+ *d = proc(*d, 0, S);
+ d++;
+ len -= 8;
+ } while (len >= 0);
+ }
+ }
+ if (rmask != 0xFF) {
+ /* Unaligned right hand case */
+ S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
+ D = proc(*d, 0, S);
+ *d = (D & ~rmask) | (*d & rmask);
+ }
+}
+#endif
+
+/* Generic ROP run code */
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME generic_rop_run1
+#include "gsroprun1.h"
+#else
+static void generic_rop_run1(rop_run_op *op, byte *d, int len)
+{
+ rop_proc proc = rop_proc_table[op->rop];
+ byte lmask, rmask;
+ const byte *s = op->s.b.ptr;
+ const byte *t = op->t.b.ptr;
+ byte S, T, D;
+ int s_skew, t_skew;
+
+ len = len * op->depth + op->dpos;
+ /* lmask = the set of bits to alter in the output bitmap on the left
+ * hand edge of the run. rmask = the set of bits NOT to alter in the
+ * output bitmap on the right hand edge of the run. */
+ lmask = 255>>(7 & op->dpos);
+ rmask = 255>>(7 & len);
+
+ /* Note #1: This mirrors what the original code did, but I think it has
+ * the risk of moving s and t back beyond officially allocated space. We
+ * may be saved by the fact that all blocks have a word or two in front
+ * of them due to the allocator. If we ever get valgrind properly marking
+ * allocated blocks as readable etc, then this may throw some spurious
+ * errors. RJW. */
+ s_skew = op->s.b.pos - op->dpos;
+ if (s_skew < 0) {
+ s_skew += 8;
+ s--;
+ }
+ t_skew = op->t.b.pos - op->dpos;
+ if (t_skew < 0) {
+ t_skew += 8;
+ t--;
+ }
+
+ len -= 8;
+ if (len < 0) {
+ /* Short case - starts and ends in the same byte */
+ lmask &= ~rmask; /* Combined mask = bits to alter */
+ S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
+ T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
+ D = proc(*d, S, T);
+ *d = (*d & ~lmask) | (D & lmask);
+ return;
+ }
+ if (lmask != 0xFF) {
+ /* Unaligned left hand case */
+ S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
+ s++;
+ T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
+ t++;
+ D = proc(*d, S, T);
+ *d = (*d & ~lmask) | (D & lmask);
+ d++;
+ len -= 8;
+ }
+ if (len >= 0) {
+ /* Simple middle case (complete destination bytes). */
+ if (s_skew == 0) {
+ if (t_skew == 0) {
+ do {
+ *d = proc(*d, *s++, *t++);
+ d++;
+ len -= 8;
+ } while (len >= 0);
+ } else {
+ do {
+ T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
+ t++;
+ *d = proc(*d, *s++, T);
+ d++;
+ len -= 8;
+ } while (len >= 0);
+ }
+ } else {
+ if (t_skew == 0) {
+ do {
+ S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
+ s++;
+ *d = proc(*d, S, *t++);
+ d++;
+ len -= 8;
+ } while (len >= 0);
+ } else {
+ do {
+ S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
+ s++;
+ T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
+ t++;
+ *d = proc(*d, S, T);
+ d++;
+ len -= 8;
+ } while (len >= 0);
+ }
+ }
+ }
+ if (rmask != 0xFF) {
+ /* Unaligned right hand case */
+ S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
+ T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
+ D = proc(*d, S, T);
+ *d = (D & ~rmask) | (*d & rmask);
+ }
+}
+#endif
+
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME generic_rop_run8
+#include "gsroprun8.h"
+#else
+static void generic_rop_run8(rop_run_op *op, byte *d, int len)
+{
+ rop_proc proc = rop_proc_table[op->rop];
+ const byte *s = op->s.b.ptr;
+ const byte *t = op->t.b.ptr;
+ do {
+ *d = proc(*d, *s++, *t++);
+ d++;
+ }
+ while (--len);
+}
+#endif
+
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME generic_rop_run8_trans_S
+#define S_TRANS YES
+#include "gsroprun8.h"
+#else
+static void generic_rop_run8_trans_S(rop_run_op *op, byte *d, int len)
+{
+ rop_proc proc = rop_proc_table[lop_rop(op->rop)];
+ const byte *s = op->s.b.ptr;
+ const byte *t = op->t.b.ptr;
+ do {
+ rop_operand S = *s++;
+ if (S != 255)
+ *d = proc(*d, S, *t);
+ t++;
+ d++;
+ }
+ while (--len);
+}
+#endif
+
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME generic_rop_run8_trans_T
+#define T_TRANS YES
+#include "gsroprun8.h"
+#else
+static void generic_rop_run8_trans_T(rop_run_op *op, byte *d, int len)
+{
+ rop_proc proc = rop_proc_table[lop_rop(op->rop)];
+ const byte *s = op->s.b.ptr;
+ const byte *t = op->t.b.ptr;
+ do {
+ rop_operand T = *t++;
+ if (T != 255)
+ *d = proc(*d, *s, T);
+ s++;
+ d++;
+ }
+ while (--len);
+}
+#endif
+
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME generic_rop_run8_trans_ST
+#define S_TRANS YES
+#define T_TRANS YES
+#include "gsroprun8.h"
+#else
+static void generic_rop_run8_trans_ST(rop_run_op *op, byte *d, int len)
+{
+ rop_proc proc = rop_proc_table[lop_rop(op->rop)];
+ const byte *s = op->s.b.ptr;
+ const byte *t = op->t.b.ptr;
+ do {
+ rop_operand S = *s++;
+ rop_operand T = *t++;
+ if ((S != 255) && (T != 255))
+ *d = proc(*d, S, T);
+ d++;
+ }
+ while (--len);
+}
+#endif
+
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME generic_rop_run8_1bit
+#define S_TRANS MAYBE
+#define T_TRANS MAYBE
+#define S_1BIT MAYBE
+#define T_1BIT MAYBE
+#include "gsroprun8.h"
+#else
+static void generic_rop_run8_1bit(rop_run_op *op, byte *d, int len)
+{
+ rop_proc proc = rop_proc_table[lop_rop(op->rop)];
+ const byte *s = op->s.b.ptr;
+ const byte *t = op->t.b.ptr;
+ rop_operand strans = (op->rop & lop_S_transparent ? 255 : -1);
+ rop_operand ttrans = (op->rop & lop_T_transparent ? 255 : -1);
+ int sroll, troll;
+ const byte *scolors = op->scolors;
+ const byte *tcolors = op->tcolors;
+ if (op->flags & rop_s_1bit) {
+ s = op->s.b.ptr + (op->s.b.pos>>3);
+ sroll = 8-(op->s.b.pos & 7);
+ } else
+ sroll = 0;
+ if (op->flags & rop_t_1bit) {
+ t = op->t.b.ptr + (op->t.b.pos>>3);
+ troll = 8-(op->t.b.pos & 7);
+ } else
+ troll = 0;
+ do {
+ rop_operand S, T;
+ if (sroll == 0)
+ S = *s++;
+ else {
+ --sroll;
+ S = scolors[(*s >> sroll) & 1];
+ if (sroll == 0) {
+ sroll = 8;
+ s++;
+ }
+ }
+ if (troll == 0)
+ T = *t++;
+ else {
+ --troll;
+ T = tcolors[(*t >> troll) & 1];
+ if (troll == 0) {
+ troll = 8;
+ t++;
+ }
+ }
+ if ((S != strans) && (T != ttrans))
+ *d = proc(*d, S, T);
+ d++;
+ }
+ while (--len);
+}
+#endif
+
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME generic_rop_run24
+#include "gsroprun24.h"
+#else
+static void generic_rop_run24(rop_run_op *op, byte *d, int len)
+{
+ rop_proc proc = rop_proc_table[op->rop];
+ const byte *s = op->s.b.ptr;
+ const byte *t = op->t.b.ptr;
+ do
+ {
+ rop_operand D = proc(get24(d), get24(s), get24(t));
+ put24(d, D);
+ s += 3;
+ t += 3;
+ d += 3;
+ }
+ while (--len);
+}
+#endif
+
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME generic_rop_run24_trans
+#define T_TRANS MAYBE
+#define S_TRANS MAYBE
+#include "gsroprun24.h"
+#else
+static void generic_rop_run24_trans(rop_run_op *op, byte *d, int len)
+{
+ rop_proc proc = rop_proc_table[lop_rop(op->rop)];
+ const byte *s = op->s.b.ptr;
+ const byte *t = op->t.b.ptr;
+ rop_operand strans = (op->rop & lop_S_transparent ? 0xFFFFFF : -1);
+ rop_operand ttrans = (op->rop & lop_T_transparent ? 0xFFFFFF : -1);
+ do
+ {
+ rop_operand S = get24(s);
+ rop_operand T = get24(t);
+ if ((S != strans) && (T != ttrans)) {
+ rop_operand D = proc(get24(d), S, T);
+ put24(d, D);
+ }
+ s += 3;
+ t += 3;
+ d += 3;
+ }
+ while (--len);
+}
+#endif
+
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME generic_rop_run24_1bit
+#define S_TRANS MAYBE
+#define T_TRANS MAYBE
+#define S_1BIT MAYBE
+#define T_1BIT MAYBE
+#include "gsroprun24.h"
+#else
+static void generic_rop_run24_1bit(rop_run_op *op, byte *d, int len)
+{
+ rop_proc proc = rop_proc_table[lop_rop(op->rop)];
+ const byte *s = op->s.b.ptr;
+ const byte *t = op->t.b.ptr;
+ rop_operand strans = (op->rop & lop_S_transparent ? 0xFFFFFF : -1);
+ rop_operand ttrans = (op->rop & lop_T_transparent ? 0xFFFFFF : -1);
+ int sroll, troll;
+ const byte *scolors = op->scolors;
+ const byte *tcolors = op->tcolors;
+ rop_operand sc[2], tc[2];
+ if (op->flags & rop_s_1bit) {
+ s = op->s.b.ptr + (op->s.b.pos>>3);
+ sroll = 8-(op->s.b.pos & 7);
+ sc[0] = get24(&op->scolors[0]);
+ sc[1] = get24(&op->scolors[3]);
+ } else
+ sroll = 0;
+ if (op->flags & rop_t_1bit) {
+ t = op->t.b.ptr + (op->t.b.pos>>3);
+ troll = 8-(op->t.b.pos & 7);
+ tc[0] = get24(&op->tcolors[0]);
+ tc[1] = get24(&op->tcolors[3]);
+ } else
+ troll = 0;
+ do {
+ rop_operand S, T;
+ if (sroll == 0) {
+ S = get24(s);
+ s += 3;
+ } else {
+ --sroll;
+ S = sc[(*s >> sroll) & 1];
+ if (sroll == 0) {
+ sroll = 8;
+ s++;
+ }
+ }
+ if (troll == 0) {
+ T = get24(t);
+ t += 3;
+ } else {
+ --troll;
+ T = tc[(*t >> troll) & 1];
+ if (troll == 0) {
+ troll = 8;
+ t++;
+ }
+ }
+ if ((S != strans) && (T != ttrans)) {
+ rop_operand D = proc(get24(d), S, T);
+ put24(d, D);
+ }
+ d += 3;
+ }
+ while (--len);
+}
+#endif
+
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME generic_rop_run1_const_s
+#define S_CONST
+#include "gsroprun1.h"
+#else
+static void generic_rop_run1_const_s(rop_run_op *op, byte *d, int len)
+{
+ rop_proc proc = rop_proc_table[op->rop];
+ byte lmask, rmask;
+ byte S = (byte)op->s.c;
+ byte T, D;
+ const byte *t = op->t.b.ptr;
+ int t_skew;
+
+ /* S should be supplied as 'depth' bits. Duplicate that up to be byte
+ * size (if it's supplied byte sized, that's fine too). */
+ if (op->depth & 1)
+ S |= S<<1;
+ if (op->depth & 3)
+ S |= S<<2;
+ if (op->depth & 7)
+ S |= S<<4;
+
+ len = len*op->depth + op->dpos;
+ /* lmask = the set of bits to alter in the output bitmap on the left
+ * hand edge of the run. rmask = the set of bits NOT to alter in the
+ * output bitmap on the right hand edge of the run. */
+ lmask = 255>>(7 & op->dpos);
+ rmask = 255>>(7 & len);
+
+ /* See note #1 above. RJW. */
+ t_skew = op->t.b.pos - op->dpos;
+ if (t_skew < 0) {
+ t_skew += 8;
+ t--;
+ }
+
+ len -= 8;
+ if (len < 0) {
+ /* Short case - starts and ends in the same byte */
+ lmask &= ~rmask; /* Combined mask = bits to alter */
+ T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
+ D = proc(*d, S, T);
+ *d = (*d & ~lmask) | (D & lmask);
+ return;
+ }
+ if (lmask != 0xFF) {
+ /* Unaligned left hand case */
+ T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
+ t++;
+ D = proc(*d, S, T);
+ *d = (*d & ~lmask) | (D & lmask);
+ d++;
+ len -= 8;
+ }
+ if (len >= 0) {
+ /* Simple middle case (complete destination bytes). */
+ if (t_skew == 0) {
+ do {
+ *d = proc(*d, S, *t++);
+ d++;
+ len -= 8;
+ } while (len >= 0);
+ } else {
+ do {
+ T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
+ t++;
+ *d = proc(*d, S, T);
+ d++;
+ len -= 8;
+ } while (len >= 0);
+ }
+ }
+ if (rmask != 0xFF) {
+ /* Unaligned right hand case */
+ T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
+ D = proc(*d, S, T);
+ *d = (D & ~rmask) | (*d & rmask);
+ }
+}
+#endif
+
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME generic_rop_run8_const_s
+#define S_CONST
+#include "gsroprun8.h"
+#else
+static void generic_rop_run8_const_s(rop_run_op *op, byte *d, int len)
+{
+ rop_proc proc = rop_proc_table[op->rop];
+ byte s = op->s.c;
+ const byte *t = op->t.b.ptr;
+ do
+ {
+ *d = proc(*d, s, *t++);
+ d++;
+ }
+ while (--len);
+}
+#endif
+
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME generic_rop_run8_const_s_trans
+#define S_CONST
+#define S_TRANS MAYBE
+#define T_TRANS MAYBE
+#include "gsroprun8.h"
+#else
+static void generic_rop_run8_const_s_trans(rop_run_op *op, byte *d, int len)
+{
+ rop_proc proc = rop_proc_table[lop_rop(op->rop)];
+ byte S = op->s.c;
+ const byte *t = op->t.b.ptr;
+ rop_operand strans = (op->rop & lop_S_transparent ? 255 : -1);
+ rop_operand ttrans = (op->rop & lop_T_transparent ? 255 : -1);
+ if (S == strans)
+ return;
+
+ do
+ {
+ rop_operand T = *t++;
+ if (T != ttrans)
+ *d = proc(*d, S, T);
+ d++;
+ }
+ while (--len);
+}
+#endif
+
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME generic_rop_run8_const_s_1bit
+#define S_CONST
+#define S_TRANS MAYBE
+#define T_TRANS MAYBE
+#define T_1BIT MAYBE
+#include "gsroprun8.h"
+#else
+static void generic_rop_run8_const_s_1bit(rop_run_op *op, byte *d, int len)
+{
+ rop_proc proc = rop_proc_table[lop_rop(op->rop)];
+ byte S = op->s.c;
+ const byte *t = op->t.b.ptr;
+ rop_operand strans = (op->rop & lop_S_transparent ? 255 : -1);
+ rop_operand ttrans = (op->rop & lop_T_transparent ? 255 : -1);
+ int troll;
+ const byte *tcolors = op->tcolors;
+ if (S == strans)
+ return;
+ if (op->flags & rop_t_1bit) {
+ t = op->t.b.ptr + (op->t.b.pos>>3);
+ troll = 8-(op->t.b.pos & 7);
+ } else
+ troll = 0;
+ do {
+ rop_operand T;
+ if (troll == 0)
+ T = *t++;
+ else {
+ --troll;
+ T = tcolors[(*t >> troll) & 1];
+ if (troll == 0) {
+ troll = 8;
+ t++;
+ }
+ }
+ if ((T != ttrans))
+ *d = proc(*d, S, T);
+ d++;
+ }
+ while (--len);
+}
+#endif
+
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME generic_rop_run24_const_s
+#define S_CONST
+#include "gsroprun24.h"
+#else
+static void generic_rop_run24_const_s(rop_run_op *op, byte *d, int len)
+{
+ rop_proc proc = rop_proc_table[op->rop];
+ rop_operand s = op->s.c;
+ const byte *t = op->t.b.ptr;
+ do
+ {
+ rop_operand D = proc(get24(d), s, get24(t));
+ put24(d, D);
+ t += 3;
+ d += 3;
+ }
+ while (--len);
+}
+#endif
+
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME generic_rop_run24_const_s_trans
+#define S_CONST
+#define S_TRANS MAYBE
+#define T_TRANS MAYBE
+#include "gsroprun24.h"
+#else
+static void generic_rop_run24_const_s_trans(rop_run_op *op, byte *d, int len)
+{
+ rop_proc proc = rop_proc_table[lop_rop(op->rop)];
+ rop_operand s = op->s.c;
+ const byte *t = op->t.b.ptr;
+ rop_operand strans = (op->rop & lop_S_transparent ? 0xFFFFFF : -1);
+ rop_operand ttrans = (op->rop & lop_T_transparent ? 0xFFFFFF : -1);
+ if (s == strans)
+ return;
+ do
+ {
+ rop_operand T = get24(t);
+ rop_operand D;
+ if (T != ttrans) {
+ D = proc(get24(d), s, get24(t));
+ put24(d, D);
+ }
+ t += 3;
+ d += 3;
+ }
+ while (--len);
+}
+#endif
+
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME generic_rop_run24_const_s_1bit
+#define S_CONST
+#define S_TRANS MAYBE
+#define T_TRANS MAYBE
+#define T_1BIT MAYBE
+#include "gsroprun24.h"
+#else
+static void generic_rop_run24_const_s_1bit(rop_run_op *op, byte *d, int len)
+{
+ rop_proc proc = rop_proc_table[lop_rop(op->rop)];
+ rop_operand S = op->s.c;
+ const byte *t = op->t.b.ptr;
+ rop_operand strans = (op->rop & lop_S_transparent ? 0xFFFFFF : -1);
+ rop_operand ttrans = (op->rop & lop_T_transparent ? 0xFFFFFF : -1);
+ int troll;
+ const byte *tcolors = op->tcolors;
+ rop_operand tc[2];
+ if (S == strans)
+ return;
+ if (op->flags & rop_t_1bit) {
+ t = op->t.b.ptr + (op->t.b.pos>>3);
+ troll = 8-(op->t.b.pos & 7);
+ tc[0] = get24(&op->tcolors[0]);
+ tc[1] = get24(&op->tcolors[3]);
+ } else
+ troll = 0;
+ do {
+ rop_operand T;
+ if (troll == 0)
+ T = *t++;
+ else {
+ --troll;
+ T = tc[(*t >> troll) & 1];
+ if (troll == 0) {
+ troll = 8;
+ t++;
+ }
+ }
+ if ((T != ttrans)) {
+ rop_operand D = proc(get24(d), S, T);
+ put24(d, D);
+ }
+ d += 3;
+ }
+ while (--len);
+}
+#endif
+
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME generic_rop_run1_const_st
+#define T_CONST
+#define S_CONST
+#include "gsroprun1.h"
+#else
+static void generic_rop_run1_const_st(rop_run_op *op, byte *d, int len)
+{
+ rop_proc proc = rop_proc_table[op->rop];
+ byte lmask, rmask;
+ byte S = (byte)op->s.c;
+ byte T = (byte)op->t.c;
+ byte D;
+
+ /* S and T should be supplied as 'depth' bits. Duplicate them up to be
+ * byte size (if they are supplied byte sized, that's fine too). */
+ if (op->depth & 1) {
+ S |= S<<1;
+ T |= T<<1;
+ }
+ if (op->depth & 3) {
+ S |= S<<2;
+ T |= T<<2;
+ }
+ if (op->depth & 7) {
+ S |= S<<4;
+ T |= T<<4;
+ }
+
+ len = len*op->depth + op->dpos;
+ /* lmask = the set of bits to alter in the output bitmap on the left
+ * hand edge of the run. rmask = the set of bits NOT to alter in the
+ * output bitmap on the right hand edge of the run. */
+ lmask = 255>>(7 & op->dpos);
+ rmask = 255>>(7 & len);
+
+ len -= 8;
+ if (len < 0) {
+ /* Short case - starts and ends in the same byte */
+ lmask &= ~rmask; /* Combined mask = bits to alter */
+ D = proc(*d, S, T);
+ *d = (*d & ~lmask) | (D & lmask);
+ return;
+ }
+ if (lmask != 0xFF) {
+ /* Unaligned left hand case */
+ D = proc(*d, S, T);
+ *d = (*d & ~lmask) | (D & lmask);
+ d++;
+ len -= 8;
+ }
+ while (len >= 0) {
+ /* Simple middle case (complete destination bytes). */
+ *d = proc(*d, S, T);
+ d++;
+ len -= 8;
+ }
+ if (rmask != 0xFF) {
+ /* Unaligned right hand case */
+ D = proc(*d, S, T);
+ *d = (D & ~rmask) | (*d & rmask);
+ }
+}
+#endif
+
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME generic_rop_run8_const_st
+#define S_CONST
+#define T_CONST
+#include "gsroprun8.h"
+#else
+static void generic_rop_run8_const_st(rop_run_op *op, byte *d, int len)
+{
+ rop_proc proc = rop_proc_table[op->rop];
+ byte s = op->s.c;
+ byte t = op->t.c;
+ do
+ {
+ *d = proc(*d, s, t);
+ d++;
+ }
+ while (--len);
+}
+#endif
+
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME generic_rop_run8_const_st_trans
+#define S_CONST
+#define T_CONST
+#define S_TRANS MAYBE
+#define T_TRANS MAYBE
+#include "gsroprun8.h"
+#else
+static void generic_rop_run8_const_st_trans(rop_run_op *op, byte *d, int len)
+{
+ rop_proc proc = rop_proc_table[lop_rop(op->rop)];
+ byte s = op->s.c;
+ byte t = op->t.c;
+ rop_operand strans = (op->rop & lop_S_transparent ? 0xFF : -1);
+ rop_operand ttrans = (op->rop & lop_T_transparent ? 0xFF : -1);
+ if ((s == strans) || (t == ttrans))
+ return;
+ do
+ {
+ *d = proc(*d, s, t);
+ d++;
+ }
+ while (--len);
+}
+#endif
+
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME generic_rop_run24_const_st
+#define S_CONST
+#define T_CONST
+#include "gsroprun24.h"
+#else
+static void generic_rop_run24_const_st(rop_run_op *op, byte *d, int len)
+{
+ rop_proc proc = rop_proc_table[op->rop];
+ rop_operand s = op->s.c;
+ rop_operand t = op->t.c;
+ do
+ {
+ rop_operand D = proc(get24(d), s, t);
+ put24(d, D);
+ d += 3;
+ }
+ while (--len);
+}
+#endif
+
+#ifdef USE_TEMPLATES
+#define TEMPLATE_NAME generic_rop_run24_const_st_trans
+#define S_CONST
+#define T_CONST
+#define S_TRANS MAYBE
+#define T_TRANS MAYBE
+#include "gsroprun24.h"
+#else
+static void generic_rop_run24_const_st_trans(rop_run_op *op, byte *d, int len)
+{
+ rop_proc proc = rop_proc_table[lop_rop(op->rop)];
+ rop_operand s = op->s.c;
+ rop_operand t = op->t.c;
+ rop_operand strans = (op->rop & lop_S_transparent ? 0xFFFFFF : -1);
+ rop_operand ttrans = (op->rop & lop_T_transparent ? 0xFFFFFF : -1);
+ if ((s == strans) || (t == ttrans))
+ return;
+ do
+ {
+ rop_operand D = proc(get24(d), s, t);
+ put24(d, D);
+ d += 3;
+ }
+ while (--len);
+}
+#endif
+
+#ifdef RECORD_ROP_USAGE
+static void record_run(rop_run_op *op, byte *d, int len)
+{
+ rop_run_op local;
+
+ usage[(int)op->opaque*3 + 1]++;
+ usage[(int)op->opaque*3 + 2] += len;
+
+ local.run = op->runswap;
+ local.s = op->s;
+ local.t = op->t;
+ local.scolors = op->scolors;
+ local.tcolors = op->tcolors;
+ local.rop = op->rop;
+ local.depth = op->depth;
+ local.flags = op->flags;
+ local.dpos = op->dpos;
+ local.release = op->release;
+ local.opaque = op->opaque;
+
+ op->runswap(&local, d, len);
+}
+#endif
+
+static void rop_run_swapped(rop_run_op *op, byte *d, int len)
+{
+ rop_run_op local;
+
+#ifdef RECORD_ROP_USAGE
+ usage[(int)op->opaque*3 + 1]++;
+ usage[(int)op->opaque*3 + 2] += len;
+#endif
+
+ local.run = op->runswap;
+ local.s = op->t;
+ local.t = op->s;
+ local.scolors = op->tcolors;
+ local.tcolors = op->scolors;
+ local.rop = op->rop;
+ local.depth = op->depth;
+ local.flags = op->flags;
+ local.dpos = op->dpos;
+ local.release = op->release;
+ local.opaque = op->opaque;
+
+ op->runswap(&local, d, len);
+}
+
+void rop_get_run_op(rop_run_op *op, int rop, int depth, int flags)
+{
+ int key;
+ int swap = 0;
+ int could_swap = 0;
+
+#ifdef DISABLE_ROPS
+ rop = 0xAA;
+#endif
+
+ /* If the rop ignores either S or T, then we might as well set them to
+ * be constants; will save us slaving through memory. Also, they can't
+ * count towards transparency. */
+ if (!rop3_uses_S(rop)) {
+ flags |= rop_s_constant;
+ flags &= ~rop_s_1bit;
+ rop &= ~lop_S_transparent;
+ }
+ if (!rop3_uses_T(rop)) {
+ flags |= rop_t_constant;
+ flags &= ~rop_t_1bit;
+ rop &= ~lop_T_transparent;
+ }
+
+ /* Cut down the number of cases by mapping 'S bitmap,T constant' onto
+ * 'S constant,Tbitmap'. */
+ could_swap = ((flags & (rop_s_constant | rop_t_constant)) == rop_t_constant);
+ if (0 == 1) {
+force_swap:
+#ifdef RECORD_ROP_USAGE
+ unrecord((int)op->opaque);
+#endif
+ could_swap = 0;
+ swap = 1;
+ }
+ if (swap) {
+ flags = ((flags & rop_t_constant ? rop_s_constant : 0) |
+ (flags & rop_s_constant ? rop_t_constant : 0) |
+ (flags & rop_t_1bit ? rop_s_1bit : 0) |
+ (flags & rop_s_1bit ? rop_t_1bit : 0));
+ rop = lop_swap_S_T(rop);
+ }
+
+ op->flags = (flags & (rop_s_constant | rop_t_constant | rop_s_1bit | rop_t_1bit));
+ op->depth = (byte)depth;
+ op->rop = rop & (0xFF | lop_S_transparent | lop_T_transparent);
+ op->release = NULL;
+
+#define ROP_SPECIFIC_KEY(rop, depth, flags) (((rop)<<7)+(1<<6)+((depth>>3)<<4)+(flags))
+#define KEY_IS_ROP_SPECIFIC(key) (key & (1<<6))
+#define STRIP_ROP_SPECIFICITY(key) (key &= ((1<<6)-1))
+#define KEY(depth, flags) (((depth>>3)<<4)+(flags))
+
+ key = ROP_SPECIFIC_KEY(rop, depth, flags);
+#ifdef RECORD_ROP_USAGE
+ op->opaque = (void*)(key & (MAX-1));
+ record((int)op->opaque);
+#endif
+retry:
+ switch (key)
+ {
+ /* First, the rop specific ones */
+ /* 0x0F = T */
+ case ROP_SPECIFIC_KEY(0x0F, 1, rop_s_constant):
+ op->run = notT_rop_run1_const_s;
+ break;
+ /* 0x55 = Invert */
+ case ROP_SPECIFIC_KEY(0x55, 1, rop_s_constant | rop_t_constant):
+ op->run = invert_rop_run1;
+ op->s.b.pos = 0;
+ op->t.b.pos = 0;
+ op->dpos = 0;
+ break;
+ case ROP_SPECIFIC_KEY(0x55, 8, rop_s_constant | rop_t_constant):
+ op->run = invert_rop_run8;
+ break;
+ case ROP_SPECIFIC_KEY(0x55, 24, rop_s_constant | rop_t_constant):
+ op->run = invert_rop_run24;
+ break;
+ /* 0x66 = D xor S */
+ case ROP_SPECIFIC_KEY(0x5a, 1, rop_s_constant):
+ op->run = xor_rop_run1_const_s;
+ break;
+ case ROP_SPECIFIC_KEY(0x5a, 8, rop_s_constant | rop_t_constant):
+ goto force_swap;
+ case ROP_SPECIFIC_KEY(0x66, 8, rop_s_constant | rop_t_constant):
+ op->run = xor_rop_run8_const_st;
+ break;
+ case ROP_SPECIFIC_KEY(0x5a, 24, rop_s_constant | rop_t_constant):
+ goto force_swap;
+ case ROP_SPECIFIC_KEY(0x66, 24, rop_s_constant | rop_t_constant):
+ op->run = xor_rop_run24_const_st;
+ break;
+ case ROP_SPECIFIC_KEY(0xFC, 24, rop_s_constant | rop_t_constant):
+ op->run = sort_rop_run24_const_st;
+ break;
+ case ROP_SPECIFIC_KEY(0xAA, 1, rop_s_constant | rop_t_constant):
+ case ROP_SPECIFIC_KEY(0xAA, 8, rop_s_constant | rop_t_constant):
+ case ROP_SPECIFIC_KEY(0xAA, 24, rop_s_constant | rop_t_constant):
+ op->run = nop_rop_const_st;
+ break;
+ /* 0xCC = S */
+ case ROP_SPECIFIC_KEY(0xCC, 1, rop_t_constant):
+ op->run = sets_rop_run1_const_t;
+ break;
+ /* 0xEE = D or S */
+ case ROP_SPECIFIC_KEY(0xEE, 1, rop_t_constant):
+ op->run = dors_rop_run1_const_t;
+ break;
+ /* 0xF0 = T */
+ case ROP_SPECIFIC_KEY(0xF0, 1, rop_s_constant):
+ op->run = sett_rop_run1_const_s;
+ break;
+ /* 0xFA = D or T */
+ case ROP_SPECIFIC_KEY(0xFA, 1, rop_s_constant):
+ op->run = dort_rop_run1_const_s;
+ break;
+ /* Then the generic ones */
+ case KEY(1, 0):
+ op->run = generic_rop_run1;
+ op->s.b.pos = 0;
+ op->t.b.pos = 0;
+ op->dpos = 0;
+ break;
+ case KEY(8, 0):
+ if (rop & lop_S_transparent)
+ if (rop & lop_T_transparent)
+ op->run = generic_rop_run8_trans_ST;
+ else
+ op->run = generic_rop_run8_trans_S;
+ else
+ if (rop & lop_T_transparent)
+ op->run = generic_rop_run8_trans_T;
+ else
+ op->run = generic_rop_run8;
+ break;
+ case KEY(8, rop_s_1bit):
+ case KEY(8, rop_t_1bit):
+ case KEY(8, rop_s_1bit | rop_t_1bit ):
+ op->run = generic_rop_run8_1bit;
+ break;
+ case KEY(24, 0):
+ if (rop & (lop_S_transparent | lop_T_transparent))
+ op->run = generic_rop_run24_trans;
+ else
+ op->run = generic_rop_run24;
+ break;
+ case KEY(24, rop_s_1bit):
+ case KEY(24, rop_t_1bit):
+ case KEY(24, rop_s_1bit | rop_t_1bit ):
+ op->run = generic_rop_run24_1bit;
+ break;
+ case KEY(1, rop_s_constant):
+ op->run = generic_rop_run1_const_s;
+ op->s.b.pos = 0;
+ op->t.b.pos = 0;
+ op->dpos = 0;
+ break;
+ case KEY(8, rop_s_constant):
+ if (rop & (lop_S_transparent | lop_T_transparent))
+ op->run = generic_rop_run8_const_s_trans;
+ else
+ op->run = generic_rop_run8_const_s;
+ break;
+ case KEY(8, rop_s_constant | rop_s_1bit):
+ case KEY(8, rop_s_constant | rop_t_1bit):
+ case KEY(8, rop_s_constant | rop_s_1bit | rop_t_1bit ):
+ op->run = generic_rop_run8_const_s_1bit;
+ break;
+ case KEY(24, rop_s_constant):
+ if (rop & (lop_S_transparent | lop_T_transparent))
+ op->run = generic_rop_run24_const_s_trans;
+ else
+ op->run = generic_rop_run24_const_s;
+ break;
+ case KEY(24, rop_s_constant | rop_s_1bit):
+ case KEY(24, rop_s_constant | rop_t_1bit):
+ case KEY(24, rop_s_constant | rop_s_1bit | rop_t_1bit ):
+ op->run = generic_rop_run24_const_s_1bit;
+ break;
+ case KEY(1, rop_s_constant | rop_t_constant):
+ op->run = generic_rop_run1_const_st;
+ op->s.b.pos = 0;
+ op->t.b.pos = 0;
+ op->dpos = 0;
+ break;
+ case KEY(8, rop_s_constant | rop_t_constant):
+ if (rop & (lop_S_transparent | lop_T_transparent))
+ op->run = generic_rop_run8_const_st_trans;
+ else
+ op->run = generic_rop_run8_const_st;
+ break;
+ case KEY(8, rop_s_constant | rop_t_constant | rop_s_1bit):
+ case KEY(8, rop_s_constant | rop_t_constant | rop_t_1bit):
+ case KEY(8, rop_s_constant | rop_t_constant | rop_s_1bit | rop_t_1bit ):
+ /* Nothing in the code calls constant and 1 bit together. Which
+ * means that we can only get here if we spotted that the rop ignores
+ * S and/or T earlier. We know we aren't using transparency, so
+ * the 1 bit becomes moot. */
+ op->run = generic_rop_run8_const_st;
+ break;
+ case KEY(24, rop_s_constant | rop_t_constant):
+ if (rop & (lop_S_transparent | lop_T_transparent))
+ op->run = generic_rop_run24_const_st_trans;
+ else
+ op->run = generic_rop_run24_const_st;
+ break;
+ case KEY(24, rop_s_constant | rop_t_constant | rop_s_1bit):
+ case KEY(24, rop_s_constant | rop_t_constant | rop_t_1bit):
+ case KEY(24, rop_s_constant | rop_t_constant | rop_s_1bit | rop_t_1bit ):
+ /* Nothing in the code calls constant and 1 bit together. Which
+ * means that we can only get here if we spotted that the rop ignores
+ * S and/or T earlier. We know we aren't using transparency, so
+ * the 1 bit becomes moot. */
+ op->run = generic_rop_run24_const_st;
+ break;
+ default:
+ /* If we failed to find a specific one, and swapping is an option,
+ * then try swapping. */
+ if (could_swap)
+ goto force_swap;
+ /* If we failed to find a specific one for this rop value, try again
+ * for a generic one. */
+ if (KEY_IS_ROP_SPECIFIC(key))
+ {
+ STRIP_ROP_SPECIFICITY(key);
+ goto retry;
+ }
+ eprintf1("This should never happen! key=%x\n", key);
+ break;
+ }
+
+ if (swap)
+ {
+ op->runswap = op->run;
+ op->run = rop_run_swapped;
+ }
+#ifdef RECORD_ROP_USAGE
+ else
+ {
+ op->runswap = op->run;
+ op->run = record_run;
+ }
+#endif
+}
+
+void (rop_set_s_constant)(rop_run_op *op, int s)
+{
+ rop_set_s_constant(op, s);
+}
+
+void (rop_set_s_bitmap)(rop_run_op *op, const byte *s)
+{
+ rop_set_s_bitmap(op, s);
+}
+
+void (rop_set_s_bitmap_subbyte)(rop_run_op *op, const byte *s, int pos)
+{
+ rop_set_s_bitmap_subbyte(op, s, pos);
+}
+
+void (rop_set_s_colors)(rop_run_op *op, const byte *scolors)
+{
+ rop_set_s_colors(op, scolors);
+}
+
+void (rop_set_t_constant)(rop_run_op *op, int t)
+{
+ rop_set_t_constant(op, t);
+}
+
+void (rop_set_t_bitmap)(rop_run_op *op, const byte *t)
+{
+ rop_set_t_bitmap(op, t);
+}
+
+void (rop_set_t_bitmap_subbyte)(rop_run_op *op, const byte *t, int pos)
+{
+ rop_set_t_bitmap_subbyte(op, t, pos);
+}
+
+void (rop_set_t_colors)(rop_run_op *op, const byte *tcolors)
+{
+ rop_set_t_colors(op, tcolors);
+}
+
+void (rop_run)(rop_run_op *op, byte *d, int len)
+{
+ rop_run(op, d, len);
+}
+
+void (rop_run_subbyte)(rop_run_op *op, byte *d, int start, int len)
+{
+ rop_run_subbyte(op, d, start, len);
+}
+
+void (rop_release_run_op)(rop_run_op *op)
+{
+ rop_release_run_op(op);
+}