/*////////////////////////////////////////////////////////////////////////
//                                                                      //
//              INTEL CORPORATION PROPRIETARY INFORMATION               //
//                                                                      //
//      This software is supplied under the terms of a license          //
//      agreement or nondisclosure agreement with Intel Corporation     //
//      and may not be copied or disclosed except in accordance         //
//      with the terms of that agreement.                               //
//                                                                      //
////////////////////////////////////////////////////////////////////////*/


/*******************************************************************
 *
 *	  FILE:			bresnham.cpp
 *
 *    DESCRIPTION:	One component of the stretch routine for DCI 
 *					sample driver.  This part builds a byte code, 
 *					using an adaptation of a Bresenham line algorithm, 
 *					which tells the routine whether to copy or skip a 
 *					pixel.
 *
 *    AUTHOR:		Blake Bender
 *
 *	  DATE:			1/25/94
 *
 *******************************************************************/

#include <windows.h>
#include "debug.h"

/*
 ** CalculateStretchCode
 *
 *  Parameters:		LONG srcLength -- original width or height of a stretched
 *						bitmap.
 *					LONG dstLength -- width or height to stretch bitmap to.
 *					LPBYTE code    -- pointer to a BYTE code which will 
 *						represent the # of times to copy pixels in this row 
 *						or column of the bitmap, i.e. zero at code[i] means
 *						skip pixels in row or column i, and n means copy 
 *						pixels in row or column i n times.
 *
 *  Description:	Uses a Bresenham line algorithm to generate a code of 
 *					length = srcLength parameter.
 *
 *  Returns:		none.
 *
 *	Side Effects:	Copies values into code array.
 */
void FAR CalculateStretchCode(LONG srcLength, LONG dstLength, LPBYTE code)
{
	LONG	dwDeltaX, dwDeltaY, dwConst1, dwConst2, dwP;
	int		i, j, k;
	BYTE	bStretchIndex = 0;
	int 	total = 0;		
	
	/*
	 * for some strange reason I'd like to figure out but haven't got time to, the
	 * replication code generation seems to have a problem between 1:1 and 2:1 stretch
	 * ratios.  Fix is to zero-initialize index (the problem occurs in the first one
	 * generated) when stretch is betw. those ratios, and one-initialize it otherwise.
	 */
	if ((dstLength <= srcLength * 2L) && (dstLength >= srcLength))
		bStretchIndex = 0;
	else 
		bStretchIndex = 1;	
	
	/* 
	 * initialize code array, to get rid of anything which might have been 
	 * left over in it.
	 */
	for (i = 0; i < srcLength; i++)
		code[i] = 0;

	/*
	 * Variable names roughly represent what you will find in any graphics
	 * text.  Consult text for an explanation of Bresenham line alg., it's
	 * beyond the scope of my comments here.
	 */
	dwDeltaX = srcLength;
	dwDeltaY = dstLength;

	if (dstLength < srcLength)
	{
		/* size is shrinking, use standard Bresenham alg. */
		dwConst1 = 2L * dwDeltaY;
		dwConst2 = 2L * (dwDeltaY - dwDeltaX);
		dwP = 2L * dwDeltaY - dwDeltaX;

		for (i = 0; i < dwDeltaX; i++)
		{
			if (dwP <= 0L)
			{
				dwP += dwConst1;
			}
			else
			{
				dwP += dwConst2;
				code[i]++;
				total++;
			}
		}

	}
	else
	{
		/* 
		 * size is increasing.  Use Bresenham adapted for slope > 1, and 
		 * use a loop invariant to generate code array.  Run index i from 
		 * 0 to dwDeltaY - 1, and when i = dwDeltaY - 1, j will 
		 * be = dwDeltaX - 1.
		 */
		dwConst1 = 2L * dwDeltaX;
		dwConst2 = 2L * (dwDeltaX - dwDeltaY);
		dwP = 2L * dwDeltaX - dwDeltaY;
		j = 0;
				
		for (i = 0; i < dwDeltaY; i++)
		{
			if (dwP <= 0L)
			{
				dwP += dwConst1;
				bStretchIndex++;
			}
			else
			{
				dwP += dwConst2;
				code[j++] = ++bStretchIndex;
				bStretchIndex = 0;
				total += (int)code[j - 1];
			}
		}            

		/*
		 * UGLY fix up for wacky bug which I have no time to fix properly.  The 'total' of
		 * entries is screwed up for slopes > 4, so add the difference back into the array.
		 */
		 if (total < dwDeltaY)
		 {      
			while (total < dwDeltaY)
			{
		 		j = (int)dwDeltaY - total;
			 	k = (int)dwDeltaY / j;
			 	for (i = 0; i < dwDeltaX; i++)
			 	{                    
			 		if (!(i % k) && (total < dwDeltaY)) 
			 		{
			 			code[i]++;
			 			total++;
			 		}
			 	}
			}
		 }
	}
}

	
