Cases:

                no src   1-bit src   8-bit src
                ------   ---------   ---------

1-bit dst         1         2          3

8-bit dst         4         5          6

-------------------------------------------------------------------------------

function components:   raster-operation
                       foreground color 
                       background color

-------------------------------------------------------------------------------

raster functions:      ( by src/~src pairs)

      ~0                1111
       0                0000

       DST              1010
      ~DST              0101

       SRC              1100
      ~SRC              0011

       SRC |  DST       1110
      ~SRC |  DST       1011

       SRC | ~DST       1101
      ~SRC | ~DST       0111

       SRC &  DST       1000
       SRC & ~DST       0100

      ~SRC &  DST       0010
      ~SRC & ~DST       0001
 
       SRC ^  DST       0110
      ~SRC ^  DST       1001

-------------------------------------------------------------------------------
raster functions:      ( arbitrarily by numerical value)

       0                0000
      ~SRC & ~DST       0001
      ~SRC &  DST       0010
      ~SRC              0011
       SRC & ~DST       0100
      ~DST              0101
       SRC ^  DST       0110
      ~SRC | ~DST       0111
       SRC &  DST       1000
      ~SRC ^  DST       1001
       DST              1010
      ~SRC |  DST       1011
       SRC              1100
       SRC | ~DST       1101
       SRC |  DST       1110
      ~0                1111

-------------------------------------------------------------------------------
raster functions:      ( by src grouping II)

      ~0                1111  No source involved
       0                0000
       DST              1010
      ~DST              0101

       SRC              1100  Source
       SRC |  DST       1110
       SRC | ~DST       1101
       SRC &  DST       1000
       SRC & ~DST       0100
       SRC ^  DST       0110

      ~SRC              0011 ~Source
      ~SRC |  DST       1011
      ~SRC | ~DST       0111
      ~SRC &  DST       0010
      ~SRC & ~DST       0001
      ~SRC ^  DST       1001

-------------------------------------------------------------------------------

raster functions:      ( by inverse functions)

      ~0                1111
       0                0000

       DST              1010
      ~DST              0101

       SRC              1100
      ~SRC              0011

       SRC |  DST       1110
      ~SRC | ~DST       0111

      ~SRC |  DST       1011
       SRC | ~DST       1101

       SRC &  DST       1000
      ~SRC & ~DST       0001

       SRC & ~DST       0100
      ~SRC &  DST       0010

       SRC ^  DST       0110
      ~SRC ^  DST       1001
-------------------------------------------------------------------------------

The goal is to impose  a consistent set of semantics on: blit(src,dst,func)
where "src" and "dst" are bitmaps, and have either 1 bit pixels, 8 bit pixels
or are NULL, and "func" is the set of binary operations to perform pixel by
on corresponding elements of "src" and "dst", such that 
   dst <- func(src,dst)
We start by describing a consistent (and well known) set of semantics for 1 bit
pixels, and then extend the semantics to 8 bit pixels in such a way that
applications can be ignorant of the underlying pixel size.

After that we'll invent a mechanism for mapping color onto multi-bit
pixels in a consistant manner.
-------------------------------------------------------------------------------
					Various combinations of arguments

                no src   1-bit src   8-bit src
1-bit dst         1         2          3
8-bit dst         4         5          6

-------------------------------------------------------------------------------
1) 1 bit dst, no source
  	Only the 4 functions with no SRC, apply: 
      ~0        set
       0      	 clear
       DST      no-op
      ~DST      invert
   For the rest of the functions, one can assume either a source of all
   0's or a source of all 1's.  The rest of the cases fold as follows,
	when 0 or 1 is substituded for SRC.
		 function         source 0's                 source 1's (~0)

       SRC                  0                         ~0
       SRC |  DST           DST                       ~0
       SRC | ~DST          ~DST                       ~0
       SRC &  DST           0                          DST
       SRC & ~DST           0                         ~DST
       SRC ^  DST           DST                       ~DST
      ~SRC                 ~0                          0
      ~SRC |  DST          ~0                          DST
      ~SRC | ~DST          ~0                         ~DST
      ~SRC &  DST           DST                        0
      ~SRC & ~DST          ~DST                        0
      ~SRC ^  DST          ~DST                        DST

