executor/src/qIMIV.c
2009-06-16 14:55:37 -06:00

474 lines
13 KiB
C

/* Copyright 1989, 1990, 1995 by Abacus Research and
* Development, Inc. All rights reserved.
*/
#if !defined (OMIT_RCSID_STRINGS)
char ROMlib_rcsid_qIMIV[] =
"$Id: qIMIV.c 63 2004-12-24 18:19:43Z ctm $";
#endif
/* Forward declarations in QuickDraw.h (DO NOT DELETE THIS LINE) */
#include "rsys/common.h"
#include "QuickDraw.h"
#include "CQuickDraw.h"
#include "rsys/quick.h"
#include "rsys/cquick.h"
#include "rsys/stdbits.h"
#include "rsys/safe_alloca.h"
#include "rsys/tempalloc.h"
#include "rsys/dirtyrect.h"
#include "rsys/vdriver.h"
#undef ALLOCABEGIN
#define ALLOCABEGIN SAFE_DECL();
#undef ALLOCA
#define ALLOCA(n) SAFE_alloca(n)
#include "seedtables.c"
#define DOLEFT 1
#define DORIGHT 2
#define DOMASK (DOLEFT|DORIGHT)
typedef struct {
unsigned char *p;
unsigned char seed;
unsigned char flags;
} stackentry;
typedef enum { Copy, Xor, Negate } transferop;
A7(PRIVATE, void, transfer, INTEGER *, srcp, INTEGER *, dstp, INTEGER, srcr,
INTEGER, dstr, INTEGER, height, INTEGER, widthw, transferop, op)
{
register INTEGER sbump, dbump;
register INTEGER *ep0, *ep1;
sbump = srcr/2 - widthw;
dbump = dstr/2 - widthw;
ep0 = dstp + (LONGINT) height * dstr/2;
switch (op) {
case Copy:
while (dstp != ep0) {
for (ep1 = srcp + widthw; srcp != ep1; *dstp++ = *srcp++)
;
srcp += sbump;
dstp += dbump;
}
break;
case Xor:
while (dstp != ep0) {
for (ep1 = srcp + widthw; srcp != ep1; *dstp++ ^= *srcp++)
;
srcp += sbump;
dstp += dbump;
}
break;
case Negate:
while (dstp != ep0) {
for (ep1 = dstp + widthw; dstp != ep1; *dstp++ ^= ~0)
;
dstp += dbump;
}
break;
}
}
#define LEFTBIT (0x80)
#define RIGHTBIT (1)
#define ADDTOSTACK(ptr, s, f) (sp->p = (ptr), sp->seed = (s), \
sp->flags = (f), sp++)
#define EXPAND(p, s) (tempuc = ~*(p), expandtable[binarytotrinary[tempuc] + \
binarytotrinary[tempuc&(s)]])
#define CHECKLEFT(lp, op) \
{ \
--cur; \
if ((expanded & LEFTBIT) && !atleft && !(*cur & RIGHTBIT)) \
{ \
if (lp->p op dstr == cur) \
lp->p = cur; \
else \
lp = ADDTOSTACK(cur, RIGHTBIT, DOLEFT); \
} \
++cur; \
}
#define CHECKRIGHT(lp, op) \
{ \
++cur; \
if ((expanded & RIGHTBIT) && !atright && !(*cur & LEFTBIT)) \
{ \
if (lp->p op dstr == cur) \
lp->p = cur; \
else \
lp = ADDTOSTACK(cur, LEFTBIT, DORIGHT); \
} \
--cur; \
}
A9 (PRIVATE, void, xSeedFill, unsigned char *, srcp, unsigned char *, dstp,
INTEGER, srcr, INTEGER, dstr, INTEGER, height, INTEGER, width,
BOOLEAN, useseeds, INTEGER, seedh, INTEGER, seedv)
{
unsigned char *cur, *savecur, expanded, saveexpanded, seed, *edstp;
stackentry bogusentry, *topleftp, *toprightp, *bottomleftp, *bottomrightp,
*stackp, stacke;
BOOLEAN atleft, atright;
unsigned char tempuc;
stackentry stack[4000], *sp;
unsigned char *ecur;
Rect temprect;
LONGINT byteoff, voff;
/* should be a sanity check of seedh and seedv here with just a zering
of the destrect and early return if they are bad */
TRAPBEGIN();
transfer((INTEGER *) srcp, (INTEGER *) dstp, srcr, dstr, height, width,
Copy);
sp = stack;
bogusentry.p = 0;
edstp = dstp + (LONGINT) height * dstr;
if (useseeds) {
cur = dstp + (LONGINT) seedv * dstr + seedh / 8;
seed = LEFTBIT >> (seedh % 8);
ADDTOSTACK(cur, seed, DOLEFT|DORIGHT);
} else {
/* this is setting things up for CalcMask */
for (cur = dstp, ecur = cur + width*2; cur != ecur; cur++)
if (*cur != 0xFF)
ADDTOSTACK(cur, 0xFF, DOLEFT|DORIGHT);
for (cur = dstp + (height-1) * (LONGINT) dstr, ecur = cur + width*2;
cur != ecur; cur++)
if (*cur != 0xFF)
ADDTOSTACK(cur, 0xFF, DOLEFT|DORIGHT);
bottomleftp = &bogusentry;
for (cur = dstp; cur < edstp; cur += dstr) {
if (!(*cur & LEFTBIT))
{
if (bottomleftp->p + dstr == cur)
bottomleftp->p = cur;
else
bottomleftp = ADDTOSTACK(cur, LEFTBIT, DORIGHT);
}
}
bottomrightp = &bogusentry;
for (cur = dstp + width*2 - 1; cur < edstp; cur += dstr) {
if (!(*cur & RIGHTBIT))
{
if (bottomrightp->p + dstr == cur)
bottomrightp->p = cur;
else
bottomrightp = ADDTOSTACK(cur, RIGHTBIT, DOLEFT);
}
}
}
while ((stackp = --sp) >= stack) {
stacke = *stackp;
topleftp = toprightp = bottomleftp = bottomrightp = &bogusentry;
cur = stacke.p;
atleft = !((cur - dstp) % dstr);
atright = (cur - dstp) % dstr == width*2 - 1;
saveexpanded = expanded = EXPAND(cur, stacke.seed);
savecur = cur;
cur[0] |= expanded;
if (stacke.flags & DOLEFT)
CHECKLEFT(topleftp, +); /* op doesn't really matter */
bottomleftp = topleftp;
if (stacke.flags & DORIGHT)
CHECKRIGHT(toprightp, +); /* op doesn't really matter */
bottomrightp = toprightp;
/* go flying up the top */
while ((cur -= dstr, cur >= dstp) &&
(expanded = EXPAND(cur, expanded))) {
cur[0] |= expanded;
CHECKLEFT(topleftp, -);
CHECKRIGHT(toprightp, -);
if ((cur[dstr] & expanded) != expanded)
ADDTOSTACK(cur+dstr, expanded, DOLEFT|DORIGHT);
}
/* go flying down the bottom */
cur = savecur;
expanded = saveexpanded;
while ((cur += dstr, cur < edstp) &&
(expanded = EXPAND(cur, expanded))) {
cur[0] |= expanded;
CHECKLEFT(bottomleftp, +);
CHECKRIGHT(bottomrightp, +);
if ((cur[-dstr] & expanded) != expanded)
ADDTOSTACK(cur-dstr, expanded, DOLEFT|DORIGHT);
}
}
transfer((INTEGER *) srcp, (INTEGER *) dstp, srcr, dstr, height, width,
Xor);
if (!useseeds)
transfer((INTEGER *) 0, (INTEGER *) dstp, 0, dstr, height,
width, Negate);
if (dstp >= (unsigned char *) MR(screenBitsX.baseAddr)) {
byteoff = dstp - (unsigned char *) MR(screenBitsX.baseAddr);
voff = byteoff / CW(screenBitsX.rowBytes);
if (voff < CW(screenBitsX.bounds.bottom) - CW(screenBitsX.bounds.top))
{
dirty_rect_accrue (CW (screenBitsX.bounds.top) + voff,
(CW (screenBitsX.bounds.left)
+ (byteoff % CW(screenBitsX.rowBytes) * 8L)),
CW (temprect.top) + height,
CW (temprect.left) + (LONGINT) width * 16);
}
}
TRAPEND();
}
#if defined (VDRIVER_SUPPORTS_REAL_SCREEN_BLITS)
static boolean_t
create_scratch_bitmap_if_necessary (uint8 **_fbuf,
/* dummy */ int row_words,
int height, int word_width,
write_back_data_t *write_back_data)
{
PixMapHandle gd_pmap;
uint8 *screen_fbuf, *fbuf;
int screen_row_bytes;
int screen_height;
gd_pmap = GD_PMAP (MR (MainDevice));
screen_fbuf = PIXMAP_BASEADDR (gd_pmap);
screen_row_bytes = PIXMAP_ROWBYTES (gd_pmap);
screen_height = RECT_HEIGHT (&PIXMAP_BOUNDS (gd_pmap));
fbuf = *_fbuf;
if (VDRIVER_BYPASS_INTERNAL_FBUF_P ()
&& (screen_fbuf <= fbuf
&& fbuf < screen_fbuf + (screen_row_bytes * screen_height)))
{
PixMap *src_pm, *dst_pm;
Rect *src_rect, *dst_rect;
int offset;
src_pm = &write_back_data->dst_pm;
src_rect = &write_back_data->dst_rect;
dst_pm = &write_back_data->src_pm;
dst_rect = &write_back_data->src_rect;
offset = fbuf - screen_fbuf;
src_rect->top = CW (offset / screen_row_bytes);
src_rect->bottom = CW (offset / screen_row_bytes + height);
src_rect->left = CW ((offset % screen_row_bytes) * 8);
src_rect->right = CW ((offset % screen_row_bytes) * 8
+ word_width * 16);
*src_pm = *STARH (gd_pmap);
pixmap_copy (src_pm, src_rect, dst_pm, dst_rect);
*_fbuf = BITMAP_BASEADDR (dst_pm);
return TRUE;
}
return FALSE;
}
static void
SeedFill_handle_direct_screen_access (uint8 *srcp, uint8 *dstp,
int src_row_words, int dst_row_words,
int height, int word_width,
boolean_t use_seed_pt_p,
int seedh, int seedv)
{
write_back_data_t write_back_data;
boolean_t write_back_p = FALSE;
create_scratch_bitmap_if_necessary (&srcp, src_row_words,
height, word_width,
NULL);
write_back_p = create_scratch_bitmap_if_necessary (&dstp, dst_row_words,
height, word_width,
&write_back_data);
xSeedFill (srcp, dstp, src_row_words, dst_row_words,
height, word_width, use_seed_pt_p, seedh, seedv);
if (write_back_p)
{
CopyBits ((BitMap *) &write_back_data.src_pm,
(BitMap *) &write_back_data.dst_pm,
&write_back_data.src_rect, &write_back_data.dst_rect,
srcCopy, NULL);
pixmap_free_copy (&write_back_data.src_pm);
}
}
#else
#define SeedFill_handle_direct_screen_access xSeedFill
#endif
P8 (PUBLIC pascal trap, void, SeedFill, Ptr, srcp, Ptr, dstp, /* IMIV-24 */
INTEGER, srcr, INTEGER, dstr, INTEGER, height, INTEGER, width,
INTEGER, seedh, INTEGER, seedv)
{
SeedFill_handle_direct_screen_access ((uint8 *) srcp, (uint8 *) dstp,
srcr, dstr,
height, width, TRUE, seedh, seedv);
}
P6 (PUBLIC pascal trap, void, CalcMask, Ptr, srcp, Ptr, dstp, /* IMIV-24 */
INTEGER, srcr, INTEGER, dstr, INTEGER, height, INTEGER, width)
{
SeedFill_handle_direct_screen_access ((uint8 *) srcp, (uint8 *) dstp,
srcr, dstr,
height, width, FALSE, 0, 0);
}
static void
copy_mask_1 (BitMap *src_bm, BitMap *mask_bm, BitMap *dst_bm,
Rect *src_rect, Rect *mask_rect, Rect *dst_rect)
{
RgnHandle mask_rgn;
mask_rgn = NewRgn ();
if (BitMapToRegion (mask_rgn, mask_bm) == noErr)
{
Handle save_pic_handle, save_graf_procs;
RgnHandle mask_rect_rgn;
mask_rect_rgn = NewRgn ();
RectRgn (mask_rect_rgn, mask_rect);
SectRgn (mask_rgn, mask_rect_rgn, mask_rgn);
MapRgn (mask_rgn, mask_rect, dst_rect);
save_pic_handle = PORT_PIC_SAVE_X (thePort);
save_graf_procs = (Handle) PORT_GRAF_PROCS_X (thePort);
PORT_PIC_SAVE_X (thePort) = RM (NULL);
PORT_GRAF_PROCS_X (thePort) = RM (NULL);
CopyBits (src_bm, dst_bm, src_rect, dst_rect, srcCopy, mask_rgn);
PORT_PIC_SAVE_X (thePort) = save_pic_handle;
PORT_GRAF_PROCS_X (thePort) = (void *) save_graf_procs;
DisposeRgn (mask_rect_rgn);
DisposeRgn (mask_rgn);
}
else
{
Rect src_top, src_bottom, mask_top, mask_bottom, dst_top, dst_bottom;
int16 src_half, mask_half, dst_half;
BitMap mask_top_bm, mask_bottom_bm;
DisposeRgn (mask_rgn);
src_half = RECT_HEIGHT (src_rect) / 2;
mask_half = RECT_HEIGHT (mask_rect) / 2;
dst_half = RECT_HEIGHT (dst_rect) / 2;
src_top = src_bottom = *src_rect;
mask_top = mask_bottom = *mask_rect;
dst_top = dst_bottom = *dst_rect;
src_bottom.top = src_top.bottom
= CW (CW (src_top.bottom) - src_half);
mask_bottom.top = mask_top.bottom
= CW (CW (mask_top.bottom) - mask_half);
dst_bottom.top = dst_top.bottom
= CW (CW (dst_top.bottom) - dst_half);
mask_top_bm = *mask_bm;
mask_bottom_bm = *mask_bm;
mask_bottom_bm.bounds.top = mask_top_bm.bounds.bottom
= CW (CW (mask_top_bm.bounds.bottom) - mask_half);
copy_mask_1 (src_bm, &mask_top_bm, dst_bm,
&src_top, &mask_top, &dst_top);
copy_mask_1 (src_bm, &mask_bottom_bm, dst_bm,
&src_bottom, &mask_bottom, &dst_bottom);
}
}
P6 (PUBLIC pascal trap, void, CopyMask, /* IMIV-24 */
BitMap *, src_bogo_map, BitMap *, mask_bogo_map, BitMap *, dst_bogo_map,
Rect *, src_rect, Rect *, mask_rect, Rect *, dst_rect)
{
BitMap mask_bm;
void *mask_bits;
int row_bytes;
TEMP_ALLOC_DECL (temp_mask_bits);
if (ROMlib_text_output_disabled_p)
/*-->*/ return;
if (EmptyRect (mask_rect))
return;
row_bytes = (RECT_WIDTH (mask_rect) + 31) / 32 * 4;
TEMP_ALLOC_ALLOCATE (mask_bits, temp_mask_bits,
row_bytes * RECT_HEIGHT (mask_rect));
mask_bm.baseAddr = RM (mask_bits);
mask_bm.rowBytes = CW (row_bytes);
mask_bm.bounds = *mask_rect;
CopyBits (mask_bogo_map, &mask_bm,
mask_rect, mask_rect, srcCopy, NULL);
copy_mask_1 (src_bogo_map, &mask_bm, dst_bogo_map,
src_rect, mask_rect, dst_rect);
TEMP_ALLOC_FREE (temp_mask_bits);
}
P8 (PUBLIC pascal trap, void, IMVI_CopyDeepMask,
BitMap *, srcBits,
BitMap *, maskBits,
BitMap *, dstBits,
Rect *, srcRect,
Rect *, maskRect,
Rect *, dstRect,
INTEGER, mode,
RgnHandle, maskRgn)
{
warning_unimplemented ("poorly implemented");
if (ROMlib_text_output_disabled_p)
/*-->*/ return;
C_CopyMask (srcBits, maskBits, dstBits, srcRect, maskRect, dstRect);
}
/* MeasureText is in qd/qStdText.c */
A0(PUBLIC a0trap, INTEGER *, GetMaskTable) /* IMIV-25 */
{
static unsigned char table[] __attribute__ ((aligned (2))) = {
0x00, 0x00, 0x80, 0x00, 0xC0, 0x00, 0xE0, 0x00,
0xF0, 0x00, 0xF8, 0x00, 0xFC, 0x00, 0xFE, 0x00,
0xFF, 0x00, 0xFF, 0x80, 0xFF, 0xC0, 0xFF, 0xE0,
0xFF, 0xF0, 0xFF, 0xF8, 0xFF, 0xFC, 0xFF, 0xFE,
0xFF, 0xFF, 0x7F, 0xFF, 0x3F, 0xFF, 0x1F, 0xFF,
0x0F, 0xFF, 0x07, 0xFF, 0x03, 0xFF, 0x01, 0xFF,
0x00, 0xFF, 0x00, 0x7F, 0x00, 0x3F, 0x00, 0x1F,
0x00, 0x0F, 0x00, 0x07, 0x00, 0x03, 0x00, 0x01,
0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x00,
0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x01, 0x00,
0x00, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10,
0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x01,
};
EM_A0 = (LONGINT) US_TO_SYN68K(table);
return (INTEGER *) table;
}