mirror of
https://github.com/ctm/executor.git
synced 2024-09-29 18:58:01 +00:00
475 lines
13 KiB
C
475 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/screen.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;
|
||
|
}
|