Test.c

/*
    File:       Test.c
 
    Contains:   This snippet drag races CopyBits (using a mask region) and CopyMask 
                (using a mask BitMap). Which do you think is faster? The results may
                surprise you.
    
    Written by: Tony Myles
 
    Copyright:  Copyright © 1992-1999 by Apple Computer, Inc., All Rights Reserved.
 
                You may incorporate this Apple sample source code into your program(s) without
                restriction. This Apple sample source code has been provided "AS IS" and the
                responsibility for its operation is yours. You are not permitted to redistribute
                this Apple sample source code as "Apple sample source code" after having made
                changes. If you're going to re-distribute the source, we require that you make
                it clear in the source that the code was descended from Apple sample source
                code, but that you've made changes.
 
    Change History (most recent first):
                7/9/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
                
 
*/
#include <QuickDraw.h>
//#include <DebugUtils.h>
#include <Dialogs.h>
//#include <GWorldUtils.h>
#include <TextUtils.h>
#include <Resources.h>
#include "Sample.h"
#include "Test.h"
#include <Sound.h>
 
 
///--------------------------------------------------------------------------------------
//  LetTheGameBegin
///--------------------------------------------------------------------------------------
 
void LetTheGameBegin(DialogPtr srcDialogP)
{
    OSErr err;
    CGrafPtr saveCPort;
    GDHandle saveGDevice;
    PixMapHandle srcPixMap;
    GWorldPtr pictGWorld = NULL, maskGWorld = NULL;
    GrafPtr offScrnPort = NULL;
    RgnHandle maskRgn = NULL;
    Rect srcRect, dstRect, itemRect;
    short frame;
    long ticks;
    Str255 itemStr;
    PixPatHandle pixPatH;
 
    SetCursor(*GetCursor(watchCursor));
 
    GetGWorld(&saveCPort, &saveGDevice);
    SetGWorld((CGrafPtr)srcDialogP, NULL);
 
    itemStr[0] = 0;
    SetDItemText(srcDialogP, kCopyBitsFramesItem, itemStr);
    SetDItemText(srcDialogP, kCopyBitsTicksItem, itemStr);
    SetDItemText(srcDialogP, kCopyBitsFPSItem, itemStr);
    SetDItemText(srcDialogP, kCopyMaskFramesItem, itemStr);
    SetDItemText(srcDialogP, kCopyMaskTicksItem, itemStr);
    SetDItemText(srcDialogP, kCopyMaskFPSItem, itemStr);
 
    GetDItemRect(srcDialogP, kCopyBitsPictItem, &itemRect);
    OffsetRect(&itemRect, -itemRect.left, -itemRect.top);
    itemRect.right += kFrameCount;
 
    err = CreateOptimumGWorld(&pictGWorld, &itemRect);
 
    if (err == noErr)
    {
        SetGWorld(pictGWorld, NULL);
        srcPixMap = GetGWorldPixMap(pictGWorld);
        (void)LockPixels(srcPixMap);
 
        pixPatH = GetPixPat(kPixPatResID);
 
        if (pixPatH != NULL)
        {
            FillCRect(&itemRect, pixPatH);
            DisposePixPat(pixPatH);
        }
 
        err = CreateGWorldFromPictResource(&maskGWorld, kApplePictResID);
    }
 
    if (err == noErr)
    {
        offScrnPort = NULL;
        err = CreateGrafPortFromPictResource(kApplePictResID, &offScrnPort);
    }
 
    if (err == noErr)
    {
        maskRgn = NewRgn();
    
        err = BitMapToRegion(maskRgn, &offScrnPort->portBits);
    }
 
    if (err == noErr)
    {
        GetDItemRect(srcDialogP, kCopyBitsPictItem, &itemRect);
        OffsetRgn(maskRgn, itemRect.left, itemRect.top);
    
        srcRect = itemRect;
        OffsetRect(&srcRect, -srcRect.left, -srcRect.top);
        dstRect = itemRect;
    
        SetGWorld((CGrafPtr)srcDialogP, NULL);
 
        ticks = TickCount();
 
        for (frame = 0; frame < kFrameCount; frame++)
        {
            CopyBits((BitMapPtr)*srcPixMap, &srcDialogP->portBits,
                        &srcRect, &dstRect, srcCopy, maskRgn);
    
            srcRect.left++;
            srcRect.right++;
        }
    
        ticks = TickCount() - ticks;
    
        NumToString(kFrameCount, itemStr);
        SetDItemText(srcDialogP, kCopyBitsFramesItem, itemStr);
        NumToString(ticks, itemStr);
        SetDItemText(srcDialogP, kCopyBitsTicksItem, itemStr);
        NumToString((ticks < 60) ? kFrameCount : kFrameCount / (ticks / 60), itemStr);
        SetDItemText(srcDialogP, kCopyBitsFPSItem, itemStr);
    
        GetDItemRect(srcDialogP, kCopyMaskPictItem, &itemRect);
        srcRect = itemRect;
        OffsetRect(&srcRect, -srcRect.left, -srcRect.top);
        dstRect = itemRect;
    
        ticks = TickCount();
    
        for (frame = 0; frame < kFrameCount; frame++)
        {
            CopyMask((BitMapPtr)*srcPixMap, &offScrnPort->portBits, &srcDialogP->portBits,
                        &srcRect, &offScrnPort->portRect, &dstRect);
    
            srcRect.left++;
            srcRect.right++;
        }
    
        ticks = TickCount() - ticks;
    
        NumToString(kFrameCount, itemStr);
        SetDItemText(srcDialogP, kCopyMaskFramesItem, itemStr);
        NumToString(ticks, itemStr);
        SetDItemText(srcDialogP, kCopyMaskTicksItem, itemStr);
        NumToString((ticks < 60) ? kFrameCount : kFrameCount / (ticks / 60), itemStr);
        SetDItemText(srcDialogP, kCopyMaskFPSItem, itemStr);
    
        UnlockPixels(srcPixMap);
    }
 
    if (maskRgn != NULL)
        DisposeRgn(maskRgn);
 
    if (offScrnPort != NULL)
        DisposeGrafPort(offScrnPort);
 
    if (maskGWorld != NULL)
        DisposeGWorld(maskGWorld);
 
    if (pictGWorld != NULL)
        DisposeGWorld(pictGWorld);
 
    SetCursor(&qd.arrow);
 
    SysBeep(0);
}
 
 
///--------------------------------------------------------------------------------------
// CreateOptimumGWorld
//
//  create a new GWorld optimized for speed in copying
//  to the graphics device that intersects the given rect.
///--------------------------------------------------------------------------------------
 
