JPEGView/Source/C/CustomCopyBits.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 */
/*********************************************************/
//=====================================================================================
// 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