mirror of
https://github.com/aaronsgiles/JPEGView.git
synced 2024-06-06 21:29:27 +00:00
92bdb55672
These are the sources for the final official release of JPEGView for the Mac, back in 1994.
1 line
9.6 KiB
C
1 line
9.6 KiB
C
/*********************************************************/
|
|
/* This source code copyright (c) 1991-2001, Aaron Giles */
|
|
/* See the Read Me file for licensing information. */
|
|
/* Contact email: mac@aarongiles.com */
|
|
/*********************************************************/
|
|
|
|
//=====================================================================================
|
|
// Generic includes for Macintosh headers
|
|
//=====================================================================================
|
|
|
|
#if THINK_C
|
|
#include "THINK.Header"
|
|
#elif applec
|
|
#pragma load ":Headers:MPW.Header"
|
|
#elif __MWERKS__
|
|
//#include "MW.Header"
|
|
#else
|
|
#include "JPEGView.h"
|
|
#endif
|
|
|
|
//=====================================================================================
|
|
// Includes specific to this module
|
|
//=====================================================================================
|
|
|
|
#include "QuickDrawUtils.h"
|
|
|
|
//=====================================================================================
|
|
// PortStackItem: structure to store port and device information for when we push/pop
|
|
// the current port.
|
|
//=====================================================================================
|
|
|
|
typedef struct PortStackItem {
|
|
CGrafPtr port;
|
|
GDHandle device;
|
|
} PortStackItem, *PortStackPtr, **PortStackHandle;
|
|
|
|
//=====================================================================================
|
|
// Global variables local to this module
|
|
//=====================================================================================
|
|
|
|
static PortStackItem gPortStack[64];
|
|
static PortStackPtr gPortStackPtr = gPortStack;
|
|
|
|
//=====================================================================================
|
|
// void PushPort(void)
|
|
//
|
|
// Pushes the current port and device onto the port stack.
|
|
//
|
|
// External calls: none
|
|
//=====================================================================================
|
|
|
|
void PushPort(void)
|
|
{
|
|
GetGWorld(&gPortStackPtr->port, &gPortStackPtr->device);
|
|
gPortStackPtr++;
|
|
}
|
|
|
|
//=====================================================================================
|
|
// void PopPort(void)
|
|
//
|
|
// Pops a port and device from the port stack into the current graphics environment.
|
|
//
|
|
// External calls: none
|
|
//=====================================================================================
|
|
|
|
void PopPort(void)
|
|
{
|
|
gPortStackPtr--;
|
|
SetGWorld(gPortStackPtr->port, gPortStackPtr->device);
|
|
}
|
|
|
|
//=====================================================================================
|
|
// void MySetPort(CGrafPtr thePort)
|
|
//
|
|
// Sets the current port; if nil is passed as the port, the current port is set to
|
|
// the window manager's port.
|
|
//
|
|
// External calls: none
|
|
//=====================================================================================
|
|
|
|
void MySetPort(CGrafPtr thePort)
|
|
{
|
|
if (!thePort) GetCWMgrPort(&thePort);
|
|
if (thePort) SetGWorld(thePort, nil);
|
|
}
|
|
|
|
extern GWorldPtr NewTempGWorld(short width, short height, short depth, CTabHandle colors)
|
|
{
|
|
Boolean oldState = GetQDxDispatchPatchState();
|
|
GWorldPtr theGWorld = nil;
|
|
OSErr theErr = noErr;
|
|
Rect theRect;
|
|
|
|
SetRect(&theRect, 0, 0, width, height);
|
|
do {
|
|
InstallQDxDispatchPatch(false);
|
|
theErr = NewGWorld(&theGWorld, depth, &theRect, colors, nil, keepLocal + useTempMem);
|
|
SetQDxDispatchPatchState(oldState);
|
|
if (theErr != noErr) {
|
|
if (IsMemAvailable(EstGWorldSize(&theRect, depth)))
|
|
theErr = NewGWorld(&theGWorld, depth, &theRect, colors, nil, keepLocal);
|
|
else theErr = memFullErr;
|
|
}
|
|
if (theErr != noErr) {
|
|
if (theRect.bottom == 8) {
|
|
theGWorld = nil;
|
|
break;
|
|
}
|
|
theRect.bottom -= height / 8;
|
|
if (theRect.bottom < 8) theRect.bottom = 8;
|
|
}
|
|
} while (theErr != noErr);
|
|
return (theErr == noErr) ? theGWorld : nil;
|
|
}
|
|
|
|
//=====================================================================================
|
|
// GWorldPtr MyNewGWorld(Rect *theRect, short theDepth, CTabHandle theColors,
|
|
// GDHandle theDevice, Boolean whiteBack, Boolean inTempMem)
|
|
//
|
|
// Creates a new GWorld, erases it, and initializes the colors.
|
|
//
|
|
// External calls: none
|
|
//=====================================================================================
|
|
|
|
GWorldPtr MyNewGWorld(Rect *theRect, short theDepth, CTabHandle theColors,
|
|
GDHandle theDevice, Boolean whiteBack, Boolean inTempMem)
|
|
{
|
|
Boolean oldState = GetQDxDispatchPatchState();
|
|
long flags = keepLocal;
|
|
GWorldPtr theGWorld;
|
|
|
|
PushPort();
|
|
MySetPort(nil);
|
|
if (inTempMem) {
|
|
flags += useTempMem;
|
|
InstallQDxDispatchPatch(false);
|
|
}
|
|
if (NewGWorld(&theGWorld, theDepth, theRect, theColors, theDevice, flags) == noErr) {
|
|
MySetPort(theGWorld);
|
|
LockPixels(GetGWorldPixMap(theGWorld));
|
|
RectRgn(theGWorld->visRgn, theRect);
|
|
RectRgn(theGWorld->clipRgn, theRect);
|
|
RGBForeColor(&gBlack);
|
|
RGBBackColor(&gWhite);
|
|
if (!whiteBack) PaintRect(theRect);
|
|
else EraseRect(theRect);
|
|
UnlockPixels(GetGWorldPixMap(theGWorld));
|
|
PopPort();
|
|
if (inTempMem) SetQDxDispatchPatchState(oldState);
|
|
return theGWorld;
|
|
}
|
|
PopPort();
|
|
if (inTempMem) SetQDxDispatchPatchState(oldState);
|
|
return nil;
|
|
}
|
|
|
|
extern void MaxRect(Rect *srcRect, Rect *boundingRect, Rect *dstRect)
|
|
{
|
|
dstRect->top = dstRect->left = 0;
|
|
if (Width(srcRect) > Height(srcRect)) {
|
|
dstRect->right = Width(boundingRect);
|
|
dstRect->bottom = (long)Height(srcRect) * Width(boundingRect) / (long)Width(srcRect);
|
|
} else {
|
|
dstRect->right = (long)Width(srcRect) * Height(boundingRect) / (long)Height(srcRect);
|
|
dstRect->bottom = Height(boundingRect);
|
|
}
|
|
OffsetRect(dstRect, boundingRect->left, boundingRect->top);
|
|
}
|
|
|
|
extern void MaxSquare(Rect *srcRect, Rect *squareRect)
|
|
{
|
|
*squareRect = *srcRect;
|
|
if (Width(srcRect) > Height(srcRect)) {
|
|
squareRect->left += (Width(srcRect) - Height(srcRect)) >> 1;
|
|
squareRect->right = squareRect->left + Height(srcRect);
|
|
} else {
|
|
squareRect->top += (Height(srcRect) - Width(srcRect)) >> 1;
|
|
squareRect->bottom = squareRect->top + Width(srcRect);
|
|
}
|
|
}
|
|
|
|
extern void CopyGWorldToGWorld(GWorldPtr gw1, GWorldPtr gw2, Rect *srcRect, Rect *dstRect,
|
|
short mode, RgnHandle mask)
|
|
{
|
|
PixMapHandle pm1 = GetGWorldPixMap(gw1), pm2 = GetGWorldPixMap(gw2);
|
|
GWorldFlags state1 = GetPixelsState(pm1), state2 = GetPixelsState(pm2);
|
|
char hstate1 = HGetState((Handle)pm1), hstate2 = HGetState((Handle)pm2);
|
|
|
|
PushPort();
|
|
MySetPort(gw2);
|
|
HLock((Handle)pm1);
|
|
HLock((Handle)pm2);
|
|
LockPixels(pm1);
|
|
LockPixels(pm2);
|
|
CopyBits((BitMap *)*pm1, (BitMap *)*pm2, srcRect, dstRect, mode, mask);
|
|
SetPixelsState(pm1, state1);
|
|
SetPixelsState(pm2, state2);
|
|
HSetState((Handle)pm1, hstate1);
|
|
HSetState((Handle)pm2, hstate2);
|
|
PopPort();
|
|
}
|
|
|
|
//=====================================================================================
|
|
// void GlobalRect(Rect *theRect, WindowPtr theWindow)
|
|
//
|
|
// Converts the given rectangle to global coordinates, relative to the window.
|
|
//
|
|
// External calls: none
|
|
//=====================================================================================
|
|
|
|
void GlobalRect(Rect *theRect, WindowPtr theWindow)
|
|
{
|
|
Boolean change = (theWindow != qd.thePort);
|
|
Point thePoint = { 0, 0 };
|
|
|
|
if (change) {
|
|
PushPort();
|
|
MySetPort((CGrafPtr)theWindow);
|
|
}
|
|
LocalToGlobal(&thePoint);
|
|
if (change) PopPort();
|
|
OffsetRect(theRect, thePoint.h, thePoint.v);
|
|
}
|
|
|
|
//=====================================================================================
|
|
// void GlobalRgn(RgnHandle theRgn, WindowPtr theWindow)
|
|
//
|
|
// Converts the given region to global coordinates, relative to the window.
|
|
//
|
|
// External calls: none
|
|
//=====================================================================================
|
|
|
|
void GlobalRgn(RgnHandle theRgn, WindowPtr theWindow)
|
|
{
|
|
Boolean change = (theWindow != qd.thePort);
|
|
Point thePoint = { 0, 0 };
|
|
|
|
if (change) {
|
|
PushPort();
|
|
MySetPort((CGrafPtr)theWindow);
|
|
}
|
|
LocalToGlobal(&thePoint);
|
|
if (change) PopPort();
|
|
OffsetRgn(theRgn, thePoint.h, thePoint.v);
|
|
}
|
|
|
|
//=====================================================================================
|
|
// void LocalRect(Rect *theRect, WindowPtr theWindow)
|
|
//
|
|
// Converts the given rectangle to local coordinates, relative to the window.
|
|
//
|
|
// External calls: none
|
|
//=====================================================================================
|
|
|
|
void LocalRect(Rect *theRect, WindowPtr theWindow)
|
|
{
|
|
Boolean change = (theWindow != qd.thePort);
|
|
Point thePoint = { 0, 0 };
|
|
|
|
if (change) {
|
|
PushPort();
|
|
MySetPort((CGrafPtr)theWindow);
|
|
}
|
|
GlobalToLocal(&thePoint);
|
|
if (change) PopPort();
|
|
OffsetRect(theRect, thePoint.h, thePoint.v);
|
|
}
|
|
|
|
//=====================================================================================
|
|
// void LocalRgn(RgnHandle theRgn, WindowPtr theWindow)
|
|
//
|
|
// Converts the given region to local coordinates, relative to the window.
|
|
//
|
|
// External calls: none
|
|
//=====================================================================================
|
|
|
|
void LocalRgn(RgnHandle theRgn, WindowPtr theWindow)
|
|
{
|
|
Boolean change = (theWindow != qd.thePort);
|
|
Point thePoint = { 0, 0 };
|
|
|
|
if (change) {
|
|
PushPort();
|
|
MySetPort((CGrafPtr)theWindow);
|
|
}
|
|
GlobalToLocal(&thePoint);
|
|
if (change) PopPort();
|
|
OffsetRgn(theRgn, thePoint.h, thePoint.v);
|
|
}
|
|
|
|
//=====================================================================================
|
|
// Boolean Clipped(Rect *theRect, RgnHandle clipRgn)
|
|
//
|
|
// Determines if the given rectangle is clipped by the region.
|
|
//
|
|
// External calls: none
|
|
//=====================================================================================
|
|
|
|
Boolean Clipped(Rect *theRect, RgnHandle clipRgn)
|
|
{
|
|
RgnHandle rectRgn, clippedRgn;
|
|
Boolean result = false;
|
|
|
|
if (!clipRgn || !theRect) return false;
|
|
if (rectRgn = NewRgn()) {
|
|
if (clippedRgn = NewRgn()) {
|
|
RectRgn(rectRgn, theRect);
|
|
SectRgn(rectRgn, clipRgn, clippedRgn);
|
|
result = !EqualRgn(rectRgn, clippedRgn);
|
|
DisposeRgn(clippedRgn);
|
|
}
|
|
DisposeRgn(rectRgn);
|
|
}
|
|
return result;
|
|
}
|