/*
 * display24.c Michael Saunby	M.Saunby@reading.ac.uk
 *
 * Release 1.1
 *
 * Display 24 bit RGB data using the Albert HAM8 screen.
 */

#include <exec/memory.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <intuition/intuition.h>
#include <graphics/gfxbase.h>
#include <graphics/displayinfo.h>
#include <intuition/screens.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>

#include <stdlib.h>
#include "display24.h"

/* 
 * Change USE_STD_COLOURS to 0 for ham only.  Faster but not as sharp. 
 * More code could be disabled for greater speed.
 */
#define USE_STD_COLOURS 1

typedef UBYTE std_pal_type;
static ULONG red_dist[9], green_dist[9], blue_dist[9];
static UWORD standard_pens[48];


/*
 * The following defines set the standard palette colours.
 * The __inline functions are used to compare these colours with the input
 * colour.
 *
 * Greys
 */
#define STD_COLOUR_01 {0,0,0}
static __inline ULONG 
dist_fn_01 ()
{
  return (red_dist[0] + green_dist[0] + blue_dist[0]);
}

#define STD_COLOUR_02 {32,32,32}
static __inline ULONG 
dist_fn_02 ()
{
  return (red_dist[1] + green_dist[1] + blue_dist[1]);
}

#define STD_COLOUR_03 {64,64,64}
static __inline ULONG 
dist_fn_03 ()
{
  return (red_dist[2] + green_dist[2] + blue_dist[2]);
}

#define STD_COLOUR_04 {96,96,96}
static __inline ULONG 
dist_fn_04 ()
{
  return (red_dist[3] + green_dist[3] + blue_dist[3]);
}

#define STD_COLOUR_05 {128,128,128}
static __inline ULONG 
dist_fn_05 ()
{
  return (red_dist[4] + green_dist[4] + blue_dist[4]);
}

#define STD_COLOUR_06 {160,160,160}
static __inline ULONG 
dist_fn_06 ()
{
  return (red_dist[5] + green_dist[5] + blue_dist[5]);
}

#define STD_COLOUR_07 {192,192,192}
static __inline ULONG 
dist_fn_07 ()
{
  return (red_dist[6] + green_dist[6] + blue_dist[6]);
}

#define STD_COLOUR_08 {224,224,224}
static __inline ULONG 
dist_fn_08 ()
{
  return (red_dist[7] + green_dist[7] + blue_dist[7]);
}

#define STD_COLOUR_09 {255,255,255}
static __inline ULONG 
dist_fn_09 ()
{
  return (red_dist[8] + green_dist[8] + blue_dist[8]);
}

/*
 * reds
 */
#define STD_COLOUR_10 {64,0,0}
static __inline ULONG 
dist_fn_10 ()
{
  return (red_dist[2] + green_dist[0] + blue_dist[0]);
}

#define STD_COLOUR_11 {128,0,0}
static __inline ULONG 
dist_fn_11 ()
{
  return (red_dist[4] + green_dist[0] + blue_dist[0]);
}

#define STD_COLOUR_12 {192,0,0}
static __inline ULONG 
dist_fn_12 ()
{
  return (red_dist[6] + green_dist[0] + blue_dist[0]);
}

#define STD_COLOUR_13 {255,0,0}
static __inline ULONG 
dist_fn_13 ()
{
  return (red_dist[8] + green_dist[0] + blue_dist[0]);
}

/*
 * greens
 */
#define STD_COLOUR_14 {0,64,0}
static __inline ULONG 
dist_fn_14 ()
{
  return (red_dist[0] + green_dist[2] + blue_dist[0]);
}

#define STD_COLOUR_15 {0,128,0}
static __inline ULONG 
dist_fn_15 ()
{
  return (red_dist[0] + green_dist[4] + blue_dist[0]);
}

#define STD_COLOUR_16 {0,192,0}
static __inline ULONG 
dist_fn_16 ()
{
  return (red_dist[0] + green_dist[6] + blue_dist[0]);
}

#define STD_COLOUR_17 {0,255,0}
static __inline ULONG 
dist_fn_17 ()
{
  return (red_dist[0] + green_dist[8] + blue_dist[0]);
}

/*
 * blues
 */
#define STD_COLOUR_18 {0,0,64}
static __inline ULONG 
dist_fn_18 ()
{
  return (red_dist[0] + green_dist[0] + blue_dist[2]);
}

