home *** CD-ROM | disk | FTP | other *** search
-
- #include <X11/Xlib.h>
- #include <X11/Xutil.h>
- #include <X11/Xos.h>
- #include <sys/types.h>
- #include <sys/time.h>
- #include <sys/resource.h>
- #include <sys/param.h>
- #include <termio.h>
- #include <stdio.h>
- #include <strings.h>
- #include "mb.h"
- #include "cmap.h"
- #include "misc.h"
- #include "pix.h"
-
- #ifdef USE_NETWORK
- #include "ipc.h"
- #endif
-
- #define GEOM_PLACE 1
- #define GEOM_RIGHT 2
- #define GEOM_DOWN 4
- #define GEOM_SIZE 8
- #define GEOM_ERROR 16
-
- /* Just to make sure that the number of colors will be reasonable
- * on a 24-bit true-color display ;)
- */
- #define MAXCOLORS 1024
-
- /* dummy procedure for XCheckIfEvent */
- Bool dummy() {return(1);}
-
- #ifdef USE_NETWORK
- /* Terminology: server is the one who shows pictures, and
- * clients do the calculations.
- */
-
- #define MODE_STANDALONE 0
- #define MODE_SERVER 1
- #define MODE_CLIENT 2
-
- #define RSHCMD "rsh %s \"xnetmb -nice 10 -port %d -server %s&\" </dev/null >/dev/null"
- #endif
-
- static Display *display;
- static int screen;
- static Window win= 0, cwin= 0;
- static GC gc, gc_inv, gc_set, gc_clear;
- #ifdef USE_NETWORK
- static int mode= MODE_STANDALONE;
- static int portnum= DEF_PORT;
- static char *server;
- #endif
-
- void DrawSplitImage();
- void CalcImage();
- void DrawImage();
- void DrawRect();
- #define EraseRect() DrawRect(0, 0,0, 0,0, 0,0);
-
- static double xc= 0.0, yc= 0.0, cx= 0.0, cy= 0.0, d= 0.0, scale= 8.0;
- static int iter= 500, flags= 0;
- unsigned int width= 300, height= 300;
-
-
- int ParseComplex(string, x, y)
- char *string;
- double *x, *y;
- {
- char ii, sign;
- /* x+-yi */
- if (sscanf(string, "%lf%lf%c", x, y, &ii) == 3 &&
- ii == 'i')
- ;
- /* x+-iy */
- else if (sscanf(string, "%lf%ci%lf", x, &sign, y) == 3 &&
- (sign == '+' || sign == '-')) {
- if (sign == '-') *y = -*y;
- }
- /* x+-i */
- else if (sscanf(string, "%lf%c%c", x, &sign, &ii) == 3 &&
- (sign == '+' || sign == '-') && ii == 'i') {
- if (sign == '-')
- *y= -1.0;
- else
- *y= 1.0;
- }
- /* +-iy */
- else if (sscanf(string, "%c%c%lf", &ii, &sign, y) == 3 &&
- (sign == '+' || sign == '-') && ii == 'i') {
- *x= 0.0;
- if (sign == '-')
- *y= -*y;
- }
- /* yi */
- else if (sscanf(string, "%lf%c", y, &ii) == 2 && ii == 'i')
- *x= 0.0;
- /* iy */
- else if (sscanf(string, "%c%lf", &ii, y) == 2 && ii == 'i')
- *x= 0.0;
- /* +-i */
- else if (sscanf(string, "%c%c", &sign, &ii) == 2 &&
- (sign == '-' || sign == '+') && ii == 'i') {
- *x= 0.0;
- if (sign == '-')
- *y= -1.0;
- else
- *y= 1.0;
- }
- /* i */
- else if (sscanf(string, "%c", &ii) == 1 && ii == 'i') {
- *x= 0.0;
- *y= 1.0;
- }
- /* x */
- else if (sscanf(string, "%lf", x) == 1)
- *y= 0.0;
- else
- return(0);
- return(1);
- }
-
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- XSizeHints size_hints;
- XEvent event;
- XGCValues gcval;
- XWindowAttributes xwattr;
- XSetWindowAttributes xswattr;
- unsigned int border_width= 1;
- unsigned int display_width, display_height;
- int win_x= 0, win_y= 0;
- int cwin_x= 0, cwin_y= 0;
- int dragx, dragy;
- int buttonpressed;
- int ncolors= 0;
- int zebra= 0;
- double xstore1= xc, ystore1= yc, scalestore1= scale;
- double xstore2= xc, ystore2= yc, scalestore2= scale;
- int flagstore= flags;
- int wingeom= 0;
- char **mach;
- int nmach= 0;
- char *window_name= "XMandelbrot";
- char *icon_name= "XMandel";
- char *cwindow_name= "MBcolors";
- char *cicon_name= "MBcolors";
- char *display_name= NULL;
-
- int i;
-
- /* Command line options... boring.
- * (OH NO, it is my pseudo-intelligent commenting style attack again.
- * Sigh... Please be patient and hope for the best.)
- */
- for (i= 1; i < argc; i++) {
- if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "-display")) {
- if (++i >= argc) {
- fprintf(stderr, "%s: error in cmd line option 'display'\n",
- argv[0]);
- exit(1);
- }
- display_name= argv[i];
- }
-
- else if (!strcmp(argv[i], "-g") || !strcmp(argv[i], "-geometry")) {
- char sign1, sign2;
- if (++i >= argc) {
- fprintf(stderr, "%s: error in cmd line option 'geometry'\n",
- argv[0]);
- exit(1);
- }
- switch (sscanf(argv[i], "%ux%u%c%d%c%d",
- &width, &height, &sign1, &win_x, &sign2, &win_y)) {
- case 6:
- wingeom= GEOM_PLACE | GEOM_SIZE;
- if (sign1 == '-') wingeom |= GEOM_RIGHT;
- else if (sign1 != '+') wingeom |= GEOM_ERROR;
- if (sign2 == '-') wingeom |= GEOM_DOWN;
- else if (sign2 != '+') wingeom |= GEOM_ERROR;
- if (wingeom & GEOM_ERROR) {
- fprintf(stderr,
- "%s: error in cmd line option 'geometry'\n",
- argv[0]);
- exit(1);
- }
- break;
- case 2:
- wingeom= GEOM_SIZE;
- /* There is nothing else here to be done. */
- break;
- default:
- fprintf(stderr, "%s: error in cmd line option 'geometry'\n",
- argv[0]);
- exit(1);
- }
- }
-
- else if (!strcmp(argv[i], "-z") || !strcmp(argv[i], "-zebra")) {
- /* Need to know which of the two -z options this is... */
- if (!strcmp(argv[i], "-z") && i+1 < argc &&
- ParseComplex(argv[i+1], &xc, &yc)) {
- i++;
- xstore1= xc; ystore1= yc;
- }
- else
- zebra= 1;
- }
-
- else if (!strcmp(argv[i], "-n") || !strcmp(argv[i], "-nice")) {
- if (++i >= argc) {
- fprintf(stderr, "%s: error in cmd line option 'nice'\n",
- argv[0]);
- exit(1);
- }
- setpriority(PRIO_PROCESS,getpid(), atoi(argv[i]));
- }
-
- else if (!strcmp(argv[i], "-i") || !strcmp(argv[i], "-iters")) {
- if (++i >= argc) {
- fprintf(stderr, "%s: error in cmd line option 'iters'\n",
- argv[0]);
- exit(1);
- }
- iter= atoi(argv[i]);
- }
-
- else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "-colors")) {
- if (++i >= argc) {
- fprintf(stderr, "%s: error in cmd line option 'colors\n",
- argv[0]);
- exit(1);
- }
- ncolors= atoi(argv[i]);
- if (ncolors < 2)
- ncolors= 2;
- }
-
- else if (!strcmp(argv[i], "-j")) {
- if (++i >= argc || !ParseComplex(argv[i], &cx, &cy)) {
- fprintf(stderr, "%s: error in cmd line option 'j'\n",
- argv[0]);
- exit(1);
- }
- flagstore = (flags |= JULIA);
- }
-
- else if (!strcmp(argv[i], "-x")) {
- if (++i >= argc || sscanf(argv[i], "%lf", &scale) < 1) {
- fprintf(stderr, "%s: error in cmd line option 'x'\n",
- argv[0]);
- exit(1);
- }
- scalestore1 = (scale *= 2);
- }
-
- #ifdef USE_NETWORK
- else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "-server")) {
- int k;
- if (++i >= argc || mode != MODE_STANDALONE) {
- fprintf(stderr, "%s: error in cmd line option 'server'\n",
- argv[0]);
- exit(1);
- }
- /* We are the client, and server is specified here. */
- mode= MODE_CLIENT;
- server= argv[i];
- /* daemon */
- for (k= getdtablesize() - 1; k >= 0; --k)
- close(k);
- k= open("/dev/null", O_RDONLY);
- if (k >= 0) {
- ioctl(k, TIOCNOTTY, 0);
- close(k);
- }
- }
- #endif
-
- #ifdef USE_NETWORK
- else if (!strcmp(argv[i], "-p") || !strcmp(argv[i], "-port")) {
- if (++i >= argc) {
- fprintf(stderr, "%s: error in cmd line option 'iters'\n",
- argv[0]);
- exit(1);
- }
- portnum= atoi(argv[i]);
- }
- #endif
-
- #ifdef USE_NETWORK
- else if (!strcmp(argv[i], "-m") || !strcmp(argv[i], "-machines")) {
- if (mode != MODE_STANDALONE) {
- fprintf(stderr, "%s: error in command line option 'machines'\n",
- argv[0]);
- exit(1);
- }
-
- mode= MODE_SERVER;
- mach= &argv[i+1];
- while (++i < argc && argv[i][0] != '-')
- nmach++;
- --i;
- }
- #endif
-
- else if (!strcmp(argv[i], "-guru")) {
- if (++i >= argc) {
- fprintf(stderr, "%s: You are not a guru.\n", argv[0]);
- exit(1);
- }
- if (!strcmp(argv[i], "fast")) {
- flagstore= (flags |= FAST);
- }
- else {
- fprintf(stderr, "%s: You are not a guru.\n", argv[0]);
- exit(1);
- }
- }
-
- else {
- fprintf(stderr, "%s: unrecognized cmd line option '%s'\n\n",
- argv[0], argv[i]);
- fprintf(stderr,
- "Usage: %s -display <name> -geometry <geometry>\n",
- argv[0]);
- fprintf(stderr,
- "-zebra -nice <value> -iters <i> -colors <number>\n");
- fprintf(stderr,
- "-z <x+yi> -j <cx+cyi> -x <scale>\n");
- #ifdef USE_NETWORK
- fprintf(stderr,
- "-server <name> -port <port> -machines [list of rsh machines]\n");
- #endif
- fprintf(stderr, "\nAll options may be abbreviated.\n\n");
- exit(1);
- }
- } /* for */
-
- #ifdef USE_NETWORK
- if (mode == MODE_CLIENT) {
- Client_run(server, portnum);
- exit(0);
- }
- else if (mode == MODE_SERVER) {
- char cmd[sizeof(RSHCMD) + 2*MAXHOSTNAMELEN], host[MAXHOSTNAMELEN];
- if (gethostname(host, MAXHOSTNAMELEN) < 0) {
- perror("unable to find my name");
- exit(1);
- }
- CreateServer(portnum);
- printf("Starting remote machines:");
- for (i= 0; i < nmach; i++) {
- sprintf(cmd, RSHCMD, mach[i], portnum, host);
- printf (" %s", mach[i]); fflush(stdout);
- if ((system(cmd) >> 8) > 0) {
- fprintf(stderr, "%s: unable to rsh %s\n", argv[0],
- mach[i]);
- }
- }
- --i;
- putchar('\n');
- }
- #endif
-
- /* Open the display, if possible. */
- if(!(display= XOpenDisplay(display_name))) {
- fprintf(stderr, "cannot reach X server %s\n",
- XDisplayName(display_name));
- exit(1);
- }
-
- screen= DefaultScreen(display);
-
- display_width= DisplayWidth(display, screen);
- display_height= DisplayHeight(display, screen);
-
- if (!(wingeom & GEOM_PLACE)) {
- win_x= display_width / 2 - (int)width;
- win_y= 2 * display_height / 3;
- }
- else {
- if (wingeom & GEOM_RIGHT) win_x= (int)display_width - win_x - (int)width;
- if (wingeom & GEOM_DOWN) win_y= (int)display_height - win_y - (int)height;
- }
-
- cwin_x= display_width / 2 - 200;
- cwin_y= display_height - 250;
-
-
- if (ncolors == 0)
- ncolors= 1 << (DefaultDepth(display, screen));
- if (zebra) ncolors= 3;
- if (ncolors > MAXCOLORS)
- ncolors= MAXCOLORS;
- SetNColors(ncolors);
-
- xswattr.background_pixel= WhitePixel(display, screen);
- xswattr.border_pixel= BlackPixel(display, screen);
- win= XCreateWindow(display, RootWindow(display, screen), win_x, win_y,
- width, height, border_width, CopyFromParent,
- InputOutput, CopyFromParent,
- CWBackPixel | CWBorderPixel, &xswattr);
- cwin= XCreateWindow(display, RootWindow(display, screen), cwin_x, cwin_y,
- 400, 200, border_width, CopyFromParent,
- InputOutput, CopyFromParent,
- CWBackPixel | CWBorderPixel, &xswattr);
-
- if (!win || !cwin) {
- #ifdef USE_NETWORK
- if (mode == MODE_SERVER)
- CloseDown();
- #endif
- perror("could not open window");
- myExit();
- exit(0);
- }
-
- size_hints.flags= PMinSize;
- if (wingeom & GEOM_PLACE) size_hints.flags |= PPosition;
- if (wingeom & GEOM_SIZE) size_hints.flags |= PSize;
-
- size_hints.width= width;
- size_hints.height= height;
- size_hints.min_width= 50;
- size_hints.min_height= 50;
- size_hints.x= win_x;
- size_hints.y= win_y;
- XSetStandardProperties(display, win, window_name, icon_name,
- None, NULL, 0, &size_hints);
-
- size_hints.flags= PPosition | PSize | PMinSize;
- size_hints.width= 400;
- size_hints.height= 200;
- size_hints.min_width= 200;
- size_hints.min_height= 100;
- size_hints.x= cwin_x;
- size_hints.y= cwin_y;
- XSetStandardProperties(display, cwin, cwindow_name, cicon_name,
- None, NULL, 0, &size_hints);
-
- XSelectInput(display, win, ExposureMask | KeyPressMask |
- ButtonPressMask | ButtonReleaseMask |
- PointerMotionMask | StructureNotifyMask);
- XSelectInput(display, cwin, ExposureMask | KeyPressMask |
- ButtonPressMask | ButtonReleaseMask |
- PointerMotionMask | StructureNotifyMask);
-
- gcval.foreground= BlackPixel(display, screen);
- gcval.background= WhitePixel(display, screen);
- gc= XCreateGC(display, win, GCForeground | GCBackground, &gcval);
- gc_set= XCreateGC(display, win, GCForeground | GCBackground, &gcval);
-
- gcval.foreground= WhitePixel(display, screen);
- gc_clear= XCreateGC(display, win, GCForeground | GCBackground, &gcval);
-
- gcval.function= GXinvert;
- gc_inv= XCreateGC(display, win, GCFunction, &gcval);
-
- if (!AllocFonts(display, gc_set)) {
- fprintf(stderr, "Could not open fonts... no text will be drawn");
- }
- AllocColors(display, screen);
-
- AllocCursors(display);
- NormalCursor(display, win);
- NormalCursor(display, cwin);
-
- XMapWindow(display, win);
- buttonpressed= 0;
-
- for (;;) {
- #ifdef USE_NETWORK
- if (mode == MODE_SERVER)
- CheckClients(NOBLOCK);
-
- if (mode == MODE_SERVER && PendingRequests()) {
- while (!XCheckIfEvent(display, &event, dummy, (char *)NULL))
- CheckClients(1);
- if (!PendingRequests()) {
- NormalCursor(display, win);
- NormalCursor(display, cwin);
- }
- }
- else
- XNextEvent(display, &event);
- #else
- XNextEvent(display, &event);
- #endif
-
- if (event.xany.window == cwin) {
- switch (HandleCEvent(display, screen, cwin, gc,
- gc_set, gc_clear, &event)) {
- case DO_REDRAW:
- #ifdef USE_NETWORK
- if (mode == MODE_SERVER) Invalidate();
- #endif
- XClearArea(display, win, 0, 0, width, height, 1);
- break;
- case DO_PREVIOUS:
- if (xc != xstore1 || yc != ystore1 ||
- scale != scalestore1 || flags != flagstore) {
- xc= xstore1; yc= ystore1;
- scale= scalestore1;
- flags= flagstore;
- d= scale / (width + height);
- #ifdef USE_NETWORK
- if (mode == MODE_SERVER) Invalidate();
- #endif
- XClearArea(display, win, 0, 0, width, height, 1);
- }
- break;
- case DO_RESTART:
- xstore1= xc; ystore1= yc;
- scalestore1= scale;
- flagstore= flags;
-
- xc= 0.0; yc= 0.0;
- scale= 8.0; flags &= ~JULIA;
- d= scale / (width + height);
- #ifdef USE_NETWORK
- if (mode == MODE_SERVER) Invalidate();
- #endif
- XClearArea(display, win, 0, 0, width, height, 1);
- break;
-
- case DO_QUIT:
- #ifdef USE_NETWORK
- if (mode == MODE_SERVER)
- CloseDown();
- #endif
- myExit();
- exit(0);
- } /* switch */
- }
- else switch(event.type) {
- case Expose:
- WaitCursor(display, win);
- WaitCursor(display, cwin);
- CalcImage (event.xexpose.x, event.xexpose.y,
- event.xexpose.width, event.xexpose.height);
- break;
-
- case ConfigureNotify:
- #ifdef USE_NETWORK
- if (mode == MODE_SERVER) {
- if (width != event.xconfigure.width ||
- height != event.xconfigure.height)
- Invalidate();
- }
- #endif
- width= event.xconfigure.width;
- height= event.xconfigure.height;
- d= scale / (width + height);
- break;
-
- case ButtonPress:
- switch (event.xbutton.button) {
- case 1:
- ZoomCursor(display, win);
- dragx= event.xbutton.x;
- dragy= event.xbutton.y;
- buttonpressed= 1;
- break;
-
- case 2: /* julia stuff here */
- if (buttonpressed) {
- EraseRect();
- buttonpressed= 0;
- NormalCursor(display, win);
- }
- else if (!(flags & JULIA)) {
- /* toggle to julia set; save current context */
- xstore1= xstore2= xc; ystore1= ystore2= yc;
- scalestore1= scalestore2= scale;
- flagstore= flags;
-
- flags |= JULIA;
- cx= xc - d * (width/2.0 - event.xbutton.x);
- cy= yc + d * (height/2.0 - event.xbutton.y);
- xc= 0.0; yc= 0.0;
- scale= 8.0;
- d= scale / (width + height);
- #ifdef USE_NETWORK
- if (mode == MODE_SERVER) Invalidate();
- #endif
- XClearArea(display, win, 0, 0, width, height, 1);
- }
- else {
- /* toggle to mb set; restore context */
- xc= xstore2; yc= ystore2;
- scale= scalestore2;
- flags &= ~JULIA;
- d= scale / (width + height);
- #ifdef USE_NETWORK
- if (mode == MODE_SERVER) Invalidate();
- #endif
- XClearArea(display, win, 0, 0, width, height, 1);
- }
- break;
-
- case 3: /* open colormap window */
- if (buttonpressed) {
- EraseRect();
- buttonpressed= 0;
- NormalCursor(display, win);
- }
- else
- ToggleCWin(display, cwin, CMAP_TOGGLE);
- break;
- default:
- break;
- }
- break;
-
- case ButtonRelease:
- switch (event.xbutton.button) {
- case 1:
- if (buttonpressed) {
- int xdiff, ydiff;
- xstore1= xc; ystore1= yc;
- scalestore1= scale;
- flagstore= flags;
-
- xdiff= dragx - event.xbutton.x;
- ydiff= dragy - event.xbutton.y;
- if (xdiff < 0) xdiff= -xdiff;
- if (ydiff < 0) ydiff= -ydiff;
- if (xdiff/(double)width < ydiff/(double)height)
- scale *= (ydiff/(double)height);
- else
- scale *= (xdiff/(double)width);
- buttonpressed= 0;
- EraseRect();
-
- xc= xc - d * ((int)width - (dragx + event.xbutton.x)) / 2.0;
- yc= yc + d * ((int)height - (dragy + event.xbutton.y)) / 2.0;
- d= scale / (width + height);
- #ifdef USE_NETWORK
- if (mode == MODE_SERVER) Invalidate();
- #endif
- XClearArea(display, win, 0, 0, width, height, 1);
- }
- default:
- break;
- }
- break;
-
- case MotionNotify:
- if (buttonpressed)
- DrawRect(1, dragx, dragy, event.xmotion.x, event.xmotion.y,
- (int)width, (int)height);
- break;
-
- case KeyPress:
- #ifdef USE_NETWORK
- if (mode == MODE_SERVER)
- CloseDown();
- #endif
- myExit();
- exit(0);
-
- case MapNotify:
- /* Determine size of set (depends on width & height) */
- XGetWindowAttributes(display, win, &xwattr);
- width= xwattr.width; height= xwattr.height;
- d= scale / (width + height);
- break;
-
- case ReparentNotify:
- case UnmapNotify:
- /* I can't think of anything reasonable to do here... */
- break;
-
- default:
- printf("Unknown Event %d\n", event.type);
- break;
- } /* switch */
- } /* for(ever) */
- } /* main */
-
-
- myExit()
- {
- FreeFonts(display);
- XFreeGC(display, gc);
- XFreeGC(display, gc_inv);
- XFreeGC(display, gc_set);
- XFreeGC(display, gc_clear);
-
- FreeColors(display, screen);
- if (win) XDestroyWindow(display, win);
- if (cwin) XDestroyWindow(display, cwin);
- XCloseDisplay(display);
- }
-
-
- /* Split the image into comfortably small chunks, which
- * are then fed to DrawSplitImage()
- */
- void CalcImage(xoff, yoff, w, h)
- int xoff, yoff, w, h;
- {
- int xd=1, yd=1, xn, yn;
- /* do not accidentally crawl arond some area...
- */
- if (xc - d*(width/2.0 - xoff) < -.5 &&
- yc + d*(height/2.0 - yoff) > .5 &&
- xc - d*(width/2.0 - xoff-w) > .5 &&
- yc + d*(height/2.0 - yoff-h) < -.5) {
- int x0= width/2 - xc/d;
- int y0= height/2 + yc/d;
- int xdist= x0 - xoff;
- int ydist= y0 - yoff;
- if (w > 2*xdist) xdist= w-xdist;
- if (h > 2*ydist) ydist= h-ydist;
- if (xdist > ydist) {
- CalcImage(xoff, yoff, x0-xoff, h);
- CalcImage(x0, yoff, w-(x0-xoff), h);
- }
- else {
- CalcImage(xoff, yoff, w, y0-yoff);
- CalcImage(xoff, y0, w, h-(y0-yoff));
- }
- return;
- } /* if */
- while (w*h/(xd*yd) > 65536) {
- if (w*yd < h*xd) /* <==> w/xd<h/yd */
- yd++;
- else
- xd++;
- }
- for (yn= 0; yn < yd; yn++)
- for (xn= 0; xn < xd; xn++) {
- DrawSplitImage(xoff + xn*w/xd, yoff+yn*h/yd,
- (xn+1)*w/xd - xn*w/xd,
- (yn+1)*h/yd - yn*h/yd);
- }
- #ifdef USE_NETWORK
- if (mode == MODE_STANDALONE || !PendingRequests() ) {
- NormalCursor(display, win);
- NormalCursor(display, cwin);
- }
- #else
- NormalCursor(display, win);
- NormalCursor(display, cwin);
- #endif
- }
-
-
- /* Calculate chunks either in local or in remote machines
- */
- void DrawSplitImage(xoff, yoff, w, h)
- int xoff, yoff, w, h;
- {
- double x,y;
- u_short *dest;
- int tmpflags;
-
- x= xc - d*(width/2.0 - xoff);
- y= yc + d*(height/2.0 - yoff);
-
- XDrawRectangle(display, win, gc_set, xoff, yoff, w-1, h-1);
- XFlush(display);
-
- #ifdef USE_NETWORK
- if (mode == MODE_SERVER) {
- /* Try to delegate */
- if (CalcRequest(x, y, d, d, cx, cy, w, h, iter, flags, xoff, yoff))
- return;
- }
- #endif
- /* Always use FASTmode when using local machine */
- tmpflags= flags;
- flags |= FAST;
- iterate(x, y, d, d, cx, cy, w, h, iter, flags, &dest);
- DrawImage(xoff, yoff, w, h, dest);
- flags= tmpflags;
- }
-
-
- void DrawImage(xoff, yoff, w, h, dest)
- int xoff, yoff, w, h;
- u_short *dest;
- {
- int px, py;
- u_short *ptr, color;
- long len, i;
- XGCValues gcval;
- XPoint *xpts;
- long npts= 512;
- int fastmode= flags & FAST;
-
- ptr= dest;
- xpts= (XPoint *)malloc(npts * sizeof(XPoint));
-
- if (!fastmode)
- initialize(w, h);
- for (;;) {
- /* In fast mode, first_point() and next_point() are omitted.
- * Server will be faster but there will be over 100% more traffic
- * in the net.
- */
- if (fastmode) {
- px= *ptr++;
- if (px != LASTPIX)
- py= *ptr++;
- }
- if (fastmode && px == LASTPIX)
- break;
- if (!fastmode && first_point(&px, &py) ==0)
- break;
- color= *ptr++;
- gcval.foreground= ToPixel((int)(color & 0x7fff));
- XChangeGC(display, gc, GCForeground, &gcval);
-
- if (color & 0x8000) {
- XDrawPoint(display, win, gc, px+xoff, py+yoff);
- }
- else {
- int dir, bitindex= 7;
-
- len= *ptr++;
- if (len > npts) {
- free(xpts);
- xpts= (XPoint *)malloc((npts= len) * sizeof(XPoint));
- }
- for (i= 0; i < len; i++) {
- dir= ((*ptr) >> (bitindex*2)) & 3;
- if (!fastmode)
- next_point(dir);
-
- XDrawPoint(display, win, gc, px+xoff, py+yoff);
- xpts[i].x= px+xoff;
- xpts[i].y= py+yoff;
- switch (dir) {
- case UP: py--; break;
- case DOWN: py++; break;
- case LEFT: px--; break;
- case RIGHT: px++; break;
- }
- if (--bitindex < 0) {
- ptr++;
- bitindex= 7;
- }
- }
- if (bitindex != 7)
- ptr++;
- XFillPolygon(display, win, gc, xpts, len, Complex, CoordModeOrigin);
- } /* else */
- } /* for */
- if (!fastmode)
- deinit();
- free(dest);
- free(xpts);
- } /* DrawImage */
-
-
- void DrawRect(mode, x1, y1, x2, y2, w, h)
- int mode, x1, y1, x2, y2, w, h;
- {
- static int drawn= 0;
- static int dx, dy, dw, dh;
-
- if (drawn)
- XDrawRectangle(display, win, gc_inv, dx, dy, dw, dh);
- drawn= 0;
-
- if (mode == 0)
- return;
-
- dw= x2 - x1; dh= y2 - y1;
- if (dw == 0 && dh == 0)
- return;
-
- dx= x1; dy= y1;
- if (dw < 0) {
- dw= -dw;
- dx= x2;
- }
- if (dh < 0) {
- dh= -dh;
- dy= y2;
- }
-
- if (dw/(double)w > dh/(double)h) {
- dh= dw * (h/(double)w);
- dy= (y1 + y2 - dh)/2;
- }
- else {
- dw= dh * (w/(double)h);
- dx= (x1 + x2 - dw)/2;
- }
- XDrawRectangle(display, win, gc_inv, dx, dy, dw, dh);
- drawn= 1;
- } /* drawrect */
-
-