netscape-revival
sun-java/awt/macos/LMacImage.cp
//##############################################################################
//##############################################################################
//
// File: LMacImage.cp
// Author: Dan Clifford
//
// Copyright © 1995-1996, Netscape Communications Corporation
//
//##############################################################################
//##############################################################################
extern "C" {
#include <stdlib.h>
#include "native.h"
#include "typedefs_md.h"
#include "interpreter.h"
#include "java_awt_image_ColorModel.h"
#include "j_awt_image_IndexColorModel.h"
#include "j_awt_image_DirectColorModel.h"
#include "sun_awt_image_Image.h"
#include "s_a_image_ImageRepresentation.h"
#include "java_awt_Graphics.h"
#include "sun_awt_macos_MacGraphics.h"
#include "s_a_i_OffScreenImageSource.h"
#include "exceptions.h"
#include "mdmacmem.h"
#include "MToolkit.h"
};
#include <Quickdraw.h>
#include <QDOffscreen.h>
#include "LMacGraphics.h"
#include "fredmem.h"
struct PrivateMacImageData {
GWorldPtr imageGWorld;
Ptr imageAlpha;
long imageAlphaRowBytes;
BitMap imageMask;
long imageUsesAlpha;
long imageUsesBinaryMask;
};
typedef struct PrivateMacImageData PrivateMacImageData;
extern Hjava_awt_image_ColorModel *gStandard8BitColorModel;
GWorldPtr gSourceGWorld = NULL;
enum {
kAlphaMixingBufferWidth = 75,
kAlphaMixingBufferHeight = 75,
kImageAllocationSizeFudge = 12 * 1024
};
CTabHandle TranslateColorModelToClut(struct Hjava_awt_image_ColorModel *colorModel, short depth)
{
Classjava_awt_image_IndexColorModel *colorModelStruct;
UInt8 *currentRed;
UInt8 *currentBlue;
UInt8 *currentGreen;
short tableSize;
ColorSpec *currentArrayItem;
CTabHandle colorTable;
if (depth >= 16) {
colorTable = (CTabHandle)NewHandleClear(sizeof(ColorTable));
tableSize = 0;
}
else {
colorModelStruct = (Classjava_awt_image_IndexColorModel *)unhand(colorModel);
currentRed = (UInt8 *)unhand(colorModelStruct->red)->body;
currentBlue = (UInt8 *)unhand(colorModelStruct->blue)->body;
currentGreen = (UInt8 *)unhand(colorModelStruct->green)->body;
colorTable = GetCTable(2048);
tableSize = colorModelStruct->map_size;
}
if (colorTable == NULL)
return NULL;
// If the color table we are using is the standard color
// system color table, then donÕt rebuild it.
if (colorModel == gStandard8BitColorModel)
return colorTable;
// The color table is not the standard 8-bit one. Create
// a new 'clut' out of the color table.
currentArrayItem = (**colorTable).ctTable;
for (UInt32 count = 0; count < tableSize; count++) {
UInt8 red, blue, green;
red = *currentRed++;
blue = *currentBlue++;
green = *currentGreen++;
currentArrayItem->rgb.red = red | (red << 8);
currentArrayItem->rgb.blue = blue | (blue << 8);
currentArrayItem->rgb.green = green | (green << 8);
currentArrayItem++;
}
(**colorTable).ctSize = tableSize;
if (depth < 16)
CTabChanged(colorTable);
return colorTable;
}
extern void sun_awt_image_ImageRepresentation_offscreenInit(struct Hsun_awt_image_ImageRepresentation *imageRepresentationObject)
{
struct Classsun_awt_image_ImageRepresentation *imageRepresentationStruct = unhand(imageRepresentationObject);
}
UInt8 *GetDestinationAlphaStorage(struct Hsun_awt_image_ImageRepresentation *imageRepresentationObject)
{
Classsun_awt_image_ImageRepresentation *imageRepresentationStruct = unhand(imageRepresentationObject);
return (UInt8 *)((PrivateMacImageData *)(imageRepresentationStruct->pData))->imageAlpha;
}
UInt32 *GetDestinationMaskStorage(struct Hsun_awt_image_ImageRepresentation *imageRepresentationObject, UInt32 *rowBytes)
{
Classsun_awt_image_ImageRepresentation *imageRepresentationStruct = unhand(imageRepresentationObject);
*rowBytes = ((PrivateMacImageData *)(imageRepresentationStruct->pData))->imageMask.rowBytes;
return (UInt32 *)((PrivateMacImageData *)(imageRepresentationStruct->pData))->imageMask.baseAddr;
}
GWorldPtr GetDestinationBackingStoreWorld(struct Hsun_awt_image_ImageRepresentation *imageRepresentationObject, struct Hjava_awt_image_ColorModel *colorModel, short depth, Boolean transparent)
{
Classsun_awt_image_ImageRepresentation *imageRepresentationStruct = unhand(imageRepresentationObject);
Classsun_awt_image_Image *ownerImage = unhand(imageRepresentationStruct->image);
PrivateMacImageData *newImageData = NULL;
GWorldPtr newGWorld = NULL;
Size maskDataRowBytes;
Ptr alphaData = NULL;
Ptr maskData = NULL;
short toFillWith = transparent ? 0 : 0xFFFF;
CTabHandle colorTable = NULL;
if (imageRepresentationStruct->pData == NULL) {
Rect globalRect = { -32767, -32767, 32767, 32767 },
newOffscreenBounds;
CGrafPtr origPort;
GDHandle origDevice;
// If we are asked for an image of depth zero and it doesnÕt already
// exist, then fail.
if (depth == 0)
return NULL;
// Reserve 40% more than the actual allocation so that
// we allo some overhead for gif/jpeg buffers. This is
// part of our "pre-flight" strategy.
Size allocationSize = ((1L * imageRepresentationStruct->srcW * imageRepresentationStruct->srcH) *
((depth / 8) + 1) + kImageAllocationSizeFudge) * 14 / 10;
if (!Memory_ReserveInMacHeap(allocationSize))
return NULL;
newImageData = (PrivateMacImageData *)malloc(sizeof(PrivateMacImageData));
if (newImageData == NULL) goto errorExit;
memset(newImageData, 0, sizeof(PrivateMacImageData));
newImageData->imageUsesAlpha = false;
newImageData->imageUsesBinaryMask = true;
colorTable = TranslateColorModelToClut(colorModel, depth);
if (colorTable == NULL) goto errorExit;
// Allocate the offscreen image buffer.
SetRect(&newOffscreenBounds, 0, 0, imageRepresentationStruct->srcW, imageRepresentationStruct->srcH);
NewGWorld(&newGWorld, depth, &newOffscreenBounds, colorTable, NULL, keepLocal | useTempMem);
DisposeHandle((Handle)colorTable);
if (newGWorld == NULL) goto errorExit;
GetGWorld(&origPort, &origDevice);
SetGWorld(newGWorld, NULL);
RGBColor greyColor = { 192 << 8, 192 << 8, 192 << 8 };
::RGBForeColor(&greyColor);
::PaintRect(&newOffscreenBounds);
SetGWorld(origPort, origDevice);
newImageData->imageGWorld = newGWorld;
// Allocate the alpha channel storage.
Size alphaDataSize = imageRepresentationStruct->srcW * imageRepresentationStruct->srcH,
roundedAlphaDataSize = (alphaDataSize + 3) & 0xFFFFFFFC;
alphaData = (Ptr)malloc(roundedAlphaDataSize);
if (alphaData == NULL) goto errorExit;
newImageData->imageAlpha = alphaData;
newImageData->imageAlphaRowBytes = imageRepresentationStruct->srcW;
memset(alphaData, toFillWith, roundedAlphaDataSize);
// Allocate the bitmap storage, rounding the bitmap rowbytes to the
// nearest 32-bit boundary.
maskDataRowBytes = (((imageRepresentationStruct->srcW + 7)/ 8) + 3) & 0xFFFFFFFC;
maskData = (Ptr)malloc(maskDataRowBytes * imageRepresentationStruct->srcH);
if (maskData == NULL) goto errorExit;
newImageData->imageMask.baseAddr = maskData;
newImageData->imageMask.rowBytes = maskDataRowBytes;
newImageData->imageMask.bounds = newOffscreenBounds;
memset(maskData, toFillWith, maskDataRowBytes * imageRepresentationStruct->srcH);
imageRepresentationStruct->pData = (long)newImageData;
}
else {
newGWorld = ((PrivateMacImageData *)(imageRepresentationStruct->pData))->imageGWorld;
}
return newGWorld;
errorExit:
// Clean up and signal an error.
if (newImageData != NULL) {
if (newGWorld != NULL)
DisposeGWorld(newGWorld);
if (alphaData != NULL)
free(alphaData);
if (maskData != NULL)
free(maskData);
free(newImageData);
}
SignalError(0, JAVAPKG "OutOfMemoryError", 0);
return NULL;
}
void sun_awt_image_OffScreenImageSource_sendPixels(struct Hsun_awt_image_OffScreenImageSource *imageSource)
{
// FIX ME
}
long sun_awt_image_ImageRepresentation_setBytePixels(struct Hsun_awt_image_ImageRepresentation *imageRepresentationObject, long x, long y,
long width, long height, struct Hjava_awt_image_ColorModel *colorModel, HArrayOfByte *pixelData, long offset, long scansize)
{
Classsun_awt_image_ImageRepresentation *imageRepresentationStruct = unhand(imageRepresentationObject);
PrivateMacImageData *privateImageData;
Classjava_awt_image_IndexColorModel *colorModelStruct = (Classjava_awt_image_IndexColorModel *)unhand(colorModel);
UInt8 *alphaLookup;
UInt8 transparentIndex = colorModelStruct->transparent_index;
GWorldPtr destinationWorld;
PixMapHandle destinationPixMap;
UInt8 *baseDestinationPixel,
*currentDestinationPixel;
UInt8 *baseSourcePixel,
*currentSourcePixel;
UInt8 *baseAlpha,
*currentAlpha;
UInt32 maskRowBytes,
*currentMask,
*baseMask;
UInt32 currentBit,
baseBit;
alphaLookup = (colorModelStruct->alpha == NULL) ? NULL : (UInt8 *)unhand(colorModelStruct->alpha)->body;
// If no backing store exists for the image representation, create one.
destinationWorld = GetDestinationBackingStoreWorld(imageRepresentationObject, colorModel, 8, true);
privateImageData = (PrivateMacImageData *)(imageRepresentationStruct->pData);
if (destinationWorld == NULL)
return 0;
destinationPixMap = GetGWorldPixMap(destinationWorld);
baseSourcePixel = (UInt8 *)(unhand(pixelData)->body + offset);
baseDestinationPixel = (UInt8 *)(GetPixBaseAddr(destinationPixMap)) + ((**destinationPixMap).rowBytes & 0x7FFF) * y + x;
baseAlpha = GetDestinationAlphaStorage(imageRepresentationObject) + width * y + x;
baseMask = GetDestinationMaskStorage(imageRepresentationObject, &maskRowBytes);
maskRowBytes = maskRowBytes >> 2;
baseMask += y * maskRowBytes + (x / 32);
baseBit = 0x80000000 >> (x % 32);
while (height--) {
UInt32 widthCopy = width;
currentDestinationPixel = baseDestinationPixel;
currentSourcePixel = baseSourcePixel;
currentAlpha = baseAlpha;
currentMask = baseMask;
currentBit = baseBit;
while (widthCopy--) {
UInt8 currentSourcePixelValue = *currentSourcePixel++;
*currentDestinationPixel++ = currentSourcePixelValue;
UInt8 currentAlphaPixel = 0xFF;
if (alphaLookup != NULL)
currentAlphaPixel = alphaLookup[currentSourcePixelValue];
if ((transparentIndex == currentSourcePixelValue) && (transparentIndex != 0xFF))
currentAlphaPixel = 0;
if (currentAlphaPixel != 0xFF) {
privateImageData->imageUsesAlpha = true;
if (currentAlphaPixel != 0)
privateImageData->imageUsesBinaryMask = false;
}
*currentAlpha++ = currentAlphaPixel;
if (currentAlphaPixel == 0xFF)
*currentMask |= currentBit;
else
*currentMask &= ~currentBit;
currentBit = currentBit >> 1;
if (currentBit == 0) {
currentMask++;
currentBit = 0x80000000;
}
}
baseDestinationPixel += ((**destinationPixMap).rowBytes & 0x7FFF);
baseSourcePixel += scansize;
baseAlpha += width;
baseMask += maskRowBytes;
}
return 1;
}
long sun_awt_image_ImageRepresentation_setIntPixels(struct Hsun_awt_image_ImageRepresentation *imageRepresentationObject, long x, long y,
long width, long height, struct Hjava_awt_image_ColorModel *colorModel, HArrayOfInt *pixelData, long offset, long scansize)
{
Classsun_awt_image_ImageRepresentation *imageRepresentationStruct = unhand(imageRepresentationObject);
ClassClass *directColorModelClass;
PrivateMacImageData *privateImageData;
GWorldPtr destinationWorld;
PixMapHandle destinationPixMap;
UInt16 *baseDestinationPixel,
*currentDestinationPixel;
UInt32 *baseSourcePixel,
*currentSourcePixel;
UInt8 *baseAlpha,
*currentAlpha;
UInt32 maskRowBytes,
*currentMask,
*baseMask;
UInt32 currentBit,
baseBit;
Boolean isDirectColorModel;
Boolean usesAlpha = false;
// If no backing store exists for the image representation, create one.
destinationWorld = GetDestinationBackingStoreWorld(imageRepresentationObject, colorModel, 16, true);
directColorModelClass = FindClass(EE(), "java/awt/image/DirectColorModel", TRUE);
isDirectColorModel = (obj_classblock(colorModel) == directColorModelClass);
if (isDirectColorModel) {
Classjava_awt_image_DirectColorModel *directColorModel = (Classjava_awt_image_DirectColorModel *)unhand(colorModel);
usesAlpha = (directColorModel->alpha_bits == 8);
}
privateImageData = (PrivateMacImageData *)(imageRepresentationStruct->pData);
if (destinationWorld == NULL)
return 0;
destinationPixMap = GetGWorldPixMap(destinationWorld);
baseSourcePixel = (UInt32 *)(unhand(pixelData)->body + offset);
baseDestinationPixel = (UInt16 *)((UInt8 *)(GetPixBaseAddr(destinationPixMap)) + ((**destinationPixMap).rowBytes & 0x7FFF) * y + x);
baseAlpha = GetDestinationAlphaStorage(imageRepresentationObject) + width * y + x;
baseMask = GetDestinationMaskStorage(imageRepresentationObject, &maskRowBytes);
maskRowBytes = maskRowBytes >> 2;
baseMask += y * maskRowBytes + (x / 32);
baseBit = 0x80000000 >> (x % 32);
while (height--) {
UInt32 widthCopy = width;
currentDestinationPixel = baseDestinationPixel;
currentSourcePixel = baseSourcePixel;
currentAlpha = baseAlpha;
currentMask = baseMask;
currentBit = baseBit;
while (widthCopy--) {
UInt32 currentSourcePixelValue = *currentSourcePixel++;
UInt32 currentDestinationPixelValue = 0;
UInt8 currentAlphaPixel;
// Extract the alpha pixel
if (usesAlpha)
currentAlphaPixel = (currentSourcePixelValue & 0xFF000000) >> 24;
else
currentAlphaPixel = 0xFF;
// Convert here.
currentDestinationPixelValue = (currentSourcePixelValue & 0x000000F8) >> 3;
currentDestinationPixelValue |= (currentSourcePixelValue & 0x0000F800) >> 6;
currentDestinationPixelValue |= (currentSourcePixelValue & 0x00F80000) >> 9;
*currentDestinationPixel++ = currentDestinationPixelValue;
if (currentAlphaPixel != 0xFF) {
privateImageData->imageUsesAlpha = true;
if (currentAlphaPixel != 0)
privateImageData->imageUsesBinaryMask = false;
}
*currentAlpha++ = currentAlphaPixel;
if (currentAlphaPixel == 0xFF)
*currentMask |= currentBit;
else
*currentMask &= ~currentBit;
currentBit = currentBit >> 1;
if (currentBit == 0) {
currentMask++;
currentBit = 0x80000000;
}
}
baseDestinationPixel += ((**destinationPixMap).rowBytes & 0x7FFF) >> 1;
baseSourcePixel += scansize;
baseAlpha += width;
baseMask += maskRowBytes;
}
return 1;
}
long sun_awt_image_ImageRepresentation_finish(struct Hsun_awt_image_ImageRepresentation *imageRepresentationObject, long force)
{
return true;
}
void sun_awt_image_ImageRepresentation_imageDraw(struct Hsun_awt_image_ImageRepresentation *imageRepresentationObject, struct Hjava_awt_Graphics *graphicsObject, long x, long y, struct Hjava_awt_Color *)
{
struct Classsun_awt_image_ImageRepresentation *imageRepresentation = unhand(imageRepresentationObject);
struct Classsun_awt_image_Image *ownerImage = unhand(imageRepresentation->image);
LMacGraphics *ppMacGraphics;
GrafPtr destinationPort;
GWorldPtr imageGWorld;
Rect sourceRectangle,
destinationRectangle;
imageGWorld = GetDestinationBackingStoreWorld(imageRepresentationObject, NULL, 0, true);
// If we donÕt have the destination image yet (still need to
// create it), then do nothing.
if (imageGWorld == NULL)
return;
ppMacGraphics = (LMacGraphics *)(unhand((struct Hsun_awt_macos_MacGraphics *)graphicsObject)->pData);
if (ppMacGraphics->BeginDrawing()) {
PrivateMacImageData *privateImageData = (PrivateMacImageData *)(imageRepresentation->pData);
destinationPort = ppMacGraphics->GetOwnerPort();
sourceRectangle = (**(GetGWorldPixMap(imageGWorld))).bounds;
ppMacGraphics->ConvertToPortRect(destinationRectangle, x, y, imageRepresentation->width, imageRepresentation->height);
ForeColor(blackColor);
BackColor(whiteColor);
if (!(privateImageData->imageUsesAlpha)) {
// Simplest mode, no mask. Use simple CopyBits.
CopyBits(&(((GrafPtr)imageGWorld)->portBits),
&((GrafPtr)destinationPort)->portBits,
&sourceRectangle,
&destinationRectangle,
srcCopy,
NULL);
}
else if (privateImageData->imageUsesBinaryMask) {
// Image uses alpha mask, but is binary (no mixing necessary).
// Use CopyMask.
CopyMask(&(((GrafPtr)imageGWorld)->portBits),
&(privateImageData->imageMask),
&((GrafPtr)destinationPort)->portBits,
&sourceRectangle,
&sourceRectangle,
&destinationRectangle);
}
else {
static GWorldPtr gSourceMixingWorld = NULL;
static GWorldPtr gDestinationMixingWorld = NULL;
static UInt8 *gSourceAlphaBitMap = NULL;
PixMapHandle gSourceMixingMap;
PixMapHandle gDestiantionMixingMap;
Boolean gCanMixAlpha;
// Try to use the two bitmaps that we will use for for mixing
// the alpha channel into the final image (if we don't have
// them already).
Memory_ReserveInMacHeap(128L * 1024);
if (gSourceMixingWorld == NULL) {
Rect mixingBounds = { 0, 0, kAlphaMixingBufferWidth, kAlphaMixingBufferHeight };
::NewGWorld(&gSourceMixingWorld, 32, &mixingBounds, NULL, NULL, 0);
if (gSourceMixingWorld == NULL) {
SignalError(0, JAVAPKG "OutOfMemoryError", 0);
return;
}
}
if (gDestinationMixingWorld == NULL) {
Rect mixingBounds = { 0, 0, kAlphaMixingBufferWidth, kAlphaMixingBufferHeight };
::NewGWorld(&gDestinationMixingWorld, 32, &mixingBounds, NULL, NULL, 0);
if (gDestinationMixingWorld == NULL) {
SignalError(0, JAVAPKG "OutOfMemoryError", 0);
return;
}
}
if (gSourceAlphaBitMap == NULL) {
UInt32 allocSize = kAlphaMixingBufferWidth * kAlphaMixingBufferWidth;
gSourceAlphaBitMap = (UInt8 *)malloc(allocSize);
if (gSourceAlphaBitMap == NULL) {
SignalError(0, JAVAPKG "OutOfMemoryError", 0);
return;
}
memset(gSourceAlphaBitMap, 0xFF, allocSize);
}
gCanMixAlpha = (gSourceMixingWorld != NULL) && (gDestinationMixingWorld != NULL);
// If we have been able to allocaing alpha mixing buffers, then iterate
// over the source image, mixing it into the destination. If we were
// unsuccessful in allocating buffers, then fall back on our CopyMask code.
// This will copy the image, but won't allow transparency.
if ((imageRepresentation->width == 0) || (imageRepresentation->height == 0))
gCanMixAlpha = false;
if (gCanMixAlpha) {
UInt32 horizontalPatches = (imageRepresentation->width - 1) /
kAlphaMixingBufferWidth + 1;
UInt32 verticalPatches = (imageRepresentation->height - 1) /
kAlphaMixingBufferHeight + 1;
UInt32 currentHPatch, currentVPatch;
gSourceMixingMap = GetGWorldPixMap(gSourceMixingWorld);
gDestiantionMixingMap = GetGWorldPixMap(gDestinationMixingWorld);
for (currentVPatch = 0; currentVPatch < verticalPatches; currentVPatch++) {
for (currentHPatch = 0; currentHPatch < horizontalPatches; currentHPatch++) {
Rect currentMixRect;
::SetRect(¤tMixRect,
x + currentHPatch * kAlphaMixingBufferWidth,
y + currentVPatch * kAlphaMixingBufferWidth,
x + (currentHPatch + 1) * kAlphaMixingBufferWidth,
y + (currentVPatch + 1) * kAlphaMixingBufferWidth);
// Pin the patch rectangle to the maximum size of the
// destination rectangle.
if (currentMixRect.right > destinationRectangle.right)
currentMixRect.right = destinationRectangle.right;
if (currentMixRect.bottom > destinationRectangle.bottom)
currentMixRect.bottom = destinationRectangle.bottom;
// Set both alpha mixing worlds to use the current mixing rect.
(**gSourceMixingMap).bounds = currentMixRect;
(**gDestiantionMixingMap).bounds = currentMixRect;
gSourceMixingWorld->portRect = currentMixRect;
gDestinationMixingWorld->portRect = currentMixRect;
(**(gSourceMixingWorld->visRgn)).rgnBBox = currentMixRect;
(**(gDestinationMixingWorld->visRgn)).rgnBBox = currentMixRect;
// Save our port and device information. We will need it to
// do the final copy bits.
CGrafPtr savedPort;
GDHandle savedDevice;
GetGWorld(&savedPort, &savedDevice);
// Copy (stretch) the source image into the first buffer.
SetGWorld(gSourceMixingWorld, NULL);
CopyBits(&(((GrafPtr)imageGWorld)->portBits),
&((GrafPtr)gSourceMixingWorld)->portBits,
&sourceRectangle,
&destinationRectangle,
srcCopy,
NULL);
// Scale part of the original alpha mask into the scaled mask
UInt32 scaledSourceFactorHeight,
scaledSourceFactorWidth;
UInt32 currentAlphaX,
currentAlphaY;
UInt32 horizMax = currentMixRect.right - currentMixRect.left;
UInt32 vertMax = currentMixRect.bottom - currentMixRect.top;
scaledSourceFactorWidth = (sourceRectangle.right - sourceRectangle.left) << 16;
scaledSourceFactorWidth = scaledSourceFactorWidth / (destinationRectangle.right - destinationRectangle.left);
scaledSourceFactorHeight = (sourceRectangle.bottom - sourceRectangle.top) << 16;
scaledSourceFactorHeight = scaledSourceFactorHeight / (destinationRectangle.bottom - destinationRectangle.top);
for (currentAlphaY = 0; currentAlphaY < vertMax; currentAlphaY++) {
UInt8 *currentDestinationAlphaPixel = gSourceAlphaBitMap + (currentAlphaY * kAlphaMixingBufferWidth);
for (currentAlphaX = 0; currentAlphaX < horizMax; currentAlphaX++) {
UInt8 *sourceImageBase;
UInt32 sourceX;
UInt32 sourceY;
sourceX = ((currentMixRect.left - destinationRectangle.left
+ currentAlphaX) * scaledSourceFactorWidth) >> 16;
sourceY = ((currentMixRect.top - destinationRectangle.top
+ currentAlphaY) * scaledSourceFactorHeight) >> 16;
sourceImageBase = (UInt8 *)(privateImageData->imageAlpha) + (sourceY * imageRepresentation->srcW) + sourceX;
*currentDestinationAlphaPixel++ = *sourceImageBase;
}
}
// Copy the destination image into the second buffer.
SetGWorld(gDestinationMixingWorld, NULL);
CopyBits(&(((GrafPtr)destinationPort)->portBits),
&((GrafPtr)gDestinationMixingWorld)->portBits,
¤tMixRect,
¤tMixRect,
srcCopy,
NULL);
// Iterate over the pixels in the mixing buffers, combining
// the alpha component of the source image with the destination.
UInt32 currentPatchH,
currentPatchV;
Ptr sourceMixBase,
destinationMixBase;
UInt8 *currentSourceMixPixelPtr,
*currentDestinationMixPixelPtr;
UInt32 sourceRowBytes = ((**gSourceMixingMap).rowBytes & 0x7FFF);
UInt32 destinationRowBytes = ((**gDestiantionMixingMap).rowBytes & 0x7FFF);
UInt8 *currentAlpha;
sourceMixBase = ::GetPixBaseAddr(gSourceMixingMap);
destinationMixBase = ::GetPixBaseAddr(gDestiantionMixingMap);
for (currentPatchV = 0; currentPatchV < vertMax; currentPatchV++) {
currentSourceMixPixelPtr = (UInt8 *)(sourceMixBase + currentPatchV * sourceRowBytes);
currentDestinationMixPixelPtr = (UInt8 *)(destinationMixBase + currentPatchV * destinationRowBytes);
currentAlpha = gSourceAlphaBitMap + currentPatchV * kAlphaMixingBufferWidth;
for (currentPatchH = 0; currentPatchH < horizMax; currentPatchH++) {
UInt16 alphaS = *currentAlpha++;
if (alphaS == 0xFF) {
*((UInt32 *)currentDestinationMixPixelPtr) = *((UInt32 *)currentSourceMixPixelPtr);
currentSourceMixPixelPtr += 4;
currentDestinationMixPixelPtr += 4;
}
else if (alphaS == 0x00) {
currentSourceMixPixelPtr += 4;
currentDestinationMixPixelPtr += 4;
} else {
UInt16 alphaD = 0xFF - alphaS;
UInt32 currentSourceMixPixel = *((UInt32 *)currentSourceMixPixelPtr);
UInt32 currentDestinationMixPixel = *((UInt32 *)currentDestinationMixPixelPtr);
UInt32 addPixel1;
UInt32 addPixel2;
UInt32 resultPixel;
addPixel1 = (currentSourceMixPixel & 0x000000FF) * alphaS + 0x000000FF;
addPixel2 = (currentDestinationMixPixel & 0x000000FF) * alphaD + 0x000000FF;
resultPixel = (addPixel1 + addPixel2) & 0x0000FF00;
addPixel1 = (currentSourceMixPixel & 0x0000FF00) * alphaS + 0x0000FF00;
addPixel2 = (currentDestinationMixPixel & 0x0000FF00) * alphaD + 0x0000FF00;
resultPixel += (addPixel1 + addPixel2) & 0x00FF0000;
resultPixel &= 0xFFFFFF;
addPixel1 = (currentSourceMixPixel & 0x00FF0000) * alphaS + 0x00FF0000;
addPixel2 = (currentDestinationMixPixel & 0x00FF0000) * alphaD + 0x00FF0000;
resultPixel += (addPixel1 + addPixel2) & 0xFF000000;
resultPixel = resultPixel >> 8;
*((UInt32 *)currentDestinationMixPixelPtr) = resultPixel;
currentDestinationMixPixelPtr += 4;
currentSourceMixPixelPtr += 4;
}
}
}
// Copy the mixed result image back from where we got it.
SetGWorld(savedPort, savedDevice);
CopyBits(&(((GrafPtr)gDestinationMixingWorld)->portBits),
&((GrafPtr)destinationPort)->portBits,
¤tMixRect,
¤tMixRect,
srcCopy,
NULL);
}
}
}
else {
CopyMask(&(((GrafPtr)imageGWorld)->portBits),
&(privateImageData->imageMask),
&((GrafPtr)destinationPort)->portBits,
&sourceRectangle,
&sourceRectangle,
&destinationRectangle);
}
}
}
ppMacGraphics->FinishDrawing();
}
void sun_awt_image_ImageRepresentation_disposeImage(struct Hsun_awt_image_ImageRepresentation *imageRepresentationObject)
{
struct Classsun_awt_image_ImageRepresentation *imageRepresentationStruct = unhand(imageRepresentationObject);
if (imageRepresentationStruct->pData != NULL) {
PrivateMacImageData *imageData = (PrivateMacImageData *)(imageRepresentationStruct->pData);
if (imageData->imageAlpha != NULL)
free(imageData->imageAlpha);
if (imageData->imageMask.baseAddr != NULL)
free(imageData->imageMask.baseAddr);
if (imageData->imageGWorld != NULL)
DisposeGWorld(imageData->imageGWorld);
free(imageData);
imageRepresentationStruct->pData = NULL;
}
}