/*********************************************************/
/* This source code copyright (c) 1991-2001, Aaron Giles */
/* See the Read Me file for licensing information.       */
/* Contact email: mac@aarongiles.com                     */
/*********************************************************/

// void DitherCopyTo16Odd(ulong *srcRow, void *dstRowStart, uchar *iTable, ColorSpec *cTable,
//						  DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer,
//						  short *rgnBuffer, uchar *errorMap, short columns)

#if applec
#pragma unused(iTable, cTable)
#endif

// internals:
	ulong *src = srcRow;					// pointer to the 32-bit source row
	ushort *dst = (ushort *)dstRowStart;	// pointer to the 16-bit destination row
	ulong pixel;							// scratch for the current pixel
	long red;								// red scratch area
	long green;								// green scratch area
	long blue;								// blue scratch area
	long red2;								// 2 * the red error; used for fast calculations
	long green2;							// 2 * the green error
	long blue2;								// 2 * the blue error
	long rgnCol;							// region column counter

	// skip to the ends of everything here
	dst += columns;
	src += columns;
	eBuffer += columns;
	oBuffer += columns;

	// initialize our counters and clear out next row
	red = green = blue = 0;
	eBuffer[-1].red = eBuffer[-1].green = eBuffer[-1].blue = 0;

	// set up the region column counter
	while (*rgnBuffer++ < columns);
	--rgnBuffer;
	if (*rgnBuffer == columns) rgnCol = *--rgnBuffer - columns;
	else rgnCol = columns - *--rgnBuffer;

	// begin main loop here
	while (columns--) {

		// combine the accumulated errors and round to a pixel value
		--oBuffer;
		red += oBuffer->red + 8;
		red >>= 4;
		red = errorMap[red];
		green += oBuffer->green + 8;
		green >>= 4;
		green = errorMap[green];
		blue += oBuffer->blue + 8;
		blue >>= 4;
		blue = errorMap[blue];

		// offset the current pixel by the errors
		pixel = *--src;
		blue += pixel & 0xff;
		pixel >>= 8;
		green += pixel & 0xff;
		pixel >>= 8;
		red += pixel & 0xff;

		// check for overflows and handle them
		if (red > 255) red = 255;
		else if (red < 0) red = 0;
		if (blue > 255) blue = 255;
		else if (blue < 0) blue = 0;
		if (green > 255) green = 255;
		else if (green < 0) green = 0;

		// assemble the colors into a 16-bit color pixel
		pixel = red >> 3;
		pixel <<= 5;
		pixel += green >> 3;
		pixel <<= 5;
		pixel += blue >> 3;

		// determine whether or not to draw this pixel, and handle switches
		if (rgnCol > 0) {
			--dst;
			if (!--rgnCol) rgnCol = rgnBuffer[-1] - rgnBuffer[0], rgnBuffer--;
		} else {
			*--dst = pixel;
			if (!++rgnCol) rgnCol = rgnBuffer[0] - rgnBuffer[-1], rgnBuffer--;
		}

		// Calculate the new errors
		red = (red & 0x07) - (red >> 5);
		green = (green & 0x07) - (green >> 5);
		blue = (blue & 0x07) - (blue >> 5);

		// Calculate 2 * the new error for fast ops ahead
		red2 = red << 1;
		green2 = green << 1;
		blue2 = blue << 1;

		// Store 1/16, 3/16, and 5/16 into next row; leave 7/16 for neighbor
		--eBuffer;
		eBuffer[-1].red = red;
		eBuffer[-1].green = green;
		eBuffer[-1].blue = blue;
		eBuffer[1].red += (red += red2);
		eBuffer[1].green += (green += green2);
		eBuffer[1].blue += (blue += blue2);
		eBuffer->red += (red += red2);
		eBuffer->green += (green += green2);
		eBuffer->blue += (blue += blue2);
		red += red2;
		green += green2;
		blue += blue2;
	}
