Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
out.c
/* |
File: out.c |
Contains: This application demonstrates one method to |
produce animation on the Macintosh using QuickDraw's |
palette manager animation routines. The app simply |
creates an offscreen image, copies it to the |
screen's window, then calls AnimatePalette() |
every cycle through the eventloop. To provide the |
fastest possible animation, the image is only |
created and copied once from the offscreen GWorld. |
The actual animation is produced by shifting the |
color entries within its colortable forward or |
backward one index. Also the cTable is divided |
and shifted in two separate groups to simulate |
objects moving at different speeds. |
Written by: EL |
Copyright: Copyright © 1991-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): |
08/2000 JM Carbonized, non-Carbon code is commented out |
for demonstration purposes. |
7/16/1999 KG Updated for Metrowerks Codewarror Pro 2.1 |
*/ |
#include "out.h" |
/*******************************/ |
/* Global Variable Definitions */ |
/*******************************/ |
WindowPtr gWindow; /* Main Display Window */ |
CTabHandle gCTable; /* Window & offscreen Colortable */ |
GWorldPtr gGWorld; /* Offscreen GWorld */ |
PixMapHandle gPixMap; /* PixMap of the GWorld */ |
PaletteHandle gPalette; /* Window & offscreen Palette */ |
int gCurrentPat = 1; /* Current Test Pattern */ |
int gCurrentMove = STOP; /* Current State of Animation */ |
int gCurrentDir = FORWARD; /* Current Direction to Shift Palette Colors */ |
int gCurrentColor = COLOR; /* Current Colors: mixed or gray */ |
void main(void) |
{ |
//MaxApplZone(); /* Increase application heap. */ |
initMac(); /* Do standard mac initializations. */ |
initVariables(); /* Initialize the colortable. */ |
createWindow(); |
createPalette(); |
createGWorld(); |
createImage(); /* Create the current image offscreen. */ |
drawImage(); /* Copybits the offscreen image into the window. */ |
pollEvents(); /* Handle any events & update the palette. */ |
} |
void initMac() |
{ |
/*********************************/ |
/* Standard Initialization Calls */ |
/*********************************/ |
/*InitGraf( &qd.thePort ); |
InitFonts(); |
InitWindows(); |
InitMenus(); |
TEInit(); |
InitDialogs( nil );*/ |
InitCursor(); |
FlushEvents( 0, everyEvent ); |
setUpMenus(); |
} |
void initVariables() |
{ |
/********************************************************************/ |
/* Allocate memory for the colortable. Since ColorTable already */ |
/* contains one ColorSpec, allocate (TOTALCOLORS - 1) ColorSpec's. */ |
/* One ColorSpec is required for each entry. */ |
/********************************************************************/ |
gCTable = (CTabHandle)NewHandle( sizeof( ColorTable ) + |
((TOTALCOLORS - 1) * sizeof( ColorSpec ))); |
} |
void createWindow() |
{ |
Rect wBounds; |
BitMap bitMap; |
int top, left; |
GetQDGlobalsScreenBits(&bitMap); |
top = (((bitMap.bounds.bottom - bitMap.bounds.top) - WHEIGHT) / 2); |
left = (((bitMap.bounds.right - bitMap.bounds.left) - WWIDTH) / 2); |
/*****************************************************************/ |
/* Create and center the destination window in the main monitor. */ |
/*****************************************************************/ |
//SetRect( &wBounds, WLEFT, WTOP, WLEFT + WWIDTH, WTOP + WHEIGHT ); |
SetRect( &wBounds, left, top, left + WWIDTH, top + WHEIGHT ); |
gWindow = NewCWindow( 0L, &wBounds, "\pOut of This GWorld", true, noGrowDocProc, |
(WindowPtr)-1L, true, 0L ); |
/**************************************************************/ |
/* Display the main window and assign it as the current port. */ |
/**************************************************************/ |
ShowWindow( gWindow ); |
//SetPort( gWindow ); |
SetPortWindowPort( gWindow ); |
} |
void createPalette() |
{ |
/********************************************************************/ |
/* Allocate a palette for color animation. Using pmExplicit as the */ |
/* usage, tells QD that the index values in the palette are more */ |
/* important than the rgb values stored at that index. This is */ |
/* necessary since the animation in this application is simulated */ |
/* by shifting the colors at each palette index. */ |
/********************************************************************/ |
gPalette = NewPalette( TOTALCOLORS, nil, pmAnimated + pmExplicit, 0 ); |
/************************************************/ |
/* Define the rgb values at each palette index. */ |
/************************************************/ |
defineColorPalette(); |
/******************************************/ |
/* Attach the palette to the main window. */ |
/******************************************/ |
SetPalette( gWindow, gPalette, true ); |
} |
void createGWorld() |
{ |
int i; |
Rect gBounds; |
Rect tempRect1; |
//CGrafPtr currentPort; |
//GDHandle currentDevice; |
/*************************************************/ |
/* Define the size of the GWorld's bounding box. */ |
/*************************************************/ |
/*SetRect( &gBounds, 0, 0, gWindow->portRect.right - gWindow->portRect.left, |
gWindow->portRect.bottom - gWindow->portRect.top );*/ |
GetPortBounds(GetWindowPort(gWindow), &tempRect1); |
SetRect( &gBounds, 0, 0, tempRect1.right - tempRect1.left, tempRect1.bottom - tempRect1.top ); |
/********************************************************************************/ |
/* Convert the palette to a colortable before explicitly setting bit 14 in */ |
/* the ctFlags field of the colortable. This tells the colortable to refer */ |
/* to the palette indexes instead of its rgb values. Again, this is */ |
/* necessary since the animation is performed by altering the palette. */ |
/********************************************************************************/ |
Palette2CTab( gPalette, gCTable ); |
(**gCTable).ctFlags |= 0x4000; |
/************************************************************************/ |
/* Make sure each value field of the colortable is assigned to the */ |
/* corresponding entry in the palette and make sure the ctSeed field */ |
/* is given a unique value. */ |
/************************************************************************/ |
for (i = 0; i < TOTALCOLORS; i++) |
(**gCTable).ctTable[i].value = i; |
(**gCTable).ctSeed = GetCTSeed(); |
/*************************************************************************/ |
/* Allocate a new GWorld for the offscreen drawing and store its PixMap. */ |
/*************************************************************************/ |
NewGWorld( &gGWorld, 8, &gBounds, gCTable, nil, 0 ); |
gPixMap = GetGWorldPixMap( gGWorld ); |
} |
void updatePalette() |
{ |
/******************************************************************************/ |
/* Convert the altered colortable to a palette, then animate all its entries. */ |
/******************************************************************************/ |
Palette2CTab( gPalette, gCTable ); |
AnimatePalette( gWindow, gCTable, 0, 0, TOTALCOLORS ); |
} |
void defineColorPalette() |
{ |
int i; |
gCurrentColor = COLOR; |
/***********************************************************************/ |
/* Define the first 8 palette entries with primary & secondary colors. */ |
/***********************************************************************/ |
setRGB( 0, 0, 0, 0 ); /* black */ |
setRGB( 1, 0, 255, 0 ); /* green */ |
setRGB( 2, 0, 255, 255 ); /* cyan */ |
setRGB( 3, 0, 0, 255 ); /* blue */ |
setRGB( 4, 255, 0, 255 ); /* magenta */ |
setRGB( 5, 255, 0, 0 ); /* red */ |
setRGB( 6, 255, 255, 0 ); /* yellow */ |
setRGB( 7, 255, 255, 255 ); /* white */ |
/*******************************************************************/ |
/* Define shades of the previous colors for the remaining entries. */ |
/*******************************************************************/ |
for (i = 8; i < 48; i++) /* greens */ |
setRGB( i, 0, 10 + ((i - 8) * 6), 0 ); |
for (i = 48; i < 88; i++) /* blues */ |
setRGB( i, 0, 0, 10 + ((i - 48) * 6) ); |
for (i = 88; i < 128; i++) /* reds */ |
setRGB( i, 10 + ((i - 88) * 6), 0, 0 ); |
for (i = 128; i < 168; i++) /* magentas */ |
setRGB( i, 10 + ((i - 128) * 6), 0, 10 + ((i - 128) * 6) ); |
for (i = 168; i < 208; i++) /* yellows */ |
setRGB( i, 10 + ((i - 168) * 6), 10 + ((i - 168) * 6), 0 ); |
for (i = 208; i < 248; i++) /* cyans */ |
setRGB( i, 0, 10 + ((i - 208) * 6), ((i - 208) * 6) ); |
} |
void defineGrayPalette() |
{ |
int i; |
int shade; |
gCurrentColor = GRAY; |
/*******************************************************/ |
/* Define all the palette entries with shades of gray. */ |
/*******************************************************/ |
for (i = 1; i < 7; i++) |
{ |
shade = i * 42; |
setRGB( i, shade, shade, shade ); |
} |
for (i = 8, shade = 10; i < 248; i++) |
{ |
setRGB( i, shade, shade, shade ); |
shade += 12; |
if ((i - 8) % 20 == 0) |
shade = 10; |
} |
} |
void setRGB( index, r, g, b ) |
int index; |
int r, g, b; |
{ |
RGBColor aColor; |
/***********************************************************************/ |
/* Set the rgb values for the palette color stored at the index value. */ |
/***********************************************************************/ |
aColor.red = r * SUN2MAC; /* All colors were defined using */ |
aColor.green = g * SUN2MAC; /* SUN computer raster values. */ |
aColor.blue = b * SUN2MAC; |
SetEntryColor( gPalette, index, &aColor ); |
} |
void setColor( index ) |
int index; |
{ |
RGBColor aColor; |
/********************************************************/ |
/* Get the rgb values stored at the index value in the */ |
/* palette, then use it as the foreground color. */ |
/********************************************************/ |
GetEntryColor( gPalette, index, &aColor ); |
RGBForeColor( &aColor ); |
} |
void createImage() |
{ |
CGrafPtr currentPort; |
GDHandle currentDevice; |
RGBColor aColor; |
/******************************************************************************/ |
/* Store the current port and device before switching to the offscreen world. */ |
/******************************************************************************/ |
GetGWorld( ¤tPort, ¤tDevice ); |
/****************************************************************************/ |
/* Switch to the offscreen GWorld then lock the offscreen buffer in memory. */ |
/****************************************************************************/ |
SetGWorld( gGWorld, nil ); |
LockPixels( gPixMap ); |
/************************************************/ |
/* Set the background color to black then erase */ |
/* the PixMap's bounding box in the GWorld. */ |
/************************************************/ |
GetEntryColor( gPalette, 0, &aColor ); |
RGBBackColor( &aColor ); |
EraseRect( &(**gPixMap).bounds ); |
/*************************************************************/ |
/* Draw a 1 pixel wide white border along the PixMap's edge. */ |
/*************************************************************/ |
drawWindowBorder(); |
/*************************************************************************/ |
/* Depending on the current test pattern, create an image in the PixMap. */ |
/*************************************************************************/ |
if (gCurrentPat == 1) |
createColorScale(); |
else if (gCurrentPat == 2) |
createColorWheels(); |
else if (gCurrentPat == 3) |
createColorRings(); |
else if (gCurrentPat == 4) |
createColorGears(); |
else if (gCurrentPat == 5) |
createColorCurves(); |
else if (gCurrentPat == 6) |
createColorBalls(); |
else if (gCurrentPat == 7) |
createColorWave(); |
else if (gCurrentPat == 8) |
createColorText(); |
else |
doAbout(); /* Treat the About message as a test pattern. */ |
/********************************************************************/ |
/* After drawing the image, unlock the offscreen buffer in memory */ |
/* and set the port and device back to the window's. */ |
/********************************************************************/ |
UnlockPixels( gPixMap ); |
SetGWorld( currentPort, currentDevice ); |
} |
void drawWindowBorder() |
{ |
/********************************************************************/ |
/* Set the foreground color to white before drawing a 1 pixel wide */ |
/* frame around the PixMap's bounding box. */ |
/********************************************************************/ |
setColor( 7 ); |
PenSize( 1, 1 ); |
MoveTo( 0, 0 ); |
LineTo( 0, (**gPixMap).bounds.bottom - 1 ); |
LineTo( (**gPixMap).bounds.right - 1, (**gPixMap).bounds.bottom - 1 ); |
LineTo( (**gPixMap).bounds.right - 1, 0 ); |
} |
void drawImage() |
{ |
Rect tempRect1; |
/***********************************************************/ |
/* Transfer the contents of the PixMap to the main window. */ |
/***********************************************************/ |
/*CopyBits( (BitMap*)*gPixMap, &gWindow->portBits, &(**gPixMap).bounds, |
&gWindow->portRect, srcCopy, 0l);*/ |
CopyBits( (BitMap *)*gPixMap, GetPortBitMapForCopyBits(GetWindowPort(gWindow)), &(**gPixMap).bounds, |
GetPortBounds(GetWindowPort(gWindow), &tempRect1), srcCopy, 0L); |
} |
void animateCTable() |
{ |
static int counter = 0; |
RGBColor aColor; |
/**************************************************************************/ |
/* Convert the Palette to a colortable before shifting the color entries. */ |
/**************************************************************************/ |
Palette2CTab( gPalette, gCTable ); |
/************************************************************************/ |
/* Depending on the current direction, shift 239 palette entries either */ |
/* ahead 1 or behind 1 index. Store the first or last entry before */ |
/* shifting to avoid overwriting its rgb values. */ |
/************************************************************************/ |
if (gCurrentDir == FORWARD) |
{ |
aColor = (**gCTable).ctTable[247].rgb; |
BlockMove( &(**gCTable).ctTable[8].value, &(**gCTable).ctTable[9].value, |
239 * sizeof(ColorSpec) ); |
(**gCTable).ctTable[8].rgb = aColor; |
} |
else |
{ |
aColor = (**gCTable).ctTable[8].rgb; |
BlockMove( &(**gCTable).ctTable[9].value, &(**gCTable).ctTable[8].value, |
239 * sizeof(ColorSpec) ); |
(**gCTable).ctTable[247].rgb = aColor; |
} |
/**************************************************************/ |
/* Shift the first 5 colortable entries once every 6 updates. */ |
/**************************************************************/ |
if (counter == 0) |
{ |
aColor = (**gCTable).ctTable[1].rgb; |
BlockMove( &(**gCTable).ctTable[2].value, &(**gCTable).ctTable[1].value, |
5 * sizeof(ColorSpec) ); |
(**gCTable).ctTable[6].rgb = aColor; |
} |
/********************************************************/ |
/* Update the window's colors by passing the new */ |
/* colortable as the srcCTab field of AnimatePalette. */ |
/********************************************************/ |
AnimatePalette( gWindow, gCTable, 0, 0, TOTALCOLORS ); |
/**********************************************/ |
/* Increment the counter by 1 on each update. */ |
/**********************************************/ |
counter = (counter + 1) % 6; |
} |
void doAbout() |
{ |
Rect rect; |
PicHandle thePict; |
int width, height; |
/*******************************************************/ |
/* Load the About picture stored in the resource fork. */ |
/*******************************************************/ |
thePict = (PicHandle)GetResource( 'PICT', 128 ); |
/************************************************/ |
/* Define the rect used to enclose the picture. */ |
/************************************************/ |
width = (**thePict).picFrame.right - (**thePict).picFrame.left; |
height = (**thePict).picFrame.bottom - (**thePict).picFrame.top; |
SetRect( &rect, (WWIDTH - width) / 2, (WHEIGHT - height) / 2, |
((WWIDTH - width) / 2) + width, ((WHEIGHT - height) / 2 ) + height ); |
/*********************************/ |
/* Draw the picture in the rect. */ |
/*********************************/ |
DrawPicture( thePict, &rect ); |
ReleaseResource( (Handle)thePict ); |
} |
void cleanUp() |
{ |
/*****************************************************************************/ |
/* Free the memory set aside for the GWorld and main window before exitting. */ |
/*****************************************************************************/ |
DisposeGWorld( gGWorld ); |
DisposeWindow( gWindow ); |
ExitToShell(); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-03-12