📄 xgeneral.c
字号:
MetaWord(MAKEWORD(0 /* Strikeout */, C)); \
MetaWord(MAKEWORD(4 /* TrueType */, 0 /* Clip */))
#define MetaBkMode(M) MetaRecord(4, 0x102); MetaWord(M)
#define MetaTextAlign(A) MetaRecord(4, 0x12E); MetaWord(A)
#define MetaTextColor(C) MetaRecord(5, 0x209); MetaLong(C);
#define MetaTextOut(X, Y, S) MetaRecord(7+((S)+1)/2, 0xA32); \
MetaWord(Y); MetaWord(X); MetaWord(S); MetaWord(0 /* ETO */)
#define MetaRectangle(X1, Y1, X2, Y2) MetaRecord(7, 0x41B); \
MetaWord(Y2); MetaWord(X2); MetaWord(Y1); MetaWord(X1)
#define MetaEllipse(X1, Y1, X2, Y2) MetaRecord(7, 0x418); \
MetaWord(Y2); MetaWord(X2); MetaWord(Y1); MetaWord(X1)
#define MetaEscape(S) MetaRecord((S), 0x626); \
MetaWord(15 /* MFCOMMENT */); MetaWord(((S)-5)*2 /* Bytes in comment */);
/* Output one 16 bit or 32 bit value into the metafile buffer stream. */
void MetaWord(w)
word w;
{
if ((byte PTR)metacur - bm >= MAXMETA) {
PrintError("Metafile would be more than %ld bytes.", MAXMETA);
Terminate(_FATAL);
}
*metacur = w;
metacur++;
}
void MetaLong(l)
long l;
{
MetaWord(LOWORD(l));
MetaWord(HIWORD(l));
}
/* Output any necessary metafile records to make the current actual */
/* settings of line color, fill color, etc, be those that we know are */
/* desired. This is generally called by the primitives routines before */
/* any figure record is actually written into a metafile. We wait until */
/* the last moment before changing any settings to ensure that we don't */
/* output any unnecessary records, e.g. two select colors in a row. */
void MetaSelect()
{
if (metalinedes != metalineact) {
MetaSelectObject(metalinedes);
metalineact = metalinedes;
}
if (metafilldes != metafillact) {
MetaSelectObject(16*4 + metafilldes);
metafillact = metafilldes;
}
if (metafontdes != metafontact) {
MetaSelectObject(16*5 + metafontdes);
metafontact = metafontdes;
}
if (metatxtcdes != metatxtcact) {
MetaTextColor(rgbbmp[metatxtcdes]);
metatxtcact = metatxtcdes;
}
if (metatxtades != metatxtaact) {
MetaTextAlign(metatxtades);
metatxtaact = metatxtades;
}
xpen = -1; /* Invalidate PolyLine cache */
}
/* Output initial metafile header information into our metafile buffer. */
/* We also setup and create all pen, brush, and font objects that may */
/* possibly be used in the generation and playing of the picture. */
void MetaInit()
{
int i, j, k;
metacur = (word PTR)bm;
/* Placable Metaheader */
MetaLong(0x9AC6CDD7L);
MetaWord(0); /* Not used */
MetaWord(0); MetaWord(0);
MetaWord(chartx); MetaWord(charty);
MetaWord(chartx/6); /* Units per inch */
MetaLong(0L); /* Not used */
MetaWord(0x9AC6 ^ 0xCDD7 ^ chartx ^ charty ^ chartx/6); /* Checksum */
/* Metaheader */
MetaWord(1); /* Metafile type */
MetaWord(9); /* Size of header in words */
MetaWord(0x300); /* Windows version */
MetaLong(0L); /* Size of entire metafile in words */
MetaWord(16*5+1+(xfont>0)*4); /* Number of objects in metafile */
MetaLong(17L); /* Size of largest record in words */
MetaWord(0); /* Not used */
/* Setup */
MetaEscape(17);
MetaLong(MAKEQUAD('A', 's', 't', 'r')); /* "Astr" */
MetaWord(4); /* Creator */
MetaLong(14L); /* Bytes in string */
MetaLong(MAKEQUAD('A', 's', 't', 'r')); /* "Astr" */
MetaLong(MAKEQUAD('o', 'l', 'o', 'g')); /* "olog" */
MetaLong(MAKEQUAD(' ', '4', '.', '0')); /* " 3.2" */
MetaWord(MAKEWORD('0', 0)); /* "0" */
MetaSaveDc();
MetaWindowOrg(0, 0);
MetaWindowExt(chartx, charty);
MetaBkMode(1 /* Transparent */);
/* Colors */
for (j = 1; j <= 4; j++)
for (i = 0; i < 16; i++) {
k = j <= 1 ? metawid : 0;
MetaCreatePen(j <= 2 ? 0 : j-2 /* PS_SOLID; PS_DASH; PS_DOT */,
k, rgbbmp[i]);
}
for (i = 0; i < 16; i++) {
MetaCreateBrush(0 /* BS_SOLID */, rgbbmp[i]);
}
MetaCreateBrush(1 /* BS_NULL */, 0L);
/* Fonts */
if (xfont) {
MetaCreateFont(5, 0, -8*SCALE, 2 /* Symbol Charset */);
MetaWord(MAKEWORD(1 /* Draft */, 1 | 0x10 /* Fixed | Roman */));
MetaLong(MAKEQUAD('W', 'i', 'n', 'g'));
MetaLong(MAKEQUAD('d', 'i', 'n', 'g'));
MetaWord(MAKEWORD('s', 0));
MetaCreateFont(8, 0, -6*SCALE, 0 /* Ansi Charset */);
MetaWord(MAKEWORD(0 /* Default */, 2 | 0x10 /* Variable | Roman */));
MetaLong(MAKEQUAD('T', 'i', 'm', 'e'));
MetaLong(MAKEQUAD('s', ' ', 'N', 'e'));
MetaLong(MAKEQUAD('w', ' ', 'R', 'o'));
MetaLong(MAKEQUAD('m', 'a', 'n', 0));
MetaCreateFont(6, 6*METAMUL, 10*METAMUL, 0 /* Ansi Charset */);
MetaWord(MAKEWORD(1 /* Draft */, 1 | 0x30 /* Fixed | Modern */));
MetaLong(MAKEQUAD('C', 'o', 'u', 'r'));
MetaLong(MAKEQUAD('i', 'e', 'r', ' '));
MetaLong(MAKEQUAD('N', 'e', 'w', 0));
MetaCreateFont(8, 0, -11*SCALE, 0 /* Ansi Charset */);
MetaWord(MAKEWORD(0 /* Default */, 2 | 0 /* Variable | Don't Care */));
MetaLong(MAKEQUAD('A', 's', 't', 'r'));
MetaLong(MAKEQUAD('o', '-', 'S', 'e'));
MetaLong(MAKEQUAD('m', 'i', 'B', 'o'));
MetaLong(MAKEQUAD('l', 'd', 0, 0));
}
}
/* Output trailing records to indicate the end of the metafile and then */
/* actually write out the entire buffer to the specifed file. */
void WriteMeta(data)
FILE *data;
{
word PTR w;
#if FALSE
int i;
for (i = 16*5+1+(xfont>0)*4; i >= 0; i--) {
MetaDeleteObject(i);
}
#endif
MetaRestoreDc();
MetaRecord(3, NULL); /* End record */
*(long PTR)(bm + 22 + 6) = ((long)((byte PTR)metacur - bm) - 22) / 2;
for (w = (word PTR)bm; w < metacur; w++) {
PutWord(*w);
}
}
#endif /* META */
/*
******************************************************************************
** Core Graphic Procedures.
******************************************************************************
*/
/* Set the current color to use in drawing on the screen or bitmap array. */
void DrawColor(col)
colpal col;
{
#ifdef PS
if (psfile) {
if (colcur != col) {
PSforcestroke(); /* Render existing path with current color */
fprintf(psdata, "%.2f %.2f %.2f c\n",
(real)RGBR(rgbbmp[col])/255.0, (real)RGBG(rgbbmp[col])/255.0,
(real)RGBB(rgbbmp[col])/255.0);
}
colcur = col;
return;
}
#endif
#ifdef META
if (metafile)
metalinedes = col;
#endif
#ifdef X11
else if (!xfile)
XSetForeground(disp, gc, rgbind[col]);
#endif
#ifdef MSG
else if (!xfile)
_setcolor(col);
#endif
colcur = col;
}
/* Set a single point on the screen. This is the most basic graphic function */
/* and is called by all the more complex routines. Based on what mode we are */
/* in, we either set a cell in the bitmap array or a pixel on the window. */
void DrawPoint(x, y)
int x, y;
{
if (xfile) {
if (xbitmap) {
/* Force the coordinates to be within the bounds of the bitmap array. */
if (x < 0)
x = 0;
else if (x >= chartx)
x = chartx-1;
if (y < 0)
y = 0;
else if (y >= charty)
y = charty-1;
PSET(bm, x, y, colcur);
}
#ifdef PS
else if (psfile) {
DrawColor(colcur);
PSlinecap(TRUE);
fprintf(psdata, "%d %d d\n", x, y);
PSstroke(2);
}
#endif
#ifdef META
else {
metafilldes = colcur;
MetaSelect();
MetaEllipse(x-metawid/2, y-metawid/2, x+metawid/2, y+metawid/2);
}
#endif
}
#ifdef X11
else
XDrawPoint(disp, pixmap, gc, x, y);
#endif
#ifdef MSG
else
_setpixel(offsetx + x, offsety + y);
#endif
}
/* Draw dot a little larger than just a single pixel at specified location. */
void DrawSpot(x, y)
int x, y;
{
#ifdef PS
if (psfile) {
PSlinewidth(currentlinewidth*3);
DrawPoint(x, y);
PSlinewidth(currentlinewidth/3);
return;
}
#endif
#ifdef META
if (metafile) {
metafilldes = colcur;
MetaSelect();
MetaEllipse(x-metawid, y-metawid, x+metawid, y+metawid);
return;
}
#endif
DrawPoint(x, y);
DrawPoint(x, y-1);
DrawPoint(x-1, y);
DrawPoint(x+1, y);
DrawPoint(x, y+1);
}
/* Draw a filled in block, defined by the corners of its rectangle. */
void DrawBlock(x1, y1, x2, y2)
int x1, y1, x2, y2;
{
int x, y;
if (xfile) {
if (xbitmap) {
for (y = y1; y <= y2; y++) /* For bitmap, we have to */
for (x = x1; x <= x2; x++) /* just fill in the array. */
PSET(bm, x, y, colcur);
}
#ifdef PS
else if (psfile) {
DrawColor(colcur);
fprintf(psdata, "%d %d %d %d rf\n",
x1-metawid/4, y1-metawid/4, x2-x1+metawid/4, y2-y1+metawid/4);
}
#endif
#ifdef META
else {
metafilldes = colcur;
MetaSelect();
MetaRectangle(x1-metawid/2, y1-metawid/2, x2+metawid/2, y2+metawid/2);
}
#endif
}
#ifdef X11
else
XFillRectangle(disp, pixmap, gc, x1, y1, x2, y2);
#endif
#ifdef MSG
else
_rectangle(_GFILLINTERIOR,
offsetx + x1, offsety + y1, offsetx + x2, offsety + y2);
#endif
}
/* Draw a rectangle on the screen with specified thickness. This is just */
/* like DrawBlock() except that we are only drawing the edges of the area. */
void DrawBox(x1, y1, x2, y2, xsiz, ysiz)
int x1, y1, x2, y2, xsiz, ysiz;
{
#ifdef META
if (metafile)
/* For thin boxes in metafiles, we can just output one rectangle record */
/* instead of drawing each side separately as we have to do otherwise. */
if (xsiz <= 1 && ysiz <= 1) {
metafilldes = 16; /* Specify a hollow fill brush. */
MetaSelect();
MetaRectangle(x1, y1, x2, y2);
return;
}
#endif
DrawBlock(x1, y1, x2, y1 + ysiz - 1);
DrawBlock(x1, y1 + ysiz, x1 + xsiz - 1, y2 - ysiz);
DrawBlock(x2 - xsiz + 1, y1 + ysiz, x2, y2 - ysiz);
DrawBlock(x1, y2 - ysiz + 1, x2, y2);
}
/* Clear and erase the graphics screen or bitmap contents. */
void DrawClearScreen()
{
#ifdef PS
if (psfile) {
/* For PostScript charts first output page orientation information. */
if (!epsfile) {
if (modex == MODEL || modex == MODEW ||
(modex == MODEZ && (todisplay & DASHZ0) == 0)) {
/* Chartx and charty are reversed for Landscape mode. */
fprintf(psdata, "%d %d translate\n",
((int)(8.5*72) + charty)/2, (chartx + 11*72)/2);
fprintf(psdata, "-90 rotate\n");
} else {
/* Most charts are in Portrait mode */
fprintf(psdata, "%d %d translate\n", (int)(8.5*72/2) - chartx/2,
charty/2 + 11*72/2);
}
} else
fprintf(psdata, "0 %d translate\n", charty);
fprintf(psdata, "1 -1 scale\n");
scale *= PSMUL; chartx *= PSMUL; charty *= PSMUL;
fprintf(psdata, "1 %d div dup scale\n", PSMUL);
}
#endif
#ifdef META
if (metafile)
MetaInit(); /* For metafiles first go write our header information. */
#endif
/* Hack: If a comparison relationship chart is set and we're in the -Z */
/* horizon or -S space graphics chart modes (which normally is just the */
/* same as single chart graphics) don't actually clear the screen. */
if (relation <= DASHr0 && xnow > 0 && (modex == MODEZ || modex == MODES))
return;
#ifdef MSG
if (!xfile)
_clearscreen(_GCLEARSCREEN);
#endif
DrawColor(off);
DrawBlock(0, 0, chartx - 1, charty - 1); /* Clear bitmap screen. */
}
/* Draw a line on the screen, specified by its endpoints. In addition, we */
/* have specified a skip factor, which allows us to draw dashed lines. */
void DrawDash(x1, y1, x2, y2, skip)
int x1, y1, x2, y2, skip;
{
static word PTR poly;
int x = x1, y = y1, xadd, yadd, yinc, xabs, yabs, i, j = 0;
if (skip < 0)
skip = 0;
#ifdef ISG
if (!xfile) {
if (!skip) {
#ifdef X11
/* For non-dashed X window lines, let's have the Xlib do it for us. */
XDrawLine(disp, pixmap, gc, x1, y1, x2, y2);
#else
/* For non-dashed lines, let's have the graphics library do it for us. */
_moveto(offsetx + x1, offsety + y1);
_lineto(offsetx + x2, offsety + y2);
#endif
return;
}
}
#endif /* ISG */
#ifdef PS
if (psfile) {
/* For PostScript charts we can save file size if we output a LineTo */
/* command when the start vertex is the same as the end vertex of the */
/* previous line drawn, instead of writing out both vertices. */
PSlinecap(TRUE);
PSdash(skip);
if (xpen != x1 || ypen != y1)
fprintf(psdata, "%d %d %d %d l\n", x1, y1, x2, y2);
else
fprintf(psdata, "%d %d t\n", x2, y2);
xpen = x2; ypen = y2;
PSstroke(2);
return;
}
#endif
#ifdef META
if (metafile) {
/* For metafile charts we can really save file size for consecutive */
/* lines sharing endpoints by consolidating them into a PolyLine. */
if (xpen != x1 || ypen != y1) {
metalinedes = (metalinedes & 15) + 16*(skip > 3 ? 3 : skip);
MetaSelect();
poly = metacur;
MetaRecord(8, 0x325); /* Polyline */
MetaWord(2); MetaWord(x1); MetaWord(y1);
} else {
*poly += 2;
(*(poly+3))++;
/* Note: We should technically update the max record size in the */
/* file header if need be here too, but it doesn't seem necessary. */
}
MetaWord(x2); MetaWord(y2);
xpen = x2; ypen = y2;
return;
}
#endif
/* If none of the above cases hold, we have to draw the line dot by dot. */
xadd = x2 - x1 >= 0 ? 1 : 3;
yadd = y2 - y1 >= 0 ? 2 : 4;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -