JPEGView/Source/C/cDrawingArea.c
Aaron Giles 92bdb55672 JPEGView 3.3 for Macintosh
These are the sources for the final official release of JPEGView for the
Mac, back in 1994.
2015-02-05 00:18:10 -08:00

1 line
17 KiB
C

/*********************************************************/
/* This source code copyright (c) 1991-2001, Aaron Giles */
/* See the Read Me file for licensing information. */
/* Contact email: mac@aarongiles.com */
/*********************************************************/
#if THINK_C
#include "THINK.Header"
#elif applec
#pragma load ":Headers:MPW.Header"
#elif __MWERKS__
//#include "MW.Header"
#else
#include "JPEGView.h"
#endif
/*
* DrawingAreaAccessor(classWanted, container, containerClass, keyForm, keyData,
* resultToken, theRefCon)
*
* Purpose: Finds a drawing area according to the specified keyForm and returns the
* corresponding drawing area token
* Inputs: classWanted = the element class desired (cDrawingArea)
* container = token for this element's container
* containerClass = class of this element's container (cWindow)
* keyForm = the search key type
* keyData = descriptor containing search key data
* resultToken = descriptor containing the resulting token
* theRefCon = reference constant
* Returns: an OSErr describing the result
*
*/
pascal OSErr DrawingAreaAccessor(DescType classWanted, AEDesc *container,
DescType containerClass, DescType keyForm, AEDesc *keyData,
AEDesc *resultToken, long theRefCon)
{
#if applec
#pragma unused (classWanted, containerClass, theRefCon)
#endif
ObjectTokenHandle theList = (ObjectTokenHandle)container->dataHandle;
OSErr theErr = noErr;
if (IsValidForOne(keyForm, keyData)) {
if ((theErr = HandToHand((Handle *)&theList)) != noErr) return theErr;
PurgeNonDocuments(theList);
} else return errAENoSuchObject;
if (!theList || !(*theList)->count || (theErr != noErr)) {
DisposeHandle((Handle)theList);
if (theErr == noErr) theErr = errAENoSuchObject;
} else {
theErr = AECreateHandleDesc(cDrawingArea, (Handle)theList, resultToken);
DisposeHandle((Handle)theList);
}
return theErr;
}
/*
* DrawPropertyAccessor(classWanted, container, containerClass, keyForm, keyData,
* resultToken, theRefCon)
*
* Purpose: Finds a drawing area property and returns the corresponding property token
* Inputs: classWanted = the element class desired (typeProperty)
* container = token for this element's container
* containerClass = class of this element's container (cDrawingArea)
* keyForm = the search key type
* keyData = descriptor containing search key data
* resultToken = descriptor containing the resulting token
* theRefCon = reference constant
* Returns: an OSErr describing the result
*
*/
pascal OSErr DrawPropertyAccessor(DescType classWanted, AEDesc *container,
DescType containerClass, DescType keyForm, AEDesc *keyData,
AEDesc *resultToken, long theRefCon)
{
#if applec
#pragma unused (classWanted, containerClass, theRefCon)
#endif
ObjectTokenHandle theList = (ObjectTokenHandle)container->dataHandle;
DescType propertyType;
OSErr theErr;
if ((keyForm != formPropertyID) || (keyData->descriptorType != typeType))
return errAECantSupplyType;
propertyType = *(DescType *)*keyData->dataHandle;
switch (propertyType) {
// Non-modifiable properties
case pBestType:
case pClass:
case pDefaultType:
// Modifiable properties
case pBounds:
case pColorTable:
case pDrawQuality:
case pScale:
case pPalette:
case pTransferMode:
break;
default:
return errAEEventNotHandled;
}
theErr = HandToHand((Handle *)&theList);
if (theErr != noErr) return theErr;
(*theList)->property = propertyType;
(*theList)->objclass = cDrawingArea;
theErr = AECreateHandleDesc(typeProperty, (Handle)theList, resultToken);
DisposeHandle((Handle)theList);
return theErr;
}
/*
* GetDrawingAreaData(theWindow, typeWanted, theData)
*
* Purpose: Extracts the data from the drawing area
* Inputs: theWindow = the window associated with this object
* typeWanted = the type we're asking for
* theData = the data we save
* Returns: an OSErr describing the result
*
*/
OSErr GetDrawingAreaData(WindowPtr theWindow, DescType typeWanted, AEDesc *theData)
{
if (typeWanted == typeWildCard) typeWanted = typeObjectSpecifier;
if (typeWanted == typeBest) typeWanted = typeObjectSpecifier;
if (typeWanted != typeObjectSpecifier) return errAECantSupplyType;
return MakeDrawingAreaObject(theWindow, theData);
}
/*
* GetDrawPropertyData(theWindow, theProperty, typeWanted, theData)
*
* Purpose: Extracts the data from the drawing area's properties
* Inputs: theWindow = the window associated with this object
* theProperty = the property wanted
* typeWanted = the type we're asking for
* theData = the data we save
* Returns: an OSErr describing the result
*
*/
OSErr GetDrawPropertyData(WindowPtr theWindow, DescType theProperty, DescType typeWanted,
AEDesc *theData)
{
ImageHandle theImage = FindImage(theWindow);
Boolean theBoolean = true;
Point thePoint = { 0, 0 };
CTabHandle theColors;
DescType theType;
AEDesc bestData;
short theShort;
Rect theRect;
OSErr theErr;
if (!theImage) return errAEReadDenied;
switch (theProperty) {
case pBestType:
case pDefaultType:
theType = typeObjectSpecifier;
theErr = AECreateDesc(typeType, (void *)&theType, sizeof(DescType), &bestData);
break;
case pBounds:
theRect = (*theImage)->wrect;
theErr = AECreateDesc(typeQDRectangle, (void *)&theRect, sizeof(Rect), &bestData);
break;
case pClass:
theType = cDrawingArea;
theErr = AECreateDesc(typeType, (void *)&theType, sizeof(DescType), &bestData);
break;
case pColorTable:
theColors = (CTabHandle)NewHandle(4);
if (theColors) Palette2CTab((*theImage)->palette, theColors);
theErr = AECreateHandleDesc(typeColorTable, (Handle)theColors, &bestData);
DisposeHandle((Handle)theColors);
break;
case pDrawQuality:
if ((*theImage)->quality == iqVHigh) theType = kAEDQVeryHigh;
else if ((*theImage)->quality == iqHigh) theType = kAEDQHigh;
else if ((*theImage)->quality == iqMedium) theType = kAEDQNormal;
theErr = AECreateDesc(typeEnumerated, (void *)&theType, sizeof(DescType), &bestData);
break;
case pScale:
theShort = ((long)Width(&(*theImage)->wrect) * 100) / Width(&(*theImage)->crect);
theShort += ((long)Height(&(*theImage)->wrect) * 100) / Height(&(*theImage)->crect);
theShort >>= 1;
theErr = AECreateDesc(typeShortInteger, (void *)&theShort, sizeof(short), &bestData);
break;
case pPalette:
switch ((*theImage)->npalette) {
case plSys: theType = kAEPSystem; break;
case plGrey: theType = kAEPGrayscale; break;
case plImage: theType = kAEPImage; break;
case plQuant: theType = kAEPQuantized; break;
default: theType = typeWildCard; break;
}
theErr = AECreateDesc(typeEnumerated, (void *)&theType, sizeof(DescType), &bestData);
break;
case pTransferMode:
theType = Dithered(theImage) ? kAEQDDitherCopy : kAEQDCopy;
theErr = AECreateDesc(typeEnumerated, (void *)&theType, sizeof(DescType), &bestData);
break;
default:
theErr = errAETypeError;
break;
}
if (theErr != noErr) return theErr;
if ((bestData.descriptorType == typeWanted) ||
(typeWanted == typeWildCard) || (typeWanted == typeBest))
theErr = AEDuplicateDesc(&bestData, theData);
else theErr = AECoerceDesc(&bestData, typeWanted, theData);
AEDisposeDesc(&bestData);
return theErr;
}
/*
* SetDrawPropertyData(theWindow, theProperty, theData)
*
* Purpose: Sets the data for the drawing area's properties
* Inputs: theWindow = the associated window
* theProperty = the property wanted
* theData = the data to set it to
* Returns: an OSErr describing the result
*
*/
OSErr SetDrawPropertyData(WindowPtr theWindow, DescType theProperty, AEDesc *theData)
{
ImageHandle theImage = FindImage(theWindow);
Rect theRect, oldRect;
CTabHandle theColors;
DescType theMode;
short theShort;
Fixed theFixed;
OSErr theErr;
if (!theImage) return errAEWriteDenied;
switch (theProperty) {
case pBounds:
theErr = AEExtractQDRectangle(theData, 0, &theRect);
if (theErr == noErr) theErr = DoSetDrawBounds(theImage, &theRect);
break;
case pColorTable:
if (theData->descriptorType == typeColorTable) {
theColors = (CTabHandle)theData->dataHandle;
theErr = DoSetColorTable(theWindow, theColors);
} else theErr = errAETypeError;
break;
case pDrawQuality:
theErr = AEExtractEnumerated(theData, 0, &theMode);
if (theErr == noErr) theErr = DoSetImageQuality(theImage, theMode);
break;
case pPalette:
theErr = AEExtractEnumerated(theData, 0, &theMode);
if (theErr == noErr) theErr = DoSetPalette(theWindow, theMode);
break;
case pScale:
theErr = AEExtractShort(theData, 0, &theShort);
if (theErr == noErr) {
Rect monRect;
theRect = (*theImage)->crect;
theRect.right = theRect.left + ((theShort * Width(&theRect)) / 100);
theRect.bottom = theRect.top + ((theShort * Height(&theRect)) / 100);
OffsetRect(&theRect, -theRect.left, -theRect.top);
GetActiveRect((*theImage)->dmon, &monRect);
if (!Full(theImage)) monRect.top += gTitleBarHeight;
if (Height(&theRect) > Height(&monRect)) {
theRect.right = (long)theRect.right * (long)Height(&monRect) / (long)theRect.bottom;
theRect.bottom = Height(&monRect);
}
if (Width(&theRect) > Width(&monRect)) {
theRect.bottom = (long)theRect.bottom * (long)Width(&monRect) / (long)theRect.right;
theRect.right = Width(&monRect);
}
oldRect = (*theImage)->wrect;
(*theImage)->wrect = theRect;
ResizeWindow(theImage);
}
break;
case pTransferMode:
theErr = AEExtractEnumerated(theData, 0, &theMode);
if (theMode == kAEQDDitherCopy) theErr = DoSetImageDither(theImage, true);
else if (theMode == kAEQDCopy) theErr = DoSetImageDither(theImage, false);
else theErr = errAETypeError;
break;
default:
theErr = errAEWriteDenied;
break;
}
return theErr;
}
/*
* MakeDrawingAreaObject(theWindow, theObject)
*
* Purpose: Creates a drawing area object descriptor for the given window
* Inputs: theWindow = pointer to the window, or nil for all windows
* theObject = pointer to an AEDesc to store the result
* Returns: an OSErr describing what went wrong
*
*/
OSErr MakeDrawingAreaObject(WindowPtr theWindow, AEDesc *theObject)
{
AEDesc theKey, theContainer;
long index = kAEFirst;
OSErr theErr = noErr;
theErr = MakeWindowObject(theWindow, &theContainer);
if (theErr == noErr) {
theErr = AECreateDesc(typeAbsoluteOrdinal, (void *)&index, sizeof(long), &theKey);
if (theErr == noErr) {
theErr = CreateObjSpecifier(cDrawingArea, &theContainer, formAbsolutePosition,
&theKey, false, theObject);
AEDisposeDesc(&theKey);
}
AEDisposeDesc(&theContainer);
}
return theErr;
}
/*
* MakeDrawPropertyObject(theWindow, theProperty, theObject)
*
* Purpose: Creates a property object descriptor for the given drawing area's property
* Inputs: theWindow = pointer to the window, or nil for all windows
* theObject = pointer to an AEDesc to store the result
* Returns: an OSErr describing what went wrong
*
*/
OSErr MakeDrawPropertyObject(WindowPtr theWindow, DescType theProperty, AEDesc *theObject)
{
AEDesc theKey, theContainer;
OSErr theErr = noErr;
theErr = MakeDrawingAreaObject(theWindow, &theContainer);
if (theErr == noErr) {
theErr = AECreateDesc(typeType, (void *)&theProperty, sizeof(DescType), &theKey);
if (theErr == noErr) {
theErr = CreateObjSpecifier(typeProperty, &theContainer, formPropertyID,
&theKey, false, theObject);
AEDisposeDesc(&theKey);
}
AEDisposeDesc(&theContainer);
}
return theErr;
}
/*
* DoSetColorTable(theWindow, theColors)
*
* Purpose: Sets the palette of the given window to the given set of colors
* Inputs: theWindow = pointer to the window
* theColors = a handle to the color table
* Returns: an OSErr describing what went wrong
*
*/
OSErr DoSetColorTable(WindowPtr theWindow, CTabHandle theColors)
{
ImageHandle theImage = FindImage(theWindow);
PaletteHandle thePalette;
if (!theImage) return errAEWriteDenied;
if (thePalette = NewPalette((*theColors)->ctSize + 1, theColors, pmTolerant, 0)) {
if ((*theImage)->palette) DisposePalette((*theImage)->palette);
(*theImage)->palette = thePalette;
SetPalette(theWindow, (*theImage)->palette, true);
ActivatePalette(theWindow);
if (theWindow == FWFrontWindow()) FWSelectWindow(theWindow);
if (!GWOrigSize(theImage)) KillGWorld(theImage);
(*theImage)->npalette = plNone;
} else return memFullErr;
return noErr;
}
/*
* DoSetPalette(theWindow, thePalette)
*
* Purpose: Sets the palette of the given window to the given palette,
* via DoSetColorTable
* Inputs: theWindow = pointer to the window
* thePalette = a constant specifying which palette to use
* Returns: an OSErr describing what went wrong
*
*/
OSErr DoSetPalette(WindowPtr theWindow, DescType thePalette)
{
ImageHandle theImage = FindImage(theWindow);
PaletteHandle newPalette = nil, copyPalette;
OSErr theErr = noErr;
Boolean hadGWorld;
short depth;
if (!theImage) return errAENoSuchObject;
hadGWorld = ((*theImage)->gworld != nil);
depth = (*(*theImage)->dmon)->depth;
switch (thePalette) {
case kAEPSystem:
newPalette = SystemPalette(depth);
(*theImage)->npalette = plSys;
break;
case kAEPGrayscale:
newPalette = GreyPalette(depth);
(*theImage)->npalette = plGrey;
break;
case kAEPImage:
newPalette = (*theImage)->ipalette;
if (newPalette) (*theImage)->npalette = plImage;
break;
case kAEPQuantized:
if ((*theImage)->depth < 16) break;
if (depth > 8) depth = 8;
if (!(*theImage)->qpalette ||
((*(*theImage)->qpalette)->pmEntries != (1L << depth))) {
theErr = DoQuantize(theImage, 1L << depth, &newPalette, nil);
if ((theErr == noErr) && newPalette) {
if ((*theImage)->qpalette) DisposePalette((*theImage)->qpalette);
(*theImage)->qpalette = newPalette;
}
}
newPalette = (*theImage)->qpalette;
if (newPalette) (*theImage)->npalette = plQuant;
break;
default:
return errAETypeError;
}
if (!newPalette && !(*theImage)->palette)
newPalette = SystemPalette(depth), (*theImage)->npalette = plSys;
if (newPalette) {
copyPalette = NewPalette((*newPalette)->pmEntries, nil, pmTolerant, 0);
if (copyPalette) {
CopyPalette(newPalette, copyPalette, 0, 0, (*newPalette)->pmEntries);
if ((*theImage)->palette) DisposePalette((*theImage)->palette);
(*theImage)->palette = copyPalette;
SetPalette(theWindow, (*theImage)->palette, true);
ActivatePalette(theWindow);
if (theWindow == FWFrontWindow()) FWSelectWindow(theWindow);
if (hadGWorld && !GWOrigSize(theImage)) KillGWorld(theImage);
} else theErr = memFullErr;
}
if (theErr == noErr && (*theImage)->npalette == plQuant && (*theImage)->gworld &&
!gThePrefs.origSize && (*(*theImage)->gworld->portPixMap)->pixelSize == (*theImage)->depth)
theErr = ShrinkGWorld(theImage);
return theErr;
}
/*
* DoSetImageDither(theWindow, dither)
*
* Purpose: Sets the dither flag of the given image to the specified value
* Inputs: theWindow = pointer to the window
* dither = flag: true to dither the image; false otherwise
* Returns: an OSErr describing what went wrong
*
*/
OSErr DoSetImageDither(ImageHandle theImage, Boolean dither)
{
Rect theRect = (*theImage)->wrect;
if (dither) (*theImage)->flags |= ifDithered;
else (*theImage)->flags &= ~ifDithered;
PushPort();
MySetPort((CGrafPtr)(*theImage)->window);
InvalRect(&theRect);
PopPort();
if ((*theImage)->gworld && !GWOrigSize(theImage))
KillGWorld(theImage);
return noErr;
}
/*
* DoSetImageQuality(theWindow, dither)
*
* Purpose: Sets the quality of the given image to the specified value
* Inputs: theWindow = pointer to the window
* dither = flag: true to dither the image; false otherwise
* Returns: an OSErr describing what went wrong
*
*/
OSErr DoSetImageQuality(ImageHandle theImage, DescType theQuality)
{
Rect theRect = (*theImage)->wrect;
switch (theQuality) {
case kAEDQVeryHigh:
(*theImage)->quality = iqVHigh;
break;
case kAEDQHigh:
(*theImage)->quality = iqHigh;
break;
case kAEDQNormal:
(*theImage)->quality = iqMedium;
break;
default:
return errAETypeError;
}
if (Dithered(theImage)) {
PushPort();
MySetPort((CGrafPtr)(*theImage)->window);
InvalRect(&theRect);
PopPort();
if ((*theImage)->gworld)
if (!GWOrigSize(theImage) || ((*(*theImage)->gworld->portPixMap)->pixelSize <= 8))
KillGWorld(theImage);
}
return noErr;
}
extern OSErr DoSetDrawBounds(ImageHandle theImage, Rect *theRect)
{
Rect oldRect = (*theImage)->wrect;
(*theImage)->wrect = *theRect;
ResizeWindow(theImage);
if (!EqualSizeRect(&(*theImage)->wrect, &oldRect)) {
PushPort();
MySetPort((CGrafPtr)(*theImage)->window);
InvalRect(&(*theImage)->window->portRect);
PopPort();
}
return noErr;
}