#define STD_COLOUR_19 {0,0,128}
static __inline ULONG 
dist_fn_19 ()
{
  return (red_dist[0] + green_dist[0] + blue_dist[4]);
}

#define STD_COLOUR_20 {0,0,192}
static __inline ULONG 
dist_fn_20 ()
{
  return (red_dist[0] + green_dist[0] + blue_dist[6]);
}

#define STD_COLOUR_21 {0,0,255}
static __inline ULONG 
dist_fn_21 ()
{
  return (red_dist[0] + green_dist[0] + blue_dist[8]);
}

/*
 * red-greens
 */
#define STD_COLOUR_22 {255,64,0}
static __inline ULONG 
dist_fn_22 ()
{
  return (red_dist[8] + green_dist[2] + blue_dist[0]);
}

#define STD_COLOUR_23 {255,128,0}
static __inline ULONG 
dist_fn_23 ()
{
  return (red_dist[8] + green_dist[4] + blue_dist[0]);
}

#define STD_COLOUR_24 {255,192,0}
static __inline ULONG 
dist_fn_24 ()
{
  return (red_dist[8] + green_dist[6] + blue_dist[0]);
}

#define STD_COLOUR_25 {255,255,0}
static __inline ULONG 
dist_fn_25 ()
{
  return (red_dist[8] + green_dist[8] + blue_dist[0]);
}

/*
 * red-blues
 */
#define STD_COLOUR_26 {255,0,64}
static __inline ULONG 
dist_fn_26 ()
{
  return (red_dist[8] + green_dist[0] + blue_dist[2]);
}

#define STD_COLOUR_27 {255,0,128}
static __inline ULONG 
dist_fn_27 ()
{
  return (red_dist[8] + green_dist[0] + blue_dist[4]);
}

#define STD_COLOUR_28 {255,0,192}
static __inline ULONG 
dist_fn_28 ()
{
  return (red_dist[8] + green_dist[0] + blue_dist[6]);
}

#define STD_COLOUR_29 {255,0,255}
static __inline ULONG 
dist_fn_29 ()
{
  return (red_dist[8] + green_dist[0] + blue_dist[8]);
}

/*
 * green-reds
 */
#define STD_COLOUR_30 {64,255,0}
static __inline ULONG 
dist_fn_30 ()
{
  return (red_dist[2] + green_dist[8] + blue_dist[0]);
}

#define STD_COLOUR_31 {128,255,0}
static __inline ULONG 
dist_fn_31 ()
{
  return (red_dist[4] + green_dist[8] + blue_dist[0]);
}

#define STD_COLOUR_32 {192,255,0}
static __inline ULONG 
dist_fn_32 ()
{
  return (red_dist[6] + green_dist[8] + blue_dist[0]);
}

/*
 * green-blues
 */
#define STD_COLOUR_33 {0,255,64}
static __inline ULONG 
dist_fn_33 ()
{
  return (red_dist[0] + green_dist[8] + blue_dist[2]);
}

#define STD_COLOUR_34 {0,255,128}
static __inline ULONG 
dist_fn_34 ()
{
  return (red_dist[0] + green_dist[8] + blue_dist[4]);
}

#define STD_COLOUR_35 {0,255,192}
static __inline ULONG 
dist_fn_35 ()
{
  return (red_dist[0] + green_dist[8] + blue_dist[6]);
}

#define STD_COLOUR_36 {0,255,255}
static __inline ULONG 
dist_fn_36 ()
{
  return (red_dist[0] + green_dist[8] + blue_dist[8]);
}

/*
 * blue-reds
 */
#define STD_COLOUR_37 {64,255,0}
static __inline ULONG 
dist_fn_37 ()
{
  return (red_dist[2] + green_dist[8] + blue_dist[0]);
}

#define STD_COLOUR_38 {128,255,0}
static __inline ULONG 
dist_fn_38 ()
{
  return (red_dist[4] + green_dist[8] + blue_dist[0]);
}

#define STD_COLOUR_39 {192,255,0}
static __inline ULONG 
dist_fn_39 ()
{
  return (red_dist[6] + green_dist[8] + blue_dist[0]);
}

/*
 * blue-greens
 */