OSErr CreateOptimumGWorld(GWorldPtr *optGWorld, Rect *devRect)
{
    OSErr err;
    CGrafPtr saveCPort;
    GDHandle saveGDevice;
    GWorldPtr tempGWorld;
    //PixMapHandle pixMapH;
    Rect tempRect = *devRect;
 
    *optGWorld = NULL;
 
    GetGWorld(&saveCPort, &saveGDevice);
 
    LocalToGlobal((Point *)&tempRect.top);
    LocalToGlobal((Point *)&tempRect.bottom);
 
    err = NewGWorld(&tempGWorld, 0, &tempRect, NULL, NULL, 0);
 
    if (err == noErr)
    {
        SetGWorld(tempGWorld, NULL);
        EraseRect(&tempGWorld->portRect);
 
        *optGWorld = tempGWorld;
    }
 
    SetGWorld(saveCPort, saveGDevice);
 
    return err;
}
 
 
///--------------------------------------------------------------------------------------
//  CreateGWorldFromPict
//
//  creates a offScreen GWorld and draws the specified pict into it
///--------------------------------------------------------------------------------------
 
OSErr CreateGWorldFromPict(GWorldPtr *pictGWorld, PicHandle pictH)
{
    OSErr err;
    CGrafPtr saveCPort;
    GDHandle saveGDevice;
    GWorldPtr tempGWorld;
    PixMapHandle tempPixMapH;
    Rect pictRect;
 
    *pictGWorld = NULL;
 
    GetGWorld(&saveCPort, &saveGDevice);
 
    pictRect.left = pictRect.top = 0;
    pictRect.right = (**pictH).picFrame.right - (**pictH).picFrame.left;
    pictRect.bottom = (**pictH).picFrame.bottom - (**pictH).picFrame.top;
 
    err = CreateOptimumGWorld(&tempGWorld, &pictRect);
 
    if (err == noErr)
    {
        *pictGWorld = tempGWorld;
 
        SetGWorld(tempGWorld, NULL);
 
        tempPixMapH = GetGWorldPixMap(tempGWorld);
 
        (void)LockPixels(tempPixMapH);
        DrawPicture(pictH, &pictRect);
        UnlockPixels(tempPixMapH);
    }
 
    SetGWorld(saveCPort, saveGDevice);
 
    return err;
}
 
 
///--------------------------------------------------------------------------------------
// CreateGWorldFromPictResource
///--------------------------------------------------------------------------------------
 
OSErr CreateGWorldFromPictResource(GWorldPtr *pictGWorldP, short pictResID)
{
    OSErr err;
    PicHandle newPictH;
 
    newPictH = GetPicture(pictResID);
 
    if (newPictH != NULL)
    {
        err = CreateGWorldFromPict(pictGWorldP, newPictH);
 
        ReleaseResource((Handle)newPictH);
    }
 
    return err;
}
 
 
////--------------------------------------------------------------------------------------
//  CreateGrafPort
//
// originally written by Forrest Tanaka
////--------------------------------------------------------------------------------------
 
