mirror of
https://github.com/ctm/executor.git
synced 2024-06-16 04:29:29 +00:00
865 lines
24 KiB
C
865 lines
24 KiB
C
|
/* Copyright 1986, 1988, 1989, 1990, 1995 by Abacus Research and
|
||
|
* Development, Inc. All rights reserved.
|
||
|
*/
|
||
|
|
||
|
#if !defined (OMIT_RCSID_STRINGS)
|
||
|
char ROMlib_rcsid_qStdBits[] =
|
||
|
"$Id: qStdBits.c 87 2005-05-25 01:57:33Z ctm $";
|
||
|
#endif
|
||
|
|
||
|
/* Forward declarations in QuickDraw.h (DO NOT DELETE THIS LINE) */
|
||
|
|
||
|
#include "rsys/common.h"
|
||
|
|
||
|
#include "QuickDraw.h"
|
||
|
#include "CQuickDraw.h"
|
||
|
#include "MemoryMgr.h"
|
||
|
#include "ToolboxUtil.h"
|
||
|
|
||
|
#include "rsys/stdbits.h"
|
||
|
#include "rsys/quick.h"
|
||
|
#include "rsys/cquick.h"
|
||
|
#include "rsys/region.h"
|
||
|
#include "rsys/gworld.h"
|
||
|
#include "rsys/picture.h"
|
||
|
#include "rsys/mman.h"
|
||
|
#include "rsys/flags.h"
|
||
|
#include "rsys/host.h"
|
||
|
#include "rsys/tempalloc.h"
|
||
|
|
||
|
static void ROMlib_real_copy_bits (PixMap *src, PixMap *dst,
|
||
|
const Rect *src_rect, const Rect *dst_rect,
|
||
|
INTEGER mode, RgnHandle mask);
|
||
|
|
||
|
static boolean_t
|
||
|
src_dst_overlap_and_dst_below_src_p (const Rect *srcr, const Rect *dstr,
|
||
|
int dh, int dv)
|
||
|
{
|
||
|
if ( (CW (dstr->top)) < (CW (srcr->bottom) + dv)
|
||
|
&& (CW (srcr->top) + dv) <= (CW (dstr->top))
|
||
|
&& (CW (srcr->left) + dh) < (CW (dstr->right))
|
||
|
&& (CW (dstr->left)) < (CW (srcr->right) + dh))
|
||
|
return TRUE;
|
||
|
else
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static inline boolean_t
|
||
|
dy_zero_p (const Rect *srcr, const Rect *dstr,
|
||
|
int dh, int dv)
|
||
|
{
|
||
|
return (CW (srcr->top) + dv) == CW (dstr->top);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
canonicalize_bogo_map_cleanup (BitMap *bogo_map,
|
||
|
struct cleanup_info *info)
|
||
|
{
|
||
|
switch (info->cleanup_type)
|
||
|
{
|
||
|
case cleanup_state:
|
||
|
HSetState (info->data.handle, info->h_state);
|
||
|
break;
|
||
|
case cleanup_free:
|
||
|
DisposHandle (info->data.handle);
|
||
|
break;
|
||
|
case cleanup_unlock_gworld_pixels:
|
||
|
UnlockPixels (info->data.pixmap_handle);
|
||
|
break;
|
||
|
case cleanup_unlock_gworld_pixels_update:
|
||
|
{
|
||
|
gw_info_t *gw_info;
|
||
|
|
||
|
gw_info = info->data.gw_info;
|
||
|
|
||
|
UnlockPixels (gw_info->gw_pixmap);
|
||
|
BITMAP_BASEADDR_X ((PixMap *) bogo_map)
|
||
|
= PIXMAP_BASEADDR_X (gw_info->gw_pixmap);
|
||
|
break;
|
||
|
}
|
||
|
case cleanup_none:
|
||
|
break;
|
||
|
default:
|
||
|
gui_fatal ("unknown cleanup type `%d'", info->cleanup_type);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
canonicalize_bogo_map (BitMap *bogo_map, PixMap **canonical_addr,
|
||
|
struct cleanup_info *info)
|
||
|
{
|
||
|
int high_bits = ((unsigned short) CW (bogo_map->rowBytes)) >> 14;
|
||
|
int low_bit = ((unsigned short) CW (bogo_map->rowBytes)) & 1;
|
||
|
|
||
|
switch (high_bits)
|
||
|
{
|
||
|
/* (BitMap *) */
|
||
|
case 0:
|
||
|
{
|
||
|
PixMapHandle gd_pmap;
|
||
|
PixMap *canonical = *canonical_addr;
|
||
|
|
||
|
canonical->baseAddr = bogo_map->baseAddr;
|
||
|
canonical->bounds = bogo_map->bounds;
|
||
|
|
||
|
canonical->pmVersion = CWC (0);
|
||
|
|
||
|
/* no packing currently supported */
|
||
|
canonical->packType = CWC (0);
|
||
|
canonical->packSize = CWC (0);
|
||
|
|
||
|
canonical->vRes = canonical->hRes = CWC (72);
|
||
|
|
||
|
gd_pmap = GD_PMAP (MR (TheGDevice));
|
||
|
if (canonical->baseAddr == PIXMAP_BASEADDR_X (gd_pmap))
|
||
|
{
|
||
|
pixmap_set_pixel_fields (canonical, PIXMAP_PIXEL_SIZE (gd_pmap));
|
||
|
canonical->rowBytes = (PIXMAP_ROWBYTES_X (gd_pmap)
|
||
|
| PIXMAP_DEFAULT_ROW_BYTES_X);
|
||
|
canonical->pmTable = PIXMAP_TABLE_X (gd_pmap);
|
||
|
|
||
|
info->cleanup_type = cleanup_none;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pixmap_set_pixel_fields (canonical, 1);
|
||
|
|
||
|
canonical->rowBytes = (bogo_map->rowBytes
|
||
|
| PIXMAP_DEFAULT_ROW_BYTES_X);
|
||
|
info->cleanup_type = cleanup_none;
|
||
|
canonical->pmTable = RM (validate_relative_bw_ctab ());
|
||
|
}
|
||
|
canonical->planeBytes = CWC (0);
|
||
|
|
||
|
canonical->pmReserved = CWC (0);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/* (unknown) */
|
||
|
case 1:
|
||
|
gui_abort ();
|
||
|
|
||
|
/* pointer to pixmap */
|
||
|
case 2:
|
||
|
{
|
||
|
gw_info_t *gw_info;
|
||
|
|
||
|
gw_info = (lookup_gw_info_by_gw_pixmap_baseaddr
|
||
|
(BITMAP_BASEADDR ((PixMap *) bogo_map)));
|
||
|
if (gw_info)
|
||
|
{
|
||
|
LockPixels (gw_info->gw_pixmap);
|
||
|
BITMAP_BASEADDR_X ((PixMap *) bogo_map)
|
||
|
= PIXMAP_BASEADDR_X (gw_info->gw_pixmap);
|
||
|
|
||
|
info->cleanup_type = cleanup_unlock_gworld_pixels_update;
|
||
|
info->data.gw_info = gw_info;
|
||
|
}
|
||
|
else
|
||
|
info->cleanup_type = cleanup_none;
|
||
|
|
||
|
*canonical_addr = (PixMap *) bogo_map;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/* (CGrafPtr spew) */
|
||
|
case 3:
|
||
|
if (low_bit)
|
||
|
{
|
||
|
CGrafPtr gw;
|
||
|
PixMapHandle pixmap;
|
||
|
|
||
|
gw = (CGrafPtr) ((char *) bogo_map - 2);
|
||
|
pixmap = CPORT_PIXMAP (gw);
|
||
|
|
||
|
*canonical_addr = STARH (pixmap);
|
||
|
info->cleanup_type = cleanup_unlock_gworld_pixels;
|
||
|
info->data.pixmap_handle = pixmap;
|
||
|
|
||
|
/* lock the pixels */
|
||
|
LockPixels (pixmap);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
PixMapHandle pixmap_handle = MR (*(PixMapHandle *) bogo_map);
|
||
|
|
||
|
*canonical_addr = STARH (pixmap_handle);
|
||
|
|
||
|
info->cleanup_type = cleanup_state;
|
||
|
info->data.pixmap_handle = pixmap_handle;
|
||
|
info->h_state = HGetState ((Handle) pixmap_handle);
|
||
|
|
||
|
/* lock the pixmap handle */
|
||
|
HSetState ((Handle) pixmap_handle, info->h_state | LOCKBIT);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
#if !defined (NDEBUG)
|
||
|
if ( (RECT_WIDTH (&BITMAP_BOUNDS (*canonical_addr))
|
||
|
* CW ((*canonical_addr)->pixelSize)
|
||
|
/ 8)
|
||
|
> BITMAP_ROWBYTES (*canonical_addr))
|
||
|
warning_unexpected ("unlikely map");
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
write_copybits_picdata (PixMap *src, PixMap *dst,
|
||
|
const Rect *src_rect, const Rect *dst_rect,
|
||
|
int16 mode, RgnHandle mask)
|
||
|
{
|
||
|
int32 zero = 0;
|
||
|
int16 opcode;
|
||
|
int16 swapped_mode;
|
||
|
int16 row_bytes;
|
||
|
int16 temp_pixmap_row_bytes;
|
||
|
int16 pack_type;
|
||
|
int16 pixel_size;
|
||
|
int height;
|
||
|
int i;
|
||
|
boolean_t direct_bits_p;
|
||
|
|
||
|
{
|
||
|
/* always copy the src pixmap since the code below, as it is
|
||
|
written, will always record the _entire_ src, which is very bad
|
||
|
if the src is the screen, or some other large image */
|
||
|
/* it is also necessary to copy when we are the src is the actual
|
||
|
screen */
|
||
|
PixMap *_src;
|
||
|
Rect *_src_rect;
|
||
|
|
||
|
_src = alloca (sizeof *_src);
|
||
|
_src_rect = alloca (sizeof *_src_rect);
|
||
|
|
||
|
ZONE_SAVE_EXCURSION
|
||
|
(ApplZone,
|
||
|
{
|
||
|
if (FreeMemSys () >= FreeMem ())
|
||
|
TheZone = SysZone;
|
||
|
|
||
|
pixmap_copy (src, src_rect,
|
||
|
_src, _src_rect);
|
||
|
});
|
||
|
|
||
|
src = _src;
|
||
|
src_rect = _src_rect;
|
||
|
}
|
||
|
|
||
|
row_bytes = BITMAP_ROWBYTES (src);
|
||
|
pixel_size = CW (src->pixelSize);
|
||
|
|
||
|
direct_bits_p = (pixel_size == 16 || pixel_size == 32);
|
||
|
if (pixel_size == 32)
|
||
|
pack_type = CWC (2);
|
||
|
else
|
||
|
pack_type = CWC (0);
|
||
|
|
||
|
if (direct_bits_p)
|
||
|
opcode = mask ? OP_DirectBitsRgn : OP_DirectBitsRect;
|
||
|
else if (row_bytes < 8)
|
||
|
opcode = mask ? OP_BitsRgn : OP_BitsRect;
|
||
|
else
|
||
|
opcode = mask ? OP_PackBitsRgn : OP_PackBitsRect;
|
||
|
|
||
|
ROMlib_drawingpicupdate ();
|
||
|
PICOP (opcode);
|
||
|
|
||
|
if (direct_bits_p)
|
||
|
{
|
||
|
int32 swapped_bogo_baseaddr = CLC (0xFF);
|
||
|
|
||
|
PICWRITE (&swapped_bogo_baseaddr, sizeof swapped_bogo_baseaddr);
|
||
|
}
|
||
|
|
||
|
temp_pixmap_row_bytes = src->rowBytes | PIXMAP_DEFAULT_ROWBYTES_X;
|
||
|
PICWRITE (&temp_pixmap_row_bytes, sizeof temp_pixmap_row_bytes);
|
||
|
|
||
|
PICWRITE (&src->bounds, sizeof src->bounds);
|
||
|
PICWRITE (&src->pmVersion, sizeof src->pmVersion);
|
||
|
|
||
|
/* pack type of bits stored in the picture may not necessarily match
|
||
|
the pack type of the actual pixmap */
|
||
|
PICWRITE (&pack_type, sizeof pack_type);
|
||
|
|
||
|
PICWRITE (&src->packSize, sizeof src->packSize);
|
||
|
PICWRITE (&src->hRes, sizeof src->hRes);
|
||
|
PICWRITE (&src->vRes, sizeof src->vRes);
|
||
|
PICWRITE (&src->pixelType, sizeof src->pixelType);
|
||
|
PICWRITE (&src->pixelSize, sizeof src->pixelSize);
|
||
|
PICWRITE (&src->cmpCount, sizeof src->cmpCount);
|
||
|
PICWRITE (&src->cmpSize, sizeof src->cmpSize);
|
||
|
PICWRITE (&src->planeBytes, sizeof src->planeBytes);
|
||
|
PICWRITE (&zero, sizeof zero);
|
||
|
PICWRITE (&src->pmReserved, sizeof src->pmReserved);
|
||
|
|
||
|
if (! direct_bits_p)
|
||
|
{
|
||
|
LOCK_HANDLE_EXCURSION_1
|
||
|
(MR (src->pmTable),
|
||
|
{
|
||
|
CTabPtr ctab;
|
||
|
|
||
|
ctab = STARH (MR (src->pmTable));
|
||
|
|
||
|
/* write out the src color table */
|
||
|
PICWRITE (&zero, sizeof zero);
|
||
|
PICWRITE (&ctab->ctFlags, sizeof ctab->ctFlags);
|
||
|
PICWRITE (&ctab->ctSize, sizeof ctab->ctSize);
|
||
|
for (i = 0; i <= CW (ctab->ctSize); i ++)
|
||
|
{
|
||
|
ColorSpec *elt;
|
||
|
|
||
|
elt = &ctab->ctTable[i];
|
||
|
PICWRITE (&elt->value, sizeof elt->value);
|
||
|
PICWRITE (&elt->rgb, sizeof elt->rgb);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
PICWRITE (src_rect, sizeof *src_rect);
|
||
|
PICWRITE (dst_rect, sizeof *dst_rect);
|
||
|
swapped_mode = CW (mode);
|
||
|
PICWRITE (&swapped_mode, sizeof swapped_mode);
|
||
|
if (mask)
|
||
|
{
|
||
|
LOCK_HANDLE_EXCURSION_1
|
||
|
(mask,
|
||
|
{
|
||
|
PICWRITE (STARH (mask), Hx (mask, rgnSize));
|
||
|
});
|
||
|
}
|
||
|
height = RECT_HEIGHT (&src->bounds);
|
||
|
if (row_bytes < 8 || pack_type == CWC (2))
|
||
|
{
|
||
|
if (pack_type == CWC (2))
|
||
|
{
|
||
|
uint8 *current, *end;
|
||
|
|
||
|
current = (uint8 *) MR (src->baseAddr) + 1;
|
||
|
end = current + row_bytes * height;
|
||
|
|
||
|
while (current < end)
|
||
|
{
|
||
|
PICWRITE (current, 3 * sizeof *current);
|
||
|
current += 4;
|
||
|
}
|
||
|
if ((row_bytes / 4 * height) & 1)
|
||
|
PICWRITE ("", 1);
|
||
|
}
|
||
|
else
|
||
|
PICWRITE (MR (src->baseAddr), row_bytes * height);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
HIDDEN_Ptr ip, op;
|
||
|
int parity;
|
||
|
uint8 *packed_line;
|
||
|
int8 *countloc;
|
||
|
int16 count, swappedcount, countsize;
|
||
|
uint8 *baseaddr;
|
||
|
|
||
|
/* i copied the code below from the executor 1.2 implementation
|
||
|
of StdBits pic recording. i can't say i fully understand it */
|
||
|
|
||
|
/* #### why the extra 5 bytes? */
|
||
|
packed_line = alloca (row_bytes + 5);
|
||
|
baseaddr = (uint8 *) MR (src->baseAddr);
|
||
|
ip.p = (Ptr) baseaddr;
|
||
|
parity = 0;
|
||
|
|
||
|
if (row_bytes > 250)
|
||
|
{
|
||
|
countloc = (int8 *) &swappedcount;
|
||
|
countsize = 2;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
countloc = (int8 *) &swappedcount + 1;
|
||
|
countsize = 1;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < height; i ++)
|
||
|
{
|
||
|
op.p = (Ptr) RM (packed_line);
|
||
|
gui_assert ((uint8 *) ip.p == &baseaddr[row_bytes * i]);
|
||
|
ip.p = RM (ip.p);
|
||
|
PackBits (&ip, &op, row_bytes);
|
||
|
op.p = MR (op.p);
|
||
|
ip.p = MR (ip.p);
|
||
|
count = op.p - (Ptr) packed_line;
|
||
|
parity += count + countsize;
|
||
|
swappedcount = CW (count);
|
||
|
PICWRITE (countloc, countsize);
|
||
|
PICWRITE (packed_line, count);
|
||
|
}
|
||
|
/* even things up */
|
||
|
if (parity & 1)
|
||
|
PICWRITE ("", 1);
|
||
|
}
|
||
|
|
||
|
pixmap_free_copy (src);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
ROMlib_bogo_stdbits (BitMap *src_bogo_map, BitMap *dst_bogo_map,
|
||
|
const Rect *src_rect, const Rect *dst_rect,
|
||
|
short mode, RgnHandle mask)
|
||
|
{
|
||
|
Rect dummy_rect;
|
||
|
|
||
|
PixMap dummy_space[2];
|
||
|
PixMap *src = &dummy_space[0], *dst = &dummy_space[1];
|
||
|
|
||
|
struct cleanup_info cleanup_info[2];
|
||
|
|
||
|
if (CW (dst_rect->bottom) <= CW (dst_rect->top)
|
||
|
|| CW (dst_rect->right) <= CW (dst_rect->left)
|
||
|
|| (mask && !SectRect (dst_rect, &HxX (mask, rgnBBox), &dummy_rect)))
|
||
|
return;
|
||
|
|
||
|
/* the incoming source and destinations can be any one of the
|
||
|
following;
|
||
|
|
||
|
a `BitMap *', the high two bits of rowBytes must be zero,
|
||
|
or CGrafPort coerced to a GrafPort with the PortBits
|
||
|
passed in; in this case the high two bits of rowBytes
|
||
|
must be `11'; and the baseAddr field is a `PixMapHandle'
|
||
|
|
||
|
each of these types are canonicalized into a `PixMap *', which
|
||
|
is what we work with here */
|
||
|
/* these functions lock the PixMapHandle if src or dst
|
||
|
are from a coerced CGrafPort; we must make sure
|
||
|
to unlock those handles on the way out */
|
||
|
canonicalize_bogo_map (src_bogo_map, &src, &cleanup_info[0]);
|
||
|
canonicalize_bogo_map (dst_bogo_map, &dst, &cleanup_info[1]);
|
||
|
|
||
|
PIC_SAVE_EXCURSION
|
||
|
({
|
||
|
write_copybits_picdata (src, dst, src_rect, dst_rect, mode, mask);
|
||
|
});
|
||
|
|
||
|
if (PORT_PEN_VIS (thePort) < 0)
|
||
|
return;
|
||
|
|
||
|
ROMlib_real_copy_bits (src, dst, src_rect, dst_rect, mode, mask);
|
||
|
|
||
|
canonicalize_bogo_map_cleanup (src_bogo_map, &cleanup_info[0]);
|
||
|
canonicalize_bogo_map_cleanup (dst_bogo_map, &cleanup_info[1]);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
StdBitsPicSaveFlag (BitMap *src_bogo_map,
|
||
|
const Rect *src_rect, const Rect *dst_rect,
|
||
|
INTEGER mode, RgnHandle mask,
|
||
|
BOOLEAN savepic)
|
||
|
{
|
||
|
Rect dummy_rect;
|
||
|
|
||
|
/* we want the actual port bits, no fooling; so don't use the
|
||
|
accessor macros */
|
||
|
BitMap *dst_bogo_map = &thePort->portBits;
|
||
|
|
||
|
PixMap dummy_space[2];
|
||
|
PixMap *src = &dummy_space[0], *dst = &dummy_space[1];
|
||
|
|
||
|
struct cleanup_info cleanup_info[2];
|
||
|
|
||
|
if (CW (dst_rect->bottom) <= CW (dst_rect->top)
|
||
|
|| CW (dst_rect->right) <= CW (dst_rect->left)
|
||
|
|| (mask && !SectRect (dst_rect, &HxX (mask, rgnBBox), &dummy_rect)))
|
||
|
return;
|
||
|
|
||
|
/* the incoming source and destinations can be any one of the
|
||
|
following;
|
||
|
|
||
|
a `BitMap *', the high two bits of rowBytes must be zero,
|
||
|
or CGrafPort coerced to a GrafPort with the PortBits
|
||
|
passed in; in this case the high two bits of rowBytes
|
||
|
must be `11'; and the baseAddr field is a `PixMapHandle'
|
||
|
|
||
|
each of these types are canonicalized into a `PixMap *', which
|
||
|
is what we work with here */
|
||
|
/* these functions lock the PixMapHandle if src or dst
|
||
|
are from a coerced CGrafPort; we must make sure
|
||
|
to unlock those handles on the way out */
|
||
|
canonicalize_bogo_map (src_bogo_map, &src, &cleanup_info[0]);
|
||
|
canonicalize_bogo_map (dst_bogo_map, &dst, &cleanup_info[1]);
|
||
|
|
||
|
if (savepic)
|
||
|
{
|
||
|
PIC_SAVE_EXCURSION
|
||
|
({
|
||
|
write_copybits_picdata (src, dst, src_rect, dst_rect, mode, mask);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
if (PORT_PEN_VIS (thePort) < 0)
|
||
|
return;
|
||
|
|
||
|
ROMlib_real_copy_bits (src, dst, src_rect, dst_rect, mode, mask);
|
||
|
|
||
|
canonicalize_bogo_map_cleanup (src_bogo_map, &cleanup_info[0]);
|
||
|
canonicalize_bogo_map_cleanup (dst_bogo_map, &cleanup_info[1]);
|
||
|
}
|
||
|
|
||
|
P5 (PUBLIC pascal trap, void, StdBits,
|
||
|
/* destination is alawys the current port */
|
||
|
BitMap *, src_bogo_map,
|
||
|
const Rect *, src_rect, const Rect *, dst_rect,
|
||
|
INTEGER, mode, RgnHandle, mask)
|
||
|
{
|
||
|
StdBitsPicSaveFlag (src_bogo_map, src_rect, dst_rect, mode, mask, TRUE);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
ROMlib_real_copy_bits_helper (PixMap *src, PixMap *dst,
|
||
|
const Rect *src_rect, const Rect *dst_rect,
|
||
|
INTEGER mode, RgnHandle mask)
|
||
|
{
|
||
|
GDHandle the_gd;
|
||
|
PixMapHandle the_gd_pmap;
|
||
|
GrafPtr current_port;
|
||
|
|
||
|
Rect tmp_mask_rect;
|
||
|
uint32 bk_color, fg_color;
|
||
|
|
||
|
/* region used to compute the complete mask region */
|
||
|
RgnHandle mask_region;
|
||
|
|
||
|
/* bits of a pixel position in `src' that have a resolution
|
||
|
below that of a byte */
|
||
|
int dst_sub_byte_bits;
|
||
|
|
||
|
/* final depth of the destination */
|
||
|
int dst_depth;
|
||
|
|
||
|
const rgb_spec_t *dst_rgb_spec;
|
||
|
|
||
|
#if defined (SAVE_CURSOR)
|
||
|
int save_cursor_visible_p = FALSE;
|
||
|
int screen_src_p;
|
||
|
#endif /* SAVE_CURSOR */
|
||
|
|
||
|
TEMP_ALLOC_DECL (temp_depth_bits);
|
||
|
TEMP_ALLOC_DECL (temp_scale_bits);
|
||
|
TEMP_ALLOC_DECL (temp_overlap_bits);
|
||
|
|
||
|
the_gd = MR (TheGDevice);
|
||
|
the_gd_pmap = GD_PMAP (the_gd);
|
||
|
current_port = thePort;
|
||
|
|
||
|
#if defined (SAVE_CURSOR)
|
||
|
screen_src_p = active_screen_addr_p (src);
|
||
|
#endif
|
||
|
|
||
|
dst_rgb_spec = pixmap_rgb_spec (dst);
|
||
|
dst_depth = CW (dst->pixelSize);
|
||
|
|
||
|
switch (dst_depth)
|
||
|
{
|
||
|
case 1: dst_sub_byte_bits = 7; break;
|
||
|
case 2: dst_sub_byte_bits = 3; break;
|
||
|
case 4: dst_sub_byte_bits = 1; break;
|
||
|
default:
|
||
|
dst_sub_byte_bits = 0; break;
|
||
|
}
|
||
|
|
||
|
ROMlib_fg_bk (&fg_color, &bk_color, NULL, NULL, dst_rgb_spec,
|
||
|
active_screen_addr_p (dst), dst_depth <= 8);
|
||
|
|
||
|
/* if the source and dest differ in depths, perform a depth
|
||
|
conversion on the src, so it matches that of the depth */
|
||
|
if (src->pixelSize != dst->pixelSize
|
||
|
|| (src->pmTable != dst->pmTable &&
|
||
|
(CW (src->pixelSize) < 16
|
||
|
&& (CTAB_SEED_X (MR (src->pmTable))
|
||
|
/* we assume the destination has the same color table as
|
||
|
the current graphics device */
|
||
|
!= CTAB_SEED_X (PIXMAP_TABLE (GD_PMAP (the_gd)))
|
||
|
&& CTAB_SEED_X (MR (src->pmTable)) != CLC (0)))))
|
||
|
{
|
||
|
PixMap *new_src = (PixMap *) alloca (sizeof (PixMap));
|
||
|
/* convert_pixmap expects the src rect to be aligned to byte
|
||
|
boundaries; compute that in `widened_src_rect' */
|
||
|
Rect *widened_src_rect = (Rect *) alloca (sizeof (Rect));
|
||
|
int src_depth, src_sub_byte_bits;
|
||
|
void *new_src_bits;
|
||
|
int n_bytes_needed;
|
||
|
|
||
|
#if defined (SAVE_CURSOR)
|
||
|
if (screen_src_p)
|
||
|
{
|
||
|
save_cursor_visible_p = host_set_cursor_visible (FALSE);
|
||
|
screen_src_p = FALSE;
|
||
|
}
|
||
|
#endif /* SAVE_CURSOR */
|
||
|
|
||
|
src_depth = CW (src->pixelSize);
|
||
|
|
||
|
switch (src_depth)
|
||
|
{
|
||
|
case 1: src_sub_byte_bits = 7; break;
|
||
|
case 2: src_sub_byte_bits = 3; break;
|
||
|
case 4: src_sub_byte_bits = 1; break;
|
||
|
default:
|
||
|
src_sub_byte_bits = 0; break;
|
||
|
}
|
||
|
|
||
|
widened_src_rect->top = src_rect->top;
|
||
|
widened_src_rect->bottom = src_rect->bottom;
|
||
|
|
||
|
/* translate the left (right) src_rect coords to absolute bitmap
|
||
|
coordinates; and round down (up) to the byte boundary, and
|
||
|
re-translate to boundary-relative bitmap coords */
|
||
|
widened_src_rect->left
|
||
|
= CW (((CW (src_rect->left) - CW (src->bounds.left))
|
||
|
& ~src_sub_byte_bits)
|
||
|
+ CW (src->bounds.left));
|
||
|
widened_src_rect->right
|
||
|
= CW ((((CW (src_rect->right) - CW (src->bounds.left))
|
||
|
+ src_sub_byte_bits)
|
||
|
& ~src_sub_byte_bits) + CW (src->bounds.left));
|
||
|
|
||
|
/* the new_src should `be a pixmap' (have the pixmap bits set in
|
||
|
the rowBytes) only if the dst is a pixmap; convert_pixmap
|
||
|
does different things if the destination is a bitmap */
|
||
|
new_src->rowBytes = ( PIXMAP_DEFAULT_ROW_BYTES_X
|
||
|
| CW ((((RECT_WIDTH (widened_src_rect)
|
||
|
* dst_depth) + 31) / 32) * 4));
|
||
|
|
||
|
/* Allocate temporary storage for the new_src_bits bitmap. */
|
||
|
|
||
|
n_bytes_needed = (BITMAP_ROWBYTES (new_src)
|
||
|
* (CW (src_rect->bottom) - CW (src_rect->top)));
|
||
|
|
||
|
TEMP_ALLOC_ALLOCATE (new_src_bits, temp_depth_bits, n_bytes_needed);
|
||
|
new_src->baseAddr = RM (new_src_bits);
|
||
|
|
||
|
pixmap_set_pixel_fields (new_src, dst_depth);
|
||
|
new_src->pmTable = PIXMAP_TABLE_X (the_gd_pmap);
|
||
|
|
||
|
/* don't initialize the color table of new_src; we assume that
|
||
|
it has the same color space as the current graphics device */
|
||
|
|
||
|
convert_pixmap (src, new_src, widened_src_rect, NULL);
|
||
|
|
||
|
src = new_src;
|
||
|
/* `convert_pixmap ()' jukes the coordinates of the
|
||
|
new_src bitmap so that `src_rect' is still correct */
|
||
|
}
|
||
|
|
||
|
/* if the source and dest rectangles are not equivalent, scale the
|
||
|
source rectangle */
|
||
|
if (RECT_WIDTH (src_rect) != RECT_WIDTH (dst_rect)
|
||
|
|| RECT_HEIGHT (src_rect) != RECT_HEIGHT (dst_rect))
|
||
|
{
|
||
|
PixMap *new_src = (PixMap *) alloca (sizeof (PixMap));
|
||
|
int new_src_row_bytes;
|
||
|
void *scale_base;
|
||
|
|
||
|
#if defined (SAVE_CURSOR)
|
||
|
if (screen_src_p)
|
||
|
{
|
||
|
save_cursor_visible_p = host_set_cursor_visible (FALSE);
|
||
|
screen_src_p = FALSE;
|
||
|
}
|
||
|
#endif /* SAVE_CURSOR */
|
||
|
|
||
|
new_src_row_bytes
|
||
|
= (((RECT_WIDTH (dst_rect) * dst_depth
|
||
|
+ /* dst_sub_byte_bits */ 7) / 8) + 3) & ~3;
|
||
|
new_src->rowBytes = CW (new_src_row_bytes) | PIXMAP_DEFAULT_ROW_BYTES_X;
|
||
|
|
||
|
TEMP_ALLOC_ALLOCATE (scale_base, temp_scale_bits,
|
||
|
new_src_row_bytes * RECT_HEIGHT (dst_rect));
|
||
|
new_src->baseAddr = (Ptr) RM (scale_base);
|
||
|
|
||
|
pixmap_set_pixel_fields (new_src, dst_depth);
|
||
|
|
||
|
scale_blt_bitmap ((blt_bitmap_t *) src,
|
||
|
(blt_bitmap_t *) new_src,
|
||
|
src_rect, dst_rect, ROMlib_log2[dst_depth]);
|
||
|
|
||
|
src = new_src;
|
||
|
src_rect = dst_rect;
|
||
|
}
|
||
|
|
||
|
/* compute the mask region before checking if the source and dest
|
||
|
overlap becuase we only double buffer if dy is nonzero */
|
||
|
/* intersect the region mask with thePort bounds, thePort rect, the
|
||
|
destination rect, and the port {clip, vis} regions */
|
||
|
mask_region = NewRgn ();
|
||
|
|
||
|
SectRect (dst_rect, &dst->bounds, &tmp_mask_rect);
|
||
|
RectRgn (mask_region, &tmp_mask_rect);
|
||
|
SectRgn (PORT_CLIP_REGION (current_port), mask_region, mask_region);
|
||
|
SectRgn (PORT_VIS_REGION (current_port), mask_region, mask_region);
|
||
|
if (mask)
|
||
|
SectRgn (mask, mask_region, mask_region);
|
||
|
|
||
|
if (src->baseAddr == dst->baseAddr
|
||
|
&& (src_dst_overlap_and_dst_below_src_p
|
||
|
(src_rect, dst_rect,
|
||
|
CW (dst->bounds.left) - CW (src->bounds.left),
|
||
|
CW (dst->bounds.top) - CW (src->bounds.top)))
|
||
|
&& (! RGN_SMALL_P (mask_region)
|
||
|
|| dy_zero_p (src_rect, dst_rect,
|
||
|
CW (dst->bounds.left) - CW (src->bounds.left),
|
||
|
CW (dst->bounds.top) - CW (src->bounds.top))))
|
||
|
{
|
||
|
PixMap *new_src;
|
||
|
void *overlap_bits;
|
||
|
|
||
|
Rect copy_rect;
|
||
|
Rect clipped_src_rect;
|
||
|
int height, offset;
|
||
|
|
||
|
/* the source and destination are overlapped;
|
||
|
create a new src bitmap */
|
||
|
new_src = (PixMap *) alloca (sizeof *new_src);
|
||
|
|
||
|
#if defined (SAVE_CURSOR)
|
||
|
if (screen_src_p)
|
||
|
{
|
||
|
save_cursor_visible_p = host_set_cursor_visible (FALSE);
|
||
|
screen_src_p = FALSE;
|
||
|
}
|
||
|
#endif /* SAVE_CURSOR */
|
||
|
|
||
|
SectRect (&src->bounds, src_rect, &clipped_src_rect);
|
||
|
|
||
|
height = RECT_HEIGHT (&clipped_src_rect);
|
||
|
offset = CW (clipped_src_rect.top) - CW (src_rect->top);
|
||
|
|
||
|
copy_rect.top = CW (CW (src_rect->top) + offset);
|
||
|
copy_rect.bottom = CW (CW (src_rect->top) + offset + height);
|
||
|
copy_rect.left = src->bounds.left;
|
||
|
copy_rect.right = src->bounds.right;
|
||
|
|
||
|
new_src->rowBytes = src->rowBytes;
|
||
|
TEMP_ALLOC_ALLOCATE (overlap_bits, temp_overlap_bits,
|
||
|
height * BITMAP_ROWBYTES (src));
|
||
|
new_src->baseAddr = (Ptr) RM (overlap_bits);
|
||
|
new_src->bounds = copy_rect;
|
||
|
|
||
|
pixmap_set_pixel_fields (new_src, dst_depth);
|
||
|
new_src->pmTable = src->pmTable;
|
||
|
|
||
|
/* pause picture recording since we don't want the recursive
|
||
|
call to copy the overlapping image to be recorded */
|
||
|
|
||
|
{
|
||
|
uint32 black_pixel, white_pixel;
|
||
|
RgnHandle rgn;
|
||
|
|
||
|
rgn = NewRgn ();
|
||
|
RectRgn (rgn, ©_rect);
|
||
|
|
||
|
pixmap_black_white (new_src, &black_pixel, &white_pixel);
|
||
|
|
||
|
ROMlib_blt_rgn_update_dirty_rect (rgn, srcCopy,
|
||
|
FALSE, dst_depth,
|
||
|
src, new_src,
|
||
|
©_rect, ©_rect,
|
||
|
black_pixel, white_pixel);
|
||
|
DisposeRgn (rgn);
|
||
|
}
|
||
|
|
||
|
src = new_src;
|
||
|
}
|
||
|
|
||
|
ROMlib_blt_rgn_update_dirty_rect
|
||
|
(mask_region, mode, FALSE, dst_depth,
|
||
|
src, dst, src_rect, dst_rect,
|
||
|
fg_color, bk_color);
|
||
|
|
||
|
#if defined (SAVE_CURSOR)
|
||
|
if (save_cursor_visible_p)
|
||
|
host_set_cursor_visible (TRUE);
|
||
|
#endif
|
||
|
|
||
|
DisposeRgn (mask_region);
|
||
|
|
||
|
TEMP_ALLOC_FREE (temp_overlap_bits);
|
||
|
TEMP_ALLOC_FREE (temp_scale_bits);
|
||
|
TEMP_ALLOC_FREE (temp_depth_bits);
|
||
|
}
|
||
|
|
||
|
#if 1
|
||
|
|
||
|
/*
|
||
|
* If we're copying a big 1-bpp bitmap to a small 8-bpp pixmap, we really
|
||
|
* want to first copy to a temporary small 1-bpp bitmap and then copy that
|
||
|
* to a small 8-bpp pixmap, otherwise we expand our large bitmap by a factor
|
||
|
* of 8, which can be excessive.
|
||
|
*/
|
||
|
|
||
|
static void
|
||
|
ROMlib_real_copy_bits (PixMap *src, PixMap *dst,
|
||
|
const Rect *src_rect, const Rect *dst_rect,
|
||
|
INTEGER mode, RgnHandle mask)
|
||
|
{
|
||
|
boolean_t shrink_first_p;
|
||
|
|
||
|
if (src->pixelSize == dst->pixelSize)
|
||
|
shrink_first_p = FALSE;
|
||
|
else
|
||
|
{
|
||
|
int default_nbits, new_nbits;
|
||
|
|
||
|
default_nbits = (RECT_WIDTH (src_rect) * CW (dst->pixelSize) *
|
||
|
RECT_HEIGHT (src_rect));
|
||
|
|
||
|
new_nbits = ((RECT_WIDTH (dst_rect) * CW (src->pixelSize) *
|
||
|
RECT_HEIGHT (dst_rect)) +
|
||
|
(RECT_WIDTH (dst_rect) * CW (dst->pixelSize) *
|
||
|
RECT_HEIGHT (dst_rect)));
|
||
|
shrink_first_p = (new_nbits < default_nbits);
|
||
|
}
|
||
|
|
||
|
if (!shrink_first_p)
|
||
|
ROMlib_real_copy_bits_helper (src, dst, src_rect, dst_rect, mode, mask);
|
||
|
else
|
||
|
{
|
||
|
PixMap *new_src;
|
||
|
int temp_bytes_needed;
|
||
|
void *temp_bits;
|
||
|
INTEGER temp_row_bytes;
|
||
|
int src_depth;
|
||
|
#if defined (SAVE_CURSOR)
|
||
|
int save_cursor_visible_p = FALSE;
|
||
|
int screen_src_p;
|
||
|
#endif /* SAVE_CURSOR */
|
||
|
TEMP_ALLOC_DECL (temp_alloc_bits);
|
||
|
|
||
|
#if defined (SAVE_CURSOR)
|
||
|
screen_src_p = active_screen_addr_p (src);
|
||
|
if (screen_src_p)
|
||
|
{
|
||
|
save_cursor_visible_p = host_set_cursor_visible (FALSE);
|
||
|
screen_src_p = FALSE;
|
||
|
}
|
||
|
#endif /* SAVE_CURSOR */
|
||
|
|
||
|
new_src = (PixMap *) alloca (sizeof *new_src);
|
||
|
src_depth = CW (src->pixelSize);
|
||
|
temp_row_bytes = (RECT_WIDTH (dst_rect) * src_depth + 31) / 32 * 4;
|
||
|
temp_bytes_needed = temp_row_bytes * RECT_HEIGHT (dst_rect);
|
||
|
TEMP_ALLOC_ALLOCATE (temp_bits, temp_alloc_bits, temp_bytes_needed);
|
||
|
|
||
|
*new_src = *src;
|
||
|
new_src->baseAddr = RM (temp_bits);
|
||
|
new_src->rowBytes = CW (temp_row_bytes | PIXMAP_DEFAULT_ROWBYTES);
|
||
|
new_src->bounds = *dst_rect;
|
||
|
|
||
|
scale_blt_bitmap ((blt_bitmap_t *) src, (blt_bitmap_t *) new_src,
|
||
|
src_rect, dst_rect, ROMlib_log2[src_depth]);
|
||
|
ROMlib_real_copy_bits_helper (new_src, dst, dst_rect, dst_rect, mode,
|
||
|
mask);
|
||
|
|
||
|
TEMP_ALLOC_FREE (temp_alloc_bits);
|
||
|
}
|
||
|
}
|
||
|
#endif
|