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
17 KiB
C
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 */
|
|
/*********************************************************/
|
|
|
|
//=====================================================================================
|
|
// Generic includes for Macintosh headers
|
|
//=====================================================================================
|
|
|
|
#if THINK_C
|
|
#include "THINK.Header"
|
|
#include <stddef.h>
|
|
#elif applec
|
|
#pragma load ":Headers:MPW.Header"
|
|
#elif __MWERKS__
|
|
//#include "MW.Header"
|
|
#else
|
|
#include "JPEGView.h"
|
|
#endif
|
|
|
|
//=====================================================================================
|
|
// Includes specific to this module
|
|
//=====================================================================================
|
|
|
|
#include "CustomCopyBits.h"
|
|
#include "QuickDrawUtils.h"
|
|
|
|
#if !USE_ASM
|
|
#if __MWERKS__
|
|
#define kStackRowWidth 1024
|
|
#else
|
|
#define kStackRowWidth 1750
|
|
#endif
|
|
#endif
|
|
|
|
//=====================================================================================
|
|
// CopyData: structure for passing data between the C and assembly language portions of
|
|
// the code
|
|
//=====================================================================================
|
|
|
|
#if USE_ASM
|
|
typedef struct DitherErrors {
|
|
short red;
|
|
short green;
|
|
short blue;
|
|
} DitherErrors, *DitherErrorsPtr;
|
|
|
|
typedef struct RgnBuffer {
|
|
short yCount;
|
|
short zero;
|
|
short buffer[127];
|
|
} RgnBuffer, *RgnBufferPtr;
|
|
#else
|
|
typedef struct DitherErrors {
|
|
long red;
|
|
long green;
|
|
long blue;
|
|
} DitherErrors, *DitherErrorsPtr;
|
|
|
|
typedef struct RgnBuffer {
|
|
long yCount;
|
|
long zero;
|
|
long buffer[127];
|
|
} RgnBuffer, *RgnBufferPtr;
|
|
#endif
|
|
|
|
typedef (*DitherToDestPtr)(ulong *srcRow, void *dstRow, uchar *iTable,
|
|
ColorSpec *cTable, DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer,
|
|
long *rgnBuffer, short *errorMap, long columns);
|
|
|
|
typedef struct CopyData {
|
|
// Needed for all copy routines
|
|
ColorSpec *ctAddr; // color table address
|
|
uchar *itAddr; // inverse color table address
|
|
DitherErrorsPtr evenAddr,// even dithering buffer
|
|
oddAddr; // odd dithering buffer
|
|
DitherToDestPtr even, // address of even row dithering routine
|
|
odd; // address of odd row dithering routine
|
|
short *errTable; // address of dithering table
|
|
long srcRow, // row bytes in source pixmap
|
|
dstRow; // row bytes in destination pixmap
|
|
Ptr srcBase, // base address of source pixmap
|
|
dstBase; // base address of destination pixmap
|
|
#if USE_ASM
|
|
short rgnBuffer[512], // buffer for holding region data
|
|
width, // total width of image
|
|
height, // total height of image
|
|
evodd; // word holding the even/odd row status
|
|
#else
|
|
long rgnBuffer[512],
|
|
width, // total width of image
|
|
height, // total height of image
|
|
evodd; // word holding the even/odd row status
|
|
#endif
|
|
RgnHandle theRgn; // handle to the clipping region
|
|
Rect boxRect; // outer rect of the region
|
|
|
|
// Needed only for CopyScaled routines
|
|
#if USE_ASM
|
|
short srcHeight, // height of the source rectangle
|
|
srcWidth, // width of same
|
|
dstHeight, // height of the destination rectangle
|
|
dstWidth, // width of same
|
|
xRemainder, // starting remainder in x
|
|
yRemainder, // starting remainder in y
|
|
columns, // internal counter for columns
|
|
rows; // internal counter for rows
|
|
#else
|
|
long srcHeight, // height of the source rectangle
|
|
srcWidth, // width of same
|
|
dstHeight, // height of the destination rectangle
|
|
dstWidth, // width of same
|
|
xRemainder, // starting remainder in x
|
|
yRemainder, // starting remainder in y
|
|
columns, // internal counter for columns
|
|
rows; // internal counter for rows
|
|
#endif
|
|
Ptr outputAddr, // internal holder for destination address
|
|
sTable[6]; // pointers into the scaling table
|
|
} CopyData, *CopyDataPtr, **CopyDataHandle;
|
|
|
|
//=====================================================================================
|
|
// Global variables local to this module
|
|
//=====================================================================================
|
|
|
|
static Point gZeroPoint = { 0, 0 };
|
|
static RgnHandle gTheRgn = nil;
|
|
static CopyData gCopyData;
|
|
|
|
//=====================================================================================
|
|
// Prototypes for functions local to this module
|
|
//=====================================================================================
|
|
|
|
static void InitCopyData(void);
|
|
|
|
#if !USE_ASM
|
|
static void CopyUnscaledFrom32(CopyDataPtr theData);
|
|
static void CopyReallyFastScaledFrom32(CopyDataPtr theData);
|
|
static void CopyFastScaledFrom32(CopyDataPtr theData);
|
|
static void CopyScaledFrom32(CopyDataPtr theData);
|
|
static void CopyTo32(ulong *srcRow, void *dstRow, uchar *iTable, ColorSpec *cTable,
|
|
DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer, long *rgnBuffer,
|
|
short *errorMap, long columns);
|
|
static void DitherCopyTo16Even(ulong *srcRow, void *dstRow, uchar *iTable,
|
|
ColorSpec *cTable, DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer,
|
|
long *rgnBuffer, short *errorMap, long columns);
|
|
static void DitherCopyTo16Odd(ulong *srcRow, void *dstRow, uchar *iTable,
|
|
ColorSpec *cTable, DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer,
|
|
long *rgnBuffer, short *errorMap, long columns);
|
|
static void DitherCopyTo8Even(ulong *srcRow, void *dstRow, uchar *iTable,
|
|
ColorSpec *cTable, DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer,
|
|
long *rgnBuffer, short *errorMap, long columns);
|
|
static void DitherCopyTo8Odd(ulong *srcRow, void *dstRow, uchar *iTable,
|
|
ColorSpec *cTable, DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer,
|
|
long *rgnBuffer, short *errorMap, long columns);
|
|
static short *InitRegion(RgnPtr rgn, RgnBufferPtr rgnBuffer, Rect *boxRect);
|
|
static short *UpdateRegion(short *rgnData, RgnBufferPtr rgnBuffer, Rect *boxRect);
|
|
#elif THINK_C
|
|
static void CopyUnscaledFrom32(CopyDataPtr theData);
|
|
static void CopyReallyFastScaledFrom32(CopyDataPtr theData);
|
|
static void CopyScaledFrom32(CopyDataPtr theData);
|
|
static void CopyFastScaledFrom32(CopyDataPtr theData);
|
|
static void CopyTo32(void);
|
|
static void DitherCopyTo16Even(void);
|
|
static void DitherCopyTo16Odd(void);
|
|
static void DitherCopyTo8Even(void);
|
|
static void DitherCopyTo8Odd(void);
|
|
static void InitRegion(void);
|
|
static void UpdateRegion(void);
|
|
#else
|
|
extern void CopyUnscaledFrom32(CopyDataPtr theData);
|
|
extern void CopyReallyFastScaledFrom32(CopyDataPtr theData);
|
|
extern void CopyScaledFrom32(CopyDataPtr theData);
|
|
extern void CopyFastScaledFrom32(CopyDataPtr theData);
|
|
extern void CopyTo32(void);
|
|
extern void DitherCopyTo16Even(void);
|
|
extern void DitherCopyTo16Odd(void);
|
|
extern void DitherCopyTo8Even(void);
|
|
extern void DitherCopyTo8Odd(void);
|
|
#endif
|
|
|
|
//=====================================================================================
|
|
// void InitCopyData(void)
|
|
//
|
|
// One-time initialization of several static fields in the global CopyData structure
|
|
//
|
|
// External calls: none
|
|
//=====================================================================================
|
|
|
|
void InitCopyData(void)
|
|
{
|
|
gCopyData.theRgn = gTheRgn = NewRgn();
|
|
gCopyData.errTable = gErrTable;
|
|
gCopyData.sTable[0] = (Ptr)gScaleTable;
|
|
gCopyData.sTable[1] = gCopyData.sTable[0] + (3 << 8);
|
|
gCopyData.sTable[2] = gCopyData.sTable[1] + (4 << 8);
|
|
gCopyData.sTable[3] = gCopyData.sTable[2] + (5 << 8);
|
|
gCopyData.sTable[4] = gCopyData.sTable[3] + (6 << 8);
|
|
gCopyData.sTable[5] = gCopyData.sTable[4] + (7 << 8);
|
|
}
|
|
|
|
//=====================================================================================
|
|
// void DoCustomCopy(PixMap *src, PixMap *dst, Rect *srcRect, Rect *dstRect,
|
|
// Boolean fast, short depth)
|
|
//
|
|
// Performs the appropriate variation of our custom CopyBits routine, according to the
|
|
// fast, depth, and srcRect/dstRect parameters.
|
|
//
|
|
// External calls: GlobalRect, GlobalRgn, Width, Height
|
|
//=====================================================================================
|
|
|
|
void DoCustomCopy(PixMap *src, PixMap *dst, Rect *srcRect, Rect *dstRect,
|
|
Boolean fast, short depth)
|
|
{
|
|
GDHandle theGDevice = GetGDevice();
|
|
Boolean onScreen = ((*theGDevice)->gdFlags & (1L << screenActive)) != 0;
|
|
char mode = true32b;
|
|
CTabHandle theCTab;
|
|
ITabHandle theITab;
|
|
Rect globDRect;
|
|
|
|
// Initialize the global copy data, if necessary
|
|
if (!gTheRgn) InitCopyData();
|
|
|
|
// Initialize the even/odd function pointers
|
|
switch (depth) {
|
|
case 32:
|
|
gCopyData.even = (DitherToDestPtr)CopyTo32;
|
|
gCopyData.odd = (DitherToDestPtr)CopyTo32;
|
|
break;
|
|
case 16:
|
|
gCopyData.even = (DitherToDestPtr)DitherCopyTo16Even;
|
|
gCopyData.odd = (DitherToDestPtr)DitherCopyTo16Odd;
|
|
break;
|
|
case 8:
|
|
gCopyData.even = (DitherToDestPtr)DitherCopyTo8Even;
|
|
gCopyData.odd = (DitherToDestPtr)DitherCopyTo8Odd;
|
|
break;
|
|
}
|
|
|
|
// Globalize the destination rectangle
|
|
globDRect = *dstRect;
|
|
if (onScreen) GlobalRect(&globDRect, qd.thePort);
|
|
|
|
// Calculate the global intersection of the clipRgn, visRgn, and dstRect
|
|
// Note that we set the evodd value while the rectangle is still *local*
|
|
RectRgn(gCopyData.theRgn, dstRect);
|
|
SectRgn(qd.thePort->clipRgn, gCopyData.theRgn, gCopyData.theRgn);
|
|
SectRgn(qd.thePort->visRgn, gCopyData.theRgn, gCopyData.theRgn);
|
|
gCopyData.evodd = (*gCopyData.theRgn)->rgnBBox.top;
|
|
if (onScreen) GlobalRgn(gCopyData.theRgn, qd.thePort);
|
|
|
|
// If the resulting region is empty, return before we do anything
|
|
if (EmptyRgn(gCopyData.theRgn)) return;
|
|
|
|
// Use the resulting region bounding box as our real dst rect
|
|
gCopyData.boxRect = (*gCopyData.theRgn)->rgnBBox;
|
|
gCopyData.height = Height(&gCopyData.boxRect);
|
|
gCopyData.width = Width(&gCopyData.boxRect);
|
|
|
|
// Calculate widths and heights
|
|
gCopyData.dstHeight = Height(dstRect);
|
|
gCopyData.dstWidth = Width(dstRect);
|
|
gCopyData.srcHeight = Height(srcRect);
|
|
gCopyData.srcWidth = Width(srcRect);
|
|
|
|
// Get the base addresses, offset by the dst and src rectangles
|
|
gCopyData.srcBase = GetPixBaseAddr(&src);
|
|
gCopyData.dstBase = GetPixBaseAddr(&dst);
|
|
gCopyData.srcRow = src->rowBytes & 0x3fff;
|
|
gCopyData.dstRow = dst->rowBytes & 0x3fff;
|
|
gCopyData.srcBase += gCopyData.srcRow *
|
|
((srcRect->top - src->bounds.top) +
|
|
((long)(gCopyData.boxRect.top - globDRect.top) *
|
|
(long)gCopyData.srcHeight / (long)gCopyData.dstHeight));
|
|
gCopyData.srcBase += ((srcRect->left - src->bounds.left) +
|
|
(long)(gCopyData.boxRect.left - globDRect.left) *
|
|
(long)gCopyData.srcWidth / (long)gCopyData.dstWidth) << 2;
|
|
gCopyData.dstBase += gCopyData.dstRow *
|
|
(gCopyData.boxRect.top - dst->bounds.top) +
|
|
(((long)(gCopyData.boxRect.left - dst->bounds.left) * (long)dst->pixelSize) >> 3);
|
|
|
|
// Calculate initial remainders for the source at this point
|
|
gCopyData.xRemainder = gCopyData.dstWidth -
|
|
((long)(gCopyData.boxRect.left - globDRect.left) * (long)gCopyData.srcWidth) %
|
|
(long)gCopyData.dstWidth;
|
|
#if USE_ASM
|
|
gCopyData.xRemainder = ((long)gCopyData.xRemainder << 10) / (long)gCopyData.srcWidth;
|
|
#else
|
|
gCopyData.xRemainder = ((long)gCopyData.xRemainder << 16) / (long)gCopyData.srcWidth;
|
|
#endif
|
|
gCopyData.yRemainder = gCopyData.dstHeight -
|
|
((long)(gCopyData.boxRect.top - globDRect.top) * (long)gCopyData.srcHeight) %
|
|
(long)gCopyData.dstHeight;
|
|
#if USE_ASM
|
|
gCopyData.yRemainder = ((long)gCopyData.yRemainder << 10) / (long)gCopyData.srcHeight;
|
|
#else
|
|
gCopyData.yRemainder = ((long)gCopyData.yRemainder << 16) / (long)gCopyData.srcHeight;
|
|
#endif
|
|
|
|
// Get handles to the color tables
|
|
theCTab = (*(*theGDevice)->gdPMap)->pmTable;
|
|
theITab = (*theGDevice)->gdITable;
|
|
|
|
// Shield the cursor if necessary and get the final pointers
|
|
if (onScreen) ShieldCursor(&gCopyData.boxRect, gZeroPoint);
|
|
if (theITab) gCopyData.itAddr = (*theITab)->iTTable;
|
|
if (theCTab) gCopyData.ctAddr = (*theCTab)->ctTable;
|
|
|
|
// Do the copy
|
|
SwapMMUMode(&mode);
|
|
if (EqualSizeRect(srcRect, dstRect)) CopyUnscaledFrom32(&gCopyData);
|
|
else if (fast) CopyReallyFastScaledFrom32(&gCopyData);//CopyFastScaledFrom32(&gCopyData);
|
|
else CopyScaledFrom32(&gCopyData);
|
|
SwapMMUMode(&mode);
|
|
if (onScreen) ShowCursor();
|
|
}
|
|
|
|
#if !USE_ASM
|
|
|
|
//=====================================================================================
|
|
// Generic C substitutes for the assembly functions defined below.
|
|
//=====================================================================================
|
|
|
|
static void CopyUnscaledFrom32(CopyDataPtr theData)
|
|
{
|
|
#include "CopyUnscaledFrom32.c"
|
|
}
|
|
|
|
static void CopyReallyFastScaledFrom32(CopyDataPtr theData)
|
|
{
|
|
#include "CopyReallyFastScaledFrom32.c"
|
|
}
|
|
|
|
static void CopyFastScaledFrom32(CopyDataPtr theData)
|
|
{
|
|
#include "CopyFastScaledFrom32.c"
|
|
}
|
|
|
|
static void CopyScaledFrom32(CopyDataPtr theData)
|
|
{
|
|
#include "CopyScaledFrom32.c"
|
|
}
|
|
|
|
static void CopyTo32(ulong *srcRow, void *dstRow, uchar *iTable, ColorSpec *cTable,
|
|
DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer, long *rgnBuffer,
|
|
short *errorMap, long columns)
|
|
{
|
|
#include "CopyTo32.c"
|
|
}
|
|
|
|
static void DitherCopyTo16Even(ulong *srcRow, void *dstRowStart, uchar *iTable,
|
|
ColorSpec *cTable, DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer,
|
|
long *rgnBuffer, short *errorMap, long columns)
|
|
{
|
|
#include "DitherCopyTo16Even.c"
|
|
}
|
|
|
|
static void DitherCopyTo16Odd(ulong *srcRow, void *dstRowStart, uchar *iTable,
|
|
ColorSpec *cTable, DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer,
|
|
long *rgnBuffer, short *errorMap, long columns)
|
|
{
|
|
#include "DitherCopyTo16Odd.c"
|
|
}
|
|
|
|
static void DitherCopyTo8Even(ulong *srcRow, void *dstRowStart, uchar *iTable,
|
|
ColorSpec *cTable, DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer,
|
|
long *rgnBuffer, short *errorMap, long columns)
|
|
{
|
|
#include "DitherCopyTo8Even.c"
|
|
}
|
|
|
|
static void DitherCopyTo8Odd(ulong *srcRow, void *dstRowStart, uchar *iTable,
|
|
ColorSpec *cTable, DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer,
|
|
long *rgnBuffer, short *errorMap, long columns)
|
|
{
|
|
#include "DitherCopyTo8Odd.c"
|
|
}
|
|
|
|
static short *InitRegion(RgnPtr rgn, RgnBufferPtr rgnBuffer, Rect *boxRect)
|
|
{
|
|
#include "InitRegion.c"
|
|
}
|
|
|
|
static short *UpdateRegion(short *rgnData, RgnBufferPtr rgnBuffer, Rect *boxRect)
|
|
{
|
|
#include "UpdateRegion.c"
|
|
}
|
|
|
|
#elif THINK_C
|
|
|
|
//=====================================================================================
|
|
// Assembly language interfaces for THINK C; here we define the offsets of all fields
|
|
// within the CopyData structure, and then provide C function wrappers around asm { }
|
|
// statements that #include the actual assembly code. In MPW, we just need to compile
|
|
// CustomCopyBits.a to get the assembly routines.
|
|
//=====================================================================================
|
|
|
|
#define ctAddr offsetof(CopyData, ctAddr) /* 0 */
|
|
#define itAddr offsetof(CopyData, itAddr) /* 4 */
|
|
#define evenAddr offsetof(CopyData, evenAddr) /* 8 */
|
|
#define oddAddr offsetof(CopyData, oddAddr) /* 12 */
|
|
#define even offsetof(CopyData, even) /* 16 */
|
|
#define odd offsetof(CopyData, odd) /* 20 */
|
|
#define errTable offsetof(CopyData, errTable) /* 24 */
|
|
#define srcRow offsetof(CopyData, srcRow) /* 28 */
|
|
#define dstRow offsetof(CopyData, dstRow) /* 32 */
|
|
#define srcBase offsetof(CopyData, srcBase) /* 36 */
|
|
#define dstBase offsetof(CopyData, dstBase) /* 40 */
|
|
#define rgnBuffer offsetof(CopyData, rgnBuffer) /* 44 */
|
|
#define width offsetof(CopyData, width) /* 1068 */
|
|
#define height offsetof(CopyData, height) /* 1070 */
|
|
#define evodd offsetof(CopyData, evodd) /* 1072 */
|
|
#define theRgn offsetof(CopyData, theRgn) /* 1074 */
|
|
#define boxRect offsetof(CopyData, boxRect) /* 1078 */
|
|
#define srcHeight offsetof(CopyData, srcHeight) /* 1086 */
|
|
#define srcWidth offsetof(CopyData, srcWidth) /* 1088 */
|
|
#define dstHeight offsetof(CopyData, dstHeight) /* 1090 */
|
|
#define dstWidth offsetof(CopyData, dstWidth) /* 1092 */
|
|
#define xRemainder offsetof(CopyData, xRemainder)/* 1094 */
|
|
#define yRemainder offsetof(CopyData, yRemainder)/* 1096 */
|
|
#define columns offsetof(CopyData, columns) /* 1098 */
|
|
#define rows offsetof(CopyData, rows) /* 1100 */
|
|
#define outputAddr offsetof(CopyData, outputAddr)/* 1102 */
|
|
#define sTable offsetof(CopyData, sTable) /* 1106 */
|
|
|
|
void CopyUnscaledFrom32(CopyDataPtr theData)
|
|
{
|
|
asm {
|
|
#include "CopyUnscaledFrom32.a"
|
|
}
|
|
}
|
|
|
|
void CopyScaledFrom32(CopyDataPtr theData)
|
|
{
|
|
asm {
|
|
#include "CopyScaledFrom32.a"
|
|
}
|
|
}
|
|
|
|
void CopyReallyFastScaledFrom32(CopyDataPtr theData)
|
|
{
|
|
asm {
|
|
#include "CopyReallyFastScaledFrom32.a"
|
|
}
|
|
}
|
|
|
|
void CopyFastScaledFrom32(CopyDataPtr theData)
|
|
{
|
|
asm {
|
|
#include "CopyFastScaledFrom32.a"
|
|
}
|
|
}
|
|
|
|
void CopyTo32(void)
|
|
{
|
|
asm {
|
|
#include "CopyTo32.a"
|
|
}
|
|
}
|
|
|
|
void DitherCopyTo16Even(void)
|
|
{
|
|
asm {
|
|
#include "DitherCopyTo16Even.a"
|
|
}
|
|
}
|
|
|
|
void DitherCopyTo16Odd(void)
|
|
{
|
|
asm {
|
|
#include "DitherCopyTo16Odd.a"
|
|
}
|
|
}
|
|
|
|
void DitherCopyTo8Even(void)
|
|
{
|
|
asm {
|
|
#include "DitherCopyTo8Even.a"
|
|
}
|
|
}
|
|
|
|
void DitherCopyTo8Odd(void)
|
|
{
|
|
asm {
|
|
#include "DitherCopyTo8Odd.a"
|
|
}
|
|
}
|
|
|
|
void InitRegion(void)
|
|
{
|
|
asm {
|
|
#include "InitRegion.a"
|
|
}
|
|
}
|
|
|
|
void UpdateRegion(void)
|
|
{
|
|
asm {
|
|
#include "UpdateRegion.a"
|
|
}
|
|
}
|
|
|
|
#endif
|