#define STD_COLOUR_40 {0,64,255}
static __inline ULONG 
dist_fn_40 ()
{
  return (red_dist[0] + green_dist[2] + blue_dist[8]);
}

#define STD_COLOUR_41 {0,128,255}
static __inline ULONG 
dist_fn_41 ()
{
  return (red_dist[0] + green_dist[4] + blue_dist[8]);
}

#define STD_COLOUR_42 {0,192,255}
static __inline ULONG 
dist_fn_42 ()
{
  return (red_dist[0] + green_dist[6] + blue_dist[8]);
}

/*
 * red green blue
 */
#define STD_COLOUR_43 {255,255,64}
static __inline ULONG 
dist_fn_43 ()
{
  return (red_dist[8] + green_dist[8] + blue_dist[2]);
}

#define STD_COLOUR_44 {255,255,128}
static __inline ULONG 
dist_fn_44 ()
{
  return (red_dist[8] + green_dist[8] + blue_dist[4]);
}

/*
 * red blue green
 */
#define STD_COLOUR_45 {255,64,255}
static __inline ULONG 
dist_fn_45 ()
{
  return (red_dist[8] + green_dist[2] + blue_dist[8]);
}

#define STD_COLOUR_46 {255,128,255}
static __inline ULONG 
dist_fn_46 ()
{
  return (red_dist[8] + green_dist[4] + blue_dist[8]);
}

/*
 * green blue red
*/
#define STD_COLOUR_47 {64,255,255}
static __inline ULONG 
dist_fn_47 ()
{
  return (red_dist[2] + green_dist[8] + blue_dist[8]);
}

#define STD_COLOUR_48 {128,255,255}
static __inline ULONG 
dist_fn_48 ()
{
  return (red_dist[4] + green_dist[8] + blue_dist[8]);
}


static std_pal_type standard_palette[48][3] =
{
  STD_COLOUR_01, STD_COLOUR_02, STD_COLOUR_03, STD_COLOUR_04, STD_COLOUR_05,
  STD_COLOUR_06, STD_COLOUR_07, STD_COLOUR_08, STD_COLOUR_09, STD_COLOUR_10,
  STD_COLOUR_11, STD_COLOUR_12, STD_COLOUR_13, STD_COLOUR_14, STD_COLOUR_15,
  STD_COLOUR_16, STD_COLOUR_17, STD_COLOUR_18, STD_COLOUR_19, STD_COLOUR_20,
  STD_COLOUR_21, STD_COLOUR_22, STD_COLOUR_23, STD_COLOUR_24, STD_COLOUR_25,
  STD_COLOUR_26, STD_COLOUR_27, STD_COLOUR_28, STD_COLOUR_29, STD_COLOUR_30,
  STD_COLOUR_31, STD_COLOUR_32, STD_COLOUR_33, STD_COLOUR_34, STD_COLOUR_35,
  STD_COLOUR_36, STD_COLOUR_37, STD_COLOUR_38, STD_COLOUR_39, STD_COLOUR_40,
  STD_COLOUR_41, STD_COLOUR_42, STD_COLOUR_43, STD_COLOUR_44, STD_COLOUR_45,
  STD_COLOUR_46, STD_COLOUR_47, STD_COLOUR_48};

/*
 * StandardPalette() - If shared == FALSE allocate a set of 48 standard
 * colours which may be shared by other programs. If shared == TRUE attemps
 * to share those same colours.
 */
int
StandardPalette (struct ViewPort * vp, UWORD shared)
{
  int i, error = 0;
  if (shared)
    {
      for (i = 0; i < 48; i++)
	{
	  if ((standard_pens[i] = ObtainBestPen (vp->ColorMap,
				     ((ULONG)standard_palette[i][0] << 24),
				     ((ULONG)standard_palette[i][1] << 24),
				     ((ULONG)standard_palette[i][2] << 24),
						 NULL)) == -1)
	    error++;
	}
    }
  else
    {
      for (i = 0; i < 48; i++)
	{
	  if ((standard_pens[i] = ObtainPen (vp->ColorMap,
					     -1,
				((ULONG)standard_palette[i][0] << 24),
				((ULONG)standard_palette[i][1] << 24),
				((ULONG)standard_palette[i][2] << 24),
					     0L)) == -1)
	    error++;
	}
    }
  return (error);
}

/*
 * ReleasePens() - Release the pens allocated by StandardPalette()
 */
