/*	File:		ScaleBlit.cpp	Contains:	fast scaling blitter	Written by:	Strout	Copyright:	Copyright ©1999 the Salk Institute	Change History (most recent first):         <4>    06/17/99    JJS     bug fix in yscale calculation         <3>    06/17/99    JJS     enable non-square scaling         <2>    06/11/99    JJS     revert to CopyBits when scale factor is odd         <1>    06/11/99    JJS     initial checkin to StimulusLib2 project*/#include "ScaleBlit.h"#ifndef __ERRORS__#include <Errors.h>#endifOSErr ScaleBlitOffscreen(PixMapPtr srcpm, PixMapPtr destpm, Rect *srcR, Rect *destR){	// note scale ("scale" means X scale; we'll note Y scale separately below)	long scale = (destR->right-destR->left) / (srcR->right-srcR->left);		// if scaling is odd, then we can't do it -- just use CopyBits	if (scale & 1) {		CopyBits( (BitMapPtr)srcpm, (BitMapPtr)destpm, srcR, destR, srcCopy, NULL);		return noErr;	}			// get destination address	short destRowBytes = destpm->rowBytes & 0x3FFF;	double* destBits = (double*)(destpm->baseAddr);	if (!destBits) return paramErr;	long destRowDoubles = destRowBytes / sizeof(double);	// find how many bytes to iterate over the dest buffer while drawing	long pixelBytes = (srcpm->pixelSize == 16 ? 2 : 4);	long drawBytes = (destR->right - destR->left) * pixelBytes;	long drawDoubles = drawBytes / sizeof(double);	// get source memory address	long *srcBits = (long*)srcpm->baseAddr;	long srcRowLongs = (srcpm->rowBytes & 0x3FFF) / sizeof(long);	// stuff therein	double *destRowStart = destBits;	long *srcRowStart = srcBits;	long yscale = (destR->bottom-destR->top) / (srcR->bottom-srcR->top);	long row = yscale;		// remaining dest rows for this source row	long colDoublesInScale = scale * pixelBytes / sizeof(double);	long col = colDoublesInScale;	int zero = 0;	for (long y=destR->top; y<destR->bottom; y++) {		// copy source row to dest row		long *srcp = srcRowStart;		double *destp = destRowStart;		union {			double pixd;			long pixl[2];		} pixel;		// get initial source pixels (2 at a time, or 8 bytes)		pixel.pixl[0] = pixel.pixl[1] = *srcp;		for (long x=drawDoubles; x; x--) {			// OFI: unroll this loop, to avoid so much branching and checking!			// (But then you must be very careful of boundary conditions.)			if (not ((long)destp & 31)) __dcbz(destp, zero);	// clear cache line			double foo = pixel.pixd;			*destp++ = pixel.pixd;			if ((col=col-1)==0) {				// advance to next source pixel				srcp++;				pixel.pixl[0] = pixel.pixl[1] = *srcp;				col = colDoublesInScale;			}		}		// advance to next dest row		destRowStart += destRowDoubles;		if (--row == 0) {			// advance to next source row			srcRowStart += srcRowLongs;			row = yscale;		}	}	return noErr;}//	Use this function when scaling to the screen:OSErr ScaleBlitToScreen(PixMapPtr srcpm, PixMapPtr destpm, PixMapPtr tempm, 						Rect *srcR, Rect *destR){	ScaleBlitOffscreen( srcpm, tempm, srcR, destR );	CopyBits( (BitMapPtr)tempm, (BitMapPtr)destpm, destR, destR, srcCopy, NULL );	return noErr;}