home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacFormat 1999 Spring
/
macformat-077.iso
/
Shareware Plus
/
Development
/
SpriteWorld 2.2
/
SpriteWorld files
/
Utils
/
SWFastLine.c
< prev
next >
Encoding:
Amiga
Atari
Commodore
DOS
FM Towns/JPY
Macintosh
Macintosh JP
NeXTSTEP
RISC OS/Acorn
UTF-8
Wrap
Text File
|
1999-01-01
|
57.3 KB
|
2,096 lines
|
[
TEXT/CWIE
]
///--------------------------------------------------------------------------------------
// SWFastLine.c
//
// Everything except BlitLine68kAsm is by Vern Jensen, 12/21/98.
// BlitLine68kAsm is by Oleg Doperchuk, and is believed to be in the public domain.
// Thanks to Alex Ni for getting it to compile under CodeWarrior.
///--------------------------------------------------------------------------------------
#include "SWFastLine.h"
#define SIGN(x) ((x) < 0 ? -1 : ((x) > 0 ? 1 : 0))
#define ABS(x) ((x) < 0 ? -(x) : (x))
#if !SW_PPC
///--------------------------------------------------------------------------------------
// SWDrawLine68kAsm - warning, no clipping is performed by this function!
///--------------------------------------------------------------------------------------
SW_FUNC void SWDrawLine68kAsm(
FramePtr dstFrameP,
Point srcPoint,
Point dstPoint,
Byte color)
{
Ptr baseAddr = dstFrameP->frameBaseAddr + dstFrameP->scanLinePtrArray[0];
unsigned long rowBytes = dstFrameP->frameRowBytes;
SW_ASSERT(dstFrameP != NULL && dstFrameP->isFrameLocked);
SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
SW_ASSERT(srcPoint.h >= dstFrameP->frameRect.left && srcPoint.h < dstFrameP->frameRect.right);
SW_ASSERT(srcPoint.v >= dstFrameP->frameRect.top && srcPoint.v < dstFrameP->frameRect.bottom);
SW_ASSERT(dstPoint.h >= dstFrameP->frameRect.left && dstPoint.h < dstFrameP->frameRect.right);
SW_ASSERT(dstPoint.v >= dstFrameP->frameRect.top && dstPoint.v < dstFrameP->frameRect.bottom);
START_32_BIT_MODE
BlitLine68kAsm(baseAddr, rowBytes, srcPoint.h, dstPoint.h, srcPoint.v, dstPoint.v, color);
END_32_BIT_MODE
}
#endif
///--------------------------------------------------------------------------------------
// SWDrawLine
///--------------------------------------------------------------------------------------
SW_FUNC void SWDrawLine(
FramePtr dstFrameP,
Point srcPoint,
Point dstPoint,
Byte color)
{
Boolean thereIsALine = true;
SW_ASSERT(dstFrameP != NULL && dstFrameP->isFrameLocked);
SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
START_32_BIT_MODE
// Check to see if the line is straight horizontally or vertically
if (srcPoint.v == dstPoint.v || srcPoint.h == dstPoint.h)
{
BlitStraightLine(dstFrameP, srcPoint, dstPoint, color);
}
else
{
// Clip the line with the frameRect
thereIsALine = SWClipLineWithRect(&srcPoint, &dstPoint, &dstFrameP->frameRect);
if (thereIsALine)
BlitLine(dstFrameP, srcPoint, dstPoint, color);
}
END_32_BIT_MODE
}
///--------------------------------------------------------------------------------------
// SWCopyLine
///--------------------------------------------------------------------------------------
SW_FUNC void SWCopyLine(
FramePtr srcFrameP,
FramePtr dstFrameP,
Point srcPoint,
Point dstPoint)
{
Boolean thereIsALine = true;
SW_ASSERT(srcFrameP != NULL && srcFrameP->isFrameLocked);
SW_ASSERT(dstFrameP != NULL && dstFrameP->isFrameLocked);
SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 8);
SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
START_32_BIT_MODE
// Check to see if the line is straight horizontally or vertically
if (srcPoint.v == dstPoint.v || srcPoint.h == dstPoint.h)
{
BPCopyStraightLine(srcFrameP, dstFrameP, srcPoint, dstPoint);
}
else
{
// Clip the line with the dstFrameP->frameRect
thereIsALine = SWClipLineWithRect(&srcPoint, &dstPoint, &dstFrameP->frameRect);
if (thereIsALine)
BPCopyLine(srcFrameP, dstFrameP, srcPoint, dstPoint);
}
END_32_BIT_MODE
}
///--------------------------------------------------------------------------------------
// SWDrawFrameRect
///--------------------------------------------------------------------------------------
SW_FUNC void SWDrawFrameRect(
FramePtr dstFrameP,
Rect *dstRectP,
Byte color)
{
Point srcPoint, dstPoint;
Rect destRect = *dstRectP;
SW_ASSERT(dstFrameP != NULL && dstFrameP->isFrameLocked);
SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
START_32_BIT_MODE
// Swap things around if they're in the wrong order
if (destRect.right < destRect.left)
{
destRect.right = destRect.left;
destRect.left = dstRectP->right;
}
if (destRect.bottom < destRect.top)
{
destRect.bottom = destRect.top;
destRect.top = dstRectP->bottom;
}
// Clip destRect with dstFrameP->frameRect
if (destRect.top < dstFrameP->frameRect.top)
destRect.top = dstFrameP->frameRect.top;
if (destRect.bottom > dstFrameP->frameRect.bottom)
destRect.bottom = dstFrameP->frameRect.bottom;
if (destRect.left < dstFrameP->frameRect.left)
destRect.left = dstFrameP->frameRect.left;
if (destRect.right > dstFrameP->frameRect.right)
destRect.right = dstFrameP->frameRect.right;
if (destRect.right <= destRect.left || destRect.bottom <= destRect.top)
return;
// Draw top side
srcPoint.h = destRect.left;
srcPoint.v = destRect.top;
dstPoint.h = destRect.right-1;
dstPoint.v = destRect.top;
BlitStraightLine(dstFrameP, srcPoint, dstPoint, color);
// Draw right side
srcPoint.h = destRect.right-1;
dstPoint.v = destRect.bottom-1;
BlitStraightLine(dstFrameP, srcPoint, dstPoint, color);
// Draw bottom side
srcPoint.h = destRect.left;
srcPoint.v = destRect.bottom-1;
BlitStraightLine(dstFrameP, srcPoint, dstPoint, color);
// Draw left side
srcPoint.v = destRect.top;
dstPoint.h = destRect.left;
BlitStraightLine(dstFrameP, srcPoint, dstPoint, color);
END_32_BIT_MODE
}
///--------------------------------------------------------------------------------------
// SWCopyFrameRect
///--------------------------------------------------------------------------------------
SW_FUNC void SWCopyFrameRect(
FramePtr srcFrameP,
FramePtr dstFrameP,
Rect *dstRectP)
{
Point srcPoint, dstPoint;
Rect destRect = *dstRectP;
SW_ASSERT(srcFrameP != NULL && srcFrameP->isFrameLocked);
SW_ASSERT(dstFrameP != NULL && dstFrameP->isFrameLocked);
SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 8);
SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
START_32_BIT_MODE
// Swap things around if they're in the wrong order
if (destRect.right < destRect.left)
{
destRect.right = destRect.left;
destRect.left = dstRectP->right;
}
if (destRect.bottom < destRect.top)
{
destRect.bottom = destRect.top;
destRect.top = dstRectP->bottom;
}
// Clip destRect with dstFrameP->frameRect
if (destRect.top < dstFrameP->frameRect.top)
destRect.top = dstFrameP->frameRect.top;
if (destRect.bottom > dstFrameP->frameRect.bottom)
destRect.bottom = dstFrameP->frameRect.bottom;
if (destRect.left < dstFrameP->frameRect.left)
destRect.left = dstFrameP->frameRect.left;
if (destRect.right > dstFrameP->frameRect.right)
destRect.right = dstFrameP->frameRect.right;
if (destRect.right <= destRect.left || destRect.bottom <= destRect.top)
return;
// Draw top side
srcPoint.h = destRect.left;
srcPoint.v = destRect.top;
dstPoint.h = destRect.right-1;
dstPoint.v = destRect.top;
BPCopyStraightLine(srcFrameP, dstFrameP, srcPoint, dstPoint);
// Draw right side
srcPoint.h = destRect.right-1;
dstPoint.v = destRect.bottom-1;
BPCopyStraightLine(srcFrameP, dstFrameP, srcPoint, dstPoint);
// Draw bottom side
srcPoint.h = destRect.left;
srcPoint.v = destRect.bottom-1;
BPCopyStraightLine(srcFrameP, dstFrameP, srcPoint, dstPoint);
// Draw left side
srcPoint.v = destRect.top;
dstPoint.h = destRect.left;
BPCopyStraightLine(srcFrameP, dstFrameP, srcPoint, dstPoint);
END_32_BIT_MODE
}
///--------------------------------------------------------------------------------------
// SWDrawLineInScrollingWorld - clips drawing to the visScrollRect
///--------------------------------------------------------------------------------------
SW_FUNC void SWDrawLineInScrollingWorld(
SpriteWorldPtr spriteWorldP,
FramePtr dstFrameP,
Point srcPoint,
Point dstPoint,
Byte color)
{
Boolean thereIsALine;
Rect frameRect = dstFrameP->frameRect;
SW_ASSERT(spriteWorldP != NULL);
SW_ASSERT(dstFrameP != NULL && dstFrameP->isFrameLocked);
SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
START_32_BIT_MODE
// Check to see if the line is straight horizontally or vertically
if (srcPoint.v == dstPoint.v || srcPoint.h == dstPoint.h)
{
Rect visScrollRect = spriteWorldP->visScrollRect;
// Clip the line with the visScrollRect
if (srcPoint.v < visScrollRect.top) srcPoint.v = visScrollRect.top;
if (dstPoint.v < visScrollRect.top) dstPoint.v = visScrollRect.top;
if (srcPoint.v >= visScrollRect.bottom) srcPoint.v = visScrollRect.bottom-1;
if (dstPoint.v >= visScrollRect.bottom) dstPoint.v = visScrollRect.bottom-1;
if (srcPoint.h < visScrollRect.left) srcPoint.h = visScrollRect.left;
if (dstPoint.h < visScrollRect.left) dstPoint.h = visScrollRect.left;
if (srcPoint.h >= visScrollRect.right) srcPoint.h = visScrollRect.right-1;
if (dstPoint.h >= visScrollRect.right) dstPoint.h = visScrollRect.right-1;
// Make the line's points local to the offscreen area
srcPoint.h -= spriteWorldP->horizScrollRectOffset;
srcPoint.v -= spriteWorldP->vertScrollRectOffset;
dstPoint.h -= spriteWorldP->horizScrollRectOffset;
dstPoint.v -= spriteWorldP->vertScrollRectOffset;
// Determine whether to call the wrapping or non-wrapping version
if (srcPoint.h >= frameRect.left && srcPoint.h < frameRect.right &&
dstPoint.h >= frameRect.left && dstPoint.h < frameRect.right &&
srcPoint.v >= frameRect.top && srcPoint.v < frameRect.bottom &&
dstPoint.v >= frameRect.top && dstPoint.v < frameRect.bottom)
{
// The line is contained entirely inside the dstFrameP
BlitStraightLine(dstFrameP, srcPoint, dstPoint, color);
}
else
{
// The line needs wrapping
BlitStraightWrappingLine(dstFrameP, srcPoint, dstPoint, color);
}
}
else
{
// Clip the line with the visScrollRect
thereIsALine = SWClipLineWithRect(&srcPoint, &dstPoint, &spriteWorldP->visScrollRect);
// Make the line's points local to the offscreen area
srcPoint.h -= spriteWorldP->horizScrollRectOffset;
srcPoint.v -= spriteWorldP->vertScrollRectOffset;
dstPoint.h -= spriteWorldP->horizScrollRectOffset;
dstPoint.v -= spriteWorldP->vertScrollRectOffset;
if (thereIsALine)
{
// Determine whether to call the wrapping or non-wrapping version
if (srcPoint.h >= frameRect.left && srcPoint.h < frameRect.right &&
dstPoint.h >= frameRect.left && dstPoint.h < frameRect.right &&
srcPoint.v >= frameRect.top && srcPoint.v < frameRect.bottom &&
dstPoint.v >= frameRect.top && dstPoint.v < frameRect.bottom)
{
// The line is contained entirely inside the dstFrameP
BlitLine(dstFrameP, srcPoint, dstPoint, color);
}
else
{
// The line needs wrapping
BlitWrappingLine(dstFrameP, srcPoint, dstPoint, color);
}
}
}
END_32_BIT_MODE
}
///--------------------------------------------------------------------------------------
// SWCopyLineInScrollingWorld - clips drawing to the visScrollRect
///--------------------------------------------------------------------------------------
SW_FUNC void SWCopyLineInScrollingWorld(
SpriteWorldPtr spriteWorldP,
FramePtr srcFrameP,
FramePtr dstFrameP,
Point srcPoint,
Point dstPoint,
Rect *clipRectP)
{
Boolean thereIsALine;
Rect frameRect = dstFrameP->frameRect;
short vertScrollRectOffset, horizScrollRectOffset;
SW_ASSERT(spriteWorldP != NULL);
SW_ASSERT(srcFrameP != NULL && srcFrameP->isFrameLocked);
SW_ASSERT(dstFrameP != NULL && dstFrameP->isFrameLocked);
SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
START_32_BIT_MODE
// ClipRectP should be either the visScrollRect or oldVisScrollRect
vertScrollRectOffset = spriteWorldP->backRect.bottom *
(clipRectP->top / spriteWorldP->backRect.bottom);
horizScrollRectOffset = spriteWorldP->backRect.right *
(clipRectP->left / spriteWorldP->backRect.right);
// Check to see if the line is straight horizontally or vertically
if (srcPoint.v == dstPoint.v || srcPoint.h == dstPoint.h)
{
// Clip the line with the visScrollRect
if (srcPoint.v < clipRectP->top) srcPoint.v = clipRectP->top;
if (dstPoint.v < clipRectP->top) dstPoint.v = clipRectP->top;
if (srcPoint.v >= clipRectP->bottom) srcPoint.v = clipRectP->bottom-1;
if (dstPoint.v >= clipRectP->bottom) dstPoint.v = clipRectP->bottom-1;
if (srcPoint.h < clipRectP->left) srcPoint.h = clipRectP->left;
if (dstPoint.h < clipRectP->left) dstPoint.h = clipRectP->left;
if (srcPoint.h >= clipRectP->right) srcPoint.h = clipRectP->right-1;
if (dstPoint.h >= clipRectP->right) dstPoint.h = clipRectP->right-1;
// Make the line's points local to the offscreen area
srcPoint.h -= horizScrollRectOffset;
srcPoint.v -= vertScrollRectOffset;
dstPoint.h -= horizScrollRectOffset;
dstPoint.v -= vertScrollRectOffset;
// Determine whether to call the wrapping or non-wrapping version
if (srcPoint.h >= frameRect.left && srcPoint.h < frameRect.right &&
dstPoint.h >= frameRect.left && dstPoint.h < frameRect.right &&
srcPoint.v >= frameRect.top && srcPoint.v < frameRect.bottom &&
dstPoint.v >= frameRect.top && dstPoint.v < frameRect.bottom)
{
// The line is contained entirely inside the dstFrameP
BPCopyStraightLine(srcFrameP, dstFrameP, srcPoint, dstPoint);
}
else
{
// The line needs wrapping
BPCopyStraightWrappingLine(srcFrameP, dstFrameP, srcPoint, dstPoint);
}
}
else
{
// Clip the line with clipRectP (visScrollRect or oldVisScrollRect)
thereIsALine = SWClipLineWithRect(&srcPoint, &dstPoint, clipRectP);
// Make the line's points local to the offscreen area
srcPoint.h -= horizScrollRectOffset;
srcPoint.v -= vertScrollRectOffset;
dstPoint.h -= horizScrollRectOffset;
dstPoint.v -= vertScrollRectOffset;
if (thereIsALine)
{
// Determine whether to call the wrapping or non-wrapping version
if (srcPoint.h >= frameRect.left && srcPoint.h < frameRect.right &&
dstPoint.h >= frameRect.left && dstPoint.h < frameRect.right &&
srcPoint.v >= frameRect.top && srcPoint.v < frameRect.bottom &&
dstPoint.v >= frameRect.top && dstPoint.v < frameRect.bottom)
{
// The line is contained entirely inside the frameRect
BPCopyLine(srcFrameP, dstFrameP, srcPoint, dstPoint);
}
else
{
// The line needs wrapping
BPCopyWrappingLine(srcFrameP, dstFrameP, srcPoint, dstPoint);
}
}
}
END_32_BIT_MODE
}
///--------------------------------------------------------------------------------------
// SWDrawFrameRectInScrollingWorld
// The dstFrameP should be either the work area or the background area.
///--------------------------------------------------------------------------------------
SW_FUNC void SWDrawFrameRectInScrollingWorld(
SpriteWorldPtr spriteWorldP,
FramePtr dstFrameP,
Rect *dstRectP,
Byte color)
{
Point srcPoint, dstPoint;
Rect destRect = *dstRectP;
Rect frameRect = dstFrameP->frameRect;
Boolean leftClipped, topClipped, rightClipped, bottomClipped;
BlitLineProcPtr lineProcPtr;
SW_ASSERT(spriteWorldP != NULL);
SW_ASSERT(dstFrameP != NULL && dstFrameP->isFrameLocked);
SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
START_32_BIT_MODE
leftClipped = topClipped = rightClipped = bottomClipped = false;
// Clip destRect with spriteWorldP->visScrollRect
if (destRect.top < spriteWorldP->visScrollRect.top)
{
destRect.top = spriteWorldP->visScrollRect.top;
topClipped = true;
}
if (destRect.bottom > spriteWorldP->visScrollRect.bottom)
{
destRect.bottom = spriteWorldP->visScrollRect.bottom;
bottomClipped = true;
}
if (destRect.left < spriteWorldP->visScrollRect.left)
{
destRect.left = spriteWorldP->visScrollRect.left;
leftClipped = true;
}
if (destRect.right > spriteWorldP->visScrollRect.right)
{
destRect.right = spriteWorldP->visScrollRect.right;
rightClipped = true;
}
if (destRect.right <= destRect.left || destRect.bottom <= destRect.top)
return;
// Make the line's points local to the offscreen area
destRect.left -= spriteWorldP->horizScrollRectOffset;
destRect.right -= spriteWorldP->horizScrollRectOffset;
destRect.top -= spriteWorldP->vertScrollRectOffset;
destRect.bottom -= spriteWorldP->vertScrollRectOffset;
// Determine whether to call the wrapping or non-wrapping version
if (destRect.left >= frameRect.left && destRect.left < frameRect.right &&
destRect.right >= frameRect.left && destRect.right < frameRect.right &&
destRect.top >= frameRect.top && destRect.top < frameRect.bottom &&
destRect.bottom >= frameRect.top && destRect.bottom < frameRect.bottom)
{
lineProcPtr = BlitLine; // The line is contained entirely inside the frameRect
}
else
{
lineProcPtr = BlitWrappingLine; // The line needs wrapping
}
// Draw top side
srcPoint.h = destRect.left;
srcPoint.v = destRect.top;
dstPoint.h = destRect.right-1;
dstPoint.v = destRect.top;
if (!topClipped)
(*lineProcPtr)(dstFrameP, srcPoint, dstPoint, color);
// Draw right side
srcPoint.h = destRect.right-1;
dstPoint.v = destRect.bottom-1;
if (!rightClipped)
(*lineProcPtr)(dstFrameP, srcPoint, dstPoint, color);
// Draw bottom side
srcPoint.h = destRect.left;
srcPoint.v = destRect.bottom-1;
if (!bottomClipped)
(*lineProcPtr)(dstFrameP, srcPoint, dstPoint, color);
// Draw left side
srcPoint.v = destRect.top;
dstPoint.h = destRect.left;
if (!leftClipped)
(*lineProcPtr)(dstFrameP, srcPoint, dstPoint, color);
END_32_BIT_MODE
}
///--------------------------------------------------------------------------------------
// SWCopyFrameRectInScrollingWorld
// The dstFrameP should be either the work area or the background area.
///--------------------------------------------------------------------------------------
SW_FUNC void SWCopyFrameRectInScrollingWorld(
SpriteWorldPtr spriteWorldP,
FramePtr srcFrameP,
FramePtr dstFrameP,
Rect *dstRectP,
Rect *clipRectP)
{
Point srcPoint, dstPoint;
Rect destRect = *dstRectP;
Rect frameRect = dstFrameP->frameRect;
Boolean leftClipped, topClipped, rightClipped, bottomClipped;
short horizScrollRectOffset, vertScrollRectOffset;
CopyLineProcPtr lineProcPtr;
SW_ASSERT(spriteWorldP != NULL);
SW_ASSERT(srcFrameP != NULL && srcFrameP->isFrameLocked);
SW_ASSERT(dstFrameP != NULL && dstFrameP->isFrameLocked);
SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 8);
SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
START_32_BIT_MODE
// ClipRectP should be either the visScrollRect or oldVisScrollRect
vertScrollRectOffset = spriteWorldP->backRect.bottom *
(clipRectP->top / spriteWorldP->backRect.bottom);
horizScrollRectOffset = spriteWorldP->backRect.right *
(clipRectP->left / spriteWorldP->backRect.right);
leftClipped = topClipped = rightClipped = bottomClipped = false;
// Clip destRect with spriteWorldP->visScrollRect
if (destRect.top < clipRectP->top)
{
destRect.top = clipRectP->top;
topClipped = true;
}
if (destRect.bottom > clipRectP->bottom)
{
destRect.bottom = clipRectP->bottom;
bottomClipped = true;
}
if (destRect.left < clipRectP->left)
{
destRect.left = clipRectP->left;
leftClipped = true;
}
if (destRect.right > clipRectP->right)
{
destRect.right = clipRectP->right;
rightClipped = true;
}
if (destRect.right <= destRect.left || destRect.bottom <= destRect.top)
return;
// Make the line's points local to the offscreen area
destRect.left -= horizScrollRectOffset;
destRect.right -= horizScrollRectOffset;
destRect.top -= vertScrollRectOffset;
destRect.bottom -= vertScrollRectOffset;
// Determine whether to call the wrapping or non-wrapping version
if (destRect.left >= frameRect.left && destRect.left < frameRect.right &&
destRect.right >= frameRect.left && destRect.right < frameRect.right &&
destRect.top >= frameRect.top && destRect.top < frameRect.bottom &&
destRect.bottom >= frameRect.top && destRect.bottom < frameRect.bottom)
{
lineProcPtr = BPCopyStraightLine; // The line is contained entirely inside the frameRect
}
else
{
lineProcPtr = BPCopyStraightWrappingLine; // The line needs wrapping
}
// Draw top side
srcPoint.h = destRect.left;
srcPoint.v = destRect.top;
dstPoint.h = destRect.right-1;
dstPoint.v = destRect.top;
if (!topClipped) // Draw top if it wasn't clipped
(*lineProcPtr)(srcFrameP, dstFrameP, srcPoint, dstPoint);
// Draw right side
srcPoint.h = destRect.right-1;
dstPoint.v = destRect.bottom-1;
if (!rightClipped) // Draw right if it wasn't clipped
(*lineProcPtr)(srcFrameP, dstFrameP, srcPoint, dstPoint);
// Draw bottom side
srcPoint.h = destRect.left;
srcPoint.v = destRect.bottom-1;
if (!bottomClipped) // Draw bottom if it wasn't clipped
(*lineProcPtr)(srcFrameP, dstFrameP, srcPoint, dstPoint);
// Draw left side
srcPoint.v = destRect.top;
dstPoint.h = destRect.left;
if (!leftClipped) // Draw left if it wasn't clipped
(*lineProcPtr)(srcFrameP, dstFrameP, srcPoint, dstPoint);
END_32_BIT_MODE
}
#pragma mark -
#pragma mark *** Diagonal Line Blitters:
///--------------------------------------------------------------------------------------
// SWClipLineWithRect - Note: lines clipped with this routine will always be slightly
// different than the unclipped version, since the accum and dx or dy from this routine
// are not passed to the actual line drawing function.
///--------------------------------------------------------------------------------------
SW_FUNC Boolean SWClipLineWithRect(
Point *srcPoint,
Point *dstPoint,
Rect *clipRectP)
{
short x1 = srcPoint->h, y1 = srcPoint->v,
x2 = dstPoint->h, y2 = dstPoint->v;
short dx, dy, sx, sy, accum;
short lastX, lastY;
Boolean x1IsInRect, y1IsInRect, x2IsInRect, y2IsInRect;
Boolean foundStartPt, endPointIsInRect;
Rect clipRect = *clipRectP;
// InsetRect(&clipRect, 50, 50); // Useful for testing
x1IsInRect = (x1 >= clipRect.left && x1 < clipRect.right);
y1IsInRect = (y1 >= clipRect.top && y1 < clipRect.bottom);
x2IsInRect = (x2 >= clipRect.left && x2 < clipRect.right);
y2IsInRect = (y2 >= clipRect.top && y2 < clipRect.bottom);
// If line needs no clipping, return
if (x1IsInRect && y1IsInRect && x2IsInRect && y2IsInRect)
{
return true;
}
dx = x2 - x1;
dy = y2 - y1;
sx = SIGN(dx);
sy = SIGN(dy);
dx = ABS(dx);
dy = ABS(dy);
foundStartPt = false;
endPointIsInRect = false;
// The possibilities are: A) Both start and end points are outside the rect.
// B) Only the start point is outside. C) Only the end point is outside.
// We know that at least one point is outside, since otherwise this function
// would have returned already.
// Check first pixel in line
if (x1IsInRect && y1IsInRect)
{
foundStartPt = true;
lastX = x1; // Store last point in line as well, in case only
lastY = y1; // one pixel is inside the clipRect.
}
if (x2IsInRect && y2IsInRect)
{
endPointIsInRect = true;
}
if (dx > dy) // Longer horizontally than vertically
{
accum = dx >> 1; // accum = dx/2;
while (x1 != x2)
{
accum -= dy;
if (accum < 0)
{
accum += dx;
y1 += sy;
y1IsInRect = (y1 >= clipRect.top && y1 < clipRect.bottom);
}
x1 += sx;
x1IsInRect = (x1 >= clipRect.left && x1 < clipRect.right);
if (x1IsInRect && y1IsInRect) // Determine if current point is in rect
{
if (foundStartPt == false)
{
srcPoint->h = x1; // Store first point in line
srcPoint->v = y1;
foundStartPt = true;
if (endPointIsInRect)
return true; // Leave early, since we only needed to clip the first half
}
lastX = x1; // Store last point in line
lastY = y1; // (We keep doing this until we hit the end.)
}
else if (foundStartPt == true)
{
break; // the line is leaving clipRect, so break early to save time
}
}
}
else // Longer vertically than horizontally, or both equal in length
{
accum = dy >> 1; // accum = dy/2;
while (y1 != y2)
{
accum -= dx;
if (accum < 0)
{
accum += dy;
x1 += sx;
x1IsInRect = (x1 >= clipRect.left && x1 < clipRect.right);
}
y1 += sy;
y1IsInRect = (y1 >= clipRect.top && y1 < clipRect.bottom);
if (x1IsInRect && y1IsInRect) // Determine if current point is in rect
{
if (foundStartPt == false)
{
srcPoint->h = x1; // Store first point in line
srcPoint->v = y1;
foundStartPt = true;
if (endPointIsInRect)
return true; // Leave early, since we only needed to clip the first half
}
lastX = x1; // Store last point in line
lastY = y1; // (We keep doing this until we hit the end.)
}
else if (foundStartPt == true)
{
break; // the line is leaving clipRect, so break early to save time
}
}
}
// Store last point in line
dstPoint->h = lastX; // lastX is the pixel just before we ran into the pixel outside bounds
dstPoint->v = lastY;
// Tell caller if we ever found any point of the line inside clipRect
return foundStartPt;
}
#if !SW_PPC
///--------------------------------------------------------------------------------------
// BlitLine68kAsm - called by SWDrawLine68kAsm. Written by Oleg Doperchuk.
///--------------------------------------------------------------------------------------
SW_ASM_FUNC void BlitLine68kAsm
(Ptr baseAddr,
unsigned long rowBytes,
short x1,
short x2,
short y1,
short y2,
Byte color)
{
SW_ASM_BEGIN
#if __MWERKS__
fralloc +
#endif
//dc.w 0xA9FF
movem.l d0-d7/a0-a6,-(a7)
moveq #0,d0
moveq #0,d1
moveq #0,d2
moveq #0,d3
move.w x1,d0
move.w y1,d1
move.w x2,d2
move.w y2,d3
sub.w d0,d2 // d2 = !x = ( x2 - x1 )
bpl.s @noswap
exg d1,d3 // swap endpoints
neg.w d2 // !x = -!x = ( x1 - x2 )
sub.w d2,d0 // d0 = x1 - ( x1 - x2 ) = x2
@noswap:
sub.w d1,d3 // d3 = !y = ( y2 - y1 )
move.l baseAddr,a0
move.l rowBytes,d6
mulu.l d6,d1
add.l d1,d0
add.l d0,a0 // a0 = address of the first point to draw
move.b color,d7
// now we can freely use d0/d1
tst.w d3 // Line upward?
bmi @LineUp // yes
beq @Horiz // horizontal line
tst.w d2 // !x = 0 - vertical line downward
beq @VertDn
cmp.w d2,d3 // test line slope
beq @DiagDn // slope = 1
bpl @SteepDn // slope > 1
moveq #0,d0 // lower 32bits
divu.l d2,d3:d0 // d0 = 32bit ( !y/!x )
moveq #0,d1 // accumulated error
@FDLoop:
move.b d7,(a0)+ // Plot a point and move 1 pixel rightward
add.l d0,d1 // Add an accumulated error
bcs.s @FDCarry
dbra d2,@FDLoop
bra @exit
@FDCarry:
add.l d6,a0 // One line down
dbra d2,@FDLoop
bra @exit
@DiagDn:
addq.l #1,d6 // Offset is rowbytes+1
@DDLoop:
move.b d7,(a0) // draw line
add.l d6,a0
dbra d2,@DDLoop
bra @exit
@SteepDn:
moveq #0,d0
divu.l d3,d2:d0 // d0 = 32bit ( !x/!y )
moveq #0,d1 // accumulated error
@SDLoop:
move.b d7,(a0) // plot a point
add.l d6,a0 // move 1 pixel downward
add.l d0,d1 // Add an accumulated error
bcs.s @SDCarry
dbra d3,@SDLoop
bra @exit
@SDCarry:
addq.l #1,a0
dbra d3,@SDLoop
bra @exit
@Horiz:
move.b d7,(a0)+
dbra d2,@Horiz
bra @exit
@VertDn:
move.b d7,(a0) // offset is rowbytes
add.l d6,a0
dbra d3,@VertDn
bra @exit
@LineUp:
neg.w d3
tst.w d2
beq @VertUp
cmp.w d2,d3
beq @DiagUp // slope = -1
bpl @SteepUp // slope < -1
moveq #0,d0 // lower 32bits
divu.l d2,d3:d0 // d0 = 32bit ( !y/!x )
moveq #0,d1 // accumulated error
@FULoop:
move.b d7,(a0)+ // Plot a point and move 1 pixel rightward
add.l d0,d1 // Add an accumulated error
bcs.s @FUCarry
dbra d2,@FULoop
bra @exit
@FUCarry:
sub.l d6,a0 // One line up
dbra d2,@FULoop
bra @exit
@DiagUp:
subq.l #1,d6 // offset is 1-rowbytes
@DULoop:
move.b d7,(a0) // draw line
sub.l d6,a0
dbra d2,@DULoop
bra @exit
@SteepUp:
moveq #0,d0
divu.l d3,d2:d0 // d0 = 32bit ( !x/!y )
moveq #0,d1 // accumulated error
@SULoop:
move.b d7,(a0) // plot a point
sub.l d6,a0 // move 1 pixel upward
add.l d0,d1 // Add an accumulated error
bcs.s @SUCarry
dbra d3,@SULoop
bra @exit
@SUCarry:
addq.l #1,a0
dbra d3,@SULoop
bra @exit
@VertUp:
move.b d7,(a0) // offset is -rowbytes
sub.l d6,a0
dbra d3,@VertUp
@exit: movem.l (a7)+,d0-d7/a0-a6
#if __MWERKS__
frfree
#endif
SW_ASM_END
}
#endif
///--------------------------------------------------------------------------------------
// BlitLine - line-drawing code in C. Clipping must be done before this is called.
///--------------------------------------------------------------------------------------
SW_FUNC void BlitLine(
FramePtr dstFrameP,
Point srcPoint,
Point dstPoint,
Byte color)
{
register Ptr baseAddr = dstFrameP->frameBaseAddr;
unsigned long rowBytes = dstFrameP->frameRowBytes;
short x1 = srcPoint.h, y1 = srcPoint.v,
x2 = dstPoint.h, y2 = dstPoint.v;
short dx, dy, sx, sy, iy;
short accum;
dx = x2 - x1;
dy = y2 - y1;
sx = SIGN(dx);
sy = SIGN(dy);
dx = ABS(dx);
dy = ABS(dy);
iy = (sy < 0) ? -rowBytes : rowBytes;
baseAddr += dstFrameP->scanLinePtrArray[y1] + x1;
*baseAddr = color; // Draw the first pixel
if(dx > dy) // Longer horizontally than vertically
{
accum = dx >> 1;
while(x1 != x2)
{
accum -= dy;
if(accum < 0)
{
accum += dx;
baseAddr += iy;
}
x1 += sx;
baseAddr += sx;
*baseAddr = color;
}
}
else // Longer vertically than horizontally, or both equal in length
{
accum = dy >> 1;
while(y1 != y2)
{
accum -= dx;
if(accum < 0)
{
accum += dy;
baseAddr += sx;
}
y1 += sy;
baseAddr += iy;
*baseAddr = color;
}
}
}
///--------------------------------------------------------------------------------------
// BPCopyLine - line-drawing code in C. Clipping must be done before this is called.
///--------------------------------------------------------------------------------------
SW_FUNC void BPCopyLine(
FramePtr srcFrameP,
FramePtr dstFrameP,
Point srcPoint,
Point dstPoint)
{
Ptr srcBaseAddr = srcFrameP->frameBaseAddr;
Ptr dstBaseAddr = dstFrameP->frameBaseAddr;
unsigned long srcRowBytes = srcFrameP->frameRowBytes;
unsigned long dstRowBytes = dstFrameP->frameRowBytes;
short x1 = srcPoint.h, y1 = srcPoint.v,
x2 = dstPoint.h, y2 = dstPoint.v;
short dx, dy, sx, sy, srciy, dstiy;
short accum;
dx = x2 - x1;
dy = y2 - y1;
sx = SIGN(dx);
sy = SIGN(dy);
dx = ABS(dx);
dy = ABS(dy);
srcBaseAddr += srcFrameP->scanLinePtrArray[y1] + x1;
dstBaseAddr += dstFrameP->scanLinePtrArray[y1] + x1;
// Copy the first pixel in the line
*dstBaseAddr = *srcBaseAddr;
srciy = (sy < 0) ? -srcRowBytes : srcRowBytes;
dstiy = (sy < 0) ? -dstRowBytes : dstRowBytes;
if (dx > dy) // Longer horizontally than vertically
{
accum = dx >> 1;
while(x1 != x2)
{
accum -= dy;
if(accum < 0)
{
accum += dx;
srcBaseAddr += srciy;
dstBaseAddr += dstiy;
}
x1 += sx;
srcBaseAddr += sx;
dstBaseAddr += sx;
*dstBaseAddr = *srcBaseAddr;
}
}
else // Longer vertically than horizontally, or both equal in length
{
accum = dy >> 1;
while(y1 != y2)
{
accum -= dx;
if(accum < 0)
{
accum += dy;
srcBaseAddr += sx;
dstBaseAddr += sx;
}
y1 += sy;
srcBaseAddr += srciy;
dstBaseAddr += dstiy;
*dstBaseAddr = *srcBaseAddr;
}
}
}
///--------------------------------------------------------------------------------------
// BlitWrappingLine
///--------------------------------------------------------------------------------------
SW_FUNC void BlitWrappingLine(
FramePtr dstFrameP,
Point srcPoint,
Point dstPoint,
Byte color)
{
Ptr baseAddr;
unsigned long rowBytes = dstFrameP->frameRowBytes;
unsigned long vertOffset;
short x1 = srcPoint.h, y1 = srcPoint.v,
x2 = dstPoint.h, y2 = dstPoint.v;
short dx, dy, sx, sy, iy;
short accum;
Rect frameRect = dstFrameP->frameRect;
short frameWidth, frameHeight;
frameWidth = SW_RECT_WIDTH(frameRect);
frameHeight = SW_RECT_HEIGHT(frameRect);
// vertOffset = rowBytes * frameHeight;
vertOffset = dstFrameP->scanLinePtrArray[dstFrameP->numScanLines-1] + rowBytes -
dstFrameP->scanLinePtrArray[0];
dx = x2 - x1;
dy = y2 - y1;
sx = SIGN(dx);
sy = SIGN(dy);
dx = ABS(dx);
dy = ABS(dy);
// Even the very first pixel we draw might need to be wrapped before we draw it.
if (y1 >= frameRect.bottom)
{
y1 -= frameHeight;
y2 -= frameHeight;
}
else if (y1 < frameRect.top)
{
y1 += frameHeight;
y2 += frameHeight;
}
if (x1 >= frameRect.right)
{
x1 -= frameWidth;
x2 -= frameWidth;
}
else if (x1 < frameRect.left)
{
x1 += frameWidth;
x2 += frameWidth;
}
baseAddr = dstFrameP->frameBaseAddr + dstFrameP->scanLinePtrArray[y1] + x1;
*baseAddr = color;
iy = (sy < 0) ? -rowBytes : rowBytes;
if (dx > dy) // Longer horizontally than vertically
{
accum = dx >> 1; // accum = dx/2;
while (x1 != x2)
{
accum -= dy;
if (accum < 0)
{
accum += dx;
y1 += sy;
baseAddr += iy; // Move pixel up/down one row
if (y1 >= frameRect.bottom)
{
y1 -= frameHeight;
y2 -= frameHeight;
baseAddr -= vertOffset; // Jump to top side
}
else if (y1 < frameRect.top)
{
y1 += frameHeight;
y2 += frameHeight;
baseAddr += vertOffset; // Jump to bottom side
}
}
x1 += sx;
baseAddr += sx; // Move left/right one pixel
if (x1 >= frameRect.right)
{
x1 -= frameWidth;
x2 -= frameWidth;
baseAddr -= frameWidth; // Jump to left side
}
else if (x1 < frameRect.left)
{
x1 += frameWidth;
x2 += frameWidth;
baseAddr += frameWidth; // Jump to right side
}
*baseAddr = color;
}
}
else // Longer vertically than horizontally, or both equal in length
{
accum = dy >> 1; // accum = dy/2;
while (y1 != y2)
{
accum -= dx;
if (accum < 0)
{
accum += dy;
x1 += sx;
baseAddr += sx;
if (x1 >= frameRect.right)
{
x1 -= frameWidth;
x2 -= frameWidth;
baseAddr -= frameWidth; // Jump to left side
}
else if (x1 < frameRect.left)
{
x1 += frameWidth;
x2 += frameWidth;
baseAddr += frameWidth; // Jump to right side
}
}
y1 += sy;
baseAddr += iy;
if (y1 >= frameRect.bottom)
{
y1 -= frameHeight;
y2 -= frameHeight;
baseAddr -= vertOffset; // Jump to top side
}
else if (y1 < frameRect.top)
{
y1 += frameHeight;
y2 += frameHeight;
baseAddr += vertOffset; // Jump to bottom side
}
*baseAddr = color;
}
}
}
///--------------------------------------------------------------------------------------
// BPCopyWrappingLine - assumes srcFrameP and dstFrameP are the same size!
///--------------------------------------------------------------------------------------
SW_FUNC void BPCopyWrappingLine(
FramePtr srcFrameP,
FramePtr dstFrameP,
Point srcPoint,
Point dstPoint)
{
Ptr srcBaseAddr = srcFrameP->frameBaseAddr;
Ptr dstBaseAddr = dstFrameP->frameBaseAddr;
unsigned long srcRowBytes = srcFrameP->frameRowBytes;
unsigned long dstRowBytes = dstFrameP->frameRowBytes;
unsigned long srcVertOffset, dstVertOffset;
short x1 = srcPoint.h, y1 = srcPoint.v,
x2 = dstPoint.h, y2 = dstPoint.v;
short dx, dy, sx, sy, srciy, dstiy;
short accum;
Rect frameRect = dstFrameP->frameRect;
short frameWidth, frameHeight;
frameWidth = SW_RECT_WIDTH(frameRect);
frameHeight = SW_RECT_HEIGHT(frameRect);
// srcVertOffset = srcRowBytes * frameHeight;
srcVertOffset = srcFrameP->scanLinePtrArray[srcFrameP->numScanLines-1] + srcRowBytes -
srcFrameP->scanLinePtrArray[0];
dstVertOffset = dstFrameP->scanLinePtrArray[dstFrameP->numScanLines-1] + dstRowBytes -
dstFrameP->scanLinePtrArray[0];
dx = x2 - x1;
dy = y2 - y1;
sx = SIGN(dx);
sy = SIGN(dy);
dx = ABS(dx);
dy = ABS(dy);
// Even the very first pixel we draw might need to be wrapped before we draw it.
if (y1 >= frameRect.bottom)
{
y1 -= frameHeight;
y2 -= frameHeight;
}
else if (y1 < frameRect.top)
{
y1 += frameHeight;
y2 += frameHeight;
}
if (x1 >= frameRect.right)
{
x1 -= frameWidth;
x2 -= frameWidth;
}
else if (x1 < frameRect.left)
{
x1 += frameWidth;
x2 += frameWidth;
}
srcBaseAddr += srcFrameP->scanLinePtrArray[y1] + x1;
dstBaseAddr += dstFrameP->scanLinePtrArray[y1] + x1;
// Copy the first pixel in the line
*dstBaseAddr = *srcBaseAddr;
srciy = (sy < 0) ? -srcRowBytes : srcRowBytes;
dstiy = (sy < 0) ? -dstRowBytes : dstRowBytes;
if (dx > dy) // Longer horizontally than vertically
{
accum = dx >> 1; // accum = dx/2;
while (x1 != x2)
{
accum -= dy;
if (accum < 0)
{
accum += dx;
y1 += sy;
srcBaseAddr += srciy; // Move pixel up/down one row
dstBaseAddr += dstiy;
if (y1 >= frameRect.bottom)
{
y1 -= frameHeight;
y2 -= frameHeight;
srcBaseAddr -= srcVertOffset; // Jump to top side
dstBaseAddr -= dstVertOffset;
}
else if (y1 < frameRect.top)
{
y1 += frameHeight;
y2 += frameHeight;
srcBaseAddr += srcVertOffset; // Jump to bottom side
dstBaseAddr += dstVertOffset;
}
}
x1 += sx;
srcBaseAddr += sx; // Move left/right one pixel
dstBaseAddr += sx;
if (x1 >= frameRect.right)
{
x1 -= frameWidth;
x2 -= frameWidth;
srcBaseAddr -= frameWidth; // Jump to left side
dstBaseAddr -= frameWidth;
}
else if (x1 < frameRect.left)
{
x1 += frameWidth;
x2 += frameWidth;
srcBaseAddr += frameWidth; // Jump to right side
dstBaseAddr += frameWidth;
}
*dstBaseAddr = *srcBaseAddr; // Copy the pixel
}
}
else // Longer vertically than horizontally, or both equal in length
{
accum = dy >> 1; // accum = dy/2;
while (y1 != y2)
{
accum -= dx;
if (accum < 0)
{
accum += dy;
x1 += sx;
srcBaseAddr += sx;
dstBaseAddr += sx;
if (x1 >= frameRect.right)
{
x1 -= frameWidth;
x2 -= frameWidth;
srcBaseAddr -= frameWidth; // Jump to left side
dstBaseAddr -= frameWidth;
}
else if (x1 < frameRect.left)
{
x1 += frameWidth;
x2 += frameWidth;
srcBaseAddr += frameWidth; // Jump to right side
dstBaseAddr += frameWidth;
}
}
y1 += sy;
srcBaseAddr += srciy;
dstBaseAddr += dstiy;
if (y1 >= frameRect.bottom)
{
y1 -= frameHeight;
y2 -= frameHeight;
srcBaseAddr -= srcVertOffset; // Jump to top side
dstBaseAddr -= dstVertOffset;
}
else if (y1 < frameRect.top)
{
y1 += frameHeight;
y2 += frameHeight;
srcBaseAddr += srcVertOffset; // Jump to bottom side
dstBaseAddr += dstVertOffset;
}
*dstBaseAddr = *srcBaseAddr; // Copy the pixel
}
}
}
#pragma mark -
#pragma mark ***Straight Line Blitters:
///--------------------------------------------------------------------------------------
// BlitStraightLine - Clipping is performed by function, since it's easy for a straight line.
///--------------------------------------------------------------------------------------
SW_FUNC void BlitStraightLine(
FramePtr dstFrameP,
Point srcPoint,
Point dstPoint,
register Byte color)
{
unsigned long rowBytes = dstFrameP->frameRowBytes;
short x1 = srcPoint.h, y1 = srcPoint.v,
x2 = dstPoint.h, y2 = dstPoint.v;
short dx, dy;
if (x1 == x2) // Straight vertical line
{
register Ptr baseAddr;
if (y2 < y1)
{
y1 = dstPoint.v; // Swap y1 and y2 if they're
y2 = srcPoint.v; // in the wrong order.
}
// Make sure some part of the line is inside the frameRect
if (x1 < dstFrameP->frameRect.left || x1 >= dstFrameP->frameRect.right)
return;
// Clip the ends of the line
if (y1 < dstFrameP->frameRect.top)
y1 = dstFrameP->frameRect.top;
if (y2 >= dstFrameP->frameRect.bottom)
y2 = dstFrameP->frameRect.bottom-1;
dy = y2 - y1 + 1; // dy = number of pixels in line
if (dy > 0) // Make sure there is a line first!
{
baseAddr = dstFrameP->frameBaseAddr + dstFrameP->scanLinePtrArray[y1] + x1;
*baseAddr = color;
while (--dy)
{
baseAddr += rowBytes;
*baseAddr = color;
}
}
}
else if (y1 == y2) // Straight horizontal line
{
register unsigned long *longBaseAddr;
register numLongBlits;
unsigned long longColor;
// Fill longColor with color
longColor = (color<<24) | (color<<16) | (color<<8) | (color);
if (x2 < x1)
{
x1 = dstPoint.h; // Swap x1 and x2 if they're
x2 = srcPoint.h; // in the wrong order.
}
// Make sure some part of the line is inside the frameRect
if (y1 < dstFrameP->frameRect.top || y1 >= dstFrameP->frameRect.bottom)
return;
if (x1 < dstFrameP->frameRect.left)
x1 = dstFrameP->frameRect.left;
if (x2 >= dstFrameP->frameRect.right)
x2 = dstFrameP->frameRect.right-1;
dx = x2 - x1 + 1; // dx = number of pixels in line
if (dx > 0) // Make sure there is a line first!
{
numLongBlits = (dx >> 2);
longBaseAddr = (unsigned long *)(dstFrameP->frameBaseAddr +
dstFrameP->scanLinePtrArray[y1] + x1);
while (numLongBlits--)
{
*(longBaseAddr)++ = longColor;
}
#ifdef __MWERKS__ // Do it nicely
// Handle extra pixels at end of line
if (dx & 0x2)
*((unsigned short *) longBaseAddr)++ = (unsigned short)longColor;
if (dx & 0x1)
*((unsigned char *) longBaseAddr)++ = color;
#else // Make Think C happy
// Handle extra pixels at end of line
if (dx & 0x2)
{
*((unsigned short *) longBaseAddr) = (unsigned short)longColor;
longBaseAddr = (unsigned long *)(((unsigned short *)longBaseAddr) + 1);
}
if (dx & 0x1)
{
*((unsigned char *) longBaseAddr) = color;
longBaseAddr = (unsigned long *)(((unsigned char *)longBaseAddr) + 1);
}
#endif
}
}
}
///--------------------------------------------------------------------------------------
// BPCopyStraightLine - Clipping is performed by function, since it's easy for a straight
// line. Assumes srcFrameP->frameRect and dstFrameP->frameRect are the same size!
///--------------------------------------------------------------------------------------
SW_FUNC void BPCopyStraightLine(
FramePtr srcFrameP,
FramePtr dstFrameP,
Point srcPoint,
Point dstPoint)
{
unsigned long srcRowBytes = srcFrameP->frameRowBytes;
unsigned long dstRowBytes = dstFrameP->frameRowBytes;
short x1 = srcPoint.h, y1 = srcPoint.v,
x2 = dstPoint.h, y2 = dstPoint.v;
short dx, dy;
if (x1 == x2) // Straight vertical line
{
register Ptr srcBaseAddr;
register Ptr dstBaseAddr;
if (y2 < y1)
{
y1 = dstPoint.v; // Swap y1 and y2 if they're
y2 = srcPoint.v; // in the wrong order.
}
// Make sure some part of the line is inside the frameRect
if (x1 < dstFrameP->frameRect.left || x1 >= dstFrameP->frameRect.right)
return;
// Clip the ends of the line
if (y1 < dstFrameP->frameRect.top)
y1 = dstFrameP->frameRect.top;
if (y2 >= dstFrameP->frameRect.bottom)
y2 = dstFrameP->frameRect.bottom-1;
dy = y2 - y1 + 1; // dy = number of pixels in line
if (dy > 0) // Make sure there is a line first!
{
srcBaseAddr = srcFrameP->frameBaseAddr + srcFrameP->scanLinePtrArray[y1] + x1;
dstBaseAddr = dstFrameP->frameBaseAddr + dstFrameP->scanLinePtrArray[y1] + x1;
*dstBaseAddr = *srcBaseAddr; // Copy the first pixel
while (--dy)
{
srcBaseAddr += srcRowBytes;
dstBaseAddr += dstRowBytes;
*dstBaseAddr = *srcBaseAddr;
}
}
}
else if (y1 == y2) // Straight horizontal line
{
register unsigned long *srcBaseAddr;
register unsigned long *dstBaseAddr;
register numLongBlits;
if (x2 < x1)
{
x1 = dstPoint.h; // Swap x1 and x2 if they're
x2 = srcPoint.h; // in the wrong order.
}
// Make sure some part of the line is inside the frameRect
if (y1 < dstFrameP->frameRect.top || y1 >= dstFrameP->frameRect.bottom)
return;
// Clip the ends of the line
if (x1 < dstFrameP->frameRect.left)
x1 = dstFrameP->frameRect.left;
if (x2 >= dstFrameP->frameRect.right)
x2 = dstFrameP->frameRect.right-1;
dx = x2 - x1 + 1; // dx = number of pixels in line
if (dx > 0) // Make sure there is a line first!
{
numLongBlits = (dx >> 2);
srcBaseAddr = (unsigned long *)(srcFrameP->frameBaseAddr +
srcFrameP->scanLinePtrArray[y1] + x1);
dstBaseAddr = (unsigned long *)(dstFrameP->frameBaseAddr +
dstFrameP->scanLinePtrArray[y1] + x1);
while (numLongBlits--)
{
*(dstBaseAddr)++ = *(srcBaseAddr)++;
}
#ifdef __MWERKS__ // Do it nicely
// Handle extra pixels at end of line
if (dx & 0x2)
*((unsigned short *) dstBaseAddr)++ = *((unsigned short *) srcBaseAddr)++;
if (dx & 0x1)
*((unsigned char *) dstBaseAddr)++ = *((unsigned char *) srcBaseAddr)++;
#else // Make Think C happy
// Handle extra pixels at end of line
if (dx & 0x2)
{
*((unsigned short *) dstBaseAddr) = *((unsigned short *) srcBaseAddr);
dstBaseAddr = (unsigned long *)(((unsigned short *)dstBaseAddr) + 1);
srcBaseAddr = (unsigned long *)(((unsigned short *)srcBaseAddr) + 1);
}
if (dx & 0x1)
{
*((unsigned char *) dstBaseAddr) = *((unsigned char *) srcBaseAddr);
dstBaseAddr = (unsigned long *)(((unsigned char *)dstBaseAddr) + 1);
srcBaseAddr = (unsigned long *)(((unsigned char *)srcBaseAddr) + 1);
}
#endif
}
}
}
///--------------------------------------------------------------------------------------
// BlitStraightWrappingLine - No clipping performed by function.
// Assumes srcFrameP->frameRect and dstFrameP->frameRect are the same size!
///--------------------------------------------------------------------------------------
SW_FUNC void BlitStraightWrappingLine(
FramePtr dstFrameP,
Point srcPoint,
Point dstPoint,
register Byte color)
{
unsigned long rowBytes = dstFrameP->frameRowBytes;
short x1 = srcPoint.h, y1 = srcPoint.v,
x2 = dstPoint.h, y2 = dstPoint.v;
short dx, dy;
if (x1 == x2) // Straight vertical line
{
register Ptr baseAddr;
short y3, y4; // Second half of wrapped line
if (y2 < y1)
{
y1 = dstPoint.v; // Swap y1 and y2 if they're
y2 = srcPoint.v; // in the wrong order.
}
// Wrap line horizontally if necessary before we start (only done once)
// Remember x1 and x2 are the same, and x2 isn't used.
if (x1 < dstFrameP->frameRect.left)
x1 += dstFrameP->frameRect.right;
else if (x1 >= dstFrameP->frameRect.right)
x1 -= dstFrameP->frameRect.right;
// Now we check to see if the line wraps vertically, in which case we
// split it into two lines before drawing it.
if (y1 < dstFrameP->frameRect.top)
{
if (y2 < dstFrameP->frameRect.top)
y4 = y2 + dstFrameP->frameRect.bottom;
else
y4 = dstFrameP->frameRect.bottom-1;
y3 = y1 + dstFrameP->frameRect.bottom;
y1 = dstFrameP->frameRect.top;
}
else if (y2 >= dstFrameP->frameRect.bottom)
{
if (y1 >= dstFrameP->frameRect.bottom)
y3 = y1 - dstFrameP->frameRect.bottom;
else
y3 = dstFrameP->frameRect.top;
y4 = y2 - dstFrameP->frameRect.bottom;
y2 = dstFrameP->frameRect.bottom-1;
}
else
{
y3 = 0; // The formula for no second line
y4 = -1;
}
// -----Draw the first line-----
dy = y2 - y1 + 1; // dy = number of pixels in line
if (dy > 0) // Make sure there is a line first!
{
baseAddr = dstFrameP->frameBaseAddr + dstFrameP->scanLinePtrArray[y1] + x1;
*baseAddr = color;
while(--dy)
{
baseAddr += rowBytes;
*baseAddr = color;
}
}
// -----Draw the second line-----
dy = y4 - y3 + 1; // dy = number of pixels in line
if (dy > 0) // Make sure there is a line first!
{
baseAddr = dstFrameP->frameBaseAddr + dstFrameP->scanLinePtrArray[y3] + x1;
*baseAddr = color;
while(--dy)
{
baseAddr += rowBytes;
*baseAddr = color;
}
}
}
else if (y1 == y2) // Straight horizontal line
{
register unsigned long *longBaseAddr;
register numLongBlits;
unsigned long longColor;
short x3, x4; // Second half of wrapped line
// Fill longColor with color
longColor = (color<<24) | (color<<16) | (color<<8) | (color);
if (x2 < x1)
{
x1 = dstPoint.h; // Swap x1 and x2 if they're
x2 = srcPoint.h; // in the wrong order.
}
// Wrap line vertically if necessary before we start (only done once)
// Remember y1 and y2 are the same, and y2 isn't used.
if (y1 < dstFrameP->frameRect.top)
y1 += dstFrameP->frameRect.bottom;
else if (y1 >= dstFrameP->frameRect.bottom)
y1 -= dstFrameP->frameRect.bottom;
// Now we check to see if the line wraps horizontally, in which case we
// split it into two lines before drawing it.
if (x1 < dstFrameP->frameRect.left)
{
if (x2 < dstFrameP->frameRect.left)
x4 = x2 + dstFrameP->frameRect.right;
else
x4 = dstFrameP->frameRect.right-1;
x3 = x1 + dstFrameP->frameRect.right;
x1 = dstFrameP->frameRect.left;
}
else if (x2 >= dstFrameP->frameRect.right)
{
if (x1 >= dstFrameP->frameRect.right)
x3 = x1 - dstFrameP->frameRect.right;
else
x3 = dstFrameP->frameRect.left;
x4 = x2 - dstFrameP->frameRect.right;
x2 = dstFrameP->frameRect.right-1;
}
else
{
x3 = 0; // The formula for no second line
x4 = -1;
}
// ----Draw the first line----
dx = x2 - x1 + 1; // dx = number of pixels in line
if (dx > 0) // Make sure there is a line first!
{
numLongBlits = (dx >> 2);
longBaseAddr = (unsigned long *)(dstFrameP->frameBaseAddr +
dstFrameP->scanLinePtrArray[y1] + x1);
while (numLongBlits--)
{
*(longBaseAddr)++ = longColor;
}
#ifdef __MWERKS__ // Do it nicely
// Handle extra pixels at end of line
if (dx & 0x2)
*((unsigned short *) longBaseAddr)++ = (unsigned short)longColor;
if (dx & 0x1)
*((unsigned char *) longBaseAddr)++ = color;
#else // Make Think C happy
// Handle extra pixels at end of line
if (dx & 0x2)
{
*((unsigned short *) longBaseAddr) = (unsigned short)longColor;
longBaseAddr = (unsigned long *)(((unsigned short *)longBaseAddr) + 1);
}
if (dx & 0x1)
{
*((unsigned char *) longBaseAddr) = color;
longBaseAddr = (unsigned long *)(((unsigned char *)longBaseAddr) + 1);
}
#endif
}
// ----Draw the second line----
dx = x4 - x3 + 1; // dx = number of pixels in line
if (dx > 0) // Make sure there is a line first!
{
numLongBlits = (dx >> 2);
longBaseAddr = (unsigned long *)(dstFrameP->frameBaseAddr +
dstFrameP->scanLinePtrArray[y1] + x3);
while (numLongBlits--)
{
*(longBaseAddr)++ = longColor;
}
#ifdef __MWERKS__ // Do it nicely
// Handle extra pixels at end of line
if (dx & 0x2)
*((unsigned short *) longBaseAddr)++ = (unsigned short)longColor;
if (dx & 0x1)
*((unsigned char *) longBaseAddr)++ = color;
#else // Make Think C happy
// Handle extra pixels at end of line
if (dx & 0x2)
{
*((unsigned short *) longBaseAddr) = (unsigned short)longColor;
longBaseAddr = (unsigned long *)(((unsigned short *)longBaseAddr) + 1);
}
if (dx & 0x1)
{
*((unsigned char *) longBaseAddr) = color;
longBaseAddr = (unsigned long *)(((unsigned char *)longBaseAddr) + 1);
}
#endif
}
}
}
///--------------------------------------------------------------------------------------
// BPCopyStraightWrappingLine - No clipping performed by function.
// Assumes srcFrameP->frameRect and dstFrameP->frameRect are the same size!
///--------------------------------------------------------------------------------------
SW_FUNC void BPCopyStraightWrappingLine(
FramePtr srcFrameP,
FramePtr dstFrameP,
Point srcPoint,
Point dstPoint)
{
unsigned long srcRowBytes = srcFrameP->frameRowBytes;
unsigned long dstRowBytes = dstFrameP->frameRowBytes;
short x1 = srcPoint.h, y1 = srcPoint.v,
x2 = dstPoint.h, y2 = dstPoint.v;
short dx, dy;
if (x1 == x2) // Straight vertical line
{
register Ptr srcBaseAddr, dstBaseAddr;
short y3, y4; // Second half of wrapped line
if (y2 < y1)
{
y1 = dstPoint.v; // Swap y1 and y2 if they're
y2 = srcPoint.v; // in the wrong order.
}
// Wrap line horizontally if necessary before we start (only done once)
// Remember x1 and x2 are the same, and x2 isn't used.
if (x1 < dstFrameP->frameRect.left)
x1 += dstFrameP->frameRect.right;
else if (x1 >= dstFrameP->frameRect.right)
x1 -= dstFrameP->frameRect.right;
// Now we check to see if the line wraps vertically, in which case we
// split it into two lines before drawing it.
if (y1 < dstFrameP->frameRect.top)
{
if (y2 < dstFrameP->frameRect.top)
y4 = y2 + dstFrameP->frameRect.bottom;
else
y4 = dstFrameP->frameRect.bottom-1;
y3 = y1 + dstFrameP->frameRect.bottom;
y1 = dstFrameP->frameRect.top;
}
else if (y2 >= dstFrameP->frameRect.bottom)
{
if (y1 >= dstFrameP->frameRect.bottom)
y3 = y1 - dstFrameP->frameRect.bottom;
else
y3 = dstFrameP->frameRect.top;
y4 = y2 - dstFrameP->frameRect.bottom;
y2 = dstFrameP->frameRect.bottom-1;
}
else
{
y3 = 0; // The formula for no second line
y4 = -1;
}
// -----Draw the first line-----
dy = y2 - y1 + 1; // dy = number of pixels in line
if (dy > 0) // Make sure there is a line first!
{
srcBaseAddr = srcFrameP->frameBaseAddr + srcFrameP->scanLinePtrArray[y1] + x1;
dstBaseAddr = dstFrameP->frameBaseAddr + dstFrameP->scanLinePtrArray[y1] + x1;
*dstBaseAddr = *srcBaseAddr; // Copy the first pixel
while (--dy)
{
srcBaseAddr += srcRowBytes;
dstBaseAddr += dstRowBytes;
*dstBaseAddr = *srcBaseAddr;
}
}
// -----Draw the second line-----
dy = y4 - y3 + 1; // dy = number of pixels in line
if (dy > 0) // Make sure there is a line first!
{
srcBaseAddr = srcFrameP->frameBaseAddr + srcFrameP->scanLinePtrArray[y3] + x1;
dstBaseAddr = dstFrameP->frameBaseAddr + dstFrameP->scanLinePtrArray[y3] + x1;
*dstBaseAddr = *srcBaseAddr; // Copy the first pixel
while (--dy)
{
srcBaseAddr += srcRowBytes;
dstBaseAddr += dstRowBytes;
*dstBaseAddr = *srcBaseAddr;
}
}
}
else if (y1 == y2) // Straight horizontal line
{
register unsigned long *srcBaseAddr, *dstBaseAddr;
register numLongBlits;
short x3, x4; // Second half of wrapped line
if (x2 < x1)
{
x1 = dstPoint.h; // Swap x1 and x2 if they're
x2 = srcPoint.h; // in the wrong order.
}
// Wrap line vertically if necessary before we start (only done once)
// Remember y1 and y2 are the same, and y2 isn't used.
if (y1 < dstFrameP->frameRect.top)
y1 += dstFrameP->frameRect.bottom;
else if (y1 >= dstFrameP->frameRect.bottom)
y1 -= dstFrameP->frameRect.bottom;
// Now we check to see if the line wraps horizontally, in which case we
// split it into two lines before drawing it.
if (x1 < dstFrameP->frameRect.left)
{
if (x2 < dstFrameP->frameRect.left)
x4 = x2 + dstFrameP->frameRect.right;
else
x4 = dstFrameP->frameRect.right-1;
x3 = x1 + dstFrameP->frameRect.right;
x1 = dstFrameP->frameRect.left;
}
else if (x2 >= dstFrameP->frameRect.right)
{
if (x1 >= dstFrameP->frameRect.right)
x3 = x1 - dstFrameP->frameRect.right;
else
x3 = dstFrameP->frameRect.left;
x4 = x2 - dstFrameP->frameRect.right;
x2 = dstFrameP->frameRect.right-1;
}
else
{
x3 = 0; // The formula for no second line
x4 = -1;
}
// ----Draw the first line----
dx = x2 - x1 + 1; // dx = number of pixels in line
if (dx > 0) // Make sure there is a line first!
{
numLongBlits = (dx >> 2);
srcBaseAddr = (unsigned long *)(srcFrameP->frameBaseAddr +
srcFrameP->scanLinePtrArray[y1] + x1);
dstBaseAddr = (unsigned long *)(dstFrameP->frameBaseAddr +
dstFrameP->scanLinePtrArray[y1] + x1);
while (numLongBlits--)
{
*(dstBaseAddr)++ = *(srcBaseAddr)++;
}
#ifdef __MWERKS__ // Do it nicely
// Handle extra pixels at end of line
if (dx & 0x2)
*((unsigned short *) dstBaseAddr)++ = *((unsigned short *) srcBaseAddr)++;
if (dx & 0x1)
*((unsigned char *) dstBaseAddr)++ = *((unsigned char *) srcBaseAddr)++;
#else // Make Think C happy
// Handle extra pixels at end of line
if (dx & 0x2)
{
*((unsigned short *) dstBaseAddr) = *((unsigned short *) srcBaseAddr);
dstBaseAddr = (unsigned long *)(((unsigned short *)dstBaseAddr) + 1);
srcBaseAddr = (unsigned long *)(((unsigned short *)srcBaseAddr) + 1);
}
if (dx & 0x1)
{
*((unsigned char *) dstBaseAddr) = *((unsigned char *) srcBaseAddr);
dstBaseAddr = (unsigned long *)(((unsigned char *)dstBaseAddr) + 1);
srcBaseAddr = (unsigned long *)(((unsigned char *)srcBaseAddr) + 1);
}
#endif
}
// ----Draw the second line----
dx = x4 - x3 + 1; // dx = number of pixels in line
if (dx > 0) // Make sure there is a line first!
{
numLongBlits = (dx >> 2);
srcBaseAddr = (unsigned long *)(srcFrameP->frameBaseAddr +
srcFrameP->scanLinePtrArray[y1] + x3);
dstBaseAddr = (unsigned long *)(dstFrameP->frameBaseAddr +
dstFrameP->scanLinePtrArray[y1] + x3);
while (numLongBlits--)
{
*(dstBaseAddr)++ = *(srcBaseAddr)++;
}
#ifdef __MWERKS__ // Do it nicely
// Handle extra pixels at end of line
if (dx & 0x2)
*((unsigned short *) dstBaseAddr)++ = *((unsigned short *) srcBaseAddr)++;
if (dx & 0x1)
*((unsigned char *) dstBaseAddr)++ = *((unsigned char *) srcBaseAddr)++;
#else // Make Think C happy
// Handle extra pixels at end of line
if (dx & 0x2)
{
*((unsigned short *) dstBaseAddr) = *((unsigned short *) srcBaseAddr);
dstBaseAddr = (unsigned long *)(((unsigned short *)dstBaseAddr) + 1);
srcBaseAddr = (unsigned long *)(((unsigned short *)srcBaseAddr) + 1);
}
if (dx & 0x1)
{
*((unsigned char *) dstBaseAddr) = *((unsigned char *) srcBaseAddr);
dstBaseAddr = (unsigned long *)(((unsigned char *)dstBaseAddr) + 1);
srcBaseAddr = (unsigned long *)(((unsigned char *)srcBaseAddr) + 1);
}
#endif
}
}
}