executor/src/qIMVxfer.c

722 lines
21 KiB
C

/* Copyright 1994 by Abacus Research and
* Development, Inc. All rights reserved.
*/
#if !defined (OMIT_RCSID_STRINGS)
char ROMlib_rcsid_qIMVxfer[] =
"$Id: qIMVxfer.c 87 2005-05-25 01:57:33Z ctm $";
#endif
#include "rsys/common.h"
#include "QuickDraw.h"
#include "CQuickDraw.h"
#include "rsys/cquick.h"
/* Helper function: creates a new, sorted table so the value is the
* same as the index (although we don't bother filling in most of the
* color table fields).
*/
static CTabPtr
sort_table (CTabPtr old, CTabPtr new, unsigned max_color)
{
int i;
memset (&new->ctTable, 0, (max_color + 1) * sizeof (ColorSpec));
for (i = CW (old->ctSize); i >= 0; i--)
new->ctTable[CW (old->ctTable[i].value) & max_color].rgb =
old->ctTable[i].rgb;
return new;
}
/* declare a case in the transform switch */
#define TRANSFORM_CASE(name, macro) \
case MUNGE (name, 2, FALSE): \
CONVERT_BITS (READ_INDIRECT_PIXEL, READ_INDIRECT_PIXEL, \
WRITE_INDIRECT_PIXEL, \
NONPAT_NEXT1, \
macro, 2); \
break; \
case MUNGE (name, 4, FALSE): \
CONVERT_BITS (READ_INDIRECT_PIXEL, READ_INDIRECT_PIXEL, \
WRITE_INDIRECT_PIXEL, \
NONPAT_NEXT1, \
macro, 4); \
break; \
case MUNGE (name, 8, FALSE): \
CONVERT_BITS (READ_INDIRECT_PIXEL, READ_INDIRECT_PIXEL, \
WRITE_INDIRECT_PIXEL, \
NONPAT_NEXT1, \
macro, 8); \
break; \
case MUNGE (name, 16, FALSE): \
CONVERT_BITS (READ_DIRECT16_PIXEL, READ_DIRECT16_PIXEL, \
WRITE_DIRECT16_PIXEL, \
NONPAT_NEXT1, \
macro, 8); \
break; \
case MUNGE (name, 32, FALSE): \
CONVERT_BITS (READ_DIRECT32_PIXEL, READ_DIRECT32_PIXEL, \
WRITE_DIRECT32_PIXEL, \
NONPAT_NEXT1, \
macro, 8); \
break; \
case MUNGE (name, 2, TRUE): \
CONVERT_BITS (READ_PAT_INDIRECT_PIXEL, READ_INDIRECT_PIXEL, \
WRITE_INDIRECT_PIXEL, \
PAT_NEXT1, \
macro, 2); \
break; \
case MUNGE (name, 4, TRUE): \
CONVERT_BITS (READ_PAT_INDIRECT_PIXEL, READ_INDIRECT_PIXEL, \
WRITE_INDIRECT_PIXEL, \
PAT_NEXT1, \
macro, 4); \
break; \
case MUNGE (name, 8, TRUE): \
CONVERT_BITS (READ_PAT_INDIRECT_PIXEL, READ_INDIRECT_PIXEL, \
WRITE_INDIRECT_PIXEL, \
PAT_NEXT1, \
macro, 8); \
break; \
case MUNGE (name, 16, TRUE): \
CONVERT_BITS (READ_PAT_DIRECT16_PIXEL, READ_DIRECT16_PIXEL, \
WRITE_DIRECT16_PIXEL, \
PAT_NEXT1, \
macro, 8); \
break; \
case MUNGE (name, 32, TRUE): \
CONVERT_BITS (READ_PAT_DIRECT32_PIXEL, READ_DIRECT32_PIXEL, \
WRITE_DIRECT32_PIXEL, \
PAT_NEXT1, \
macro, 8); \
break
void
convert_transparent (const PixMap *src1, const PixMap *src2,
PixMap *dst,
const Rect *r1, const Rect *r2,
int16 mode,
boolean_t tile_src1_p,
int pat_x_offset, int pat_y_offset)
{
unsigned char *src1_row_base, *src2_row_base, *dst_row_base;
int src1_rowbytes, src2_rowbytes, dst_rowbytes, src1_deltax, src2_deltax;
int width, height, s1_width, s1_height;
RGBColor *hilite_rgb;
uint32 bk_color, hilite_color;
int bits_per_pixel;
const rgb_spec_t *rgb_spec;
boolean_t copy1_p, copy2_p;
write_back_data_t write_back1, write_back2;
bits_per_pixel = CW (src1->pixelSize);
rgb_spec = pixmap_rgb_spec (src1);
/* For bits_per_pixel == 1, you are just supposed to use the original
* boolean transfer modes.
*/
gui_assert (bits_per_pixel > 1);
copy1_p = pixmap_copy_if_screen (src1, r1, &write_back1);
if (copy1_p)
{
src1 = &write_back1.src_pm;
r1 = &write_back1.src_rect;
}
copy2_p = pixmap_copy_if_screen (src2, r2, &write_back2);
if (copy2_p)
{
src2 = &write_back2.src_pm;
r2 = &write_back2.src_rect;
}
PIXMAP_ASSERT_NOT_SCREEN (dst);
if (tile_src1_p)
{
s1_width = RECT_WIDTH (&src1->bounds);
s1_height = RECT_HEIGHT (&src1->bounds);
}
else
{
s1_width = RECT_WIDTH (r1);
s1_height = RECT_HEIGHT (r1);
}
width = RECT_WIDTH (r2);
height = RECT_HEIGHT (r2);
/* Grab the rowbytes for the three bitmaps. */
src1_rowbytes = BITMAP_ROWBYTES (src1);
src2_rowbytes = BITMAP_ROWBYTES (src2);
dst_rowbytes = (width * bits_per_pixel + 31) / 32 * 4;
dst->rowBytes = CW (dst_rowbytes);
/* We want to run x from 0 to width; adding these offsets gives us
* the real x for the source bitmaps.
*/
if (tile_src1_p)
src1_deltax = pat_x_offset;
else
src1_deltax = CW (r1->left) - CW (src1->bounds.left);
src2_deltax = CW (r2->left) - CW (src2->bounds.left);
/* Compute a pointer to the base of the first row of each bitmap. */
if (tile_src1_p)
{
src1_row_base = (unsigned char *)
(MR (src1->baseAddr)
+ (src1_rowbytes * (pat_y_offset & (s1_height - 1))));
}
else
{
src1_row_base = (unsigned char *)
(MR (src1->baseAddr)
+ ((CW (r1->top) - CW (src1->bounds.top)) * src1_rowbytes));
}
src2_row_base = (unsigned char *)
(MR (src2->baseAddr)
+ (CW (r2->top) - CW (src2->bounds.top)) * src2_rowbytes);
dst_row_base = (unsigned char *) MR (dst->baseAddr);
#define RGB_TO_INDIRECT_PIXEL(rgb, pixel) \
((void) ((pixel) = Color2Index (rgb)))
#define RGB_TO_DIRECT_PIXEL(bpp, rgb, pixel) \
((void) \
({ \
uint32 swapped_pixel; \
\
swapped_pixel = ((*rgb_spec->rgbcolor_to_pixel) \
(rgb_spec, rgb, TRUE)); \
switch (bpp) \
{ \
case 16: \
(pixel) = CW (swapped_pixel); \
break; \
case 32: \
(pixel) = CL (swapped_pixel); \
break; \
default: \
gui_fatal ("unknown bpp"); \
} \
}))
#define RGB_TO_PIXEL(bpp, rgb, pixel) \
((void) \
((bpp) == 32 || (bpp) == 16 \
? RGB_TO_DIRECT_PIXEL (bpp, rgb, pixel) \
: RGB_TO_INDIRECT_PIXEL (rgb, pixel)))
if (CGrafPort_p (thePort))
bk_color = PORT_BK_COLOR (thePort);
else
{
if (active_screen_addr_p (&PORT_BITS (thePort)))
{
int i;
/* defaults */
bk_color = 0;
for (i = 0; i < 8; i ++)
if (PORT_BK_COLOR (thePort) == ROMlib_QDColors[i].value)
{
RGB_TO_PIXEL (bits_per_pixel,
&ROMlib_QDColors[i].rgb, bk_color);
break;
}
}
else
{
/* FIXME: this might not be right */
bk_color = (PORT_BK_COLOR (thePort) == whiteColor
? 0
: ((1 << bits_per_pixel) - 1));
}
}
if (CGrafPort_p (thePort))
hilite_rgb = &CPORT_HILITE_COLOR (theCPort);
else
hilite_rgb = &HiliteRGB;
RGB_TO_PIXEL (bits_per_pixel, hilite_rgb, hilite_color);
#define CONVERT_BITS(read1, read2, write, next1, transform, bpp) \
{ \
int x, y; \
\
for (y = 0; y < height; y++) \
{ \
for (x = 0; x < width; x++) \
{ \
long src1_v, src2_v, dst_v; \
\
src1_v = read1 (src1_row_base, x + src1_deltax, bpp); \
src2_v = read2 (src2_row_base, x + src2_deltax, bpp); \
dst_v = transform (src1_v, src2_v); \
\
write (dst_v, dst_row_base, x, bpp); \
} \
\
next1; \
src2_row_base += src2_rowbytes; \
dst_row_base += dst_rowbytes; \
} \
}
#define NONPAT_NEXT1 src1_row_base += src1_rowbytes
#define PAT_NEXT1 \
src1_row_base = (unsigned char *) (MR (src1->baseAddr) \
+ (src1_rowbytes * ((y + pat_y_offset) & (s1_height - 1))))
#define SHIFT_COUNT(x, bpp) (8 - (bpp) - (bpp) * ((x) & (7 / (bpp))))
#define READ_INDIRECT_PIXEL(b, x, bpp) \
((bpp) == 8 \
? b[x] \
: ((b[(x) * (bpp) / 8] >> SHIFT_COUNT ((x), (bpp))) & ((1 << (bpp)) - 1)))
#define READ_DIRECT16_PIXEL(b, x, bpp) \
((uint16 *) b)[x]
#define READ_DIRECT32_PIXEL(b, x, bpp) \
((uint32 *) b)[x]
#define READ_PAT_INDIRECT_PIXEL(b, x, bpp) \
READ_INDIRECT_PIXEL (b, (x) & (s1_width - 1), bpp)
#define READ_PAT_DIRECT16_PIXEL(b, x, bpp) \
READ_DIRECT16_PIXEL (b, (x) & (s1_width - 1), bpp)
#define READ_PAT_DIRECT32_PIXEL(b, x, bpp) \
READ_DIRECT32_PIXEL (b, (x) & (s1_width - 1), bpp)
#define WRITE_INDIRECT_PIXEL(v, b, x, bpp) \
((void) \
((bpp) == 8 ? b[x] = (v) \
: ({ \
uint8 *p; \
p = &b[(x) * (bpp) / 8]; \
*p &= ~(((1 << (bpp)) - 1) << SHIFT_COUNT (x, bpp)); \
*p |= (((v) & ((1 << (bpp)) - 1)) << SHIFT_COUNT (x, bpp)); \
})))
#define WRITE_DIRECT16_PIXEL(v, b, x, bpp) \
((void) \
(((uint16 *) (b))[(x)] = (v)))
#define WRITE_DIRECT32_PIXEL(v, b, x, bpp) \
((void) \
(((uint32 *) (b))[(x)] = (v)))
#define TRANSPARENT_TRANSFORM(src1_v, src2_v) \
(((typeof (bk_color)) src1_v != bk_color) ? src1_v : src2_v)
#define HILITE_TRANSFORM(src1_v, src2_v) \
({ \
long v; \
\
/* only invert the pixel if the src/pattern is `on', ie., not the \
background color */ \
if ((typeof (bk_color))src1_v == bk_color) \
v = src2_v; \
else \
{ \
if ((typeof (bk_color)) src2_v == bk_color) \
v = hilite_color; \
else if ((typeof (hilite_color)) src2_v == hilite_color) \
v = bk_color; \
else \
v = src2_v; \
} \
v; \
})
/* Silly macro to let me switch on both mode, bpp, tile_src1_p. */
#define MUNGE(mode, bpp, ts1) ((mode & 0x3F) + (bpp) * 0x40 + (ts1) * 0x1000)
switch (MUNGE (mode, bits_per_pixel, tile_src1_p))
{
TRANSFORM_CASE (transparent, TRANSPARENT_TRANSFORM);
TRANSFORM_CASE (hilite, HILITE_TRANSFORM);
default:
gui_fatal ("unknown (mode, bpp, tile_p)");
}
#undef CONVERT_BITS
#undef RGB_TO_PIXEL
#undef RGB_TO_DIRECT_PIXEL
#undef RGB_TO_INDIRECT_PIXEL
/* Set up the dst bitmap's bounds so that rectangle r2 identifies
the newly created bits. */
dst->bounds = *r2;
if (copy1_p)
pixmap_free_copy (&write_back1.src_pm);
if (copy2_p)
pixmap_free_copy (&write_back2.src_pm);
}
/* This function combines rectangles from two source bitmaps via one of
* the complex transfer modes described in IMV. dst must have baseAddr
* already allocated; rowBytes and bounds will be filled in by this
* function.
*/
void
convert_pixmap_with_IMV_mode (const PixMap *src1, const PixMap *src2,
PixMap *dst,
CTabHandle src1_ctabh, CTabHandle src2_ctabh,
ITabHandle itabh,
const Rect *r1, const Rect *r2,
int16 mode, const RGBColor *op_color,
boolean_t tile_src1_p,
int pat_x_offset, int pat_y_offset)
{
CTabPtr src1_ctab, src2_ctab;
unsigned max_color;
uint8 *src1_row_base, *src2_row_base, *dst_row_base;
int src1_rowbytes, src2_rowbytes, dst_rowbytes, src1_deltax, src2_deltax;
int width, height, s1_width, s1_height;
int itab_res, itab_res_mask;
const uint8 *itab_array;
uint32 op_red, op_green, op_blue;
const rgb_spec_t *rgb_spec;
int bits_per_pixel;
boolean_t copy1_p, copy2_p;
write_back_data_t write_back1, write_back2;
bits_per_pixel = CW (src1->pixelSize);
rgb_spec = pixmap_rgb_spec (src1);
/* For bits_per_pixel == 1, you are just supposed to use the original
* boolean transfer modes.
*/
gui_assert (bits_per_pixel > 1);
copy1_p = pixmap_copy_if_screen (src1, r1, &write_back1);
if (copy1_p)
{
src1 = &write_back1.src_pm;
r1 = &write_back1.src_rect;
}
copy2_p = pixmap_copy_if_screen (src2, r2, &write_back2);
if (copy2_p)
{
src2 = &write_back2.src_pm;
r2 = &write_back2.src_rect;
}
PIXMAP_ASSERT_NOT_SCREEN (dst);
if (tile_src1_p)
{
s1_width = RECT_WIDTH (&src1->bounds);
s1_height = RECT_HEIGHT (&src1->bounds);
}
else
{
s1_width = RECT_WIDTH (r1);
s1_height = RECT_HEIGHT (r1);
}
width = RECT_WIDTH (r2);
height = RECT_HEIGHT (r2);
if (rgb_spec)
{
/* initalize to some sane values to shut gcc up */
src1_ctab = src2_ctab = NULL;
itab_res = itab_res_mask = 0;
itab_array = NULL;
}
else
{
max_color = (1 << bits_per_pixel) - 1;
/* Create a nice, sorted table for src1_ctab. */
if (CTAB_FLAGS_X (src1_ctabh) & CTAB_GDEVICE_BIT_X)
{
src1_ctab = STARH (src1_ctabh);
}
else
{
src1_ctab = sort_table (STARH (src1_ctabh),
(CTabPtr) alloca (sizeof *src1_ctab
+ (max_color
* sizeof (ColorSpec))),
max_color);
}
/* Create a nice, sorted table for src2_ctab. */
if (CTAB_SEED_X (src1_ctabh) == CTAB_SEED_X (src2_ctabh))
src2_ctab = src1_ctab;
else
{
if (CTAB_FLAGS_X (src2_ctabh) & CTAB_GDEVICE_BIT_X)
{
src2_ctab = STARH (src2_ctabh);
}
else
{
src2_ctab = sort_table (STARH (src2_ctabh),
(CTabPtr) alloca (sizeof *src2_ctab
+ (max_color
* sizeof (ColorSpec))),
max_color);
}
}
/* Grab the inverse color table. Note that we are to use this
* table directly, and *not* call Color2Index.
*/
itab_res = ITAB_RES (itabh);
itab_res_mask = (1 << itab_res) - 1;
itab_array = ITAB_TABLE (itabh);
}
/* Grab the rowbytes for the three bitmaps. */
src1_rowbytes = BITMAP_ROWBYTES (src1);
src2_rowbytes = BITMAP_ROWBYTES (src2);
dst_rowbytes = (width * bits_per_pixel + 31) / 32 * 4;
dst->rowBytes = CW (dst_rowbytes);
/* We want to run x from 0 to width; adding these offsets gives us
* the real x for the source bitmaps.
*/
if (tile_src1_p)
src1_deltax = pat_x_offset;
else
src1_deltax = CW (r1->left) - CW (src1->bounds.left);
src2_deltax = CW (r2->left) - CW (src2->bounds.left);
/* Compute a pointer to the base of the first row of each bitmap. */
if (tile_src1_p)
{
src1_row_base = (unsigned char *) (MR (src1->baseAddr)
+ (src1_rowbytes * (pat_y_offset & (s1_height - 1))));
}
else
{
src1_row_base = (unsigned char *) (MR (src1->baseAddr)
+ ((CW (r1->top) - CW (src1->bounds.top))
* src1_rowbytes));
}
src2_row_base = (unsigned char *) (MR (src2->baseAddr)
+ (CW (r2->top) - CW (src2->bounds.top)) * src2_rowbytes);
dst_row_base = (unsigned char *) MR (dst->baseAddr);
/* Fetch the "op color" fields, in case they are needed. */
op_red = CW (op_color->red);
op_green = CW (op_color->green);
op_blue = CW (op_color->blue);
#define CONVERT_BITS(read1, read2, write, next1, transform, bpp) \
{ \
int x, y; \
for (y = 0; y < height; y++) \
{ \
for (x = 0; x < width; x++) \
{ \
/* source 1, 2 rgb's */ \
uint32 r1, g1, b1; \
uint32 r2, g2, b2; \
/* result rgb's */ \
uint32 rr, gr, br; \
/* final pixel value */ \
uint32 p1, p2, pr; \
\
p1 = read1 (src1_row_base, x + src1_deltax, bpp); \
p2 = read2 (src2_row_base, x + src2_deltax, bpp); \
\
PIXEL_TO_RGB (bpp, p1, r1, g1, b1, src1_ctab); \
PIXEL_TO_RGB (bpp, p2, r2, g2, b2, src2_ctab); \
\
transform (r1, g1, b1, \
r2, g2, b2, \
rr, gr, br); \
\
RGB_TO_PIXEL (bpp, rr, gr, br, pr); \
\
write (pr, dst_row_base, x, bpp); \
} \
\
next1; \
src2_row_base += src2_rowbytes; \
dst_row_base += dst_rowbytes; \
} \
}
#define INDIRECT_PIXEL_TO_RGB(pixel, r, g, b, ctab) \
((void) \
({ \
const RGBColor *color; \
color = &ctab->ctTable[pixel].rgb; \
(r) = CW (color->red); \
(g) = CW (color->green); \
(b) = CW (color->blue); \
}))
#define DIRECT_PIXEL_TO_RGB(bpp, pixel, red_out, green_out, blue_out, \
dummy_ctab) \
((void) \
({ \
RGBColor color; \
\
(*rgb_spec->pixel_to_rgbcolor) (rgb_spec, (pixel), &color); \
(red_out) = CW (color.red); \
(green_out) = CW (color.green); \
(blue_out) = CW (color.blue); \
}))
#define PIXEL_TO_RGB(bpp, pixel, red, green, blue, ctab) \
((void) \
((bpp) == 32 || (bpp) == 16 \
? DIRECT_PIXEL_TO_RGB (bpp, pixel, red, green, blue, ctab) \
: INDIRECT_PIXEL_TO_RGB (pixel, red, green, blue, ctab)))
#define RGB_TO_INDIRECT_PIXEL(red, green, blue, pixel) \
((pixel) = ITAB_LOOKUP (red, green, blue))
#define RGB_TO_DIRECT_PIXEL(bpp, red, green, blue, pixel) \
((void) \
({ \
RGBColor color = { red, green, blue }; \
\
(pixel) = ((*rgb_spec->rgbcolor_to_pixel) \
(rgb_spec, &color, FALSE)); \
}))
#define RGB_TO_PIXEL(bpp, red, green, blue, pixel) \
((void) \
((bpp) == 32 || (bpp) == 16 \
? RGB_TO_DIRECT_PIXEL (bpp, red, green, blue, pixel) \
: RGB_TO_INDIRECT_PIXEL (red, green, blue, pixel)))
#define NONPAT_NEXT1 src1_row_base += src1_rowbytes
#define PAT_NEXT1 \
src1_row_base = (unsigned char *) (MR (src1->baseAddr) \
+ (src1_rowbytes * ((y + pat_y_offset) & (s1_height - 1))))
#define SHIFT_COUNT(x, bpp) (8 - (bpp) - (bpp) * ((x) & (7 / (bpp))))
#define READ_INDIRECT_PIXEL(b, x, bpp) \
((bpp) == 8 \
? b[x] \
: ((b[(x) * (bpp) / 8] >> SHIFT_COUNT ((x), (bpp))) & ((1 << (bpp)) - 1)))
#define READ_DIRECT16_PIXEL(b, x, bpp) \
((uint16 *) b)[x]
#define READ_DIRECT32_PIXEL(b, x, bpp) \
((uint32 *) b)[x]
#define READ_PAT_INDIRECT_PIXEL(b, x, bpp) \
READ_INDIRECT_PIXEL (b, (x) & (s1_width - 1), bpp)
#define READ_PAT_DIRECT16_PIXEL(b, x, bpp) \
READ_DIRECT16_PIXEL (b, (x) & (s1_width - 1), bpp)
#define READ_PAT_DIRECT32_PIXEL(b, x, bpp) \
READ_DIRECT32_PIXEL (b, (x) & (s1_width - 1), bpp)
#define WRITE_INDIRECT_PIXEL(v, b, x, bpp) \
((void) \
((bpp) == 8 ? b[x] = (v) \
: ({ \
uint8 *p; \
p = &b[(x) * (bpp) / 8]; \
*p &= ~(((1 << (bpp)) - 1) << SHIFT_COUNT (x, bpp)); \
*p |= (((v) & ((1 << (bpp)) - 1)) << SHIFT_COUNT (x, bpp)); \
})))
#define WRITE_DIRECT16_PIXEL(v, b, x, bpp) \
((void) \
(((uint16 *) (b))[(x)] = (v)))
#define WRITE_DIRECT32_PIXEL(v, b, x, bpp) \
((void) \
(((uint32 *) (b))[(x)] = (v)))
#define ITAB_LOOKUP(r, g, b) \
itab_array[((((r) >> (16 - itab_res)) & itab_res_mask) << (2 * itab_res)) \
| ((((g) >> (16 - itab_res)) & itab_res_mask) << (1 * itab_res)) \
| ((((b) >> (16 - itab_res)) & itab_res_mask) << (0 * itab_res))]
/* Define macros to actually munge together two RGB's in the right way. */
#define ADD_OVER_TRANSFORM(red1, green1, blue1, \
red2, green2, blue2, \
redr, greenr, bluer) \
((void) \
(redr = red1 + red2, \
greenr = green1 + green2, \
bluer = blue1 + blue2))
#define ADD_PIN_TRANSFORM(red1, green1, blue1, \
red2, green2, blue2, \
redr, greenr, bluer) \
((void) \
(redr = red1 + red2, \
greenr = green1 + green2, \
bluer = blue1 + blue2, \
redr = MIN (redr, op_red), \
greenr = MIN (greenr, op_green), \
bluer = MIN (bluer, op_blue)))
#define SUB_OVER_TRANSFORM(red1, green1, blue1, \
red2, green2, blue2, \
redr, greenr, bluer) \
((void) \
(redr = red1 - red2, \
greenr = green1 - green2, \
bluer = blue1 - blue2))
#define SUB_PIN_TRANSFORM(red1, green1, blue1, \
red2, green2, blue2, \
redr, greenr, bluer) \
((void) \
(redr = red1 - red2, \
greenr = green1 - green2, \
bluer = blue1 - blue2, \
redr = MAX (redr, op_red), \
greenr = MAX (greenr, op_green), \
bluer = MAX (bluer, op_blue)))
#define AD_MAX_TRANSFORM(red1, green1, blue1, \
red2, green2, blue2, \
redr, greenr, bluer) \
((void) \
(redr = MAX (red1, red2), \
greenr = MAX (green1, green2), \
bluer = MAX (blue1, blue2)))
#define AD_MIN_TRANSFORM(red1, green1, blue1, \
red2, green2, blue2, \
redr, greenr, bluer) \
((void) \
(redr = MIN (red1, red2), \
greenr = MIN (green1, green2), \
bluer = MIN (blue1, blue2)))
#define BLEND_TRANSFORM(red1, green1, blue1, \
red2, green2, blue2, \
redr, greenr, bluer) \
((void) \
(redr = (red1 * op_red + red2 * (65535 - op_red)) / 65535, \
greenr = (green1 * op_green + green2 * (65535 - op_green)) / 65535, \
bluer = (blue1 * op_blue + blue2 * (65535 - op_blue)) / 65535))
/* Silly macro to let me switch on both mode, bpp, tile_src1_p. */
#define MUNGE(mode, bpp, ts1) ((mode & 0x3F) + (bpp) * 0x40 + (ts1) * 0x1000)
switch (MUNGE (mode, bits_per_pixel, tile_src1_p))
{
TRANSFORM_CASE (addOver, ADD_OVER_TRANSFORM);
TRANSFORM_CASE (addPin, ADD_PIN_TRANSFORM);
TRANSFORM_CASE (subOver, SUB_OVER_TRANSFORM);
TRANSFORM_CASE (subPin, SUB_PIN_TRANSFORM);
TRANSFORM_CASE (adMin, AD_MIN_TRANSFORM);
TRANSFORM_CASE (adMax, AD_MAX_TRANSFORM);
TRANSFORM_CASE (blend, BLEND_TRANSFORM);
default:
gui_fatal ("invalid case");
}
#undef CONVERT_BITS
/* Set up the dst bitmap's bounds so that rectangle r2 identifies
* the newly created bits.
*/
dst->bounds = *r2;
if (copy1_p)
pixmap_free_copy (&write_back1.src_pm);
if (copy2_p)
pixmap_free_copy (&write_back2.src_pm);
}