#include #include #include #include #include #include #include #include "misc.h" #define NUM_LEVELS 256 #define BORDER_WIDTH 2 #define C_WHITE 0 #define C_BLACK 1 static int x_backgroundcolor = C_WHITE, x_foregroundcolor = C_BLACK; static int x_screen, x_depth, x11plot_levels, x11plot_width, x11plot_height; static unsigned long x_blackpixel, x_whitepixel; static unsigned long x_colors[NUM_LEVELS]; static Colormap x_colormap; static Display *x_display; static XGCValues x_gcvalues; static Window x_window; static GC x_gc; extern int plot_mag; extern int x11_force_flush; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ static int create_gc(Window x_newwindow, GC *x_newgc) { *x_newgc = XCreateGC(x_display, x_newwindow, (unsigned long)0, &x_gcvalues); if(*x_newgc == 0) /* unable to create a GC */ return(0); XSetForeground(x_display, *x_newgc, x_whitepixel); XSetBackground(x_display, *x_newgc, x_blackpixel); x_backgroundcolor = C_BLACK; x_foregroundcolor = C_WHITE; return(1); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ static Window open_window(int width, int height) { XSetWindowAttributes x_windowattributes; unsigned long x_windowmask; Window x_newwindow; /* Set up the attributes for the window. */ x_windowattributes.backing_store = Always; x_windowattributes.event_mask = ButtonPressMask | ButtonReleaseMask; x_windowattributes.border_pixel = x_whitepixel; x_windowattributes.background_pixel = x_blackpixel; x_backgroundcolor = C_BLACK; x_foregroundcolor = C_WHITE; x_windowmask = CWBackingStore | CWEventMask | CWBackPixel | CWBorderPixel; x_windowattributes.override_redirect = False; x_windowmask |= CWOverrideRedirect; /* Open a window on the display */ x_newwindow = XCreateWindow(x_display, XRootWindow(x_display, x_screen), 0,0, width,height, BORDER_WIDTH, x_depth, InputOutput, CopyFromParent, x_windowmask, &x_windowattributes); XSetStandardProperties(x_display, x_newwindow, "X11plot", "X11plot", None, 0, 0, 0); /* Create a graphic context (GC) for the window, only for the first time */ if(create_gc(x_newwindow, &x_gc) == 0) { XDestroyWindow(x_display, x_newwindow); return((Window)0); } /* Ask X to place the window visibly on the screen */ XMapWindow(x_display, x_newwindow); XFlush(x_display); return(x_newwindow); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ static void int_to_hexstr(int i, char *str) { sprintf(str, "%2x", i); for(i = 0; i < 2; i++) if(str[i] == ' ') str[i] = '0'; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ static inline double hue_shift(double x) { return(x - floor(x)); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #define H2V(x) ((x)<1.0/6 ? 6*(x) : (x)<0.5 ? 1.0 : (x)<4.0/6 ? 4-6*(x) : 0.0) /* hue should go from 0 to 1. */ static void hsb_to_rgb(double hue, int *R, int *G, int *B) { double hueshift; hueshift = hue_shift(hue + 2.0/6); *R = 255 * H2V(hueshift) + 0.5; hueshift = hue_shift(hue); *G = 255 * H2V(hueshift) + 0.5; hueshift = hue_shift(hue - 2.0/6); *B = 255 * H2V(hueshift) + 0.5; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ void X11plot_init(int width, int height, int levels) { XColor x_hardwarecolor; char hexR[8], hexG[8], hexB[8], name[16], *display; int status, i, R, G, B; double hue; display = getenv("DISPLAY"); if((x_display = XOpenDisplay(display)) == NULL) { fprintf(stderr, "X11plot_init: could not open display %s.\n", XDisplayName(display)); exit(1); } x_screen = XDefaultScreen(x_display); x_depth = XDefaultDepth(x_display, x_screen); x_whitepixel = XWhitePixel(x_display, x_screen); x_blackpixel = XBlackPixel(x_display, x_screen); x_colormap = XDefaultColormap(x_display, x_screen); /* Initialize grey map */ if(x_depth == 1 || levels == 2) { /* monochrome system */ for(i = 0; i < NUM_LEVELS / 2; i++) x_colors[i] = x_blackpixel; for(i = NUM_LEVELS / 2; i < NUM_LEVELS; i++) x_colors[i] = x_whitepixel; } else { for(i = 0; i < NUM_LEVELS; i++) { if(i > 0) { hue = i / (NUM_LEVELS - 1.0); hsb_to_rgb(hue, &R, &G, &B); int_to_hexstr(R, hexR); int_to_hexstr(G, hexG); int_to_hexstr(B, hexB); sprintf(name,"#%s%s%s", hexR, hexG, hexB); status = XParseColor(x_display, x_colormap, name, &x_hardwarecolor); if (status != 0) { status = XAllocColor(x_display, x_colormap, &x_hardwarecolor); x_colors[i] = x_hardwarecolor.pixel; } else fprintf(stderr, "No such color %s\n", name); } else x_colors[i] = x_blackpixel; } } x11plot_width = width; x11plot_height = height; x11plot_levels = levels; x_window = open_window(width * plot_mag, height * plot_mag); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ void X11plot_point(int i, int j, int val) { int cval, ii, jj; val = (val < 0) ? 0 : (val >= x11plot_levels) ? x11plot_levels - 1: val; cval = ((double)val / (x11plot_levels - 1)) * (NUM_LEVELS - 1) + 0.5; XSetForeground(x_display, x_gc, x_colors[cval]); for(ii = 0; ii < plot_mag; ii++) for(jj = 0; jj < plot_mag; jj++) XDrawPoint(x_display, x_window, x_gc, i * plot_mag + ii, j * plot_mag + jj); if(x11_force_flush) XFlush(x_display); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ void X11plot_line(int i, int j, int k, int l, int val) { int cval, ii, jj; val = (val < 0) ? 0 : (val >= x11plot_levels) ? x11plot_levels : val; cval = ((double)val / x11plot_levels) * (NUM_LEVELS - 1) + 0.5; XSetForeground(x_display, x_gc, x_colors[cval]); #if 0 for(ii = 0; ii < plot_mag; ii++) for(jj = 0; jj < plot_mag; jj++) XDrawLine(x_display, x_window, x_gc, i * plot_mag + ii, j * plot_mag + jj, k * plot_mag + ii, l * plot_mag + jj); #else if(plot_mag == 1) XDrawLine(x_display, x_window, x_gc, i, j, k, l); else { double tx, ty, t, dt; int len; if(i == k && j == l) X11plot_point(i, j, val); else { len = MAX(ABS(i - k), ABS(j - l)); dt = 1.0 / len; for(ii = 0, t = 0.0; ii < len + 1; ii++, t += dt) { tx = t * i + (1.0 - t) * k + 0.5; ty = t * j + (1.0 - t) * l + 0.5; X11plot_point(tx, ty, val); } } } #endif } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ static Bool button_click(XEvent *ev) { return(1); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ void X11plot_finish(void) { XEvent ev; XFlush(x_display); fprintf(stderr, ">> Done. Click mouse on window to end program. <<\n"); XIfEvent(x_display, &ev, (Bool (*)()) button_click, 0); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */