/*
	File:		AltPoly.h

	Contains:	OpenDoc polygon: optional C++ savvy classes

	Written by:	Jens Alfke

	Copyright:	c 1993 by Apple Computer, Inc., all rights reserved.

	Change History (most recent first):

		 <1>	10/24/94	jpa		first checked in
		 <3>	 9/29/94	RA		1189812: Mods for 68K build.
		 <2>	 8/17/94	jpa		Updated the very-obsolete Theory Of
									Operation.
		 <1>	 6/15/94	jpa		first checked in
		----------------------------Checked into ODSOM project
		 <3>	 5/27/94	jpa		Removed unimplemented methods (GetVertex
									etc.) in ODPolygon [1160489]
		 <2>	 4/13/94	T€		jpa: Added PolyEdgeIterator from
									now-obsolete PolyIter.h. (1145831)
		 <1>	 2/17/94	JA		first checked in
		----------------------------Rename AltPoly, move to TestParts since this
									is not a part of the public API.
		 <6>	 2/16/94	JA		Stop including Point.h.
		 <5>	  2/8/94	JA		Include <FixMath.h> before GX header to
									avoid conflicts.
		 <4>	  2/7/94	JA		Only declare Mac-specific methods if on Mac
									platform.
		 <3>	  2/3/94	JA		Tiger Team Makeover!
		 <2>	 1/31/94	JA		Added Contains and AsQDRegion and improved
									New methods.
		 <1>	11/29/93	JA		first checked in
		----------------------------Moved from Utilities to Imaging project
		 <4>	11/24/93	VL		Rolled back changes as ASLM build breaks
									the THINK build.
		 <3>	11/23/93	VL		Made this work with ASLM.
		 <2>	11/23/93	VL		Added ASLM string.
		 <1>	11/23/93	JA		first checked in

	To Do:
	
	
	Theory of Operation:
	
		This is an alternate definition of ODPolygon and ODContour. The data format is
		identical, but the structs defined here have a lot of useful methods including
		constructors, accessors and conversion operators.
		
		To use these instead of the regular structs defined in Polygon.h, just include
		this header file _before_ Polygon.h. An easy way to do this is to include it
		first.
		
		QuickDraw GX users take note:
		ODContour is identical in data format to a gxPolygon.
		ODPolygonData (the data stored inside an ODPolygon) is identical in data
			format to a gxPolygons <sic>.
		See <graphics types.h>.
	
		** The way things are done has changed since A6. SOM wants all variable-sized
		structures to adhere to a common data forma, where a small struct points to
		the data and stores its size. This is so DSOM can tell how to copy the data
		across an address-space boundary. The ODPolygon structure has most of the same
		methods as before, but you can now create them directly. However, to get the
		actual polygon data you'll need to call the GetData method. **
*/


#ifndef _ALTPOLY_
#define _ALTPOLY_

#ifdef SOM_Module_OpenDoc_Polygon_defined
	#error "Must include AltPoly.h *before* Polygon.xh!"
#else
	/* Make sure Polygon.xh does NOT get included later! */
	#define SOM_Module_OpenDoc_Polygon_defined 2
#endif

#ifndef _ODTYPES_
#include "ODTypes.h"
#endif

#include <stddef.h>					// for size_t

#if _PLATFORM_MACINTOSH_
	#ifndef __QUICKDRAW__
//bgn	#include <QuickDraw.h>				// for Region and Polygon types
	#endif
	#ifndef __FIXMATH__
//bgn	#include <FixMath.h>				// Must include before GX headers...
	#endif
	#ifndef graphicsTypesIncludes
//bgn	#include "graphics types.h"			// for gxShape type
	#endif
#endif


//==============================================================================
// Classes used in this interface
//==============================================================================

struct ODRect;
class ODStorageUnit;
class ODTransform;

//==============================================================================
// ODContour
//==============================================================================

struct ODContour
{
	public:
	
	ODSLong	nVertices;
	ODPoint	vertex[1];		// Array size is actually nVertices
	
	ODContour* NextContour( )				const	{return (ODContour*)&vertex[nVertices];}
	ODBoolean	IsRectangular( )			const;
	ODBoolean	AsRectangle( ODRect* )		const;
#if _PLATFORM_MACINTOSH_
	PolyHandle	AsQDPolygon( )				const;
	ODBoolean	HasExactRegion( )			const;
#endif
#if PLATFORM_WINDOWS
	Point *AsWinPolygon( )				const;
	ODBoolean	HasExactRegion( )			const;
#endif
	
	ODBoolean	operator== ( const ODContour& )			const;
	ODBoolean	operator!= ( const ODContour &c )			const	{return !(*this==c);}
		// Equality tests not fully robust yet; may generate false negatives.
};