VOID
ReleasePens (struct ViewPort * vp)
{
  int i;
  for (i = 0; i < 48; i++)
    {
      if (standard_pens[i] != -1)
	ReleasePen (vp->ColorMap, standard_pens[i]);
    }

}

#define sqr(n) ((n)*(n))


/*
 * set_dist()
 * The input colour needs to be compared with all the standard colours to
 * find the best match.  Here we calculate the square of the distance to
 * the various colour components used in the standard palette.
 */
static VOID
set_dist (const UBYTE red, const UBYTE green, const UBYTE blue,
	  const ULONG * prev, const USHORT useprev)
{
  if ((!useprev) || (red != prev[0]))
    {
      red_dist[0] = sqr (red);
      red_dist[1] = sqr (32 - red);
      red_dist[2] = sqr (64 - red);
      red_dist[3] = sqr (96 - red);
      red_dist[4] = sqr (128 - red);
      red_dist[5] = sqr (160 - red);
      red_dist[6] = sqr (192 - red);
      red_dist[7] = sqr (224 - red);
      red_dist[8] = sqr (255 - red);
    }
  if ((!useprev) || (green != prev[1]))
    {
      green_dist[0] = sqr (green);
      green_dist[1] = sqr (32 - green);
      green_dist[2] = sqr (64 - green);
      green_dist[3] = sqr (96 - green);
      green_dist[4] = sqr (128 - green);
      green_dist[5] = sqr (160 - green);
      green_dist[6] = sqr (192 - green);
      green_dist[7] = sqr (224 - green);
      green_dist[8] = sqr (255 - green);
    }
  if ((!useprev) || (blue != prev[2]))
    {
      blue_dist[0] = sqr (blue);
      blue_dist[1] = sqr (32 - blue);
      blue_dist[2] = sqr (64 - blue);
      blue_dist[3] = sqr (96 - blue);
      blue_dist[4] = sqr (128 - blue);
      blue_dist[5] = sqr (160 - blue);
      blue_dist[6] = sqr (192 - blue);
      blue_dist[7] = sqr (224 - blue);
      blue_dist[8] = sqr (255 - blue);
    }
}

/*
 * Pen number returns the pen number needed to best represent the pixel. prev
 * is set to the actual colour used. So in normal use can be left alone.
 */
