?? xgeneral.c
字號:
xabs = abs(x2 - x1);
yabs = abs(y2 - y1);
/* Technically what we're doing here is drawing a line which is more */
/* horizontal then vertical. We always increment x by 1, and increment */
/* y whenever a fractional variable passes a certain amount. For lines */
/* that are more vertical than horizontal, we just swap x and y coords. */
if (xabs < yabs) {
SWAP(xadd, yadd);
SWAP(xabs, yabs);
}
yinc = (xabs >> 1) - ((xabs & 1 ^ 1) && xadd > 2);
for (i = xabs+1; i; i--) {
if (j < 1)
DrawPoint(x, y);
j = j < skip ? j+1 : 0;
switch (xadd) {
case 1: x++; break;
case 2: y++; break;
case 3: x--; break;
case 4: y--; break;
}
yinc += yabs;
if (yinc - xabs >= 0) {
yinc -= xabs;
switch (yadd) {
case 1: x++; break;
case 2: y++; break;
case 3: x--; break;
case 4: y--; break;
}
}
}
}
/* Draw a normal line on the screen; however, if the x coordinates are close */
/* to either of the two given bounds, then we assume that the line runs off */
/* one side and reappears on the other, so draw the appropriate two lines */
/* instead. This is used by the Ley line and astro-graph routines, which */
/* draw lines running around the world and hence off the edges of the maps. */
void DrawWrap(x1, y1, x2, y2, xmin, xmax)
int x1, y1, x2, y2;
{
int xmid, ymid, i;
if (x1 < 0) { /* Special case for drawing world map. */
DrawPoint(x2, y2);
return;
}
xmid = (xmax-xmin) / 2;
/* If endpoints aren't near opposite edges, just draw the line and return. */
if (abs(x2-x1) < xmid) {
DrawLine(x1, y1, x2, y2);
return;
}
i = (xmax-xmin+1) + (x1 < xmid ? x1-x2 : x2-x1);
/* Determine vertical coordinate where our line runs off edges of screen. */
ymid = y1+(int)((real)(y2-y1)*
(x1 < xmid ? (real)(x1-xmin) : (real)(xmax-x1))/(real)i + ROUND);
DrawLine(x1, y1, x1 < xmid ? xmin : xmax, ymid);
DrawLine(x2 < xmid ? xmin : xmax, ymid, x2, y2);
}
/* This routine, and its companion below, clips a line defined by its */
/* endpoints to either above some line y=c, or below some line y=c. By */
/* passing in parameters in different orders, we can clip to vertical */
/* lines, too. These are used by the DrawClip() routine below. */
void ClipLesser(x1, y1, x2, y2, s)
int *x1, *y1, *x2, *y2, s;
{
*x1 -= (int)((long)(*y1-s)*(*x2-*x1)/(*y2-*y1));
*y1 = s;
}
void ClipGreater(x1, y1, x2, y2, s)
int *x1, *y1, *x2, *y2, s;
{
*x1 += (int)((long)(s-*y1)*(*x2-*x1)/(*y2-*y1));
*y1 = s;
}
/* Draw a line on the screen. This is just like DrawLine() routine earlier; */
/* however, first clip the endpoints to the window viewport before drawing. */
void DrawClip(x1, y1, x2, y2, xl, yl, xh, yh, skip)
int x1, y1, x2, y2, xl, yl, xh, yh, skip;
{
if (x1 < xl)
ClipLesser (&y1, &x1, &y2, &x2, xl); /* Check left side of window. */
if (x2 < xl)
ClipLesser (&y2, &x2, &y1, &x1, xl);
if (y1 < yl)
ClipLesser (&x1, &y1, &x2, &y2, yl); /* Check top side of window. */
if (y2 < yl)
ClipLesser (&x2, &y2, &x1, &y1, yl);
if (x1 > xh)
ClipGreater(&y1, &x1, &y2, &x2, xh); /* Check right of window. */
if (x2 > xh)
ClipGreater(&y2, &x2, &y1, &x1, xh);
if (y1 > yh)
ClipGreater(&x1, &y1, &x2, &y2, yh); /* Check bottom of window. */
if (y2 > yh)
ClipGreater(&x2, &y2, &x1, &y1, yh);
DrawDash(x1, y1, x2, y2, skip); /* Go draw the line. */
}
/* Draw a circle or ellipse inside the given bounding rectangle. */
void DrawEllipse(x1, y1, x2, y2)
int x1, y1, x2, y2;
{
int x, y, rx, ry, m, n, u, v, i;
if (xfile) {
x = (x1+x2)/2; y = (y1+y2)/2; rx = (x2-x1)/2; ry = (y2-y1)/2;
if (xbitmap) {
InitCircle();
m = x + rx; n = y;
for (i = 0; i <= DEGR; i += DEGINC) {
u = x + (int)((real)rx*circ->x[i]); v = y + (int)((real)ry*circ->y[i]);
u = MIN(u, x + rx-1); v = MIN(v, y + ry-1);
DrawLine(m, n, u, v);
m = u; n = v;
}
}
#ifdef PS
else if (psfile) {
PSlinecap(FALSE);
PSforcestroke();
fprintf(psdata, "%d %d %d %d el\n", rx, ry, x, y);
}
#endif
#ifdef META
else {
metafilldes = 16; /* Specify a hollow fill brush. */
MetaSelect();
MetaEllipse(x1+metawid/3, y1+metawid/3, x2+metawid/3, y2+metawid/3);
}
#endif
}
#ifdef X11
else
XDrawArc(disp, pixmap, gc, x1, y1, x2-x1, y2-y1, 0, 360*64);
#endif
#ifdef MSG
else
_ellipse(_GBORDER, offsetx + x1, offsety + y1, offsetx + x2, offsety + y2);
#endif
}
/* Print a string of text on the graphic window at specified location. To */
/* do this we either use Astrolog's own "font" (6x10) and draw each letter */
/* separately, or else specify system fonts for PostScript and metafiles. */
void DrawText(string, x, y, base)
char *string;
int x, y, base;
{
int s = scale, c = colcur, len;
len = StringLen(string);
scale = 100 * scalet;
x += SCALE;
if (base >= FALSE)
x -= len*FONTX*SCALE/2;
if (!base)
y -= FONTY*SCALE/2;
else
y -= (FONTY-3)*SCALE;
DrawColor(off);
DrawBlock(x, y, x+FONTX*SCALE*len, y+(FONTY-1)*SCALE);
DrawColor(c);
#ifdef PS
if (psfile && xfont) {
PSfont(4);
fprintf(psdata, "%d %d(%s)center\n",
x + FONTX*SCALE*len/2, y + FONTY*SCALE/2, string);
scale = s;
return;
}
#endif
while (*string) {
#ifdef META
if (metafile && xfont) {
metafontdes = 3;
metatxtcdes = colcur;
metatxtades = 0x6 | 0 /* Center | Top */;
MetaSelect();
MetaTextOut(x, y, 1);
MetaWord(MAKEWORD(*string, 0));
} else
#endif
DrawTurtle(asciidraw[*string-' '], x, y);
x += FONTX*SCALE;
string++;
}
scale = s;
}
/* Draw the glyph of a sign at particular coordinates on the screen. */
/* To do this we either use Astrolog's turtle vector representation or */
/* we may specify a system font character for PostScript and metafiles. */
void DrawSign(i, x, y)
int i, x, y;
{
#ifdef PS
if (psfile && xfont) {
PSfont(1);
fprintf(psdata, "%d %d(%c)center\n", x, y, 'A' + i - 1);
return;
}
#endif
#ifdef META
if (metafile && xfont) {
metafontdes = 1;
metatxtcdes = colcur;
metatxtades = 0x6 | 0x8 /* Center | Bottom */;
MetaSelect();
MetaTextOut(x, y+4*SCALE, 1);
MetaWord(MAKEWORD('^' + i - 1, 0));
return;
}
#endif
DrawTurtle(signdraw[i], x, y);
}
/* Draw the number of a house at particular coordinates on the screen. */
/* We either use a turtle vector or write a number in a system font. */
void DrawHouse(i, x, y)
int i, x, y;
{
#ifdef PS
if (psfile && xfont) {
PSfont(3);
fprintf(psdata, "%d %d(%d)center\n", x, y, i);
return;
}
#endif
#ifdef META
if (metafile && xfont) {
metafontdes = 2;
metatxtcdes = colcur;
metatxtades = 0x6 | 0x8 /* Center | Bottom */;
MetaSelect();
MetaTextOut(x, y+3*SCALE, 1 + (i>9));
MetaWord(MAKEWORD(i > 9 ? '1' : '0'+i, i > 9 ? '0'+i-10 : 0));
return;
}
#endif
DrawTurtle(housedraw[i], x, y);
}
/* Draw the glyph of an object at particular coordinates on the screen. */
void DrawObject(i, x, y)
int i, x, y;
{
char glyph[4];
#ifdef PS
static char objectchar[] = "dQRSTUVWXYZ < ba ";
#endif
#ifdef META
char c = 0;
#endif
if (!xlabel) /* If we are inhibiting labels, then do nothing. */
return;
/* For other planet centered charts, we have to remember that that */
/* particular planet's index now represents the Earth. If we are given */
/* that index to draw, then change it so we draw the Earth instead. */
if (modex != MODES &&
((i == centerplanet && i > _MOO) || (centerplanet == 0 && i == _SUN)))
i = 0;
DrawColor(objectcolor[i]);
if (i <= BASE) {
#ifdef PS
if (psfile && xfont == 1 && objectchar[i] != ' ') {
PSfont(2);
fprintf(psdata, "%d %d(%c)center\n", x, y, objectchar[i]);
return;
}
#endif
#ifdef META
if (metafile && xfont == 1) {
if (i < _SUN)
c = ';';
else if (i <= _PLU) c = 'Q' + i - 1;
else if (i == _NOD) c = '<';
else if (i == _MC) c = 'b';
else if (i == _ASC) c = 'a';
}
if (c) {
metafontdes = 4;
metatxtcdes = colcur;
metatxtades = 0x6 | 0x8 /* Center | Bottom */;
MetaSelect();
MetaTextOut(x, y+5*SCALE, 1);
MetaWord(MAKEWORD(c, 0));
return;
}
#endif
DrawTurtle(objectdraw[i], x, y);
/* Normally we can just go draw the glyph; however, stars don't have */
/* glyphs, so for these draw their three letter abbreviation. */
} else {
sprintf(glyph, "%c%c%c", OBJNAM(i));
DrawText(glyph, x, y, FALSE);
}
}
/* Draw the glyph of an aspect at particular coordinates on the screen. */
/* Again we either use Astrolog's turtle vector or a system Astro font. */
void DrawAspect(i, x, y)
int i, x, y;
{
#ifdef PS
static char aspectchar[] = "!\"#$'&%()+- ";
#endif
#ifdef META
char c = 0;
#endif
#ifdef PS
if (psfile && xfont == 1 && aspectchar[i-1] != ' ') {
PSfont(2);
fprintf(psdata, "%d %d(%c)center\n", x, y, aspectchar[i-1]);
return;
}
#endif
#ifdef META
if (metafile && xfont == 1) {
if (i <= _TRI)
c = '!' + i - 1;
else if (i == _SEX) c = '\'';
else if (i == _INC) c = '&';
else if (i == _SSX) c = '%';
else if (i == _SSQ) c = '(';
else if (i == _SES) c = ')';
else if (i == _QUI) c = '+';
else if (i == _BQN) c = '-';
}
if (c) {
metafontdes = 4;
metatxtcdes = colcur;
metatxtades = 0x6 | 0x8 /* Center | Bottom */;
MetaSelect();
MetaTextOut(x, y+5*SCALE, 1);
MetaWord(MAKEWORD(c, 0));
return;
}
#endif
DrawTurtle(aspectdraw[i], x, y);
}
/* Convert a string segment to a positive number, updating the string to */
/* point beyond the number chars. Return 1 if the string doesn't point to */
/* a numeric value. This is used by the DrawTurtle() routine to extract */
/* motion vector quantities from draw strings, e.g. the "12" in "U12". */
int IntInString(str)
char **str;
{
int num = 0, i = 0;
loop {
if (**str < '0' || **str > '9')
return num > 0 ? num : (i < 1 ? 1 : 0);
num = num*10+(**str)-'0';
(*str)++;
i++;
}
}
/* This routine is used to draw complicated objects composed of lots of line */
/* segments on the screen, such as all the glyphs and coastline pieces. It */
/* is passed in a string of commands defining what to draw in relative */
/* coordinates. This is a copy of the format of the BASIC draw command found */
/* in PC's. For example, "U5R10D5L10" means go up 5 dots, right 10, down 5, */
/* and left 10 - draw a box twice as wide as it is high. */
void DrawTurtle(lin, x0, y0)
char *lin;
int x0, y0;
{
int i, j, x, y, deltax, deltay, blank, noupdate;
char cmd;
turtlex = x0; turtley = y0;
while (cmd = CAP(*lin)) {
lin++;
/* 'B' prefixing a command means just move the cursor, and don't draw. */
if (blank = cmd == 'B') {
cmd = CAP(*lin);
lin++;
}
/* 'N' prefixing a command means don't update cursor when done drawing. */
if (noupdate = cmd == 'N') {
cmd = CAP(*lin);
lin++;
}
/* Here we process the eight directional commands. */
switch (cmd) {
case 'U': deltax = 0; deltay = -1; break; /* Up */
case 'D': deltax = 0; deltay = 1; break; /* Down */
case 'L': deltax = -1; deltay = 0; break; /* Left */
case 'R': deltax = 1; deltay = 0; break; /* Right */
case 'E': deltax = 1; deltay = -1; break; /* NorthEast */
case 'F': deltax = 1; deltay = 1; break; /* SouthEast */
case 'G': deltax = -1; deltay = 1; break; /* SouthWest */
case 'H': deltax = -1; deltay = -1; break; /* NorthWest */
default: PrintError("Bad turtle subcommand."); /* Shouldn't happen. */
}
x = turtlex;
y = turtley;
j = IntInString(&lin)*SCALE; /* Figure out how far to draw. */
if (blank) {
turtlex += deltax*j;
turtley += deltay*j;
} else {
if (psfile || metafile) {
turtlex += deltax*j;
turtley += deltay*j;
DrawLine(x, y, turtlex, turtley);
} else {
DrawPoint(turtlex, turtley);
for (i = 0; i < j; i++) {
turtlex += deltax;
turtley += deltay;
DrawPoint(turtlex, turtley);
}
}
if (noupdate) {
turtlex = x;
turtley = y;
}
}
}
}
#endif /* GRAPH */
/* xgeneral.c */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -