// Graphics Importer and Exporter Samples
// This example uses graphics importers to draw an image
// then demonstrates how to perform scaling, rotation and perspective
// manipulation using matrix operations
// Originally written by Sam Bushell for QuickTime "Live" '99
// WWDC 2000 Introduction to QuickTime

#include "MacShell.h"

void ScaleAndRotate( void )
{
	OSErr err = noErr;
	Handle hOpenTypeList = NewHandle(0);
	long 	numTypes = 0;
	FSSpec	theFSSpec;
	GraphicsImportComponent importer = 0;
	Rect naturalBounds, windowBounds, scaledBounds;
	WindowPtr window = NULL;
	MatrixRecord matrix;
	Fixed naturalWidth, naturalHeight;
	FixedPoint fromQuad[4], toQuad[4];

	BuildGraphicsImporterValidFileTypes( hOpenTypeList, &numTypes );
	HLock( hOpenTypeList );
	
	err = GetOneFileWithPreview(numTypes, (OSTypePtr)*hOpenTypeList, &theFSSpec, NULL);
	DisposeHandle( hOpenTypeList );
	if ( err ) return;
	
	// locate and open a graphics importer component
	err = GetGraphicsImporterForFile( &theFSSpec, &importer );
	
	// get the native size of the image associated with the importer
	err = GraphicsImportGetNaturalBounds( importer, &naturalBounds );
	
	windowBounds = naturalBounds;
	OffsetRect( &windowBounds, 10, 45 );
	window = NewCWindow( NULL, &windowBounds, "\pScale and Rotate ", true, documentProc, (WindowPtr)-1, true, 0);
	
	// set the graphics port for drawing
	err = GraphicsImportSetGWorld( importer, GetWindowPort( window ), NULL );
	
	// draw the image
	err = GraphicsImportDraw( importer );
	
	pause();
	
	// scale the image by a factor of 2x.  
	// the top-left coordinate of an image's natural bounds is always (0,0).
	scaledBounds = naturalBounds;
	scaledBounds.right = scaledBounds.right * 2;
	scaledBounds.bottom = scaledBounds.bottom * 2;
	
	// define the rectangle in which to draw an image
	err = GraphicsImportSetBoundsRect( importer,		// importer instance
									   &scaledBounds ); // desired bounds
	
	// resize the window to fit, and redraw.
	SizeWindow( window, scaledBounds.right, scaledBounds.bottom, false );
	err = GraphicsImportDraw( importer );
	
	pause();
	
	// rotate the image ninety degrees clockwise
	// set the contents of a matrix so that it performs no transformation
	SetIdentityMatrix( &matrix );
	
	// modify the contents of a matrix so that it defines a rotation operation
	// 90 degrees to the right - anchor at 0.0 top-left 
	RotateMatrix( &matrix,			// pointer to the matrix structure
				  Long2Fix( 90 ),	// the number of degrees of rotation NOTE: THIS IS A FIXED VALUE
				  0,				// x coordinate of anchor point
				  0 );				// y coordinate of anchor point
	
		  
	// we need to return the top-left corner of the rotated image back to it's
	// origin, so add a translation value to a specified matrix 
	TranslateMatrix( &matrix,							// pointer to the matrix structure
					 Long2Fix( naturalBounds.bottom ),	// deltaH - value added to the x coordinate NOTE: FIXED VALUES
					 0 );								// deltaV - value added to the y coordinate 
	
	// set the transformation matrix to use for drawing an image			 
	err = GraphicsImportSetMatrix( importer, &matrix );
	
	// resize the window to fit, and redraw.
	// get the new bounds rect, size the window then draw
	err = GraphicsImportGetBoundsRect( importer, &scaledBounds );
	SizeWindow( window, scaledBounds.right, scaledBounds.bottom, false );
	err = GraphicsImportDraw( importer );
	
	pause();
	
	// give the image some hefty perspective.
	// set up two quadrilateral coordinates and create a translation matrix
	// from one to the other using QuadToQuadMatrix()
	// QuadToQuadMatrix was added in QuickTime 4.0.
	naturalWidth = Long2Fix( naturalBounds.right );
	naturalHeight = Long2Fix( naturalBounds.bottom );
	fromQuad[0].x = 0;
	fromQuad[0].y = 0;
	fromQuad[1].x = naturalWidth;
	fromQuad[1].y = 0;
	fromQuad[2].x = naturalWidth;
	fromQuad[2].y = naturalHeight;
	fromQuad[3].x = 0;
	fromQuad[3].y = naturalHeight;
	toQuad[0].x = naturalWidth/8;
	toQuad[0].y = naturalHeight/4;
	toQuad[1].x = naturalWidth*9/8;
	toQuad[1].y = 0;
	toQuad[2].x = naturalWidth;
	toQuad[2].y = naturalHeight*6/4;
	toQuad[3].x = 0;
	toQuad[3].y = naturalHeight;
	SetIdentityMatrix( &matrix );
	QuadToQuadMatrix( (Fixed *)fromQuad, (Fixed *)toQuad, &matrix );
	err = GraphicsImportSetMatrix( importer, &matrix );
	
	// resize the window to fit, and redraw
	// get the new bounds rect, size the window then draw
	err = GraphicsImportGetBoundsRect( importer, &scaledBounds );
	SizeWindow( window, scaledBounds.right, scaledBounds.bottom, false );
	SetPortWindowPort( window );
	EraseRect( &scaledBounds );
	err = GraphicsImportDraw( importer );

	CloseComponent( importer );
}