-------------------------------------------------------------------------------
2) 1 bit dst, 1 bit source
	The 16 functions apply on a pixel by pixel basis.  The only question is:
   whats "on", 1 or 0.  To convert from "1 is on" to "0 is on" and
   visa-versa, in each of the 16 functions, replace both the SRC and
   the DST with its complement, to generate the following function mappings:

      ~0            <==>   0          +
       DST          <==>  ~DST
       SRC          <==>  ~SRC
       SRC |  DST   <==>  ~SRC | ~DST
      ~SRC |  DST   <==>   SRC | ~DST
       SRC &  DST   <==>  ~SRC & ~DST
       SRC & ~DST   <==>  ~SRC &  DST
       SRC ^  DST   <==>   SRC ^  DST *
      ~SRC ^  DST   <==>  ~SRC ^  DST *

   * The 2 "^" functions are invarient under this transformation
   + One could argue that these 2 should be invarient as well.
       0 == DST & ~DST or SRC & ~SRC or  SRC ^ SRC or  DST ^ DST
      ~0 == DST | ~DST or SRC | ~SRC or ~SRC ^ SRC or ~DST ^ DST
     Then every binary combination of SRC, ~SRC, DST, and ~DST is combined
     with each of &, |, and ^.  All of these functions are invarient
     when both DST and SRC are negated.  These functions are usually
     labeled "set" and "clear".  Under this transfor the labels exchange
	  places, which is equivalent to exchanging the functions, sort of.

-------------------------------------------------------------------------------
3) 1 bit dst, 8 bit source.
   This ones hard, because it depends upon the meaning associated with the
   "value" for the 8 bit source.  Possiblilities:

   In the general case, there are 2^512 different functions that can be
   performed between a 1 bit dst and a 8 bit source, consisting of all 
   possible source mappings for each DST=1 combined with all possible
   source mappings when DST=0.  Its would be difficult, and probably
   not useful to enumerate all of the possiblilites, so we need to 
   pick a subset.  (That is 2^(x+y) where x is the number of distinct values
   a SRC pixel can have, and y is the number of distinct values the
   DST pixel can have.)
   2^(8+1) = 134078079299425970995740249982058461274793658205923933777235614
			4372176403007354697680187429816690342769003185818648605085375388281
			1946569946433649006084096

   Since we just went to all of this trouble characterizing the 16
   functions for 1 x 1 bit combinations, one strategy, that preserves all of
	the above semantics involves mapping the 8 bit source
   pixels to one bit pixels, then applying one of the 16 functions.
   In addition to the 16 function codes, we also have 2 8-bit values,
   the "forground color" and the "background color" that we need for
   1->8 stuff.

	When do we want to do this anyway:
   -) when we have 8 bit images and we are running on a monochrome display.
   -) we have 8 bits everywhere, but we wish to do 1 bit stuff for some
      intermediate calculations.

   1 Assume 256 grey values, and dither to 1 bit, using fg, and/or bg
     to control the contrast/brightness.  For color, map the colors to
     intensity (grey) values first.  This is good for arbitrary color/gray
     images of real objects, where std techniques are used to render using
     the best reasonable approximation in 1 bit.

   2 Use fg as a plane mask; use the 1st "on" bit and pick a single
     plane from the source.  When each plane is used to hold a separate
     set of objects, as is a text plane, an annotation plane, etc,
     Then this technique is used to select the plane of interest.

   3 do thesholding.  Everything != bg is on, else off.  In this notion,
     objects are drawn on a background (e.g. the background color) in
     various foreground colors.  We can distinguish the background from
     the forground.

   Pick 3, 'cause it matches the model for our intended use, a window
   system, and the notion of "background color" is already avaliable.
   We can map (2) to (3) by doing a NULL src to 8 bit operation to mask off
   all of the unwanted planes, then set the BG color to zero.

	As for 1, by the time we're at this level, we don't know about colors,
   we just have 8 bit values.  It would be presumptuous to impose a
   color scheme here.  Instead we will let the dithering happen at the
   application level.  There are widely availiable programs for doing
   this conversion.

