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.
Source/BitBlitz.c
/*-------------------------------------------------------------------------------------- |
// |
// File: BitBlitz.c |
// |
// Contents: This files contains all of the main routines that comprise the BitBlitz tool. |
// The tool was designed to be a learning/testing tool for the Copybits(), CopyMask(), |
// and CopyDeepMask() QuickDraw calls. It makes extensive use of GWorlds as well as |
// the above mentioned QuickDraw bit tools. |
// |
// |
// By Georgiann ("George") Delaney |
// ©Ê1989 - 1990, Apple Computer, Inc. |
// |
//--------------------------------------------------------------------------------------*/ |
#include "MacHeaders.h" |
#include "WCenter.h" |
#include "ColorTools.h" |
#include "MainStuff.h" |
#include "BlendUtils.h" |
#include "OffscreenUtils.h" |
#include "PICTUtils.h" |
#include "AlertDlogUtils.h" |
#include "AlrtDlogTools.h" |
#include "BitBlitz.h" |
#pragma segment CopyTests |
/*--------------------------------------------------------------------------------------*/ |
/* Constants */ |
#define AttrbDlogID 300 /* Attributes dialog constants */ |
#define diDlogTitle 3 |
#define diLine1 4 |
#define diLine2 5 |
#define diLine3 10 |
#define diLine4 16 |
#define diBitmapButton 6 |
#define diGWorldButton 7 |
#define diDepthPopUp 8 |
#define diContentPopUp 9 |
#define diHeightText 14 |
#define diWidthText 15 |
#define TrapDlogID 301 /* Trap selection dialog contents */ |
#define diTrapLine1 4 |
#define diTrapLine2 5 |
#define diCopyMaskButton 6 |
#define diCopyDeepButton 7 |
#define diCopyBitsButton 8 |
#define Sys7DlogID 302 /* Need 7.0 dialog constants */ |
#define AboutBoxDlogID 303 |
#define kDepthMenu 300 /* Attributes dialog menu constants */ |
#define kContentMenu 301 |
#define kNone 0 /* Buffer type constants */ |
#define kBitMap 1 |
#define kPixMap 2 |
#define kGWorld 3 |
#define km1bpp 1 /* Constants for depth menu selecions */ |
#define km2bpp 2 |
#define km4bpp 3 |
#define km8bpp 4 |
#define km16bpp 5 |
#define km32bpp 6 |
#define kmMaxbpp 8 |
#define kTitleStrings 4000 /* String resource constants */ |
#define kErrorStrings 4001 |
#define kBootMemErr 1 |
#define kDepthMemErr 2 |
#define kResizeMemErr 3 |
#define kPICTReadErr 4 |
#define kAttribDlogStrings 4002 |
#define kHLSRectBlend 1 |
#define kHLSHBlend 2 |
#define kHLSVBlend 3 |
#define kGrayRectBlend 5 |
#define kGrayHBlend 6 |
#define kGrayVBlend 7 |
#define kGrayPatRectBlend 9 |
#define kGrayPatHBlend 10 |
#define kGrayPatVBlend 11 |
#define kSolidRGB 13 |
#define kPICT 15 |
/*--------------------------------------------------------------------------------------*/ |
/* Global Variables */ |
RGBColor gLastRGB; /* The last RGB Color selected for a solid fill. |
Used as a starting color for the color picker for selection. */ |
Point gZeroPt; /* Its just what you think - a point initialized to (0,0) */ |
/* Array containing the 8 standard colors */ |
long gColorArray[8] = {blackColor, whiteColor, redColor, greenColor, blueColor, cyanColor, magentaColor, yellowColor}; |
/* Array containing rgb equivalents of 8 standard colors & gray*/ |
RGBColor gRGBArray[9]; |
/*======================================================================================*/ |
/* Initialization Routines */ |
/*--------------------------------------------------------------------------------------*/ |
Boolean myTrapAvailable(theNumber,theType) |
/* |
// This procedure tests to see if the specified trap is available in the current system. |
*/ |
short theNumber; |
TrapType theType; |
{ |
return NGetTrapAddress(theNumber,theType) != GetTrapAddress(_Unimplemented); |
} |
/*--------------------------------------------------------------------------------------*/ |
Boolean HasGWorlds() |
/* |
// This procedure tests to see if the GWorlds are available. |
*/ |
{ |
#define _GWorldDispatch (short)0xAB1D |
return(myTrapAvailable(_GWorldDispatch,ToolTrap)); |
} |
/*--------------------------------------------------------------------------------------*/ |
void InitTestGlobals() |
/* |
// This procedure is called during the program's initialization to set the initial values |
// of the app's constants. |
*/ |
{ |
gColorAvail = HasColorQD(); |
gGWorldsAvail = HasGWorlds(); |
gZeroPt.h = gZeroPt.v = 0; |
} |
/*--------------------------------------------------------------------------------------*/ |
void InitTestWindowAttributes() |
/* |
// InitTestWindowAttributes() performs initialization of the global structs defining the |
// attributes of the source, mask, and destination bit images. |
*/ |
{ |
register i; |
/* initialize all of the common fields */ |
for (i=kSrcWindow; i <= kBitWindow; i++) { |
gWList[i].window = nil; |
gWList[i].buffer.gworld = nil; |
if (gGWorldsAvail) { |
gWList[i].bufferType = kGWorld; |
gWList[i].bufferDepth = 0; |
} |
else { |
gWList[i].bufferType = kBitMap; |
gWList[i].bufferDepth = 1; |
} |
} |
/* set initial window contents with respect to the availability of color. */ |
if (gColorAvail) { |
gWList[kSrcWindow].contentType = kHLSRectBlend; |
gWList[kSrcWindow].content.saturation = 65535; |
gWList[kMskWindow].contentType = kGrayVBlend; |
gWList[kDstWindow].contentType = kSolidRGB; |
gWList[kDstWindow].content.RGB.red = 0xFFFF; |
gWList[kDstWindow].content.RGB.green = 0xFFFF; |
gWList[kDstWindow].content.RGB.blue = 0x0000; |
} |
else { |
gWList[kSrcWindow].contentType = kGrayPatRectBlend; |
gWList[kMskWindow].contentType = kGrayPatVBlend; |
gWList[kDstWindow].contentType = kGrayPatHBlend; |
} |
} |
/*--------------------------------------------------------------------------------------*/ |
void InitColorSettings() |
/* |
// InitColorSettings() initializes the values in the color array. |
*/ |
{ |
gRGBArray[0].red = 0x0000; gRGBArray[0].green = 0x0000; gRGBArray[0].blue = 0x0000; |
gRGBArray[1].red = 0xFFFF; gRGBArray[1].green = 0xFFFF; gRGBArray[1].blue = 0xFFFF; |
gRGBArray[2].red = 0xDD6B; gRGBArray[2].green = 0x08C2; gRGBArray[2].blue = 0x06A2; |
gRGBArray[3].red = 0x0000; gRGBArray[3].green = 0x8000; gRGBArray[3].blue = 0x11B0; |
gRGBArray[4].red = 0x0000; gRGBArray[4].green = 0x0000; gRGBArray[4].blue = 0xD400; |
gRGBArray[5].red = 0x0241; gRGBArray[5].green = 0xAB54; gRGBArray[5].blue = 0xEAFF; |
gRGBArray[6].red = 0xF2D7; gRGBArray[6].green = 0x0856; gRGBArray[6].blue = 0x84EC; |
gRGBArray[7].red = 0xFC00; gRGBArray[7].green = 0xF37D; gRGBArray[7].blue = 0x052F; |
gRGBArray[8].red = 0x7FFF; gRGBArray[8].green = 0x7FFF; gRGBArray[8].blue = 0x7FFF; |
gFGColor.menuIndex = kBlack; |
gFGColor.rgb = gRGBArray[kBlack-1]; |
gBKColor.menuIndex = kWhite; |
gBKColor.rgb = gRGBArray[kWhite-1]; |
gOPColor.menuIndex = kGray; |
gOPColor.rgb = gRGBArray[kGray-1]; |
gHiliteColor.menuIndex = kBlue; |
gHiliteColor.rgb = gRGBArray[kBlue-1]; |
} |
/*--------------------------------------------------------------------------------------*/ |
void InitRgnSettings() |
/* |
// InitRgnSettings() initializes all of the region settings to nil. |
*/ |
{ |
register i; |
for (i=kClpRgn; i<=kMskRgn; i++) { |
gRList[i].type = kNoRgn; |
gRList[i].rgn = nil; |
} |
} |
/*--------------------------------------------------------------------------------------*/ |
void DisposeRgnSettings() |
/* |
// DisposeRgnSettings() disposes any region settings that may have been set by the user. |
*/ |
{ |
register i; |
for (i=kClpRgn; i<=kMskRgn; i++) { |
if (gRList[i].rgn != nil) { |
DisposeRgn(gRList[i].rgn); |
gRList[i].rgn = nil; |
} |
} |
} |
/*--------------------------------------------------------------------------------------*/ |
void MenuIndex2RGB(ColorAttributes colorSelect, RGBColor *theRGB) |
{ |
if (colorSelect.menuIndex == kCustomColor) |
*theRGB = colorSelect.rgb; |
else |
*theRGB = gRGBArray[colorSelect.menuIndex-1]; |
} |
/*--------------------------------------------------------------------------------------*/ |
void DrawOval() |
{ |
Rect tempRect; |
tempRect = gWList[kBitWindow].window->portRect; |
InsetRect(&tempRect, 10, 10); |
FrameOval(&tempRect); |
} |
/*--------------------------------------------------------------------------------------*/ |
void DrawDiamond() |
{ |
Rect tempRect; |
Point centerPt; |
tempRect = gWList[kBitWindow].window->portRect; |
InsetRect(&tempRect, 10, 10); |
centerPt.h = tempRect.left + ((tempRect.right - tempRect.left)>>1); |
centerPt.v = tempRect.top + ((tempRect.bottom - tempRect.top )>>1); |
MoveTo(centerPt.h, tempRect.top); |
LineTo(tempRect.right, centerPt.v); |
LineTo(centerPt.h, tempRect.bottom); |
LineTo(tempRect.left, centerPt.v); |
LineTo(centerPt.h, tempRect.top); |
} |
/*--------------------------------------------------------------------------------------*/ |
void DrawHole() |
{ |
Rect tempRect; |
tempRect = gWList[kBitWindow].window->portRect; |
InsetRect(&tempRect, 10, 10); |
FrameOval(&tempRect); |
InsetRect(&tempRect, ((tempRect.right - tempRect.left)>>2), ((tempRect.bottom - tempRect.top )>>2)); |
FrameOval(&tempRect); |
} |
/*--------------------------------------------------------------------------------------*/ |
void DrawStar() |
{ |
Rect tempRect; |
Point centerPt; |
tempRect = gWList[kBitWindow].window->portRect; |
InsetRect(&tempRect, 10, 10); |
centerPt.h = tempRect.left + ((tempRect.right - tempRect.left)>>1); |
centerPt.v = tempRect.top + ((tempRect.bottom - tempRect.top )/3); |
MoveTo(centerPt.h, tempRect.top); |
LineTo(tempRect.right, tempRect.bottom); |
LineTo(tempRect.left, centerPt.v); |
LineTo(tempRect.right, centerPt.v); |
LineTo(tempRect.left, tempRect.bottom); |
LineTo(centerPt.h, tempRect.top); |
} |
/*--------------------------------------------------------------------------------------*/ |
void UpdateRgnSettings() |
/* |
// UpdateRgnSettings() updates any region settings that the user has selected after the |
// corresponding window has been resized. |
*/ |
{ |
register i; |
DisposeRgnSettings(); |
for (i=kClpRgn; i<=kMskRgn; i++) |
if (gRList[i].type != kNoRgn) { |
gRList[i].rgn = NewRgn(); |
OpenRgn(); |
switch(gRList[i].type) { |
case kDiamondClip: DrawDiamond(); break; |
case kOvalClip: DrawOval(); break; |
case kStarClip: DrawStar(); break; |
case kHoleClip: DrawHole(); break; |
} |
CloseRgn(gRList[i].rgn); |
} |
} |
/*--------------------------------------------------------------------------------------*/ |
void SetEnv() |
/* |
// SetEnv() is called to set the color environment and clip regions the user haa designated |
// for use in the copy call. |
*/ |
{ |
GrafPtr thePort; |
if (gColorAvail) { |
RGBForeColor(&gFGColor.rgb); |
RGBBackColor(&gBKColor.rgb); |
OpColor (&gOPColor.rgb); |
HiliteColor (&gHiliteColor.rgb); |
} |
else { |
ForeColor(gColorArray[gFGColor.menuIndex-1]); |
BackColor(gColorArray[gBKColor.menuIndex-1]); |
} |
if (gRList[kClpRgn].rgn != nil) { |
gHoldClpRgn = NewRgn(); |
GetClip(gHoldClpRgn); |
SetClip(gRList[kClpRgn].rgn); |
} |
if (gRList[kVisRgn].rgn != nil) { |
GetPort(&thePort); |
gHoldVisRgn = thePort->visRgn; |
thePort->visRgn = gRList[kVisRgn].rgn; |
} |
} |
/*--------------------------------------------------------------------------------------*/ |
void RestoreEnv() |
/* |
// RestoreEnv() restores the color and clip settings following the copy call. |
*/ |
{ |
GrafPtr thePort; |
if (gColorAvail) { |
RGBForeColor(&gRGBArray[kBlack-1]); |
RGBBackColor(&gRGBArray[kWhite-1]); |
} |
else { |
ForeColor(gColorArray[kBlack-1]); |
BackColor(gColorArray[kWhite-1]); |
} |
if (gHoldClpRgn != nil) { |
SetClip(gHoldClpRgn); |
DisposeRgn(gHoldClpRgn); |
gHoldClpRgn = nil; |
} |
if (gHoldVisRgn != nil) { |
GetPort(&thePort); |
thePort->visRgn = gHoldVisRgn; |
} |
} |
/*======================================================================================*/ |
/* Routines to handle CopyMode selection */ |
/*--------------------------------------------------------------------------------------*/ |
short ModeMenuItem2CopyMode(short theItem) |
/* |
// This routine is used to convert a copy mode menu selection to an actual QuickDraw |
// copy mode. The reason a switch statement is required here is because the |
// QuickDraw copy mode constants are not contiguous. |
*/ |
{ |
short theMode; |
switch(theItem) { |
case kSrcCopy: if (gDither) |
theMode = ditherCopy; |
else theMode = theItem -1; |
break; |
case kSrcOr: |
case kSrcXor: |
case kSrcBic: |
case kNotSrcCopy: |
case kNotSrcOr: |
case kNotSrcXor: |
case kNotSrcBic: theMode = theItem -1; break; |
case kBlend: theMode = blend; break; |
case kAddPin: theMode = addPin; break; |
case kAddOver: theMode = addOver; break; |
case kAddMax: theMode = addMax; break; |
case kAddMin: theMode = adMin; break; |
case kSubOver: theMode = subOver; break; |
case kSubPin: theMode = subPin; break; |
case kTransparent: theMode = transparent; break; |
case kHilite: theMode = hilite; break; |
} |
return(theMode); |
} |
/*--------------------------------------------------------------------------------------*/ |
short CopyMode2ModeMenuItem(short theMode) |
/* |
// This routine is used to convert a QuickDraw copy mode to a copy mode menu selection. |
// The reason a switch statement is required here is because the QuickDraw copy mode |
// constants are not contiguous. |
*/ |
{ |
short theItem; |
switch(theMode) { |
case ditherCopy: theItem = srcCopy +1; break; |
case srcCopy: |
case srcOr: |
case srcXor: |
case srcBic: |
case notSrcOr: |
case notSrcCopy: |
case notSrcXor: |
case notSrcBic: theItem = theMode +1; break; |
case blend: theItem = kBlend; break; |
case addPin: theItem = kAddPin; break; |
case addOver: theItem = kAddOver; break; |
case adMin : theItem = kAddMin; break; |
case addMax: theItem = kAddMax; break; |
case subOver: theItem = kSubOver; break; |
case subPin: theItem = kSubPin; break; |
case transparent: theItem = kTransparent; break; |
case hilite: theItem = kHilite; break; |
} |
return(theItem); |
} |
/*======================================================================================*/ |
/* Window Attribute PICT handle cleanup. */ |
/*--------------------------------------------------------------------------------------*/ |
void DisposePICTInfo(short windowCode) |
/* |
// DisposePICTInfo() tests to determine if the specified window has a PICT handle allocated |
// for buffer updating and disposes it if it is not already nil. |
*/ |
{ |
if ((gWList[windowCode].contentType == kPICT) && (gWList[windowCode].content.pictInfo != nil)) { |
DisposHandle((Handle)gWList[windowCode].content.pictInfo); |
gWList[windowCode].content.pictInfo = nil; |
} |
} |
/*======================================================================================*/ |
/* Offscreen Buffer Maintainance Routines */ |
/*--------------------------------------------------------------------------------------*/ |
Boolean CreateWindowBuffer(short windowCode) |
/* |
// CreateWindowBuffer() creates an offscreen buffer of the designated size with respect to the |
// attributes set in the window's attribute information. |
*/ |
{ |
Boolean bufferCreated = false; |
switch(gWList[windowCode].bufferType) { |
case kBitMap: |
bufferCreated = CreateOSBitmap(&gWList[windowCode].buffer.bitmap, &gWList[windowCode].window->portRect); |
break; |
case kGWorld: |
bufferCreated = (NewGWorld(&gWList[windowCode].buffer.gworld, gWList[windowCode].bufferDepth, &gWList[windowCode].window->portRect, nil, nil, 0) == noErr); |
break; |
} |
return(bufferCreated); |
} |
/*--------------------------------------------------------------------------------------*/ |
Boolean UpdateWindowBuffer(short windowCode, short depth) |
/* |
// This routine updates the specified window's offscreen buffer to the desired depth. |
*/ |
{ |
Boolean bufferChanged = false; |
long gwError; |
if (gWList[windowCode].bufferType == kGWorld) { |
gWList[windowCode].bufferDepth = depth; |
gwError = (UpdateGWorld(&gWList[windowCode].buffer.gworld, depth, &gWList[windowCode].buffer.gworld->portRect, 0, 0, 0) == noErr); |
bufferChanged = (gwError & gwFlagErr); |
} |
return(true); |
} |
/*--------------------------------------------------------------------------------------*/ |
void DisposeWindowBuffer(short windowCode) |
/* |
// DisposeWindowBuffer() determines the type of buffer that is associated with the specified |
// window and performs the appropriate dispose. |
*/ |
{ |
if (gWList[windowCode].buffer.gworld != nil) |
switch(gWList[windowCode].bufferType) { |
case kBitMap: DisposeOSBitmap(gWList[windowCode].buffer.bitmap); break; |
case kGWorld: DisposeGWorld (gWList[windowCode].buffer.gworld); break; |
} |
} |
/*--------------------------------------------------------------------------------------*/ |
Boolean SetOffscreen(short windowCode, short type, short depth) |
/* |
// Hey, guess what, it does what you expect - sets the specified window's buffer to the |
// specified offscreen type and depth. |
*/ |
{ |
Boolean bufferChanged = false; |
if (type != gWList[windowCode].bufferType) { |
DisposeWindowBuffer(windowCode); |
gWList[windowCode].bufferType = type; |
gWList[windowCode].bufferDepth = depth; |
bufferChanged = CreateWindowBuffer(windowCode); |
if (!bufferChanged) |
OKRsrcAlert(kErrorStrings,kDepthMemErr); |
} |
else { |
if (depth != gWList[windowCode].bufferDepth) { |
gWList[windowCode].bufferDepth = depth; |
bufferChanged = UpdateWindowBuffer(windowCode, depth); |
if (!bufferChanged) |
OKRsrcAlert(kErrorStrings,kDepthMemErr); |
} |
} |
return(bufferChanged); |
} |
/*--------------------------------------------------------------------------------------*/ |
Boolean UpdateOffscreen(short windowCode, short type, short depth) |
/* |
// UpdateOffscreen() tests to determine if the specified window's offscreen buffer has the |
// specified type and depth attributes and performs whatever buffer updating necessary. |
*/ |
{ |
Boolean depthChanged = false; |
depthChanged = SetOffscreen(windowCode,type,depth); |
/* Since the dest and copy window must be the same depth, if the user changes |
// the depth of the dest window, the copy window should also be set to the |
// new selected depth/ |
*/ |
if ((depthChanged) && (windowCode == kDstWindow)) { |
depthChanged = SetOffscreen(kBitWindow,type,depth); |
/* However, if an error occurs and the copy window can not be set to the |
// new depth then return the dest window to the original depth so that both are |
// equal. |
*/ |
if (!depthChanged) |
SetOffscreen(kDstWindow,gWList[kBitWindow].bufferType,gWList[kBitWindow].bufferDepth); |
} |
if (depthChanged) { |
DrawBuffer(windowCode); |
DrawBuffer(kBitWindow); |
} |
return(depthChanged); |
} |
/*======================================================================================*/ |
/* Attributes Dialog Routines */ |
/*--------------------------------------------------------------------------------------*/ |
void SetDepthMenuSelection(DialogPtr theDlog, short theItem, short theDepth) |
/* |
// This procedure initializes the attributes dialog's depth popup to the depth of the |
// selected window's offscreen depth. |
*/ |
{ |
short itemType; |
Handle itemHdl; |
Rect itemRect; |
short selection; |
MenuHandle depthMenuHdl; |
depthMenuHdl = GetMHandle(kDepthMenu); |
if ((!gGWorldsAvail) || (!gColorAvail)) { |
DisableItem(depthMenuHdl, km2bpp); |
DisableItem(depthMenuHdl, km4bpp); |
DisableItem(depthMenuHdl, km8bpp); |
DisableItem(depthMenuHdl, km16bpp); |
DisableItem(depthMenuHdl, km32bpp); |
} |
if (!gGWorldsAvail) |
DisableItem(depthMenuHdl, kmMaxbpp); |
GetDItem(theDlog,theItem,&itemType,&itemHdl,&itemRect); |
switch(theDepth) { |
case 1 : selection = km1bpp; break; |
case 2 : selection = km2bpp; break; |
case 4 : selection = km4bpp; break; |
case 8 : selection = km8bpp; break; |
case 16 : selection = km16bpp; break; |
case 32 : selection = km32bpp; break; |
case 0 : selection = kmMaxbpp; break; |
} |
SetCtlValue((ControlHandle)itemHdl,selection); |
} |
/*--------------------------------------------------------------------------------------*/ |
short GetDepthMenuSelection(DialogPtr theDlog, short theItem) |
/* |
// This procedure converts the attributes dialog's depth popup selection to its |
// equivalent depth value. |
*/ |
{ |
short itemType; |
Handle itemHdl; |
Rect itemRect; |
short selection,depth; |
GetDItem(theDlog,theItem,&itemType,&itemHdl,&itemRect); |
selection = GetCtlValue((ControlHandle)itemHdl); |
switch(selection) { |
case km1bpp : depth = 1; break; |
case km2bpp : depth = 2; break; |
case km4bpp : depth = 4; break; |
case km8bpp : depth = 8; break; |
case km16bpp : depth = 16; break; |
case km32bpp : depth = 32; break; |
case kmMaxbpp: depth = 0; break; |
} |
return(depth); |
} |
/*--------------------------------------------------------------------------------------*/ |
void SetContentMenuSelection(DialogPtr theDlog, short theItem, short theContent) |
/* |
// This procedure initializes the attributes dialog's content popup to reflect the |
// selected window's current content type. |
*/ |
{ |
short itemType; |
Handle itemHdl; |
Rect itemRect; |
MenuHandle contentMenuHdl; |
contentMenuHdl = GetMHandle(kContentMenu); |
if (!gColorAvail) { |
DisableItem(contentMenuHdl, kHLSRectBlend); |
DisableItem(contentMenuHdl, kHLSHBlend); |
DisableItem(contentMenuHdl, kHLSVBlend); |
DisableItem(contentMenuHdl, kGrayRectBlend); |
DisableItem(contentMenuHdl, kGrayHBlend); |
DisableItem(contentMenuHdl, kGrayVBlend); |
DisableItem(contentMenuHdl, kSolidRGB); |
} |
GetDItem(theDlog,theItem,&itemType,&itemHdl,&itemRect); |
SetCtlValue((ControlHandle)itemHdl,theContent); |
} |
/*--------------------------------------------------------------------------------------*/ |
short GetContentMenuSelection(DialogPtr theDlog, short theItem) |
/* |
// This procedure returns the attributes dialog's content popup selection. |
*/ |
{ |
short itemType; |
Handle itemHdl; |
Rect itemRect; |
GetDItem(theDlog,theItem,&itemType,&itemHdl,&itemRect); |
return(GetCtlValue((ControlHandle)itemHdl)); |
} |
/*--------------------------------------------------------------------------------------*/ |
pascal Boolean AttrbDlogFilter(DialogPtr theDlog, EventRecord *theEvent, short *theItem) |
{ |
/* |
// AttrbDlogFilter() is the dialog filter for the attributes dialog. |
*/ |
IBeamCursorAdjust(theDlog,(ValidTextProcPtr)StdValidDecTextProc); |
/* If we get a key down event, check to see if it is for the OK or Cancel |
// buttons. If not, filter it for numeric input only (via EditNumText()). |
*/ |
if ((theEvent->what == autoKey) || (theEvent->what == keyDown)) { |
short editItem = ((DialogPeek)theDlog)->editField + 1; |
if (HandleOkayCancel(theDlog,theEvent,theItem)) |
return(true); |
EditNumText(theDlog,theEvent,editItem,0L,1000L,decimalOnly); |
} |
return(false); |
} |
/*--------------------------------------------------------------------------------------*/ |
Boolean ChangeWindowAttributes(short windowCode) |
/* |
// ChangeWindowAttributes() allows the user to change any of the attributes of the source, |
// mask, or destination windows. |
// |
// This dialog is accessed by selecting the appropriate menu selection or by double-clicking |
// in the content region of the desired window. |
*/ |
{ |
DialogPtr theDlog; |
GrafPtr holdPort; |
short itemHit; |
Boolean okHit = false; |
Boolean done = false; |
Boolean bufferChanged = false; |
Boolean contentChanged = false; |
short tempBufferType = gWList[windowCode].bufferType; |
short tempBufferDepth = gWList[windowCode].bufferDepth; |
short tempContentType = gWList[windowCode].contentType; |
PicHandle tempPICT = nil; |
short tempSaturation = 65535; |
RGBColor tempRGB; |
register i; |
short contentSelect; |
SFReply reply; |
Str255 tempStr; |
Point oldDimen, newDimen; |
/* Initialize temporary values that have not already been initialized during |
// variable declaration. |
*/ |
if (tempContentType == kSolidRGB) |
tempRGB = gWList[windowCode].content.RGB; |
else |
tempRGB = gLastRGB; |
/* Allocate and center the dialog */ |
CenterWRsrc(DLOG,AttrbDlogID,vThird); |
theDlog = GetNewDialog(AttrbDlogID, nil, (WindowPtr)-1); |
reply.good = false; |
/* If the dialog has been allocated successfully - process the user's selections */ |
if (theDlog != nil) { |
/* Save off the current port. */ |
GetPort(&holdPort); |
SetPort(theDlog); |
/* Dialog item initialization. */ |
SetDlogItemProc(theDlog,diLine1,(ProcPtr)FrameDlogItemRect); |
SetDlogItemProc(theDlog,diLine2,(ProcPtr)FrameDlogItemRect); |
SetDlogItemProc(theDlog,diLine3,(ProcPtr)FrameDlogItemRect); |
SetDlogItemProc(theDlog,diLine4,(ProcPtr)FrameDlogItemRect); |
/* Set the appropriate dialog title */ |
GetIndString (tempStr,kAttribDlogStrings,windowCode+1); |
SetDlogString(theDlog, diDlogTitle, tempStr); |
HandleRadioButtons(theDlog,diBitmapButton,diGWorldButton,((tempBufferType == kGWorld) ? diGWorldButton : diBitmapButton)); |
SetDepthMenuSelection (theDlog, diDepthPopUp, tempBufferDepth); |
SetContentMenuSelection(theDlog, diContentPopUp,tempContentType); |
oldDimen.v = gWList[windowCode].window->portRect.bottom - gWList[windowCode].window->portRect.top; |
oldDimen.h = gWList[windowCode].window->portRect.right - gWList[windowCode].window->portRect.left; |
SetDlogShort(theDlog,diHeightText,oldDimen.v); |
SetDlogShort(theDlog,diWidthText, oldDimen.h); |
SelIText (theDlog,diHeightText, 0, 32767); |
/* Display the dialog */ |
ShowWindow(theDlog); |
/* Process the user's actions */ |
do { |
ModalDialog((ProcPtr)AttrbDlogFilter, &itemHit); |
switch (itemHit) { |
case ok: okHit = true; |
case cancel: done = true; |
break; |
case diBitmapButton: HandleRadioButtons(theDlog,diBitmapButton,diGWorldButton,itemHit); |
tempBufferDepth = 1; |
tempBufferType = kBitMap; |
break; |
case diDepthPopUp: |
case diGWorldButton: HandleRadioButtons(theDlog,diBitmapButton,diGWorldButton,diGWorldButton); |
tempBufferDepth = GetDepthMenuSelection(theDlog, diDepthPopUp); |
tempBufferType = kGWorld; |
break; |
case diContentPopUp: contentSelect = GetContentMenuSelection(theDlog, diContentPopUp); |
switch(contentSelect) { |
case kSolidRGB : |
GetColor(gZeroPt,"\pSelect a color.",&tempRGB,&tempRGB); |
tempContentType = contentSelect; |
for(i=kSrcWindow; i <= kBitWindow; i++) |
DrawWindow(i); |
break; |
case kPICT: |
StdGetPictFile(&reply); |
for(i=kSrcWindow; i <= kBitWindow; i++) |
DrawWindow(i); |
if (reply.good) |
tempContentType = contentSelect; |
break; |
default: tempContentType = contentSelect; |
} |
break; |
} |
} while ( !done ); |
GetDlogShort(theDlog,diHeightText, &newDimen.v); |
GetDlogShort(theDlog,diWidthText, &newDimen.h); |
if (newDimen.v < 2) newDimen.v = 2; |
if (newDimen.h < 2) newDimen.h = 2; |
DisposDialog(theDlog); |
SetPort(holdPort); |
} |
if (okHit) { |
SetCursor(*GetCursor(watchCursor)); |
for(i=kSrcWindow; i <= kBitWindow; i++) |
DrawWindow(i); |
/* Reset the offscreen depth if it has been changed */ |
bufferChanged = UpdateOffscreen(windowCode, tempBufferType, tempBufferDepth); |
/* Reset the content region if a new type has been selected */ |
if ((tempContentType != gWList[windowCode].contentType) || |
(tempContentType == kPICT) || (tempContentType == kSolidRGB)) { |
if (tempContentType == kPICT) { |
if (ReadPICTFile(&reply, &tempPICT) == noErr) { |
if (gWList[windowCode].contentType == kPICT) |
DisposePICTInfo(windowCode); |
gWList[windowCode].contentType = kPICT; |
gWList[windowCode].content.pictInfo = tempPICT; |
DrawBuffer(windowCode); |
contentChanged = true; |
} |
else |
if (reply.good) |
OKRsrcAlert(kErrorStrings,kPICTReadErr); |
} |
else { |
if (gWList[windowCode].contentType == kPICT) |
DisposePICTInfo(windowCode); |
gWList[windowCode].contentType = tempContentType; |
switch(tempContentType) { |
case kSolidRGB: gWList[windowCode].content.RGB = gLastRGB = tempRGB; break; |
case kHLSRectBlend: |
case kHLSHBlend: |
case kHLSVBlend: gWList[windowCode].content.saturation = tempSaturation; break; |
} |
DrawBuffer(windowCode); |
contentChanged = true; |
} |
} |
/* Resize the window if the size has been altered. Remember, the source and |
// mask windows (when available) as well as the destination and copy windows |
// must be the same size so if one is altered its corresponding window must also |
// be sized. It therefore follows that if there is not enough memory available to |
// enlarge both windows then neither should be changed. |
*/ |
if ( !EqualPt(oldDimen, newDimen) ) { |
GetPort(&holdPort); |
if ((windowCode == kSrcWindow) || (windowCode == kMskWindow)) { |
SetPort(gWList[kSrcWindow].window); |
if (ResizeTestWindow(&newDimen,kSrcWindow)) { |
oldDimen.h = gWList[kSrcWindow].window->portRect.right - gWList[kSrcWindow].window->portRect.left; |
oldDimen.v = gWList[kSrcWindow].window->portRect.bottom - gWList[kSrcWindow].window->portRect.top; |
SetPort(gWList[kMskWindow].window); |
if (ResizeTestWindow(&newDimen,kMskWindow)) { |
SizeWindow(gWList[kMskWindow].window,newDimen.h,newDimen.v,false); |
SizeWindow(gWList[kSrcWindow].window,newDimen.h,newDimen.v,false); |
} |
else { |
SetPort(gWList[kSrcWindow].window); |
ResizeTestWindow(&oldDimen,kSrcWindow); |
} |
} |
} |
if ((windowCode == kDstWindow) || (windowCode == kBitWindow)) { |
SetPort(gWList[kDstWindow].window); |
if (ResizeTestWindow(&newDimen,kDstWindow)) { |
oldDimen.h = gWList[kDstWindow].window->portRect.right - gWList[kDstWindow].window->portRect.left; |
oldDimen.v = gWList[kDstWindow].window->portRect.bottom - gWList[kDstWindow].window->portRect.top; |
SetPort(gWList[kBitWindow].window); |
if (ResizeTestWindow(&newDimen,kBitWindow)) { |
SizeWindow(gWList[kBitWindow].window,newDimen.h,newDimen.v,false); |
SizeWindow(gWList[kDstWindow].window,newDimen.h,newDimen.v,false); |
UpdateRgnSettings(); |
} |
else { |
SetPort(gWList[kDstWindow].window); |
ResizeTestWindow(&oldDimen,kDstWindow); |
} |
} |
} |
SetPort(holdPort); |
bufferChanged = true; |
} |
/* Update the screen with the new changes */ |
if (bufferChanged || contentChanged) |
DrawBuffer(kBitWindow); |
for(i=kSrcWindow; i <= kBitWindow; i++) |
DrawWindow(i); |
InitCursor(); |
} |
return(okHit); |
} |
/*--------------------------------------------------------------------------------------*/ |
void SelectFGColor (short theItem) |
{ |
register i; |
RGBColor tempRGB; |
if (theItem == kCustomColor) { |
tempRGB = gFGColor.rgb; |
if (GetColor(gZeroPt,"\pSelect a foreground color.",&tempRGB,&tempRGB)) { |
for(i=kSrcWindow; i <= kDstWindow; i++) |
DrawWindow(i); |
gFGColor.menuIndex = kCustomColor; |
gFGColor.rgb = tempRGB; |
DrawBuffer(kBitWindow); |
DrawWindow(kBitWindow); |
} |
} |
else { |
gFGColor.menuIndex = theItem; |
gFGColor.rgb = gRGBArray[theItem-1]; |
DrawBuffer(kBitWindow); |
DrawWindow(kBitWindow); |
} |
} |
/*--------------------------------------------------------------------------------------*/ |
void SelectBKColor (short theItem) |
{ |
register i; |
RGBColor tempRGB; |
if (theItem == kCustomColor) { |
tempRGB = gBKColor.rgb; |
if (GetColor(gZeroPt,"\pSelect a background color.",&tempRGB,&tempRGB)) { |
for(i=kSrcWindow; i <= kDstWindow; i++) |
DrawWindow(i); |
gBKColor.menuIndex = kCustomColor; |
gBKColor.rgb = tempRGB; |
DrawBuffer(kBitWindow); |
DrawWindow(kBitWindow); |
} |
} |
else { |
gBKColor.menuIndex = theItem; |
gBKColor.rgb = gRGBArray[theItem-1]; |
DrawBuffer(kBitWindow); |
DrawWindow(kBitWindow); |
} |
} |
/*--------------------------------------------------------------------------------------*/ |
void SelectOPColor (short theItem) |
{ |
register i; |
RGBColor tempRGB; |
if (theItem == kCustomColor) { |
tempRGB = gOPColor.rgb; |
if (GetColor(gZeroPt,"\pSelect an OpColor.",&tempRGB,&tempRGB)) { |
for(i=kSrcWindow; i <= kDstWindow; i++) |
DrawWindow(i); |
gOPColor.menuIndex = kCustomColor; |
gOPColor.rgb = tempRGB; |
DrawBuffer(kBitWindow); |
DrawWindow(kBitWindow); |
} |
} |
else { |
gOPColor.menuIndex = theItem; |
gOPColor.rgb = gRGBArray[theItem-1]; |
DrawBuffer(kBitWindow); |
DrawWindow(kBitWindow); |
} |
} |
/*--------------------------------------------------------------------------------------*/ |
void SelectHiliteColor (short theItem) |
{ |
register i; |
RGBColor tempRGB; |
if (theItem == kCustomColor) { |
tempRGB = gHiliteColor.rgb; |
if (GetColor(gZeroPt,"\pSelect a hilite color.",&tempRGB,&tempRGB)) { |
for(i=kSrcWindow; i <= kDstWindow; i++) |
DrawWindow(i); |
gHiliteColor.menuIndex = kCustomColor; |
gHiliteColor.rgb = tempRGB; |
DrawBuffer(kBitWindow); |
DrawWindow(kBitWindow); |
} |
} |
else { |
gHiliteColor.menuIndex = theItem; |
gHiliteColor.rgb = gRGBArray[theItem-1]; |
DrawBuffer(kBitWindow); |
DrawWindow(kBitWindow); |
} |
} |
/*--------------------------------------------------------------------------------------*/ |
void SelectRgn(short rgnCode, short rgnType) |
{ |
gRList[rgnCode].type = rgnType; |
if (rgnType == kNoRgn) { |
if (gRList[rgnCode].rgn != nil) { |
DisposeRgn(gRList[rgnCode].rgn); |
gRList[rgnCode].rgn = nil; |
} |
} |
else { |
gRList[rgnCode].rgn = NewRgn(); |
OpenRgn(); |
switch(rgnType) { |
case kDiamondClip: DrawDiamond(); break; |
case kOvalClip: DrawOval(); break; |
case kStarClip: DrawStar(); break; |
case kHoleClip: DrawHole(); break; |
} |
CloseRgn(gRList[rgnCode].rgn); |
} |
DrawBuffer(kBitWindow); |
DrawWindow(kBitWindow); |
} |
/*--------------------------------------------------------------------------------------*/ |
Boolean SelectTrap() |
/* |
// This call allows the user to select which of the two copymas traps he wishes to test. |
*/ |
{ |
DialogPtr theDlog; |
GrafPtr holdPort; |
short itemHit; |
Boolean okHit = false; |
Boolean done = false; |
Boolean bufferChanged = false; |
Boolean contentChanged = false; |
short tempTrapSelect = gTrapSelect; |
register i; |
Str255 tempStr; |
/* Allocate and center the dialog */ |
CenterWRsrc(DLOG,TrapDlogID,vThird); |
theDlog = GetNewDialog(TrapDlogID, nil, (WindowPtr)-1); |
/* If the dialog has been allocated successfully - process the user's selections */ |
if (theDlog != nil) { |
/* Save off the current port. */ |
GetPort(&holdPort); |
SetPort(theDlog); |
/* Set up user item divider lines */ |
SetDlogItemProc(theDlog,diTrapLine1,(ProcPtr)FrameDlogItemRect); |
SetDlogItemProc(theDlog,diTrapLine2,(ProcPtr)FrameDlogItemRect); |
/* Init the radio buttons to reflect current selection. */ |
HandleRadioButtons(theDlog,diCopyMaskButton,diCopyBitsButton,tempTrapSelect+diCopyMaskButton); |
/* Display the dialog */ |
ShowWindow(theDlog); |
/* Process the user's actions */ |
do { |
ModalDialog((ProcPtr)HandleOkayCancel, &itemHit); |
switch (itemHit) { |
case ok: okHit = true; |
case cancel: done = true; |
break; |
case diCopyMaskButton: |
case diCopyDeepButton: |
case diCopyBitsButton: HandleRadioButtons(theDlog,diCopyMaskButton,diCopyBitsButton,itemHit); |
tempTrapSelect = itemHit - diCopyMaskButton; |
break; |
} |
} while ( !done ); |
DisposDialog(theDlog); |
SetPort(holdPort); |
} |
if ((okHit) && (gTrapSelect != tempTrapSelect)) { |
for(i=kSrcWindow; i <= kBitWindow; i++) |
DrawWindow(i); |
gTrapSelect = tempTrapSelect; |
GetIndString(&tempStr, kTitleStrings, gTrapSelect+4); |
SetWTitle(gWList[kBitWindow].window,tempStr); |
ShowHide(gWList[kMskWindow].window, !(gTrapSelect==kCopyBits)); |
DrawBuffer(kBitWindow); |
DrawWindow(kBitWindow); |
} |
return(okHit); |
} |
/*--------------------------------------------------------------------------------------*/ |
void NeedSystem7Dlog() |
/* |
// This dialog alerts the user that system 7.0 is needed for the app to run. |
*/ |
{ |
DialogPtr theDlog; |
GrafPtr holdPort; |
short itemHit; |
Boolean done = false; |
/* Allocate and center the dialog */ |
CenterWRsrc(DLOG,Sys7DlogID,vThird); |
theDlog = GetNewDialog(Sys7DlogID, nil, (WindowPtr)-1); |
/* If the dialog has been allocated successfully - process the user's selections */ |
if (theDlog != nil) { |
/* Save off the current port. */ |
GetPort(&holdPort); |
SetPort(theDlog); |
FrameDlogButton (theDlog,ok); |
/* Display the dialog */ |
ShowWindow(theDlog); |
/* Process the user's actions */ |
do { |
ModalDialog((ProcPtr)HandleOkayCancel, &itemHit); |
done = (itemHit == ok); |
} while ( !done ); |
DisposDialog(theDlog); |
SetPort(holdPort); |
} |
} |
/*--------------------------------------------------------------------------------------*/ |
void AboutBitBlitz() |
{ |
DialogPtr theDlog; |
GrafPtr holdPort; |
short itemHit; |
Boolean done = false; |
CenterWRsrc(DLOG,AboutBoxDlogID,vThird); |
theDlog = GetNewDialog(AboutBoxDlogID, nil, (WindowPtr)-1); |
if (theDlog != nil) { |
/* Save off the current port. */ |
GetPort(&holdPort); |
SetPort(theDlog); |
/* Display the dialog */ |
ShowWindow(theDlog); |
/* Display about box until mouseDown */ |
do { |
ModalDialog((ProcPtr)HandleOkayCancel, &itemHit); |
done = (itemHit == 1); |
} while ( !done ); |
/* Cleanup before returning */ |
DisposDialog(theDlog); |
SetPort(holdPort); |
} |
} |
/*======================================================================================*/ |
/* Offscreen buffer imaging routines */ |
/*--------------------------------------------------------------------------------------*/ |
void FillSolid(RGBColor *theRGB, Rect *boundRect) |
/* |
// FillSolid() preserves and restores the current foreground color setting while filling |
// the specified Rect with the desired color. |
*/ |
{ |
RGBColor holdRGB; |
GetForeColor(&holdRGB); |
RGBForeColor(theRGB); |
PaintRect(boundRect); |
RGBForeColor(&holdRGB); |
} |
/*--------------------------------------------------------------------------------------*/ |
void DoCopy() |
/* |
// DoCopy() updates the buffer associated with the copy window. This update takes |
// two steps. Since the contents of the specified destination bitmap are overwritten by |
// the copy result we keep both a destination window and the copy window. Before performing |
// the copy trap, the contents of the destination window's buffer are copied into the copy |
// window's buffer. This buffer is then passed along with the source and mask window's buffers |
// to the copy routine. |
*/ |
{ |
GrafPtr holdPort; |
GDHandle holdDevice; |
BitMap *srcBits, *mskBits, *dstBits; |
Rect *srcRect, *mskRect, *dstRect; |
PixMapHandle srcBuffer, mskBuffer, dstBuffer, bitBuffer; |
/* If the user selects to use screen bits for the copy call the buffer pointer |
// that is passed to the copy call is set to the window's portbits. |
*/ |
if (gUseScreenBits) { |
srcBits = &gWList[kSrcWindow].window->portBits; |
srcRect = &gWList[kSrcWindow].window->portRect; |
if (gWList[kMskWindow].bufferType == kBitMap) { |
mskBits = &gWList[kMskWindow].buffer.bitmap->portBits; |
mskRect = &gWList[kMskWindow].buffer.bitmap->portBits.bounds; |
} |
else { |
mskBuffer = GetGWorldPixMap(gWList[kMskWindow].buffer.gworld); |
LockPixels(mskBuffer); |
mskBits = *mskBuffer; |
mskRect = &gWList[kMskWindow].buffer.gworld->portRect; |
} |
/* The cursor is hidded during the copy so as not to interfere with the image */ |
HideCursor(); |
} |
/* Otherwise, the offscreen gworld's portbits are passed */ |
else { |
if (gWList[kSrcWindow].bufferType == kBitMap) { |
srcBits = &gWList[kSrcWindow].buffer.bitmap->portBits; |
srcRect = &gWList[kSrcWindow].buffer.bitmap->portBits.bounds; |
} |
else { |
srcBuffer = GetGWorldPixMap(gWList[kSrcWindow].buffer.gworld); |
LockPixels(srcBuffer); |
srcBits = *srcBuffer; |
srcRect = &gWList[kSrcWindow].buffer.gworld->portRect; |
} |
if (gWList[kMskWindow].bufferType == kBitMap) { |
mskBits = &gWList[kMskWindow].buffer.bitmap->portBits; |
mskRect = &gWList[kMskWindow].buffer.bitmap->portBits.bounds; |
} |
else { |
mskBuffer = GetGWorldPixMap(gWList[kMskWindow].buffer.gworld); |
LockPixels(mskBuffer); |
mskBits = *mskBuffer; |
mskRect = &gWList[kMskWindow].buffer.gworld->portRect; |
} |
} |
switch(gWList[kBitWindow].bufferType) { |
case kBitMap: |
GetPort(&holdPort); |
SetPort(gWList[kBitWindow].buffer.bitmap); |
CopyBits(&gWList[kDstWindow].buffer.bitmap->portBits, &gWList[kBitWindow].buffer.bitmap->portBits, |
&gWList[kDstWindow].buffer.bitmap->portBits.bounds, &gWList[kBitWindow].buffer.bitmap->portBits.bounds, srcCopy, NULL); |
if (gUseScreenBits) { |
DrawWindow(kBitWindow); |
dstBits = &gWList[kBitWindow].window->portBits; |
dstRect = &gWList[kBitWindow].window->portRect; |
} |
else { |
dstBits = &gWList[kBitWindow].buffer.bitmap->portBits; |
dstRect = &gWList[kBitWindow].buffer.bitmap->portBits.bounds; |
} |
SetEnv(); |
if (gTrapSelect == kCopyMask) |
CopyMask(srcBits, mskBits, dstBits, srcRect, mskRect, dstRect); |
else if (gTrapSelect == kCopyDeepMask) |
CopyMask2(srcBits, mskBits, dstBits, srcRect, mskRect, dstRect, gCopyMode, gRList[kMskRgn].rgn); |
else |
CopyBits (srcBits, dstBits, srcRect, dstRect, gCopyMode, gRList[kMskRgn].rgn); |
RestoreEnv(); |
SetPort(holdPort); |
break; |
case kGWorld: |
dstBuffer = GetGWorldPixMap(gWList[kDstWindow].buffer.gworld); |
bitBuffer = GetGWorldPixMap(gWList[kBitWindow].buffer.gworld); |
LockPixels(dstBuffer); |
LockPixels(bitBuffer); |
GetGWorld(&(CGrafPtr)holdPort,&holdDevice); |
SetGWorld((CGrafPtr)gWList[kBitWindow].buffer.gworld,nil); |
CopyBits(*dstBuffer, *bitBuffer, |
&gWList[kDstWindow].buffer.gworld->portRect, &gWList[kBitWindow].buffer.gworld->portRect, srcCopy, nil); |
if (gUseScreenBits) { |
SetGWorld((CGrafPtr)holdPort,holdDevice); |
GetPort(&holdPort); |
SetPort(gWList[kBitWindow].window); |
DrawWindow(kBitWindow); |
dstBits = &gWList[kBitWindow].window->portBits; |
dstRect = &gWList[kBitWindow].window->portRect; |
} |
else { |
dstBits = *bitBuffer; |
dstRect = &gWList[kBitWindow].buffer.gworld->portRect; |
} |
SetEnv(); |
if (gTrapSelect == kCopyMask) |
CopyMask(srcBits, mskBits, dstBits, srcRect, mskRect, dstRect); |
else if (gTrapSelect == kCopyDeepMask) |
CopyMask2(srcBits, mskBits, dstBits, srcRect, mskRect, dstRect, gCopyMode, gRList[kMskRgn].rgn); |
else |
CopyBits (srcBits, dstBits, srcRect, dstRect, gCopyMode, gRList[kMskRgn].rgn); |
RestoreEnv(); |
if (gUseScreenBits) { |
SetPort(holdPort); |
GetGWorld(&(CGrafPtr)holdPort,&holdDevice); |
SetGWorld((CGrafPtr)gWList[kBitWindow].buffer.gworld,nil); |
CopyBits(dstBits, *bitBuffer, dstRect, &gWList[kBitWindow].buffer.gworld->portRect, srcCopy, nil); |
} |
SetGWorld((CGrafPtr)holdPort,holdDevice); |
UnlockPixels(dstBuffer); |
UnlockPixels(bitBuffer); |
break; |
} |
if (gUseScreenBits) |
ShowCursor(); |
else { |
if (gWList[kSrcWindow].bufferType == kGWorld) |
UnlockPixels(srcBuffer); |
if (gWList[kMskWindow].bufferType == kGWorld) |
UnlockPixels(mskBuffer); |
} |
} |
/*--------------------------------------------------------------------------------------*/ |
void ImageBuffer(short windowCode) |
/* |
// ImageBuffer() sets the current port in accordance with the buffer type, draws the image |
// designated by the contentType, and restores current port to its original setting. |
*/ |
{ |
GrafPtr holdPort; |
GDHandle holdDevice; |
Rect bufferRect; |
switch(gWList[windowCode].bufferType) { |
case kBitMap: |
GetPort(&holdPort); |
SetPort(gWList[windowCode].buffer.bitmap); |
bufferRect = gWList[windowCode].buffer.bitmap->portBits.bounds; |
break; |
case kGWorld: |
LockPixels(GetGWorldPixMap(gWList[windowCode].buffer.gworld)); |
GetGWorld(&holdPort,&holdDevice); |
SetGWorld(gWList[windowCode].buffer.gworld,nil); |
bufferRect = gWList[windowCode].buffer.gworld->portRect; |
break; |
} |
switch (gWList[windowCode].contentType) { |
case kHLSRectBlend: HLSRectBlend (&bufferRect,gWList[windowCode].content.saturation); break; |
case kHLSHBlend: HLSHLinearBlend (&bufferRect,gWList[windowCode].content.saturation); break; |
case kHLSVBlend: HLSVLinearBlend (&bufferRect,gWList[windowCode].content.saturation); break; |
case kGrayRectBlend: GrayRectBlend (&bufferRect); break; |
case kGrayHBlend: GrayHLinearBlend (&bufferRect); break; |
case kGrayVBlend: GrayVLinearBlend (&bufferRect); break; |
case kGrayPatRectBlend: GrayPatRectBlend (&bufferRect); break; |
case kGrayPatHBlend: GrayPatHLinearBlend (&bufferRect); break; |
case kGrayPatVBlend: GrayPatVLinearBlend (&bufferRect); break; |
case kSolidRGB: FillSolid (&gWList[windowCode].content.RGB,&bufferRect); break; |
case kPICT: if (gWList[windowCode].content.pictInfo != nil) |
DrawPicture(gWList[windowCode].content.pictInfo,&bufferRect); |
break; |
} |
switch(gWList[windowCode].bufferType) { |
case kBitMap: SetPort (holdPort); |
break; |
case kGWorld: SetGWorld(holdPort,holdDevice); |
UnlockPixels(GetGWorldPixMap(gWList[windowCode].buffer.gworld)); |
break; |
} |
} |
/*--------------------------------------------------------------------------------------*/ |
void DrawBuffer(short windowCode) |
/* |
// DrawBuffer() redraws the specified window's offscreen buffer. |
*/ |
{ |
if (windowCode == kBitWindow) |
DoCopy(); |
else |
ImageBuffer(windowCode); |
} |
/*======================================================================================*/ |
/* Offscreen-to-onscreen transferral */ |
/*--------------------------------------------------------------------------------------*/ |
void DrawWindow(short windowCode) |
/* |
// DrawWindow() draws the current contents of the specified window's buffer to that window. |
*/ |
{ |
GrafPtr holdPort; |
PixMapHandle windowBuffer; |
/* Save the current port setting and set the current port to the specified window */ |
GetPort(&holdPort); |
SetPort(gWList[windowCode].window); |
/* Switch off the current buffer type setting to perform the appropriate copybits */ |
switch(gWList[windowCode].bufferType) { |
case kBitMap: |
CopyBits(&gWList[windowCode].buffer.bitmap->portBits, &gWList[windowCode].window->portBits, |
&gWList[windowCode].buffer.bitmap->portBits.bounds, &gWList[windowCode].window->portRect, srcCopy, NULL); |
break; |
case kGWorld: |
windowBuffer = GetGWorldPixMap(gWList[windowCode].buffer.gworld); |
LockPixels(windowBuffer); |
CopyBits(*windowBuffer, &gWList[windowCode].window->portBits, |
&gWList[windowCode].buffer.gworld->portRect, &gWList[windowCode].window->portRect, srcCopy, NULL); |
UnlockPixels(windowBuffer); |
break; |
} |
/* Restore the current port to its original setting. */ |
SetPort(holdPort); |
} |
/*======================================================================================*/ |
/* Window/Buffer resizing routines */ |
/*--------------------------------------------------------------------------------------*/ |
Boolean ResizeTestWindow(Point *newDimen, short windowCode) |
/* |
// ResizeWindow() sizes the specifed window to the new dimensions. |
*/ |
{ |
Rect tempRect, oldRect; |
Boolean bufferScaled; |
GrafPtr tempBits; |
GWorldFlags gwError; |
switch(gWList[windowCode].bufferType) { |
case kBitMap: |
oldRect = tempRect = gWList[windowCode].buffer.bitmap->portBits.bounds; |
tempRect.bottom = tempRect.top + newDimen->v; |
tempRect.right = tempRect.left + newDimen->h; |
DisposeOSBitmap(gWList[windowCode].buffer.bitmap); |
bufferScaled = CreateOSBitmap(&tempBits,&tempRect); |
if (bufferScaled) |
gWList[windowCode].buffer.bitmap = tempBits; |
else |
CreateOSBitmap(&gWList[windowCode].buffer.bitmap,&oldRect); |
break; |
case kGWorld: |
tempRect = gWList[windowCode].buffer.gworld->portRect; |
tempRect.bottom = tempRect.top + newDimen->v; |
tempRect.right = tempRect.left + newDimen->h; |
gwError = UpdateGWorld(&gWList[windowCode].buffer.gworld, gWList[windowCode].bufferDepth, &tempRect, nil, nil, clipPix); |
bufferScaled = ((gwError & gwFlagErr) == 0); |
break; |
} |
if (bufferScaled) { |
if (windowCode != kBitWindow) |
DrawBuffer(windowCode); |
} |
else |
OKRsrcAlert(kErrorStrings,kResizeMemErr); |
return(bufferScaled); |
} |
/*======================================================================================*/ |
/* Test Window allocation/disposal routines */ |
/*--------------------------------------------------------------------------------------*/ |
void CalcWindowRect(Rect *windowRect, short windowCode) |
/* |
// This procedure calculates the window rect for the window designated by windowCode. |
// It essentially divides the screen into 4 equal quadrants and insets the rect defining |
// the window's rect appropriately in order to have it positioned correctly on whatever |
// size screen the application is run. |
*/ |
{ |
#define kTitleBarHeight 20 |
#define kWindowSep 10 /* # pixels between windows and space between edge */ |
/* of screen and window */ |
Rect screenRect; |
Point windowCenter; |
screenRect = qd.screenBits.bounds; |
screenRect.top += MBarHeight; |
windowCenter.h = screenRect.left + (HRectLength(&screenRect) >> 1); |
windowCenter.v = screenRect.top + (VRectLength(&screenRect) >> 1); |
switch (windowCode) { |
case kSrcWindow: |
SetRect(windowRect, screenRect.left+kWindowSep, |
screenRect.top+kWindowSep+kTitleBarHeight, |
windowCenter.h-(kWindowSep/2), |
windowCenter.v-(kWindowSep/2)); |
break; |
case kMskWindow: |
SetRect(windowRect, windowCenter.h+(kWindowSep/2), |
screenRect.top+kWindowSep+kTitleBarHeight, |
screenRect.right-kWindowSep, |
windowCenter.v-(kWindowSep/2)); |
break; |
case kDstWindow: |
SetRect(windowRect, screenRect.left+kWindowSep, |
windowCenter.v+(kWindowSep/2)+kTitleBarHeight, |
windowCenter.h-(kWindowSep/2), |
screenRect.bottom-kWindowSep); |
break; |
case kBitWindow: |
SetRect(windowRect ,windowCenter.h+(kWindowSep/2), |
windowCenter.v+(kWindowSep/2)+kTitleBarHeight, |
screenRect.right-kWindowSep, |
screenRect.bottom-kWindowSep); |
break; |
} |
} |
/*--------------------------------------------------------------------------------------*/ |
Boolean CreateTestWindows() |
{ |
/* This function allocates, initializes, and displays the four test windows. If an error |
// occurs during this process and error message is displayed. All memory allocated is |
// disposed. And false is returned so that the application will terminate from main. |
*/ |
register i; |
Rect tempRect; |
Str255 title; |
for (i = kSrcWindow; i <= kBitWindow; i++) { |
CalcWindowRect(&tempRect,i); |
GetIndString(&title, kTitleStrings, i+1); |
if (gColorAvail) |
gWList[i].window = NewCWindow(nil,&tempRect,title,true,documentProc,(WindowPtr)-1, false,0); |
else |
gWList[i].window = NewWindow(nil,&tempRect,title,true,documentProc,(WindowPtr)-1, false,0); |
if (gWList[i].window == nil) |
goto handle_init_error; |
if (!CreateWindowBuffer(i)) |
goto handle_init_error; |
DrawBuffer(i); |
DrawWindow(i); |
} |
return(true); |
handle_init_error: DisposeTestWindows(); |
OKRsrcAlert(kErrorStrings,kBootMemErr); |
return(false); |
} |
/*--------------------------------------------------------------------------------------*/ |
void DisposeTestWindows() |
/* |
// This procedure takes care of disposing all memory allocated in association with any |
// of the app windows before the application quits either normally or in response to an |
// unrecoverable error. |
*/ |
{ |
register i; |
for (i = kSrcWindow; i <= kBitWindow; i++) { |
if ((gWList[i].contentType == kPICT) && (gWList[i].content.pictInfo != nil)) |
DisposHandle((Handle)gWList[i].content.pictInfo); |
DisposeWindowBuffer(i); |
if (gWList[i].window != nil) |
DisposeWindow(gWList[i].window); |
} |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-10-10