executor/src/qStdRRect.c

255 lines
6.5 KiB
C

/* Copyright 1986, 1988, 1989, 1990 by Abacus Research and
* Development, Inc. All rights reserved.
*/
#if !defined (OMIT_RCSID_STRINGS)
char ROMlib_rcsid_qStdRRect[] =
"$Id: qStdRRect.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 "MemoryMgr.h"
#include "rsys/cquick.h"
#include "rsys/picture.h"
#define TERM (*ip++ = RGNSTOPX)
#define ADD4(y, x1, x2) \
(*ip++ = CW((y)), *ip++ = CW((x1)), *ip++ = CW((x2)), TERM)
#define ADD6(y, x1, x2, x3, x4) \
(*ip++ = CW((y)), *ip++ = CW((x1)), *ip++ = CW((x2)), \
*ip++ = CW((x3)), *ip++ = CW((x4)), TERM)
A1(PUBLIC, RgnHandle, ROMlib_circrgn, Rect *, r) /* INTERNAL */
{
RgnHandle rh;
register INTEGER x, y, temp; /* some variables need to be longs */
INTEGER d, e, ny, oy, nx, ox, savex, rad;
INTEGER scalex, scaley;
INTEGER dh, dv;
Size maxsize;
INTEGER top, bottom, centl, centr, centt, left, right;
INTEGER *ip, *op, *ip2, *ep;
INTEGER first;
long long_region_size; /* so we can test for overflow */
#if !defined (LETGCCWAIL)
ox = 0;
#endif /* LETGCCWAIL */
top = CW(r->top);
bottom = CW(r->bottom);
dv = bottom - top;
dh = (right = CW(r->right)) - (left = CW(r->left));
maxsize = 10 + (6 * dv + 1) * sizeof(INTEGER);
rh = (RgnHandle) NewHandle(maxsize);
HxX (rh, rgnBBox) = *r;
if (dh == dv && dh < 10) { /* do small ones by hand */
ip = (INTEGER *) STARH(rh) + 5;
if (dh >= 4) {
if (dh < 7) {
ADD4(top , left+1, right-1);
ADD6(top +1, left , left+1, right-1, right);
ADD6(bottom-1, left , left+1, right-1, right);
ADD4(bottom , left+1, right-1);
TERM;
} else {
ADD4(top , left+2, right-2);
ADD6(top +1, left+1, left+2, right-2, right-1);
ADD6(top +2, left , left+1, right-1, right );
ADD6(bottom-2, left , left+1, right-1, right );
ADD6(bottom-1, left+1, left+2, right-2, right-1);
ADD4(bottom , left+2, right-2);
TERM;
}
}
HxX(rh, rgnSize) = CW((char *) ip - (char *) STARH(rh));
SetHandleSize((Handle) rh, (Size) Hx(rh, rgnSize));
/*-->*/ return rh;
}
if (dh > dv) {
scalex = FALSE;
scaley = TRUE;
rad = dh;
} else if (dv > dh) {
scalex = TRUE;
scaley = FALSE;
rad = dv;
} else {
scalex = FALSE;
scaley = FALSE;
rad = dv;
}
centl = CW(r->left) + dh / 2;
centr = CW(r->left) + (dh + 1) / 2;
centt = top + dv / 2;
first = TRUE;
op = (INTEGER *) STARH(rh) + 5;
x = 0;
y = rad;
oy = centt - top;
d = 3 - 2 * rad;
e = 3 - 4 * rad;
while (y >= 0) {
if (d < 0) {
temp = 4 * x;
d += temp + 6;
e += temp + 4;
x++;
} else {
savex = x;
if (e > 0) {
temp = 4 * y;
d -= temp - 4;
e += -temp + 6;
} else {
d += (temp = 4 * (x - y) + 10);
e += temp;
x++;
}
y--;
if (scaley)
ny = ((LONGINT) dv * y / dh) / 2;
else
ny = y / 2;
if (ny != oy) {
if (scalex)
nx = ((LONGINT) dh * savex / dv) / 2;
else
nx = savex / 2;
if (first) {
*op++ = CW(top);
*op++ = CW(centl - nx);
*op++ = CW(centr + nx);
*op++ = RGNSTOPX;
ox = nx;
first = FALSE;
} else {
if (nx != ox) {
*op++ = CW(centt - oy);
*op++ = CW(centl - nx);
*op++ = CW(centl - ox);
*op++ = CW(centr + ox);
*op++ = CW(centr + nx);
*op++ = RGNSTOPX;
ox = nx;
}
}
oy = ny;
}
}
}
ip = op-1;
ep = (INTEGER *) STARH(rh) + 4;
while (ip != ep) {
ip -= 4;
while (ip != ep && *ip != RGNSTOPX)
ip -= 2;
ip2 = ip + 1;
*op++ = CW(bottom - (CW(*ip2++) - top));
while ((*op++ = *ip2++) != RGNSTOPX)
;
}
*op++ = RGNSTOPX;
long_region_size = sizeof(INTEGER) * (op - (INTEGER *) STARH(rh));
if (long_region_size >= 32768) /* test for overflow */
SetEmptyRgn (rh);
else
{
HxX(rh, rgnSize) = CW(sizeof(INTEGER) * (op - (INTEGER *) STARH(rh)));
SetHandleSize((Handle) rh, (Size) Hx(rh, rgnSize));
}
return rh;
}
/*
* TODO: speed up this code... it is ridiculously slow
*/
P4(PUBLIC pascal trap, void, StdRRect, GrafVerb, verb, Rect *, r,
INTEGER, width, INTEGER, height)
{
RgnHandle rh, oval, corner, smallr;
Rect tempr;
INTEGER ovaldx, ovaldy, rectdx, rectdy;
Point p;
PAUSEDECL;
PIC_SAVE_EXCURSION
({
p.h = CW (width);
p.v = CW (height);
ROMlib_drawingverbrectovalpicupdate (verb, r, &p);
PICOP (OP_frameRRect + (int) verb);
PICWRITE (r, sizeof(*r));
});
if (PORT_PEN_VIS (thePort) < 0
&& (!PORT_REGION_SAVE (thePort) || verb != frame))
/*-->*/ return;
PAUSERECORDING;
ovaldx = CW(r->right) - CW(r->left) - width;
ovaldy = CW(r->bottom) - CW(r->top) - height;
if (width < 4 && height < 4)
StdRect(verb, r);
else {
rectdx = CW(r->right) - CW(r->left) - width/2;
rectdy = CW(r->bottom) - CW(r->top) - height/2;
rh = NewRgn();
corner = NewRgn();
smallr = NewRgn();
RectRgn(rh, r);
SetRect(&tempr, CW(r->left), CW(r->top),
CW(r->left)+width, CW(r->top)+height);
oval = ROMlib_circrgn(&tempr);
SetRect(&tempr, CW(r->left), CW(r->top),
CW(r->left)+width/2, CW(r->top)+height/2);
RectRgn(smallr, &tempr);
DiffRgn(smallr, oval, corner);
DiffRgn(rh, corner, rh);
OffsetRgn(oval, ovaldx, 0);
OffsetRgn(smallr, rectdx, 0);
DiffRgn(smallr, oval, corner);
DiffRgn(rh, corner, rh);
OffsetRgn(oval, 0, ovaldy);
OffsetRgn(smallr, 0, rectdy);
DiffRgn(smallr, oval, corner);
DiffRgn(rh, corner, rh);
OffsetRgn(oval, -ovaldx, 0);
OffsetRgn(smallr, -rectdx, 0);
DiffRgn(smallr, oval, corner);
DiffRgn(rh, corner, rh);
StdRgn(verb, rh);
DisposeRgn(smallr);
DisposeRgn(corner);
DisposeRgn(oval);
DisposeRgn(rh);
}
RESUMERECORDING;
}