-------------------------------------------------------------------------------
4) no source, 8 bit dst

	Unlike (1) above, we have lots of possible functions.  So we choose a few
   (guess which 16).  For 1-bit DSTs it makes sense to choose a 1 bit SRC,
	and pick from the possible values.  Here we do the same, by specifying
   a foreground color, and a background color.  An infinite supply of the
	fg color is used for SRC, whereas an infinite supply of bg color is used
   for ~SRC.  The operators then act on a bit by bit basis.  The functions
	are:

      ~0
       0
       DST
      ~DST

       FG
       FG |  DST
       FG | ~DST
       FG &  DST
       FG & ~DST
       FG ^  DST

       BG
       BG |  DST
       BG | ~DST
       BG &  DST
       BG & ~DST
       BG ^  DST
	BG has replaced ~SRC and fg has replaced SRC.  This gives us good 
   interoperability with 1 bit and 8 bit systems.  We use SRC to set
   pixels, and ~SRC to clear pixels.  By choosing appropriate FG and BG
   colors, we map B&W into an arbitrary pair of colors. As for the first 2
   operations, 0 and ~0, they should logically set the destination to
   0 and 0xff respectively.  Its not clear if this is actually useful, as
   it is redundant with SRC and ~SRC with the FG and BG colors chosen
	appropriately.  Unfortunatley, in the 1-bit case, there are only two
   colors, 0 and ~0, so these 2 functions entirely cover the color space.
   Applications written for monochrome that use 0 and ~0 won't work as 
   expected in color, with b&w mapped to 2 arbitrary colors.  For this
   reason, it might be wise to map 0->~SRC and ~0 to SRC, so apps can be
   totally color blind.

-------------------------------------------------------------------------------
5) 1 bit source, 8 bit dst

	Here we'll logically convert the 1-bit source to an 8 bit source, 
	then do the 8->8 bitwise combination of our favorite 16 operations.
   Every '1' in the src gets turned into FG color, and every '0' gets
   turned into a BG color.  If FG == BG then we've degenerated into a
   case 4), 8 bit DST, but no source.  This is probably not what the user
   wanted to do, although it could be a valid specific instance of of
   a more genereal case mechanism.  What we could do, to protect the
   usr's from themselves is:  if FG==BG, set BG=~FG in hopes that
   something useful will result.

-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
Other Window systems systems semantics:
  
X 1->1 and 8->8.
   Different clipping scheme
  1->8.
   Semantically the same, but must use different function calls
  8->1
   Not supported
  0->1 and 0->8
   Partial support, use of SRC function only.

SUNTOOLS (pixrect)
  1->1 and 8->8
	Same, potentially different clipping scheme
  1->8
   Only one color allowed, so FG is always "0" (BROKEN)
  0->1, 0->8 ????


----------------------------------------------------------------------------
----------------------------------------------------------------------------
Preceding was by Uhler, the following addendum by Broman.

You'll notice the 8bit src - 8bit dst case was not covered above.

The implementation of Uhler's ideas in the libbitblit/colorport
code always coerced the source to the bit-depth of the destination,
using the fg and bg colors associated with the bitop,
and then applied the logical operation bitwise to the 1bit or 8bit operands.

This approach has big performance advantages, in that logical
operations map readily to bit-wise machine operations on 8-bit
colors (or even on bigendian architectures to 32-bit four-pixel groups),
but it suffers from some usability problems.
If each bit of a color is to be operated on independently,
then the colormap has to be set so as to give independent meaning
to each bit of the color.
A way to do this would be to choose a coarse 2bitx3bitx3bit true-color scheme.
In any case, at a minimum, subtracting a color from 255 should yield
a complementary color of some kind, and equations like
	color3 OR color6 => color7
must make some kind of sense.

