/*	RectMath.cpp
 *
 *		Rectangle math routines
 */

/*  YAAF - Yet another application framework
 *  Copyright (C) 1997, 1998 William Edward Woody
 *  
 *  This library is free software; you can redistribute it
 *  and/or modify it under the terms of the GNU Library
 *  General Public License as published by the Free Software
 *  Foundation; either version 2 of the License, or any
 *  later version.
 *  
 *  This library is distributed in the hope that it will be
 *  useful, but WITHOUT ANY WARRANTY; without even the implied
 *  warranty of MERCHANTABIILITY or FITNESS FOR A PARTICULAR
 *  PURPOSE. See the GNU Library General Public License for
 *  more details.
 *  
 *  You should have received a copy of the GNU Library General
 *  Public License along with this library; if not, write to the
 *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 *  Boston, MA 02111-1307, USA.
 *  
 *  To contact the author, either e-mail me at woody@pandawave.com, 
 *	or write to
 *  
 *          William Edward Woody
 *          In Phase Consulting
 *          1545 Ard Eevin Avenue
 *          Glendale, CA 91202
 *
 *	Or visit us on the web at http://www.pandawave.com
 */

#include <XConfig.h>			// must be first to optimize compile on MSVC++
#include <XDrawData.h>

#if OPT_WINOS || OPT_XWIN

/************************************************************************/
/*																		*/
/*	Simple Rectangle Routines											*/
/*																		*/
/************************************************************************/

/*	@F"SetRect"
 *	@H"XDrawData.h"
 *	@I
 *
 *		Set the rectangle based on the four coordinates
 */

void SetRect(Rect *r, short left, short top, short right, short bottom)
{
	r->left = left;
	r->top = top;
	r->right = right;
	r->bottom = bottom;
}

#if OPT_XWIN				// Defined in Microsoft Windows

/*	@F"OffsetRect"
 *	@H"XDrawData.h"
 *	@I
 *
 *		Offset the rectangle by the delta values (x,y)
 */

void OffsetRect(Rect *r, short x, short y)
{
	r->left += x;
	r->right += x;
	r->top += y;
	r->bottom += y;
}

#endif

/*	@F"InsetRect"
 *	@H"XDrawData.h"
 *	@I
 *
 *		Inset the rectangle by the delta values provided. If the
 *	values are negative, this expands the rectangel instead.
 */

void InsetRect(Rect *r, short x, short y)
{
	r->left += x;
	r->right -= x;
	r->top += y;
	r->bottom -= y;
	if (EmptyRect(r)) SetRect(r,0,0,0,0);
}

/************************************************************************/
/*																		*/
/*	Rectangle Manipulation												*/
/*																		*/
/************************************************************************/

/*	@F"EmptyRect"
 *	@H"XDrawData.h"
 *	@I
 *
 *		Return true if the rectangle is empty
 */

bool EmptyRect(Rect *r)
{
	return ((r->right <= r->left) || (r->bottom <= r->top));
}

/*	@F"EqualRect"
 *	@H"XDrawData.h"
 *	@I
 *
 *		Return true if rectangles are equal
 */

bool EqualRect(Rect *a, Rect *b)
{
	if (EmptyRect(a) && EmptyRect(b)) return true;
	
	if (a->left != b->left) return false;
	if (a->top != b->top) return false;
	if (a->right != b->right) return false;
	if (a->bottom != b->bottom) return false;
	return true;
}

/************************************************************************/
/*																		*/
/*	Rectangle Math														*/
/*																		*/
/************************************************************************/

/*	smin
 *
 *		short integer minimum
 */

static short smin(short x, short y)
{
	return (x < y) ? x : y;
}

/*	smax
 *
 *		short integer maximum
 */

static short smax(short x, short y)
{
	return (x > y) ? x : y;
}

/*	@F"SectRect"
 *	@H"XDrawData.h"
 *	@I
 *
 *		Intersect two rectangles. if empty, return false
 */

bool SectRect(Rect *a, Rect *b, Rect *out)
{
	out->left = smax(a->left,b->left);
	out->right = smin(a->right,b->right);
	out->top = smax(a->top,b->top);
	out->bottom = smin(a->bottom,b->bottom);
	
	if (EmptyRect(out)) {
		SetRect(out,0,0,0,0);
		return false;
	} else {
		return true;
	}
}

/*	@F"UnionRect"
 *	@H"XDrawData.h"
 *	@I
 *
 *		Find the largest enclosing rectangle
 */

void UnionRect(Rect *a, Rect *b, Rect *out)
{
	if (EmptyRect(a)) {
		*out = *b;
	} else if (EmptyRect(b)) {
		*out = *a;
	} else {
		out->left = smin(a->left,b->left);
		out->right = smax(a->right,b->right);
		out->top = smin(a->top,b->top);
		out->bottom = smax(a->bottom,b->bottom);
	}
}

/************************************************************************/
/*																		*/
/*	Point/Rectangle Stuff												*/
/*																		*/
/************************************************************************/

/*	@F"PtInRect"
 *	@H"XDrawData.h"
 *	@I
 *
 *		Is this point inside this rectangle?
 */

bool PtInRect(Point pt, Rect *r)
{
	return ((r->left <= pt.h) && (pt.h < r->right) &&
				(r->top <= pt.v) && (pt.v < r->bottom));
}

/*	@F"PtToRect"
 *	@H"XDrawData.h"
 *	@I
 *
 *		Create rectangle which contains these two points.
 */

void PtToRect(Point a, Point b, Rect *r)
{
	r->left = smin(a.h,b.h);
	r->right = smax(a.h,b.h);
	r->top = smin(a.v,b.v);
	r->bottom = smax(a.v,b.v);
}

#endif // OPT_WINOS || OPT_XWIN