static UBYTE
pen_number (const UBYTE red, const UBYTE green, const UBYTE blue,
	    ULONG * prev, const USHORT useprev)
{
  register ULONG dist;
  ULONG min_dist = 0xFFFFFFFF;
  ULONG pen;

#ifdef MAX_HAMSLIP
  USHORT hamslip;

  if (!useprev)
    hamslip = 0;
  else if (hamslip > MAX_HAMSLIP)
    useprev = 0;
  /* hamslip gets set to zero later */
#endif

  set_dist (red, green, blue, prev, useprev);

#if USE_STD_COLOURS
  /*
   * Use the __inline functions to find the best colour match.
   */
  min_dist = dist_fn_01 ();
  pen = 0;

  if ((dist = dist_fn_02 ()) < min_dist)
    {
      min_dist = dist;
      pen = 1;
    }
  if ((dist = dist_fn_03 ()) < min_dist)
    {
      min_dist = dist;
      pen = 2;
    }
  if ((dist = dist_fn_04 ()) < min_dist)
    {
      min_dist = dist;
      pen = 3;
    }
  if ((dist = dist_fn_05 ()) < min_dist)
    {
      min_dist = dist;
      pen = 4;
    }
  if ((dist = dist_fn_06 ()) < min_dist)
    {
      min_dist = dist;
      pen = 5;
    }
  if ((dist = dist_fn_07 ()) < min_dist)
    {
      min_dist = dist;
      pen = 6;
    }
  if ((dist = dist_fn_08 ()) < min_dist)
    {
      min_dist = dist;
      pen = 7;
    }
  if ((dist = dist_fn_09 ()) < min_dist)
    {
      min_dist = dist;
      pen = 8;
    }
  if ((dist = dist_fn_10 ()) < min_dist)
    {
      min_dist = dist;
      pen = 9;
    }
  if ((dist = dist_fn_11 ()) < min_dist)
    {
      min_dist = dist;
      pen = 10;
    }
  if ((dist = dist_fn_12 ()) < min_dist)
    {
      min_dist = dist;
      pen = 11;
    }
  if ((dist = dist_fn_13 ()) < min_dist)
    {
      min_dist = dist;
      pen = 12;
    }
  if ((dist = dist_fn_14 ()) < min_dist)
    {
      min_dist = dist;
      pen = 13;
    }
  if ((dist = dist_fn_15 ()) < min_dist)
    {
      min_dist = dist;
      pen = 14;
    }
  if ((dist = dist_fn_16 ()) < min_dist)
    {
      min_dist = dist;
      pen = 15;
    }
  if ((dist = dist_fn_17 ()) < min_dist)
    {
      min_dist = dist;
      pen = 16;
    }
  if ((dist = dist_fn_18 ()) < min_dist)
    {
      min_dist = dist;
      pen = 17;
    }
  if ((dist = dist_fn_19 ()) < min_dist)
    {
      min_dist = dist;
      pen = 18;
    }
  if ((dist = dist_fn_20 ()) < min_dist)
    {
      min_dist = dist;
      pen = 19;
    }
  if ((dist = dist_fn_21 ()) < min_dist)
    {
      min_dist = dist;
      pen = 20;
    }
  if ((dist = dist_fn_22 ()) < min_dist)
    {
      min_dist = dist;
      pen = 21;
    }
  if ((dist = dist_fn_23 ()) < min_dist)
    {
      min_dist = dist;
      pen = 22;
    }
  if ((dist = dist_fn_24 ()) < min_dist)
    {
      min_dist = dist;
      pen = 23;
    }
  if ((dist = dist_fn_25 ()) < min_dist)
    {
      min_dist = dist;
      pen = 24;
    }
  if ((dist = dist_fn_26 ()) < min_dist)
    {
      min_dist = dist;
      pen = 25;
    }
  if ((dist = dist_fn_27 ()) < min_dist)
    {
      min_dist = dist;
      pen = 26;
    }
  if ((dist = dist_fn_28 ()) < min_dist)
    {
      min_dist = dist;
      pen = 27;
    }
  if ((dist = dist_fn_29 ()) < min_dist)
    {
      min_dist = dist;
      pen = 28;
    }
  if ((dist = dist_fn_30 ()) < min_dist)
    {
      min_dist = dist;
      pen = 29;
    }
  if ((dist = dist_fn_31 ()) < min_dist)
    {
      min_dist = dist;
      pen = 30;
    }
  if ((dist = dist_fn_32 ()) < min_dist)
    {
      min_dist = dist;
      pen = 31;
    }
  if ((dist = dist_fn_33 ()) < min_dist)
    {
      min_dist = dist;
      pen = 32;
    }
  if ((dist = dist_fn_34 ()) < min_dist)
    {
      min_dist = dist;
      pen = 33;
    }
  if ((dist = dist_fn_35 ()) < min_dist)
    {
      min_dist = dist;
      pen = 34;
    }
  if ((dist = dist_fn_36 ()) < min_dist)
    {
      min_dist = dist;
      pen = 35;
    }
  if ((dist = dist_fn_37 ()) < min_dist)
    {
      min_dist = dist;
      pen = 36;
    }
  if ((dist = dist_fn_38 ()) < min_dist)
    {
      min_dist = dist;
      pen = 37;
    }
  if ((dist = dist_fn_39 ()) < min_dist)
    {
      min_dist = dist;
      pen = 38;
    }
  if ((dist = dist_fn_40 ()) < min_dist)
    {
      min_dist = dist;
      pen = 39;
    }
  if ((dist = dist_fn_41 ()) < min_dist)
    {
      min_dist = dist;
      pen = 40;
    }
  if ((dist = dist_fn_42 ()) < min_dist)
    {
      min_dist = dist;
      pen = 41;
    }
  if ((dist = dist_fn_43 ()) < min_dist)
    {
      min_dist = dist;
      pen = 42;
    }
  if ((dist = dist_fn_44 ()) < min_dist)
    {
      min_dist = dist;
      pen = 43;
    }
  if ((dist = dist_fn_45 ()) < min_dist)
    {
      min_dist = dist;
      pen = 44;
    }
  if ((dist = dist_fn_46 ()) < min_dist)
    {
      min_dist = dist;
      pen = 45;
    }
  if ((dist = dist_fn_47 ()) < min_dist)
    {
      min_dist = dist;
      pen = 46;
    }
  if ((dist = dist_fn_48 ()) < min_dist)
    {
      min_dist = dist;
      pen = 47;
    }
#else
  pen = 0;
#endif

  if (useprev)
    {
      register ULONG red_dist_pre, green_dist_pre, blue_dist_pre;

      red_dist_pre = sqr (red - prev[0]);
      green_dist_pre = sqr (green - prev[1]);
      blue_dist_pre = sqr (blue - prev[2]);

      if ((dist = green_dist_pre + blue_dist_pre) < min_dist)
	{
	  min_dist = dist;
	  pen = 101;
	}
      if ((dist = red_dist_pre + blue_dist_pre) < min_dist)
	{
	  min_dist = dist;
	  pen = 102;
	}
      if ((dist = red_dist_pre + green_dist_pre) < min_dist)
	{
	  pen = 103;
	}
    }

  /*
   * Convert pen number to true pen number 
   */
  switch (pen)
    {
    case 101:
      /* Modify Red */
      pen = (0x2 << 6) | (red >> 2);
      prev[0] = red;
#ifdef MAX_HAMSLIP
      hamslip++;
#endif
      break;
    case 102:
      pen = (0x3 << 6) | (green >> 2);
      prev[1] = green;
#ifdef MAX_HAMSLIP
      hamslip++;
#endif
      break;
    case 103:
      pen = (0x1 << 6) | (blue >> 2);
      prev[2] = blue;
#ifdef MAX_HAMSLIP
      hamslip++;
#endif
      break;
    default:
      prev[0] = standard_palette[pen][0];
      prev[1] = standard_palette[pen][1];
      prev[2] = standard_palette[pen][2];
#ifdef MAX_HAMSLIP
      hamslip = 0;
#endif
      pen = standard_pens[pen];
    }

  return ((UBYTE) pen);
}