Recent versions of the color mgr server do setup such a true-color
colormap, but this is not what is assumed by some clients expecting
the original "set_colormap" colormap, or by those Linux clients,
like color ls, which expect the default-initial VGA colormap.

Another approach for the 8-bit src - 8-bit dst case
can be defined which makes fuller use of the foreground/background
color assumption and which makes no assumptions about the colormap,
except that colors not equal to the background can be distinguished
from the background.  It rests on a few highly-reasonable premises,
plus one debatable/pragmatic premise which is justified case-by-case below.

notation:
s	color of the source operand at the pixel under consideration
d	old color of the destination operand at the corresponding pixel
f	current default foreground color
b	current background color
d'	new color of the destination pixel

d' = op(s,d)
is an eight bit logical operation analogous to a previously defined
d' = one_bit_op(s,d)

premises:
A)	d' equals either d or s, unless both values are impermissible by the
	following rules, in which case it is either f or b.
B)	If in general one_bit_op(s,d) does not depend on the value of s,
	then d' is one of d, f, or b.
C)	If in general one_bit_op(s,d) does not depend on the value of d,
	then d' is one of s, f, or b.
D)	The foreground/background-ness of d' must conform to that
	produced by the corresponding 1-bit operation, i.e. in C notation
	(d' != b) == one_bit_op( (s != b), (d != b) )

The premises A-D are sufficient to uniquely define the value of op, except
for an ambiguity when s, d, and d' are all foreground and the value of the
operation depends on both s and d in general.  For this case,
we add the premise:

E)	When s != b, d != b, and one_bit_op(1,1) == 1, then
	d' = (one_bit_op(1,0) == 1)? s: d.

Premise A makes the meaning of the logical operations nearly independent
of the colormap contents, and it preserves the variety of foreground
colors that may arise, falling back on a default foreground color only
by necessity.  Premises B and C guarantee the right thing happens for
operations like (~SRC) or (SET).  Premise D makes the 8-bit operations
analogous to the 1-bit operations.

Premise E, at first glance, tests whether the one_bit_op copies a foreground
src onto a background dst, then makes the 8-bit operation act analogously
in the case of a foreground dst.  This might seem reasonable, except that
testing one_bit_op(0,1)==0 would give an equally reasonable but contradictory
rule.  The pragmatic justification lies in making the individual
operations conform to heuristic expectations, as in the comments on the
bitops numbered 1000-1111 below.

Think of a truth table based on these input values
1100	SRC
1010	DST

Then the sixteen bit-ops in the 8-bit case are:
Number	Name op(s,d)	Bitwise op	Logical op (comments follow)
0000	ZERO/CLR	0		b
0001	NOR		~(d|s)		d==b && s==b? f: b
0010	AND2/SUBR	d&~s		s==b? d: b
0011	NPROJ2/NSRC	~s		s==b? f: b
0100	AND1/SUB	~d&s		d==b? s: b
0101	NPROJ1/NDST	~d		d==b? f: b
0110	XOR		d^s		d==b? s: (s==b? d: b)
0111	NAND		~(d&s)		d==b? (s==b? f: s): (s==b? d: b)
1000	AND		d&s		s==b? b: d
					sets parts of dst to b, s is just mask
					fg/fg preserves d
1001	NXOR/MATCH	~(d^s)		s==b? (d==b? f: b): d
					fg/fg match is d, but could be s
1010	PROJ1/DST	d		d
1011	OR2/IMPLY	d|~s		d==b && s==b? f: d
					just makes dst fg where src is bg
					fg/fg preserves d
1100	PROJ2/SRC	s		s
1101	OR1/IMPLYR	~d|s		d==b && s==b? f: s
					copies src, except when both bg
					fg/fg prefers s
1110	OR		d|s		s==b? d: s
					an overwriting copy only where src is fg
					fg/fg prefers s
1111	ONE/SET		~0		f

Fast implementation of these ops on modern memory architectures
would be hard because of the test inside the innermost loop,
but the common cases of CLR, SET, SRC require no test,
and the other common cases of OR and AND require only one test.

