/* TieTrackPixel.c */
/*****************************************************************************/
/*                                                                           */
/*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
/*    Copyright (C) 1994  Thomas R. Lawrence                                 */
/*                                                                           */
/*    This program is free software; you can redistribute it and/or modify   */
/*    it under the terms of the GNU General Public License as published by   */
/*    the Free Software Foundation; either version 2 of the License, or      */
/*    (at your option) any later version.                                    */
/*                                                                           */
/*    This program is distributed in the hope that it will be useful,        */
/*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
/*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
/*    GNU General Public License for more details.                           */
/*                                                                           */
/*    You should have received a copy of the GNU General Public License      */
/*    along with this program; if not, write to the Free Software            */
/*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
/*                                                                           */
/*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
/*                                                                           */
/*****************************************************************************/

#include "MiscInfo.h"
#include "Audit.h"
#include "Debug.h"
#include "Definitions.h"

#include "TieTrackPixel.h"
#include "Array.h"
#include "Memory.h"


typedef struct
	{
		long						SourceHorizontalPixel;
		long						SourceVerticalPixel;
		long						DestinationHorizontalPixel;
		long						DestinationVerticalPixel;
	} TiePixelRec;


struct TieTrackPixelRec
	{
		ArrayRec*				ListOfTieThangs; /* of TiePixelRec's */
	};


/* create a new tie pixel tracking object */
TieTrackPixelRec*		NewTieTrackPixel(void)
	{
		TieTrackPixelRec*	TieTrackPixel;

		TieTrackPixel = (TieTrackPixelRec*)AllocPtrCanFail(sizeof(TieTrackPixelRec),
			"TieTrackPixelRec");
		if (TieTrackPixel == NIL)
			{
			 FailurePoint1:
				return NIL;
			}
		TieTrackPixel->ListOfTieThangs = NewArray();
		if (TieTrackPixel->ListOfTieThangs == NIL)
			{
			 FailurePoint2:
				ReleasePtr((char*)TieTrackPixel);
				goto FailurePoint1;
			}
		return TieTrackPixel;
	}


/* delete a tie pixel tracking object */
void								DisposeTieTrackPixel(TieTrackPixelRec* TieTrackPixel)
	{
		long							Limit;
		long							Scan;

		CheckPtrExistence(TieTrackPixel);
		Limit = ArrayGetLength(TieTrackPixel->ListOfTieThangs);
		for (Scan = 0; Scan < Limit; Scan += 1)
			{
				TiePixelRec*			PixelRec;

				PixelRec = (TiePixelRec*)ArrayGetElement(TieTrackPixel->ListOfTieThangs,Scan);
				ReleasePtr((char*)PixelRec);
			}
		DisposeArray(TieTrackPixel->ListOfTieThangs);
		ReleasePtr((char*)TieTrackPixel);
	}


/* add a new point pair to the tracking thang */
MyBoolean						AddTieTrackPixelElement(TieTrackPixelRec* TieTrackPixel,
											long StartX, long StartY, long EndX, long EndY)
	{
		TiePixelRec*			PixelRec;

		CheckPtrExistence(TieTrackPixel);
		PixelRec = (TiePixelRec*)AllocPtrCanFail(sizeof(TiePixelRec),"TiePixelRec");
		if (PixelRec == NIL)
			{
			 FailurePoint1:
				return False;
			}
		PixelRec->SourceHorizontalPixel = StartX;
		PixelRec->SourceVerticalPixel = StartY;
		PixelRec->DestinationHorizontalPixel = EndX;
		PixelRec->DestinationVerticalPixel = EndY;
		if (!ArrayAppendElement(TieTrackPixel->ListOfTieThangs,PixelRec))
			{
			 FailurePoint2:
				ReleasePtr((char*)PixelRec);
				goto FailurePoint1;
			}
		return True;
	}


struct TieIntersectListRec
	{
		ArrayRec*				ListOfOnes;
	};


/* obtain an array of all ties which are in some manner intersecting the */
/* specified X interval */
TieIntersectListRec*	GetTieTrackPixelIntersecting(TieTrackPixelRec* TieTrackPixel,
											long XLocStart, long XLocWidth)
	{
		long							ItemCount;
		long							Scan;
		long							Limit;
		TieIntersectListRec*	List;

		CheckPtrExistence(TieTrackPixel);
		List = (TieIntersectListRec*)AllocPtrCanFail(sizeof(TieIntersectListRec),
			"TieIntersectListRec");
		if (List == NIL)
			{
			 FailurePoint1:
				return NIL;
			}
		Limit = ArrayGetLength(TieTrackPixel->ListOfTieThangs);

		/* find out how many elements need to be allocated */
		ItemCount = 0;
		for (Scan = 0; Scan < Limit; Scan += 1)
			{
				TiePixelRec*			PixelRec;

				PixelRec = (TiePixelRec*)ArrayGetElement(TieTrackPixel->ListOfTieThangs,Scan);
				if ((PixelRec->SourceHorizontalPixel < XLocStart + XLocWidth)
					&& (PixelRec->DestinationHorizontalPixel > XLocStart))
					{
						/* some part of the tie-line is visible on the screen */
						ItemCount += 1;
					}
			}

		/* allocate the array */
		List->ListOfOnes = NewArrayReserveSpace(ItemCount);
		if (List->ListOfOnes == NIL)
			{
			 FailurePoint2:
				ReleasePtr((char*)List);
				goto FailurePoint1;
			}

		/* generate the intersection list */
		ItemCount = 0;
		for (Scan = 0; Scan < Limit; Scan += 1)
			{
				TiePixelRec*			PixelRec;

				PixelRec = (TiePixelRec*)ArrayGetElement(TieTrackPixel->ListOfTieThangs,Scan);
				if ((PixelRec->SourceHorizontalPixel < XLocStart + XLocWidth)
					&& (PixelRec->DestinationHorizontalPixel > XLocStart))
					{
						ArrayAppendElement(List->ListOfOnes,PixelRec);
					}
			}

		return List;
	}


/* dispose of the tie intersection list */
void								DisposeTieTrackIntersectList(TieIntersectListRec* List)
	{
		CheckPtrExistence(List);
		/* DON'T delete the elements of the list */
		DisposeArray(List->ListOfOnes);
		ReleasePtr((char*)List);
	}


/* find out how many elements there are in the intersection list */
long								GetTieTrackIntersectListLength(TieIntersectListRec* List)
	{
		CheckPtrExistence(List);
		return ArrayGetLength(List->ListOfOnes);
	}


/* get the drawing information about a particular tie thang */
void								GetTieTrackIntersectElement(TieIntersectListRec* List, long Index,
											long* StartX, long* StartY, long* EndX, long* EndY)
	{
		TiePixelRec*			PixelRec;

		CheckPtrExistence(List);
		PixelRec = (TiePixelRec*)ArrayGetElement(List->ListOfOnes,Index);
		*StartX = PixelRec->SourceHorizontalPixel;
		*StartY = PixelRec->SourceVerticalPixel;
		*EndX = PixelRec->DestinationHorizontalPixel;
		*EndY = PixelRec->DestinationVerticalPixel;
	}