//==============================================================================
// ODPolygonData
//==============================================================================

struct ODPolygonData {
	ODSLong	nContours;						// Number of contours
	ODContour	firstContour;				// Rest of contours follow after first
};

//==============================================================================
// ODPolygon
//==============================================================================

class ODPolygon
{
	public:
	
					ODPolygon( );
#if ODDebug
				   ~ODPolygon( );		// Delete myself, but not data
#endif
	
	void			Delete( );			// Delete myself & my data
	void			Clear( );			// Just deletes my data
	
	// ACCESSORS:
	
	ODBoolean		HasData( )						const	{return _length!=0;}
	ODULong			GetDataSize( )					const	{return _length;}
	ODPolygonData*	GetData( )						const	{return _buf;}
	
	void			SetData( const ODPolygonData* );	// Does not copy the data!
	
	ODSLong			GetNContours( )					const;
	ODContour*		FirstContour( );
	const ODContour*FirstContour( )					const;
	
	// GEOMETRY:
	
	void		ComputeBoundingBox( ODRect* )		const;
	ODBoolean	IsRectangular( )					const;
	void		Transform( Environment*, ODTransform* );
	
	ODBoolean	operator== ( const ODPolygon& )		const;
	ODBoolean	operator!= ( const ODPolygon& p )	const	{return !(*this==p);}
		// $$$$$ Equality tests not fully robust yet; may generate false negatives.
	
	ODSLong	Contains( ODPoint )						const;
	ODBoolean	IsEmpty( )							const;
	
	// CONVERSIONS:
	
	ODBoolean	AsRectangle( ODRect* )				const;	// False if nonrectangular
#if _PLATFORM_MACINTOSH_
	ODBoolean	HasExactRegion( )					const;
	RgnHandle	AsQDRegion( )						const;
#endif
#if PLATFORM_WINDOWS
	ODBoolean	HasExactRegion( )					const;
	ODRgnHandle	AsWinRegion( )								const;
#endif
	
	// ALLOCATION:
	
	ODPolygon*	SetNVertices( ODSLong nVertices );
	ODPolygon*	SetVertices( ODSLong nVertices, const ODPoint *vertices );
	ODPolygon*	SetContours( ODSLong nContours, const ODSLong *contourVertices );
	ODPolygon*	SetRect( const ODRect& );

	ODPolygon*	Copy( )								const;
	ODPolygon*	CopyFrom( const ODPolygon& );
#if _PLATFORM_MACINTOSH_
	ODPolygon*	CopyFrom( gxShape );		// Accepts rect, polygon(s), path(s)
#endif
	ODPolygon*	MoveFrom( ODPolygon& );		// Justs adjusts pointers, no copying
	
	// INPUT/OUTPUT:
	
	ODPolygon*	ReadFrom( Environment*, ODStorageUnit* );
	ODPolygon*	WriteTo( Environment*, ODStorageUnit* )		const;
	
	private:
	
	void		Realloc( ODULong dataSize );
	
	// DATA MEMBERS:
	
    unsigned long _maximum;						// Exact same data as an ODByteArray
    unsigned long _length;
    ODPolygonData *_buf;
};


//==============================================================================
// ODTempPolygon
//==============================================================================

/*	ODTempPolygon is a polygon whose destructor disposes of its data.
	This is useful if you have a local variable that's a temporary polygon
	and you want to make sure the data gets disposed. Remember that our
	exception scheme does _not_ call destructors, so you still have to clear
	the polygon manually inside an exception handler.
*/

class ODTempPolygon :public ODPolygon
{
public:
	ODTempPolygon( )	{ }					// Just to avoid warnings
   ~ODTempPolygon( )	{this->Clear();}
};


//==============================================================================
// Polygon Edge Iterator
//==============================================================================


#define kPolyEdgeIteratorID "appl:PolyEdgeIterator$class,1.0.0"

class PolyEdgeIterator {
	public:

	PolyEdgeIterator( const ODPolygon* );
	
	void		CurrentEdge( const ODPoint* &v1, const ODPoint* &v2 );
	const ODContour* CurrentContour( )			{return fCurContour;}
	long		CurrentContourIndex( )			{return fCurContourIndex;}
	long		CurrentEdgeIndex( )				{return fCurVertex;}
	
	ODBoolean	Next( );
	ODBoolean	IsNotComplete( );
	
	private:
	const ODPolygon*	const fPoly;
	const ODContour*		  fCurContour;
	long					  fCurContourIndex;
	long					  fCurVertex;
};


#endif //_ALTPOLY_
