255 lines
6.5 KiB
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;
|
|
}
|