OSErr CreateGrafPort(Rect *newPortRect, GrafPtr *newPort)
{
    OSErr err = noErr;
    GrafPtr savePort;       // save port for later restore
    GrafPtr localPort;  // local copy of GrafPort
    Rect localPortRect; // local copy of bounds
 
    *newPort = NULL;
 
        // save off the current port
    GetPort(&savePort);
 
        // set the top-left corner of bounds to (0,0)
    localPortRect = *newPortRect;
    OffsetRect(&localPortRect, -newPortRect->left, -newPortRect->top);
 
        // allocate a new GrafPort
    localPort = (GrafPtr)NewPtrClear(sizeof(GrafPort));
 
    if (localPort != NULL)
    {
            // initialize the new port and make the current port
        OpenPort(localPort);
        SetPort(localPort);
        ForeColor(blackColor);
        BackColor(whiteColor);
 
            // initialize and allocate the bitmap
        localPort->portBits.bounds = localPortRect;
        localPort->portBits.rowBytes = ((localPortRect.right + 15) >> 4) << 1;
        localPort->portBits.baseAddr = NewPtrClear(localPort->portBits.rowBytes *
                                                                                            (long)localPortRect.bottom);
 
        if (localPort->portBits.baseAddr != NULL)
        {
                // clean up the new port
            localPort->portRect = localPortRect;
            ClipRect(&localPortRect);
            RectRgn(localPort->visRgn, &localPortRect);
            EraseRect(&localPortRect);
 
            *newPort = localPort;
        }
        else // allocation failed
        {
                // capture the error
            err = MemError();
 
                // deallocate the port
            ClosePort(localPort);
            DisposePtr((Ptr)localPort);
        }
    }
    else
    {
        err = MemError();
    }
 
    SetPort(savePort);
 
    return err;
}
 
 
////--------------------------------------------------------------------------------------
//  CreateGrafPortFromPictResource
//
//  this routine will set up an offscreen port, and draw a pict into it
//  the offscreen port is the exact size of the pict
///--------------------------------------------------------------------------------------
 
OSErr CreateGrafPortFromPictResource(short pictID, GrafPtr *offScrnPort)
{
    OSErr           err;
    GrafPtr     savePort;
    PicHandle   pictH;
    Rect            tmpRect;
 
    GetPort(&savePort);
 
    pictH = GetPicture(pictID);
 
    if (pictH != NULL)
    {
        tmpRect.left = tmpRect.top = 0;
        tmpRect.right = (**pictH).picFrame.right - (**pictH).picFrame.left;
        tmpRect.bottom = (**pictH).picFrame.bottom - (**pictH).picFrame.top;
 
            //  create a port
        err = CreateGrafPort(&tmpRect, offScrnPort);
 
        if (err == noErr)
        {
            SetPort(*offScrnPort);
 
                //  draw the picture
            DrawPicture(pictH, &tmpRect);
        }
 
        ReleaseResource((Handle)pictH);
    }
    else
    {
        err = ResError();
        
        if (err == noErr)
        {
            err = resNotFound;
        }
    }
 
    SetPort(savePort);
 
    return err;
}
 
 
////--------------------------------------------------------------------------------------
//  DisposeGrafPort
//
// originally written by Forrest Tanaka
///--------------------------------------------------------------------------------------
 
void DisposeGrafPort(GrafPtr doomedPort)
{
    ClosePort(doomedPort);
    DisposePtr(doomedPort->portBits.baseAddr);
    DisposePtr((Ptr)doomedPort);
}
 
 
///--------------------------------------------------------------------------------------
// GetDItemText
//
//  get the text of a dialog item
///--------------------------------------------------------------------------------------
 
void GetDItemText(DialogPtr dlgP, short itemNum, Str255 iStr)
{
    short itemType;
    Rect itemRect;
    Handle itemH;
 
    GetDialogItem(dlgP, itemNum, &itemType, &itemH, &itemRect);
    GetDialogItemText(itemH, iStr);             
}
 
 
///--------------------------------------------------------------------------------------
// SetDItemText
//
//  set the text of a dialog item
///--------------------------------------------------------------------------------------
 
void SetDItemText(DialogPtr dlgP, short itemNum, Str255 iStr)
{
    short itemType;
    Rect itemRect;
    Handle itemH;
 
    GetDialogItem(dlgP, itemNum, &itemType, &itemH, &itemRect);
    SetDialogItemText(itemH, iStr);             
}
 
 
///--------------------------------------------------------------------------------------
// GetDItemRect
//
//  return the rect of a dialog item
///--------------------------------------------------------------------------------------
 
void GetDItemRect(DialogPtr dlgP, short itemNum, Rect *itemRect)
{
    short itemType;
    Handle itemH;
 
    GetDialogItem(dlgP, itemNum, &itemType, &itemH, itemRect);
}