ralph@computing-maths.cardiff.ac.uk (Ralph Martin) (06/26/90)
I have a program (see below) which draws fractals. In the first version, I basically set up a canvas paint window, and drew straight into it, using notify_dispatch at the end of each row of pixels. All well and good, except that there was no canvas repaint proc in case of damage. So, in a second version, I create a Pixmap, and draw into that too, and then copy areas of that to the paint window as a repaint proc. This just does not seem to work. Furthermore, it also seems to screw up something else, in that some sliders which used to appear in a panel no longer appear at all. I am enclosing the program below, and I have marked with /* NEW */ all added lines which are to do with the Pixmap. Please note it needs a colour display. If you can tell me what I am doing wrong, I'd be really grateful, or if you can give me some pointers on how to do it right. The Xview Programming Manual and other Sun documentation seem rather weak on this point! Ralph ---------------------------------- cut here ---------------------------- #include <X11/Xlib.h> #include <xview/xview.h> #include <xview/panel.h> #include <xview/canvas.h> #include <xview/cms.h> #include <xview/win_input.h> #include <xview/xv_xrect.h> #define A 512 #define A1 (A-1) #define B 512 #define B1 (B-1) /* * compile with cc -O4 pretty.c -f68881 -o pretty -lxview -lX11 -lm */ Frame base_frame; Panel panel; Panel_item rslider, gslider, bslider, cslider, qbutton; Canvas canvas; Xv_cmsdata cms_data; GC gccanvas, gcpixmap; /* NEW */ /* gcpixmap only */ XGCValues gc_val; Display *display; Drawable drawable; Pixmap thepixmap; /* NEW */ int thecolour = 1; int value; unsigned char red[128], green[128], blue[128]; double xmax, xmin, ymax, ymin; main(argc, argv) int argc; char **argv; { double delta_x, delta_y; double p, q; register double x, y, x_next, y_next, r, x0, y0; int M, K; register int nx, ny, k, i; void sliderval(), csliderval(), quitproc(), repaintproc(), mouseproc(); /* NEW */ /* (repaintproc new only) */ extern Notify_error notify_dispatch(); xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL); srand(getpid()); for (i = 1; i < 127; i++) { red[i] = rand(); blue[i] = rand(); green[i] = rand(); }; red[0] = blue[0] = green[0] = 255; red[127] = blue[127] = green[127] = 0; cms_data.type = XV_DYNAMIC_CMS; cms_data.size = 128; cms_data.rgb_count = 128; cms_data.index = 0; cms_data.red = red; cms_data.green = green; cms_data.blue = blue; base_frame = xv_create(NULL, FRAME, XV_LABEL, argv[0], WIN_ERROR_MSG, "Cant open window.", WIN_DYNAMIC_VISUAL, TRUE, WIN_CMS_NAME, "Pretty", WIN_CMS_DATA, &cms_data, FRAME_INHERIT_COLORS, TRUE, NULL); canvas = xv_create(base_frame, CANVAS, XV_HEIGHT, A, XV_WIDTH, B, CANVAS_AUTO_SHRINK, FALSE, CANVAS_AUTO_EXPAND, FALSE, CANVAS_HEIGHT, A, CANVAS_WIDTH, B, CANVAS_RETAINED, TRUE, CANVAS_X_PAINT_WINDOW, TRUE, /* NEW */ CANVAS_REPAINT_PROC, repaintproc, /* NEW */ WIN_DYNAMIC_VISUAL, TRUE, WIN_CMS_NAME, "Pretty", NULL); xv_set(canvas_paint_window(canvas), WIN_CONSUME_EVENTS, WIN_NO_EVENTS, MS_LEFT, NULL, WIN_IGNORE_EVENT, WIN_UP_EVENTS, WIN_EVENT_PROC, mouseproc, NULL); panel = xv_create(base_frame, PANEL, WIN_BELOW, canvas, WIN_DYNAMIC_VISUAL, TRUE, WIN_CMS_NAME, "Pretty", WIN_X, 0, NULL); rslider = xv_create(panel, PANEL_SLIDER, PANEL_LABEL_STRING, "Red:", PANEL_VALUE_X, 65, PANEL_MIN_VALUE, 0, PANEL_MAX_VALUE, 255, PANEL_SLIDER_WIDTH, 256, PANEL_NOTIFY_PROC, sliderval, PANEL_NOTIFY_LEVEL, PANEL_ALL, PANEL_VALUE, red[1], NULL); gslider = xv_create(panel, PANEL_SLIDER, PANEL_LABEL_STRING, "Green:", PANEL_VALUE_X, 65, PANEL_MIN_VALUE, 0, PANEL_MAX_VALUE, 255, PANEL_SLIDER_WIDTH, 256, PANEL_NOTIFY_PROC, sliderval, PANEL_NOTIFY_LEVEL, PANEL_ALL, PANEL_VALUE, green[1], NULL); bslider = xv_create(panel, PANEL_SLIDER, PANEL_LABEL_STRING, "Blue:", PANEL_VALUE_X, 65, PANEL_MIN_VALUE, 0, PANEL_MAX_VALUE, 255, PANEL_SLIDER_WIDTH, 256, PANEL_NOTIFY_PROC, sliderval, PANEL_NOTIFY_LEVEL, PANEL_ALL, PANEL_VALUE, blue[1], NULL); cslider = xv_create(panel, PANEL_SLIDER, PANEL_LABEL_STRING, "Colour:", PANEL_VALUE_X, 65, PANEL_MIN_VALUE, 1, PANEL_MAX_VALUE, 126, PANEL_VALUE, 1, PANEL_SLIDER_WIDTH, 252, PANEL_NOTIFY_PROC, csliderval, NULL); qbutton = xv_create(panel, PANEL_BUTTON, XV_X, 448, XV_Y, 45, PANEL_NOTIFY_PROC, quitproc, PANEL_LABEL_STRING, "Quit", NULL); window_fit(panel); window_fit(base_frame); xv_set(base_frame, XV_SHOW, TRUE, NULL); display = (Display *) xv_get(base_frame, XV_DISPLAY); drawable = (Drawable) xv_get(canvas_paint_window(canvas), XV_XID); thepixmap = XCreatePixmap(display, DefaultRootWindow(display), A, B, 8); /* NEW */ gccanvas = XCreateGC(display, drawable, 0, NULL); gcpixmap = XCreateGC(display, thepixmap, 0, NULL); /* NEW */ xv_set(base_frame, FRAME_LEFT_FOOTER, "Calculating...", FRAME_SHOW_FOOTER, TRUE, NULL); XSync(display, 1); notify_dispatch(); xmin = -2.0; xmax = 2.0; ymin = -1.5; ymax = 1.5; delta_x = (xmax - xmin) / A1; delta_y = (ymax - ymin) / B1; M = 100; K = 128; p = 0.32; q = 0.043; y = ymin - delta_y; for (ny = 0; ny < B / 2; ny++) { y += delta_y; x = xmin - delta_x; for (nx = 0; nx < A; nx++) { x += delta_x; k = 0; x0 = x; y0 = y; do { x_next = x0 * x0 - y0 * y0 + p; y_next = x0 * y0 + x0 * y0 + q; k++; r = x_next * x_next + y_next * y_next; x0 = x_next; y0 = y_next; } while (r <= M && k < K); if (r > M) gc_val.foreground = k; else gc_val.foreground = 128 - ((int) (r * 100)) % 128; XChangeGC(display, gccanvas, GCForeground, &gc_val); XChangeGC(display, gcpixmap, GCForeground, &gc_val); /* NEW */ /* Allow for y going top to bottom, symmetry */ XDrawPoint(display, drawable, gccanvas, nx, B1 - ny); XDrawPoint(display, drawable, gccanvas, A1 - nx, ny); XDrawPoint(display, thepixmap, gcpixmap, nx, B1 - ny); /* NEW */ XDrawPoint(display, thepixmap, gcpixmap, A1 - nx, ny); /* NEW */ /* colour pixel nx, ny is 0 */ notify_dispatch(); } xv_set(base_frame, FRAME_LEFT_FOOTER, "Completed", 0); xv_main_loop(base_frame); } void sliderval(item, value, event) Panel_item item; int value; Event *event; { if (item == rslider) red[thecolour] = value; else if (item == gslider) green[thecolour] = value; else if (item == bslider) blue[thecolour] = value; xv_set(base_frame, WIN_CMS_DATA, &cms_data, NULL); } csliderval(item, value, event) Panel_item item; int value; Event *event; { int rval, gval, bval; thecolour = value; rval = red[thecolour]; xv_set(rslider, PANEL_VALUE, rval, NULL); gval = green[thecolour]; xv_set(gslider, PANEL_VALUE, gval, NULL); bval = blue[thecolour]; xv_set(bslider, PANEL_VALUE, bval, NULL); } void mouseproc(window, event) Xv_Window window; Event *event; { char msg[128]; XImage *image; int x, y, colour, rval, bval, gval; double realx, realy; if (event_left_is_down(event)) { x = event_x(event); y = event_y(event); image = XGetImage(display, drawable, x, y, 1, 1, AllPlanes, ZPixmap); thecolour = (int) XGetPixel(image, 0, 0); if (thecolour != 0) { realx = xmin + (xmax - xmin) * x / A; realy = ymax - (ymax - ymin) * y / B; sprintf(msg, "Mouse click at %f, %f", realx, realy); xv_set(base_frame, FRAME_RIGHT_FOOTER, msg, NULL); xv_set(cslider, PANEL_VALUE, thecolour, NULL); rval = red[thecolour]; xv_set(rslider, PANEL_VALUE, rval, NULL); gval = green[thecolour]; xv_set(gslider, PANEL_VALUE, gval, NULL); bval = blue[thecolour]; xv_set(bslider, PANEL_VALUE, bval, NULL); } } } void quitproc(item, event) Panel_item item; Event *event; { xv_destroy_safe(base_frame); exit(0); } repaintproc(canvas, paint_window, dpy, win, xrects) /* NEW */ /* all of it */ Canvas canvas; Xv_Window paint_window; Display *dpy; Window win; Xv_xrectlist *xrects; { GC gc; gc = XCreateGC(display, thepixmap, 0, NULL); for (xrects->count--; xrects->count >= 0; xrects->count--) { XCopyArea(dpy, thepixmap, xv_get(paint_window, XV_XID), gc, xrects->rect_array[xrects->count].x, xrects->rect_array[xrects->count].y, xrects->rect_array[xrects->count].width, xrects->rect_array[xrects->count].height, xrects->rect_array[xrects->count].x, xrects->rect_array[xrects->count].y); } } ---------------------------------- end ----------------------------------