/********************************************************************
*   DrvUtils.c
*
*   Macintosh driver utilities.
*
*   Copyright (c) 1994-1997, Willows Software Inc.  All rights reserved.
********************************************************************/

#include <stdio.h>
#include <string.h>

#include "DrvUtils.h"
#include "StringUtils.h"


/********************************************************************
*  Copy the coordinates in the windows rectangle to the mac rectangle.
********************************************************************/
void WinRect2MacRect(RECT *winR, Rect *macR)
{

	macR->left = winR->left;
	macR->right = winR->right;
	macR->top = winR->top;
	macR->bottom = winR->bottom;

}


/********************************************************************
*  Copy the coordinates in the mac rectangle to the windows rectangle.
********************************************************************/
void MacRect2WinRect(Rect *macR, RECT *winR)
{

	winR->left = macR->left;
	winR->right = macR->right;
	winR->top = macR->top;
	winR->bottom = macR->bottom;

}



/********************************************************************
*  Return absolute value of the width or height, according to the width flag.
********************************************************************/
int AbsSizeOfRect(Rect r, short width)
{
int dimention;

	/* calculate the width/height of the rectangle */
	if(width)
		dimention = r.right - r.left;	
	else
		dimention = r.bottom - r.top;	

	/* Make sure it is the absolute value */
	if(dimention < 0)
		return(dimention * -1);
	else
		return(dimention);
		
	
}



/********************************************************************
* ResetRect
*
*  Reset the rectangle, removing any flip information.
********************************************************************/
void ResetRect(Rect *r)
{
short temp;

	/* Reset horizontal coordinates */
	if(r->right < r->left)	{
		temp = r->right;
		r->right = r->left;
		r->left = temp;
	}
	
	if(r->bottom < r->top) {
		temp = r->bottom;
		r->bottom = r->top;
		r->top = temp;
	}
	
}



/********************************************************************
* NormalizeRect
*
*  Normalize the rectangle so that it's upper left coords are 
*	normalized to zero.
*  If reset, the rectangle will be set to positive coordinates,
*	this eliminates a flipped rect condition.
********************************************************************/
void NormalizeRect(Rect *r, short reset)							
{
	/* Normalize the horizontal coordinates */
	if(r->right < r->left) {					/* Flipped rectangle */
		r->left = r->left - r->right;		/* Set to width */
		r->right = 0;
	}
	else	{											/* Normal rectangle */
		r->right = r->right - r->left;	/* Set to width */
		r->left = 0;
	}
	
	/* Normalize the horizontal coordinates */
	if(r->bottom < r->top) {				/* Flipped rectangle */
		r->top = r->top - r->bottom;		/* Set to width */
		r->bottom = 0;
	}
	else {
		r->bottom = r->bottom - r->top;	/* Set to width */
		r->top = 0;	
	}

	/* See if the rectangle should be reset to positive coordinates */
	if(reset)
		ResetRect(r);

}



/********************************************************************
* IsFlipped
*
*  Check for flipped state (src and dest dimentions are fliped) exists.
*  Returns bits packed to show state, so to test which flip, perform
*   a bit AND with the constants.  ex flipH = IsFlipped(..) & FLIPH;
********************************************************************/
short IsFlipped(Rect *srcRect, Rect *destRect)
{
short flipState = NOFLIP;			/* No Flipping (or obscene jestures) */
short srcW = srcRect->right - srcRect->left;
short destW = destRect->right - destRect->left;
short srcH = srcRect->bottom - srcRect->top;
short destH = destRect->bottom - destRect->top;

	/* It is easiest to check for differences in width/height directions */
	/* i.e. if one width is positive and the other is negative */
	if((srcW < 0) ^ (destW < 0))		/* Mirror horizontally */ 
		flipState = flipState | FLIPH;	
	
	if((srcH < 0) ^ (destH < 0))	/* Mirror Vertically */ 
		flipState = flipState | FLIPV;	

	return(flipState);					
}



/********************************************************************
* IsStretched
*
*  Check for stretch state (src and dest rects differ in size) exists.
********************************************************************/
short IsStretched(Rect *srcRect, Rect *destRect)
{
	if(AbsSizeOfRect(*srcRect, TRUE) != AbsSizeOfRect(*destRect, TRUE))
		return(TRUE);
	else if(AbsSizeOfRect(*srcRect, FALSE) != AbsSizeOfRect(*destRect, FALSE))
		return(TRUE);
	else
		return(FALSE);

}


/********************************************************************
*  Check if a particular bit is set.
* Bit 32.....Bit 0   (MSB, LSB)
********************************************************************/
Boolean BitTest(long testWord, short bitNum)
{
	return((testWord >> bitNum) & 0x01);
}

/********************************************************************
* Bresenham line drawing algorithm
* x1, y1 and x2, y2 are end points
* calculate two lines, from 0,0 to x1,x2 and y1,y2
* these will be the compression/expansion arrays
********************************************************************/

int
stretch(int sx,int dx, LPINT dp)
{
	int x1,y1,x2,y2;
 	int w, h, d, dxd, dyd, dxn, dyn, dinc, ndinc, p;
 	int x, y;
 
	if (sx == dx) {
	    for (x=0; x<sx; x++)
		dp[x] = x;
	    return x;
	}
	x1 = 0;
	y1 = 0;
	x2 = dx;
	y2 = sx;

	/* Set up */
	x = x1; y = y1;                   /* start of line */
	w = x2 - x1;                      /* width domain of line */
	h = y2 - y1;                      /* height domain of line */
 
	/* Determine drawing direction */
	if (w < 0) {                       /* drawing right to left */
		w = -w;                    /* absolute width */
		dxd = -1;                  /* x increment is negative */
	} else                             /* drawing left to right */
		dxd = 1;                   /* so x incr is positive */
	if (h < 0) {                       /* drawing bottom to top */
		h = -h;                    /* so get absolute height */
		dyd = -1;                  /* y incr is negative */
	} else                             /* drawing top to bottom */
		dyd = 1;                   /* so y incr is positive */
 
	/* Determine major axis of motion */
	if (w < h) {                       /* major axis is Y */
		p = h, h = w, w = p;       /* exchange height and width */
		dxn = 0;
		dyn = dyd;
	} else {                           /* major axis is X */
		dxn = dxd;
		dyn = 0;
	}
 
	/* Set control variables */
	ndinc = h * 2 - 1;            /* Non-diagonal increment */
	d = ndinc - w;                /* pixel selection variable */
	dinc = d - w;                 /* Diagonal increment */
   
	/* Loop to draw the line */
	for (p = 0; p < w; p++) {
		/* x, y */
		dp[x] = y;

		if (d < 0) {                     /* step non-diagonally */
			x += dxn;
			y += dyn;
			d += ndinc;
		} else {                         /* step diagonally */
			x += dxd;
			y += dyd;
			d += dinc;
		}
	}
	
	return dx;
}

void
flip(LPINT data,int len)
{
    int i;
    BYTE tmp;

    for (i=0; i<len/2; i++) {
	tmp = data[i];
	data[i] = data[len-i-1];
	data[len-i-1] = tmp;
    }
}

  