__regargs VOID
WritePixelArray24 (struct RastPort * rp, const UWORD xstart,
		   const UWORD ystart, const UWORD width, const UWORD height,
		   UBYTE r[], UBYTE g[], UBYTE b[],
		   UBYTE * pen_array, struct RastPort * temprp)
{
  int x, y;
  ULONG prev[3];		/* Used by pen_number to store the previous
				 * pixel colour in 32,32,32 format. */
  UBYTE *rptr = pen_array;

  for (y = 0; y < height; y++)
    for (x = 0; x < width; x++)
      *rptr++ = pen_number (*r++, *g++, *b++, prev, x);

  WritePixelArray8 (rp, xstart, ystart, xstart + width - 1, ystart + height - 1,
		    pen_array, temprp);
}

__regargs VOID
WritePixel24 (struct RastPort * rp, const UWORD xcoord,
	    const UWORD ycoord, const UBYTE r, const UBYTE g, const UBYTE b)
{
  UBYTE nextr, nextg, nextb;
  USHORT prev_pen, old_pen, next_pen, new_pen;

  prev_pen = ReadPixel (rp, xcoord - 1, ycoord);
  old_pen = ReadPixel (rp, xcoord, ycoord);
  next_pen = ReadPixel (rp, xcoord + 1, ycoord);
  /* Could use ReadPixelLine() */

  if (next_pen > 64)
    {
      /* Need to fix next. */
      if ((prev_pen < 64) || (old_pen < 64))
	{
	  /* simple */
	}
      else
	{
	  /* take a guess at its value */
	  nextr = 0;
	  nextg = 0;
	  nextb = 0;
	  switch (prev_pen >> 6)
	    {
	    case 1:
	      nextb += prev_pen << 2;
	      break;
	    case 2:
	      nextr += prev_pen << 2;
	      break;
	    case 3:
	      nextg += prev_pen << 2;
	      break;
	    }
	  switch (old_pen >> 6)
	    {
	    case 1:
	      nextb += prev_pen << 2;
	      break;
	    case 2:
	      nextr += prev_pen << 2;
	      break;
	    case 3:
	      nextg += prev_pen << 2;
	      break;
	    }
	  switch (next_pen >> 6)
	    {
	    case 1:
	      nextb += prev_pen << 2;
	      break;
	    case 2:
	      nextr += prev_pen << 2;
	      break;
	    case 3:
	      nextg += prev_pen << 2;
	      break;
	    }
	}
    }
}
