// GSGeometry.h
//
// Copyright 1997-1999 Diehl Graphsoft, Inc.
// All Rights Reserved.
//
//  This file contains geometry types for the GraphSoft core.
//  ViewPt and ViewRect are in here.
//
//	Started 7/30/97 by Robert McBride
//
// SourceSafe information for this version:
//    $Revision: 15 $
//    $Date: 1/22/01 12:36p $
//    $Author: Mfarnan $

#ifndef _GS_GEOMETRY_
#define _GS_GEOMETRY_

#pragma once

#include "GSTypes.h"

typedef Sint16  ViewCoord;
typedef Sint32  ViewCoordLong;

#ifdef __cplusplus

	// 3D coordinate definition of the planar object
	typedef Uint32 TPlanarRefID;

	const TPlanarRefID kPlanarRefID_ScreenPlane	= TPlanarRefID(0);

	//----------------------------------------------------------------------------------------
	//----------------------------------------------------------------------------------------
	//
	// ViewPt
	//
	//----------------------------------------------------------------------------------------
	//----------------------------------------------------------------------------------------


	// WorldSpace and ViewSpace conversion functions are in TDQuickDraw.h.
	//
	// Mac and Win conversion functions are in MCCoordTypes.h:
	// 
	//     ViewPt   MacToViewPt(const Point&  p);
	//     Point    ViewToMacPt(const ViewPt& p);
	//
	//     POINT    ViewToWinPt  (const ViewPt& p);
	//     ViewPt   WinToViewPt  (const POINT&  p);


	//--------------------------------------------------------------------
	#pragma pack(push, 2) // BEGIN 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)

	class ViewPt;

	class ViewPt_ {
	public:
		ViewCoord y; 
		ViewCoord x; 

		operator const ViewPt&() const  { return *((const ViewPt*) this); }
		operator       ViewPt&()		{ return       *((ViewPt*) this); }

		ViewPt* operator&(void)	 			    { return (ViewPt *) this; }
		const ViewPt* operator&(void) const 	{ return (const ViewPt *) this; }

		Boolean operator==(const ViewPt_& p) const { return y == p.y && x == p.x; }
		Boolean operator!=(const ViewPt_& p) const { return y != p.y || x != p.x; }
	};

	#pragma pack(pop) // END 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)
	//--------------------------------------------------------------------


	//--------------------------------------------------------------------
	#pragma pack(push, 2) // BEGIN 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)

	class ViewPt : public ViewPt_ {
	public:
		ViewPt() { x = y = 0;}
		ViewPt(ViewCoord xIn, ViewCoord yIn) { x = xIn; y = yIn; }

		operator const ViewPt_&() const	{ return *((const ViewPt_*) this); }
		operator       ViewPt_&()		{ return *((ViewPt_*) this); }
		
		ViewPt&	operator=(const ViewPt& p) { x = p.x; y = p.y; return *this; }

		Bool8 operator==(const ViewPt& pt) const { return ((pt.x == x) && (pt.y == y)); }
		Bool8 operator!=(const ViewPt& pt) const { return !(*this == pt); }

		ViewPt operator+(const ViewPt& p) const	{ return ViewPt(x + p.x, y + p.y); }
		ViewPt operator-(const ViewPt& p) const	{ return ViewPt(x - p.x, y - p.y); }

		void Set(ViewCoord X, ViewCoord Y) { x = X; y = Y; }

		// Note! These use longs because we know ViewCoords are shorts. If/when ViewCoords become something 
		// else (doubles, say), these longs need to become doubles. [MAF 3/3/00]

		long Magnitude(void)        const; /* { return (long) sqrt(double((long) x * (long) x + (long) y * (long) y)); } */
		long MagnitudeSquared(void) const { return (long) x * (long) x + (long) y * (long) y; }

		long DistanceFrom(ViewPt otherPoint) const 
		{ 
			long x = (*this - otherPoint).Magnitude(); 
			return (x > 0) ? x : -x;
		}

 		long SquaredDistanceFrom(ViewPt otherPoint) const { 
			long x = ((*this - otherPoint).MagnitudeSquared()); 
			return (x > 0) ? x : -x;
		}

		void ByteSwap();
	};
	#pragma pack(pop) // END 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)
	//--------------------------------------------------------------------

	// This is a dup of the regular Num2Short that's in MCFloat.h, which apparently can't be included in this file. [MAF 12/8/05]
	inline short Num2ShortLocal(double x)
	{
		return (x >  32767) ? (short)  32767     :
			(x < -32767) ? (short) -32767     :
			(x >  0)     ? (short)  (x + 0.5000000001) :
			(x <  0)     ? (short)  (x - 0.5000000001) :
							(short)  0;
	}


	inline ViewPt operator*(const double scalar, const ViewPt thePt)	{ return ViewPt(Num2ShortLocal(thePt.x * scalar), Num2ShortLocal(thePt.y * scalar)); }
	inline ViewPt operator/(const ViewPt thePt, const double scalar)	{ return ViewPt(Num2ShortLocal(thePt.x / scalar), Num2ShortLocal(thePt.y / scalar)); }

	//----------------------------------------------------------------------------------------
	//----------------------------------------------------------------------------------------
	// TCellID
	//
	// replaces Cell structure defined by Quicktime
	//
	//----------------------------------------------------------------------------------------
	//----------------------------------------------------------------------------------------
	typedef ViewPt TCellID;
	
	//----------------------------------------------------------------------------------------
	//----------------------------------------------------------------------------------------
	//
	// XViewCoord / XViewPt / XViewRect
	//
	// double versions of ViewCoord, ViewPt and ViewRect
	//
	//----------------------------------------------------------------------------------------
	//----------------------------------------------------------------------------------------

	typedef double XViewCoord;
	//--------------------------------------------------------------------
	#pragma pack(push, 2) // BEGIN 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)

	class XViewPt {
	public:
		XViewCoord y; 
		XViewCoord x; 

		XViewPt() { x = y = 0;}
		XViewPt(ViewPt v) { x = v.x; y = v.y; }
		XViewPt(XViewCoord xIn, XViewCoord yIn) { x = xIn; y = yIn; }

		XViewPt& operator=(const XViewPt& p) { x = p.x; y = p.y; return *this; }

		Bool8 operator==(const XViewPt& pt) const { return ((pt.x == x) && (pt.y == y)); }
		Bool8 operator!=(const XViewPt& pt) const { return !(*this == pt); }

		XViewPt operator+(const XViewPt& p) const	{ return XViewPt(x + p.x, y + p.y); }
		XViewPt operator-(const XViewPt& p) const	{ return XViewPt(x - p.x, y - p.y); }

		void Set(XViewCoord X, XViewCoord Y) { x = X; y = Y; }

		XViewCoord MagnitudeSquared(void) const                  { return x*x + y*y; }
		XViewCoord SquaredDistanceFrom(XViewPt otherPoint) const 
		{ 
			XViewCoord x = (*this - otherPoint).MagnitudeSquared();
			return (x > 0) ? x : -x;
		}

		XViewCoord Magnitude(void) const; /* { return sqrt(x*x + y*y); } */

		XViewCoord DistanceFrom(XViewPt otherPoint) const
		{ 
			XViewCoord x = (*this - otherPoint).Magnitude();
			return (x > 0) ? x : -x;
		}
	};
	#pragma pack(pop) // END 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)
	//--------------------------------------------------------------------



	inline XViewPt operator*(const double scalar, const XViewPt thePt)
		{ return XViewPt(thePt.x * scalar, thePt.y * scalar); }

	inline XViewPt operator/(const XViewPt thePt, const double scalar)
		{ return XViewPt(thePt.x / scalar, thePt.y / scalar); }





	//----------------------------------------------------------------------------------------
	//----------------------------------------------------------------------------------------
	//
	// ViewRect
	//
	//----------------------------------------------------------------------------------------
	//----------------------------------------------------------------------------------------




	//--------------------------------------------------------------------
	#pragma pack(push, 2) // BEGIN 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)

	class ViewRect_ {
	public:
	//protected:
		ViewCoord			top, left, bottom, right;

		friend class ViewRect;
	};
	#pragma pack(pop) // END 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)
	//--------------------------------------------------------------------


	//--------------------------------------------------------------------
	#pragma pack(push, 2) // BEGIN 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)

	class ViewRect : public ViewRect_ {
	public:
		ViewRect&	operator=(const ViewRect& r)  { top = r.top; left = r.left; bottom = r.bottom; right = r.right; return *this; }
		ViewRect&	operator=(const ViewRect_& r) { top = r.top; left = r.left; bottom = r.bottom; right = r.right; return *this; }

		ViewRect() { top = left = bottom = right = 0;}
		ViewRect(ViewCoord leftIn, ViewCoord topIn, ViewCoord rightIn, ViewCoord bottomIn) { top = topIn; left = leftIn; right = rightIn; bottom = bottomIn; }
		ViewRect(const ViewPt& pt1, const ViewPt& pt2) {SetRect(pt1, pt2);}

		ViewCoord Top()    const { return top;    }   
		ViewCoord Left()   const { return left;   }  
		ViewCoord Bottom() const { return bottom; } 
		ViewCoord Right()  const { return right;  }

		void SetTop   (ViewCoord topIn)    { top    = topIn;    }  
		void SetLeft  (ViewCoord leftIn)   { left   = leftIn;   }  
		void SetBottom(ViewCoord bottomIn) { bottom = bottomIn; } 
		void SetRight (ViewCoord rightIn)  { right  = rightIn;  }  

		void SetRect(const ViewPt& pt1, const ViewPt& pt2);

		Bool8 operator==(const ViewRect& r) const {
				return (top == r.top && left == r.left && bottom == r.bottom && right == r.right);
		}

		Bool8 operator!=(const ViewRect& r) const { return !(*this == r); }

		inline ViewPt TopLeft()     const { return ViewPt(left, top); }
		inline ViewPt TopRight()	const { return ViewPt(right, top); }
		inline ViewPt BottomLeft()	const { return ViewPt(left, bottom); }
		inline ViewPt BottomRight() const { return ViewPt(right, bottom); }
			
		ViewCoord Width()  const { return right - left; }
		ViewCoord Height() const { return bottom - top; }
		ViewPt    Center() const { return ViewPt((Sint16)((Sint32) left + (Sint32) right) / 2, (Sint16)((Sint32) bottom + (Sint32) top) / 2); }
		
		Bool8 IsEmpty() const { return top >= bottom || left >= right; }  // Note > OR equal for ViewRect. WorldRects are different.
		Bool8 IsNotEmpty() const { return !IsEmpty(); }

		void MakeEmpty() { top = bottom = left = right = 0; }          // Note just 0,0,0,0 for now.
		
		void SetLTRB   (ViewCoord l, ViewCoord t, ViewCoord r, ViewCoord b) { left  = l; top  = t; right  = r; bottom  = b; }
		void AdjustLTRB(ViewCoord l, ViewCoord t, ViewCoord r, ViewCoord b) { left += l; top += t; right += r; bottom += b; }
		
		Bool8 Intersect(const ViewRect& src2, ViewRect& dest) const;
		Boolean Overlaps(const ViewRect& r) const      // True if the two rects share more than a point or a line.
		{ 
			if (this->IsEmpty() || r.IsEmpty())
				return false;
			else
				return ((bottom    > r.top)
		     		&& (right  > r.left)
			 		&& (left   < r.right) 
			 		&& (top < r.bottom)); 
		}

		void Inset(ViewCoord dx,  ViewCoord dy)  { left += dx; right -= dx; top += dy; bottom -= dy; }
		void Outset(ViewCoord dx, ViewCoord dy)  { left -= dx; right += dx; top -= dy; bottom += dy; }

		void Offset(ViewCoord dx, ViewCoord dy) { left += dx; right += dx; top += dy; bottom += dy; }

		void Union(const ViewRect& src2, ViewRect& dest) const { dest.top = top < src2.top ? top : src2.top; 
														dest.bottom = bottom > src2.bottom ? bottom : src2.bottom; 
														dest.left = left < src2.left ? left : src2.left; 
														dest.right = right > src2.right ? right : src2.right; }

		Bool8 PtInRect(const ViewPt& pt) const;

		void ByteSwap();
	};

	#pragma pack(pop) // END 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)
	//--------------------------------------------------------------------

	//--------------------------------------------------------------------
	#pragma pack(push, 2) // BEGIN 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)

	class XViewRect {

	public:
		XViewCoord top, left, bottom, right; 

		XViewRect()                  { top = 0;     left = 0;      bottom = 0;        right = 0; }
		XViewRect(const ViewRect& v) { top = v.top; left = v.left; bottom = v.bottom; right = v.right; }

		void SetLTRB(XViewCoord l, XViewCoord t, XViewCoord r, XViewCoord b) { left  = l; top  = t; right  = r; bottom  = b; }

		XViewPt Center() const { return XViewPt((left + right) / 2, (top + bottom) / 2); }

		XViewCoord Top()    const { return top;    }   
		XViewCoord Left()   const { return left;   }  
		XViewCoord Bottom() const { return bottom; } 
		XViewCoord Right()  const { return right;  }

		XViewCoord Width() const	{ return right - left;    }   
		XViewCoord Height() const	{ return bottom - top;    }   
	};
	#pragma pack(pop) // END 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)
	//--------------------------------------------------------------------

	//--------------------------------------------------------------------
	// I think these get obsoleted. [MAF 10/11/99]
	//
	//----------------------------------------------------------------------------------------
	//----------------------------------------------------------------------------------------
	//----------------------------------------------------------------------------------------

	//**  ViewPt manipulation functions  **
	inline void SetGSPt(ViewPt &pt, Sint16 x_in, Sint16 y_in) {pt.x = x_in; pt.y = y_in;}
	inline void AddGSPt(ViewPt const &srcPt, ViewPt &dstPt) {dstPt.x += srcPt.x; dstPt.y += srcPt.y;}
	inline void SubGSPt(ViewPt const &srcPt, ViewPt &dstPt) {dstPt.x -= srcPt.x; dstPt.y -= srcPt.y;}
	
	//**  ViewRect manipulation functions  **
	Bool8 SectViewRect(const ViewRect& src1, const ViewRect& src2, ViewRect& dest);
	Bool8 EqualViewRect(const ViewRect& rect1, const ViewRect& rect2);
	void InsetViewRect(ViewRect& rect, Sint16 dx, Sint16 dy);
	Bool8 IsEmptyViewRect(const ViewRect& rect);
	void OffsetViewRect(ViewRect& rect, Sint16 dx, Sint16 dy);
	void UnionViewRect(const ViewRect& src1, const ViewRect& src2, ViewRect& dest);
	void GSPt2ViewRect(const ViewPt& pt1, const ViewPt& pt2, ViewRect& rect);
	Bool8 GSPtInViewRect(const ViewPt& pt, const ViewRect& rect);
	Bool8 GSPtToAngle(const ViewRect& rect, const ViewPt& pt, Sint16 angle);
	void SetViewRect(ViewRect& rect, Sint16 left, Sint16 top, Sint16 right, Sint16 bottom);


	inline ViewCoord Dx(const ViewRect& rc) { return rc.Width(); }
	inline ViewCoord Dy(const ViewRect& rc) { return rc.Height(); }
	
	// WorldSpace and ViewSpace conversion functions are in TDQuickDraw.h.
	//
	// Mac and Win conversion functions are in MCCoordTypes.h:
	// 
	//     ViewRect MacToViewRect(const Rect&     r);
	//     Rect     ViewToMacRect(const ViewRect& r);
	//
	//     RECT     ViewToWinRect(const ViewRect& r);
	//     ViewRect WinToViewRect(const RECT&     r);
	//


	//----------------------------------------------------------------------------------------
	//----------------------------------------------------------------------------------------
	//
	// PageCoord / PagePt / PageRect
	//
	//----------------------------------------------------------------------------------------
	//----------------------------------------------------------------------------------------

	typedef double  PageCoord;

	class PagePt;

	//
	//----------------------------------------------------------------------------------------
	//----------------------------------------------------------------------------------------

	typedef double  PageCoord;

	class PagePt;

	//--------------------------------------------------------------------
	#pragma pack(push, 2) // BEGIN 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)

	class PagePt_ {
	public:
		PageCoord			x;
		PageCoord			y;
	};

	#pragma pack(pop) // END 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)
	//--------------------------------------------------------------------



	//--------------------------------------------------------------------
	#pragma pack(push, 2) // BEGIN 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)

	class PagePt : public PagePt_ {
	public:
		PagePt() { x = y = 0;}
		PagePt(PageCoord xIn, PageCoord yIn) { x = xIn; y = yIn; }

		void Set(PageCoord xIn, PageCoord yIn) { x = xIn; y = yIn; }

		bool operator==(const PagePt& pt) const { return ((pt.x == x) && (pt.y == y)); }
		bool operator!=(const PagePt& pt) const { return ((pt.x != x) || (pt.y != y)); }

		PagePt operator/(double scalar)   const	{ return PagePt(x / scalar, y / scalar); }
		PagePt operator*(double scalar)   const	{ return PagePt(x * scalar, y * scalar); }
		PagePt operator+(const PagePt& p) const	{ return PagePt(x + p.x, y + p.y); }
		PagePt operator-(const PagePt& p) const	{ return PagePt(x - p.x, y - p.y); }
		PagePt operator-(void) const			{ return PagePt(-x, -y); }

		void ByteSwap();
	};

	#pragma pack(pop) // END 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)
	//--------------------------------------------------------------------

	//--------------------------------------------------------------------
	#pragma pack(push, 2) // BEGIN 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)

	class PageRect_ {
	public:
		PageCoord			top;
		PageCoord			left;
		PageCoord			bottom;
		PageCoord			right;
	};
	#pragma pack(pop) // END 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)
	//--------------------------------------------------------------------

	//--------------------------------------------------------------------
	#pragma pack(push, 2) // BEGIN 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)
	class PageRect : public PageRect_ {
	public:
		PageRect() { top = left = bottom = right = 0;}
		PageRect(PageCoord leftIn, PageCoord topIn, PageCoord rightIn, PageCoord bottomIn) { top = topIn; left = leftIn; right = rightIn; bottom = bottomIn; }

		PageRect&	operator=(const PageRect& r)  { top = r.top; left = r.left; bottom = r.bottom; right = r.right; return *this; }

		const PageCoord Top()    const { return top;    }   
		const PageCoord Left()   const { return left;   } 
		const PageCoord Bottom() const { return bottom; } 
		const PageCoord Right()  const { return right;  }   

		void SetTop   (PageCoord t)    { this->top    = t; }
		void SetLeft  (PageCoord l)    { this->left   = l; }        
		void SetBottom(PageCoord b)    { this->bottom = b; }     
		void SetRight (PageCoord r)    { this->right  = r; }           

		Bool8 operator==(const PageRect& r) const {
				return (top == r.top && left == r.left && bottom == r.bottom && top == r.top);
		}

		Bool8 operator!=(const PageRect& r) const { return !(*this == r); }
		
		inline PagePt TopLeft()     const { return PagePt(left, top); }
		inline PagePt BottomRight() const { return PagePt(right, bottom); }
			
		PageCoord Width()  const { return right - left; }
		PageCoord Height() const { return bottom - top; }
		PagePt    Center() const { return PagePt((left + right) / 2, (bottom + top) / 2); }
		
		Bool8 IsEmpty() const { return top >= bottom || left >= right; }  // Note > OR equal for PageRect. WorldRects are different.
		Bool8 IsNotEmpty() const { return !IsEmpty(); }

		void MakeEmpty() { top = bottom = left = right = 0; }          // Note just 0,0,0,0 for now.
		
		void Set(PageCoord l, PageCoord t, PageCoord r, PageCoord b) { left = l; top = t; right = r; bottom = b; }
		
		Bool8 Intersect(const PageRect& src2, PageRect& dest) const;

		void Inset(PageCoord dx, PageCoord dy)  { left += dx; right -= dx; top += dy; bottom -= dy; }
		void Offset(PageCoord dx, PageCoord dy) { left += dx; right += dx; top += dy; bottom += dy; }
		void Union(const PageRect& src2, PageRect& dest) const { dest.top = top < src2.top ? top : src2.top; 
														dest.bottom = bottom > src2.bottom ? bottom : src2.bottom; 
														dest.left = left < src2.left ? left : src2.left; 
														dest.right = right > src2.right ? right : src2.right; }

	};
	#pragma pack(pop) // END 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)
	//--------------------------------------------------------------------

	//----------------------------------------------------------------------------------------


	typedef Sint32 GSCoord32;

	class GSPoint32 {
	public:
		GSCoord32	x;
		GSCoord32	y;
		
		GSPoint32() : x(0), y(0) {}
		GSPoint32(GSCoord32 inx, GSCoord32 iny) : x(inx), y(iny) {}
		GSPoint32(const GSPoint32& gp) : x(gp.x), y(gp.y) {}
		GSPoint32(const ViewPt& vp) : x(vp.x), y(vp.y) {}

		Bool8 operator==(const GSPoint32& r) const { return (x == r.x && y == r.y); }
		Bool8 operator!=(const GSPoint32& r) const { return !(*this == r); }

		GSPoint32 operator+(const GSPoint32& p) const	{ return GSPoint32(x + p.x, y + p.y); }
		GSPoint32 operator-(const GSPoint32& p) const	{ return GSPoint32(x - p.x, y - p.y); }
		
		void Set(GSCoord32 inx, GSCoord32 iny)	{ x = inx; y = iny; }

		Bool8 ScaleRound(const double f, const GSPoint32* pAboutPt=NULL);
		Bool8 ScaleTrunc(const double f, const GSPoint32* pAboutPt=NULL);
	};

	class GSRect32 {
	public:
		GSCoord32	top;
		GSCoord32	left;
		GSCoord32	bottom;
		GSCoord32	right;

		GSRect32() : top(0), left(0), bottom(0), right(0){}
		GSRect32(GSCoord32 l, GSCoord32 t, GSCoord32 r, GSCoord32 b) : top(t), left(l), bottom(b), right(r) {}
		GSRect32(const GSRect32& gr) : top(gr.top), left(gr.left), bottom(gr.bottom), right(gr.right) {}
		GSRect32(const ViewRect& vr) : top(vr.top), left(vr.left), bottom(vr.bottom), right(vr.right) {}

		Bool8 operator==(const GSRect32& r) const {
				return (top == r.top && left == r.left && bottom == r.bottom && right == r.right);
		}
		Bool8 operator!=(const GSRect32& r) const { return !(*this == r); }

		GSCoord32 Top()    const { return top;    }   
		GSCoord32 Left()   const { return left;   }  
		GSCoord32 Bottom() const { return bottom; } 
		GSCoord32 Right()  const { return right;  }

		GSCoord32 Width() const		{ return right - left; }
		GSCoord32 Height() const	{ return bottom - top; }

		void SetTop   (GSCoord32 topIn)    { top    = topIn;    }  
		void SetLeft  (GSCoord32 leftIn)   { left   = leftIn;   }  
		void SetBottom(GSCoord32 bottomIn) { bottom = bottomIn; } 
		void SetRight (GSCoord32 rightIn)  { right  = rightIn;  }  

		void Set(GSCoord32 l, GSCoord32 t, GSCoord32 r, GSCoord32 b) { left = l; top = t; right = r; bottom = b; }

		Bool8 IsEmpty() const { return top >= bottom || left >= right; }  // Note > OR equal for GSRect32. WorldRects are different.
		Bool8 IsNotEmpty() const { return !IsEmpty(); }

		void MakeEmpty() { top = bottom = left = right = 0; }

		Boolean		Intersects(const GSRect32& r) const;
		void		Intersect(const GSRect32& r);
		GSRect32	Intersection(const GSRect32& r) const;

		void Inset(GSCoord32 dx, GSCoord32 dy)  { left += dx; right -= dx; top += dy; bottom -= dy; }
		void Offset(GSCoord32 dx, GSCoord32 dy) { left += dx; right += dx; top += dy; bottom += dy; }
		void Union(const GSRect32& src2, GSRect32& dest) const { dest.top = top < src2.top ? top : src2.top; 
														dest.bottom = bottom > src2.bottom ? bottom : src2.bottom; 
														dest.left = left < src2.left ? left : src2.left; 
														dest.right = right > src2.right ? right : src2.right; }


		Bool8 ScaleRound(const double f, const GSPoint32* pAboutPt=NULL);
		Bool8 ScaleTrunc(const double f, const GSPoint32* pAboutPt=NULL);
	};
	
	inline GSCoord32 Dx(const GSRect32& rc) { return rc.Width(); }
	inline GSCoord32 Dy(const GSRect32& rc) { return rc.Height(); }

	ViewRect	GSRect32ToViewRect(const GSRect32& inRect32);
	ViewPt		GSPoint32ToViewPt(const GSPoint32& inPoint32);

	typedef Uint16 ColorCoord;

	//
	// Cross platform color
	// Even though the members are 16 bits, usually only 8 bits of color resolution are used. -DLD 2/22/99
	//
	//--------------------------------------------------------------------
	#pragma pack(push, 2) // BEGIN 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)

	struct GSColor {
		ColorCoord	red;
		ColorCoord	green;
		ColorCoord	blue;

		void Set16(ColorCoord r, ColorCoord g, ColorCoord b)			{ red = r; green = g; blue = b; }
		void Get16(ColorCoord& r, ColorCoord& g, ColorCoord& b) const	{ r = red; g = green; b = blue; }
			
		void Set8(Uint8 r, Uint8 g, Uint8 b)				{ red = (((ColorCoord)r)<<8) + r; green	= (((ColorCoord)g)<<8) + g;	blue = (((ColorCoord)b)<<8) + b; }
		void Get8(Uint8& r, Uint8& g, Uint8& b) const		{ r = (Uint8)(red>>8); g = (Uint8)(green>>8); b = (Uint8)(blue>>8); }
			
		Bool8 operator==(const GSColor& color) const {
			return (color.red == red && color.green == green && color.blue == blue);
		}
		Bool8 operator!=(const GSColor& color) const {
			return !((*this) == color);
		}

		void AssignFrom(const GSColor& src) {
			red = src.red;
			green = src.green;
			blue = src.blue;
		}
	};

	#pragma pack(pop) // END 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)
	//--------------------------------------------------------------------

	typedef struct GSColor GSColor, *PGSColor;
	typedef GSColor GSColorTable[256];

	//--------------------------------------------------------------------
	// TGSColorV2 begin
	//--------------------------------------------------------------------
	typedef float THueColorComponent;
	const THueColorComponent kUndefinedHueColorComponent	= -1.0;		// For pure grays, Hue will be Undefined.  This is ok.
	const THueColorComponent kMinHueColorComponent			= 0.0;		// Hue >= Min
	const THueColorComponent kMaxHueColorComponent			= 360.0;	// Hue < Max, (note Hue != Max)

	typedef float TUnitColorComponent;
	const TUnitColorComponent kMinUnitColorComponent		= 0.0;
	const TUnitColorComponent kMaxUnitColorComponent		= 1.0;

	typedef float TColorShadeFactor;
	const TColorShadeFactor kMinColorShadeFactor			= -1.0;
	const TColorShadeFactor kMaxColorShadeFactor			= 1.0;


	//----------------------------------------------------------------------------
	class TGSColorV2
	{
	public:
		enum TColorType {
			eCMYK,
			eRGB,
			eHSV,
			eRGB16,
			eRGB8
		};
		
		TGSColorV2( void )								{ /*k=0 just to initialize all float values*/fCMYK.k = 0; this->SetRGB( 0, 0, 0 ); }
		TGSColorV2(const TGSColorV2& in)				{ *this = in; }

		TGSColorV2(TColorType inType, float c1, float c2, float c3, float c4=0);
		TGSColorV2(TUnitColorComponent c, TUnitColorComponent m, TUnitColorComponent y, TUnitColorComponent k)	{ this->SetCMYK(c,m,y,k); }
		TGSColorV2(TUnitColorComponent r, TUnitColorComponent g, TUnitColorComponent b)							{ this->SetRGB(r,g,b); }
		TGSColorV2(Uint16 r, Uint16 g, Uint16 b)		{ this->SetRGB16(r,g,b); }
		TGSColorV2(Uint8 r, Uint8 g, Uint8 b)			{ this->SetRGB8(r,g,b); }
		TGSColorV2(const GSColor& in)					{ this->SetGSColor(in); }

		TGSColorV2(TColorType inNewType, const TGSColorV2& inColor)	{ this->Set(inNewType, inColor); }
		
		TGSColorV2 &operator = ( const TGSColorV2 &inCopy );
		
		TColorType	GetType() const						{ return fType; }

		void GetCMYK(TUnitColorComponent& c, TUnitColorComponent& m, TUnitColorComponent& y, TUnitColorComponent& k) const;
		void GetHSV(THueColorComponent& h, TUnitColorComponent& s, TUnitColorComponent& v) const;
		void GetRGB(TUnitColorComponent& r, TUnitColorComponent& g, TUnitColorComponent& b) const;
		void GetRGB16(Uint16& r, Uint16& g, Uint16& b) const;
		void GetRGB8(Uint8& r, Uint8& g, Uint8& b) const;
		void GetGSColor(GSColor& out) const;
		GSColor GetGSColor() const						{ GSColor theColor; this->GetGSColor(theColor); return theColor; }

		void SetCMYK(TUnitColorComponent c, TUnitColorComponent m, TUnitColorComponent y, TUnitColorComponent k);
		void SetHSV(THueColorComponent h, TUnitColorComponent s, TUnitColorComponent v);
		void SetRGB(TUnitColorComponent r, TUnitColorComponent g, TUnitColorComponent b);
		void SetRGB16(Uint16 r, Uint16 g, Uint16 b)		{ fType = eRGB16;	fRGB16.r = r;	fRGB16.g = g;	fRGB16.b = b; }
		void SetRGB8(Uint8 r, Uint8 g, Uint8 b)			{ fType = eRGB8;	fRGB8.r = r;	fRGB8.g = g;	fRGB8.b = b; }
		void SetGSColor(const GSColor& in);
		void Set(TColorType& inNewType, const TGSColorV2& inColor);
		void ConvertTo(TColorType inNewType)			{ if (inNewType != fType)	this->Set(inNewType, *this); }
		
		void BlendAlphaWithColor( OpacityRef inOpacity, TGSColorV2 color );
		
		float Compare(const TGSColorV2& right, TGSColorV2::TColorType inCompareType, float epsilon=0) const;
		bool LessThan(const TGSColorV2& right, TGSColorV2::TColorType inCompareType, float epsilon=0) const;
		bool EqualTo(const TGSColorV2& right, TGSColorV2::TColorType inCompareType, float epsilon=0) const;
		double DistanceSquared(const TGSColorV2& right, TGSColorV2::TColorType inCompareType) const;

		bool operator<(const TGSColorV2& right) const;
		bool operator==(const TGSColorV2& right) const;
		bool operator!=(const TGSColorV2& right) const	{ return !(*this == right); }

		// statics
		static void CMYKToRGB(TUnitColorComponent c, TUnitColorComponent m, TUnitColorComponent y, TUnitColorComponent k,
								TUnitColorComponent& r, TUnitColorComponent& g, TUnitColorComponent& b);
		static void RGBToCMYK(TUnitColorComponent r, TUnitColorComponent g, TUnitColorComponent b,
								TUnitColorComponent& c, TUnitColorComponent& m, TUnitColorComponent& y, TUnitColorComponent& k);

		static void HSVToRGB(THueColorComponent h, TUnitColorComponent s, TUnitColorComponent v,
								TUnitColorComponent& r, TUnitColorComponent& g, TUnitColorComponent& b);
		static void RGBToHSV(TUnitColorComponent r, TUnitColorComponent g, TUnitColorComponent b,
								THueColorComponent& h, TUnitColorComponent& s, TUnitColorComponent& v);

		static THueColorComponent	PinHueComponentInRange(THueColorComponent c, Bool8 bAssert = true);
		static TUnitColorComponent	PinUnitComponentInRange(TUnitColorComponent c, Bool8 bAssert = true);
		static Uint16				PinGSColorComponentInRange(Uint16 c, Bool8 bAssert = true);
		static TColorShadeFactor	PinShadeFactorInRange(TColorShadeFactor inShadeFactor);
		static TUnitColorComponent	ShadeRGBComponent(TUnitColorComponent inComp, TColorShadeFactor inShadeFactor);
		static void					ShadeColor(const TGSColorV2& in, TColorShadeFactor inShadeFactor, TGSColorV2& out);

	protected:
		TColorType	fType;
		
		union {
			struct {
				TUnitColorComponent	c, m, y, k;
			} fCMYK;
			struct {
				THueColorComponent	h;
				TUnitColorComponent s, v;
			} fHSV;
			struct {
				TUnitColorComponent	r, g, b;
			} fRGB;
			struct {
				Uint16	r, g, b;
			} fRGB16;
			struct {
				Uint8	r, g, b;
			} fRGB8;
		};
	};
	//--------------------------------------------------------------------
	// TGSColorV2 end
	//--------------------------------------------------------------------

	// The maximum number of poly vertices allowed in a GSPoly
	const int kMaxPolyVertices = (32767 - sizeof(Sint16) - sizeof(ViewRect))/sizeof(ViewPt);

	struct GSPoly {
	// Cross platform polygon
		Sint16		polySize;
		ViewRect	polyBBox;
		ViewPt		polyPoints[1];

		Sint16	GetNumPts() const;
		void	CalcBBox();

		static Sint16 CalcSize(Sint16 numPts);
	};
	typedef struct GSPoly GSPoly, *PGSPoly, **PPGSPoly;


	// XPoly is the floating point version of GSPoly
	// The maximum number of poly vertices allowed in an XPoly
	const int kMaxXPolyVertices = (2147483647L - sizeof(Sint32) - sizeof(XViewRect))/sizeof(XViewPt);

	struct XPoly {
	// Cross platform polygon
		Sint32		polySize;
		XViewRect	polyBBox;
		XViewPt		polyPoints[1];
		};
	typedef struct XPoly XPoly, *PXPoly, **PPXPoly;


	//----------------------------------------------------------------------------
	// class ViewRectVerts
	//----------------------------------------------------------------------------
	class ViewRectVerts {
	public:
		ViewRectVerts()
		{
			(this->GetPolyPtr())->polySize = sizeof(GSPoly) + sizeof(ViewPt)*4;
		}

		const ViewPt& operator[](int i) const
		{
			return (this->GetPolyPtr())->polyPoints[i]; // ASSERTN(i>=0, i<=3);
		}

		ViewPt& operator[](int i)
		{
			return (this->GetPolyPtr())->polyPoints[i]; // ASSERTN(i>=0, i<=3);
		}

		// note that the verts are clockwise in order
		const ViewPt& TopLeft(void)		const	{ return (this->GetPolyPtr())->polyPoints[0]; }
		const ViewPt& TopRight(void)	const	{ return (this->GetPolyPtr())->polyPoints[1]; }
		const ViewPt& BottomRight(void)	const	{ return (this->GetPolyPtr())->polyPoints[2]; }
		const ViewPt& BottomLeft(void)	const	{ return (this->GetPolyPtr())->polyPoints[3]; }

		ViewPt&   SetTopLeft()					{ return (this->GetPolyPtr())->polyPoints[0]; }
		ViewPt&   SetTopRight()					{ return (this->GetPolyPtr())->polyPoints[1]; }
		ViewPt&   SetBottomRight()				{ return (this->GetPolyPtr())->polyPoints[2]; }
		ViewPt&   SetBottomLeft()				{ return (this->GetPolyPtr())->polyPoints[3]; }

		void GetBoundingBox(ViewRect& outBounds) const;
		Boolean	IsNotRotatedMuch() const;

		const PGSPoly GetPoly() const
		{
			// make sure we close the poly
			(this->GetPolyPtr())->polyPoints[4] = (this->GetPolyPtr())->polyPoints[0];
			
			// Mac needs poly bbox to be set correctly
			this->GetBoundingBox((this->GetPolyPtr())->polyBBox);
			
			return this->GetPolyPtr();
		}

	protected:
		// The poly contains a point for each corner of the rectangle
		// and an extra one to close the poly.
		char buf[sizeof(GSPoly) + sizeof(ViewPt)*4];

	//	PGSPoly GetPolyPtr() { return (PGSPoly)&buf; }
		const PGSPoly GetPolyPtr() const { return (PGSPoly)&buf; }
	};

	//----------------------------------------------------------------------------
	// class GSRect32Verts
	//----------------------------------------------------------------------------
	class GSRect32Verts {
	public:
		GSRect32Verts() {}
		GSRect32Verts(const GSRect32& inRect);
		GSRect32Verts(const ViewRectVerts& inVrv);
		GSRect32Verts(const GSRect32Verts& inVrv);

		const GSPoint32& operator[](int i) const	{ return fVerts[i < 0 ? 0 : (i > 3 ? 3 : i)]; }
		GSPoint32& operator[](int i)				{ return fVerts[i < 0 ? 0 : (i > 3 ? 3 : i)]; }

		// note that the verts are clockwise in order
		const GSPoint32& TopLeft(void)		const	{ return fVerts[0]; }
		const GSPoint32& TopRight(void)	const		{ return fVerts[1]; }
		const GSPoint32& BottomRight(void)	const	{ return fVerts[2]; }
		const GSPoint32& BottomLeft(void)	const	{ return fVerts[3]; }

		GSPoint32&   SetTopLeft()					{ return fVerts[0]; }
		GSPoint32&   SetTopRight()					{ return fVerts[1]; }
		GSPoint32&   SetBottomRight()				{ return fVerts[2]; }
		GSPoint32&   SetBottomLeft()				{ return fVerts[3]; }

		void	GetBoundingBox(GSRect32& outBounds) const;
		Boolean	IsNotRotatedMuch() const;

		void ScaleRound(const double f, const GSPoint32* pAboutPt=NULL);
		void ScaleTrunc(const double f, const GSPoint32* pAboutPt=NULL);

	protected:
		GSPoint32	fVerts[4];
	};

	ViewRectVerts GSRect32VertsToViewRectVerts(const GSRect32Verts& inVrv32);

	//
	//	TBitMap - Replacement for QuickDraw BitMap structure
	//
	//--------------------------------------------------------------------
	#pragma pack(push, 2) // BEGIN 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)

	struct TBitMap {
		char *		baseAddr;
		short		rowBytes;
		ViewRect	bounds;
	};
	typedef struct TBitMap TBitMap, *TBitMapPtr;
	
	#pragma pack(pop) // END 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)
	//--------------------------------------------------------------------

	//
	//	TRGBColor - Replacement for QuickDraw RGBColor structure
	//
	//--------------------------------------------------------------------
	#pragma pack(push, 2) // BEGIN 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)

	struct TRGBColor {
		unsigned short red;
		unsigned short green; 
		unsigned short blue;
	};
	typedef struct TRGBColor TRGBColor;
	
	#pragma pack(pop) // END 2 BYTE STRUCTURE ALIGNMENT (.vwx file format)
	//--------------------------------------------------------------------

	//***************  Cross Platform Font Geometry stuff  ***************

	// The number of characters allowed in a font name
	const Uint8 kMaxFontNameSize = 64;

	// Don't change the ordering.  Mappings rely on this order.
	enum EFontFamily
	{
		kNoFamily,	
		kRoman,		//i.e. Times New Roman
		kSwiss,		//i.e. Arial
		kModern,	//i.e. Courier New
		kScript,	//i.e. Cursive
		kDecor,		//i.e. Old English
		kTech,		//i.e. Symbol
		kBidi		//i.e. Miriam
	};

	// Don't change the order of these, the mappinG in DrwPadWin.cpp
	// relies on this order!
	enum EAlignment
	{
		kAlignTextRight		= 0,
		kAlignTextLeft		= 1,
		kAlignTextCenter	= 2,
		kJustifiedText		= 3
	};

	// The following three enums are used in calls to SetFontStyle
	// Don't change the ordering!!!!!
	enum EBold
	{
		kBoldOff			= 0,
		kBoldOn				= 1,
		kBoldDontCare		= 2
	};

	enum EItalic
	{
		kItalicOff			= 0,
		kItalicOn			= 1,
		kItalicDontCare		= 2
	};

	enum EUnderline
	{
		kUnderlineOff		= 0,
		kUnderlineOn		= 1,
		kUnderlineDontCare	= 2
	};

	// Mac only. Windows ignores.
	enum EOutline
	{
		kOutlineOff			= 0,
		kOutlineOn			= 1,
		kOutlineDontCare	= 2
	};

	// Mac only. Windows ignores.
	enum EShadow					
	{
		kShadowOff			= 0,
		kShadowOn			= 1,
		kShadowDontCare		= 2
	};

	// Mac only, text from other apps. Windows ignores.
	enum ECondense		
	{
		kCondenseOff		= 0,
		kCondenseOn			= 1,
		kCondenseDontCare	= 2
	};

	// Mac only, text from other apps. Windows ignores.
	enum EExtend
	{
		kExtendOff			= 0,
		kExtendOn			= 1,
		kExtendDontCare		= 2
	};

	//The following type is used to specify the rotation angle of any
	//integral rotation (90, 180, 270), only used for non true type text.
	enum ETextTransform {
		k90DegreesClockWise,
		k180DegreesClockWise,
		k270DegreesClockWise,
		kXAxisMirror
	};

	struct DPFont {
	// Cross platform font structure
		char		nameStr[kMaxFontNameSize];	// Null terminated
		EFontFamily	family;						// This is not the same as the Mac "family" of GetFNum().
		Uint32		ptSize; 
		unsigned	italic:		1;
		unsigned	bold:		1;
		unsigned	underline:	1;
		unsigned	outline:	1;		// Mac only.
		unsigned	shadow:		1;		// Mac only.
		unsigned	condense:	1;		// Mac only, text pasted from other apps.
		unsigned	extend:		1;		// Mac only, text pasted from other apps.
		unsigned	_pad:		1;
	};
	typedef struct DPFont DPFont, *PDPFont;

	struct DPFontMetrics {
	// Cross platform structure for font metrics
		Sint32	ascent;
		Sint32	descent;
		Sint32	maxWidth;
		Sint32	leading;
		//The following is only for windows.  RWM
		Bool8	vectorFont;
		Sint32	charSet; //This is the character set as defined by windows
	};


	typedef Uint32 GSPolyRef;
			
#endif //__cplusplus  // ??
#endif //_GS_GEOMETRY_
