/* Raster scroll. */ #include #include #include #include #include #include #include /* include xpm binary */ #include "bg03.xpm" #define USE_XPM_NAME bg03_xpm #define WIN_X 0 #define WIN_Y 0 #define BORDER 0 #define OUT_W 640 #define OUT_H 360 #ifndef M_PI #define M_PI 3.14159265358979 #endif #define deg2rad(x) (x * M_PI / 180.0) /* get a color value from a color name */ static unsigned long get_color(Display *dpy, char *colorname) { Colormap cmap; XColor near_color, true_color; cmap = DefaultColormap(dpy, DefaultScreen(dpy)); XAllocNamedColor(dpy, cmap, colorname, &near_color, &true_color); return near_color.pixel; } /* scale Pixmap */ static void scale_pixmap(Display *dpy, Drawable win, Pixmap *src, Pixmap *dst, int src_w, int src_h, int dst_w, int dst_h) { GC gc; float xscale, yscale; int x, y; xscale = (float)src_w / dst_w; yscale = (float)src_h / dst_h; gc = XCreateGC(dpy, win, 0, 0); XSetGraphicsExposures(dpy, gc, False); for (x = dst_w - 1; x >= 0; x--) XCopyArea(dpy, *src, *dst, gc, (int)(x * xscale), 0, 1, src_h, x, 0); if (src_h <= dst_h) { for (y = dst_h - 1; y >= 0; y--) XCopyArea(dpy, *dst, *dst, gc, 0, (int)(y * yscale), dst_w, 1, 0, y); } else { for (y = 0; y < dst_h; y++) XCopyArea(dpy, *dst, *dst, gc, 0, (int)(y * yscale), dst_w, 1, 0, y); } XFreeGC(dpy, gc); } static void get_target_size(int src_w, int src_h, int scrw, int scrh, int *tgt_w, int *tgt_h) { double xscale, yscale, scale; xscale = (double)scrw / src_w; yscale = (double)scrh / src_h; scale = (xscale <= yscale)? xscale : yscale; *tgt_w = (int)(src_w * scale); *tgt_h = (int)(src_h * scale); } /* update and draw */ static void update(Display *dpy, Drawable win, GC gc, Pixmap pix, Pixmap buf, Pixmap outbuf, int xpm_w, int xpm_h, int src_w, int src_h, int count) { XWindowAttributes xgwa; int i; int scrw, scrh; int aw, ah; /* get window attributes */ XGetWindowAttributes(dpy, win, &xgwa); scrw = xgwa.width; /* window width */ scrh = xgwa.height; /* window height */ get_target_size(src_w, src_h, scrw, scrh, &aw, &ah); /* draw image (Pixmap) */ XSetGraphicsExposures(dpy, gc, False); XCopyArea(dpy, pix, outbuf, gc, 32, 0, src_w, 180, 0, 0); /* raster scroll */ for (i = 0; i < 180; i++) { int x, y, r; double rad; rad = deg2rad(count * 6 + i * 55); r = (5.0 * i / 180.0) + 2.0; x = (int)(r * cos(rad)); y = i + 180; XCopyArea(dpy, pix, outbuf, gc, x + 32, y, src_w, 1, 0, y); } /* scaling to screen resolution */ scale_pixmap(dpy, win, &outbuf, &buf, src_w, src_h, aw, ah); /* draw image (Pixmap) */ { int x = (scrw - aw) / 2; int y = (scrh - ah) / 2; /* clear window */ XClearWindow(dpy, win); XSetGraphicsExposures(dpy, gc, False); XCopyArea(dpy, buf, win, gc, 0, 0, aw, ah, x, y); } } int main(void) { Display *dpy; Window root; Window win; int screen; int display_w, display_h; XEvent evt; unsigned long black, white; XWindowAttributes xgwa; GC gc; Pixmap pix; Pixmap buf; Pixmap outbuf; int busy_loop; int count; int xpm_w, xpm_h; /* open display */ dpy = XOpenDisplay(NULL); root = DefaultRootWindow(dpy); screen = DefaultScreen(dpy); /* get display size */ display_w = DisplayWidth(dpy, screen); display_h = DisplayHeight(dpy, screen); printf("Screen: %d x %d\n", display_w, display_h); /* get color black and white */ white = WhitePixel(dpy, screen); black = BlackPixel(dpy, screen); /* create window */ win = XCreateSimpleWindow(dpy, root, WIN_X, WIN_Y, display_w, display_h, BORDER, white, black); XSelectInput(dpy, win, KeyPressMask | ExposureMask); XMapWindow(dpy, win); /* wait display window */ do { XNextEvent(dpy, &evt); } while (evt.type != Expose); XMoveWindow(dpy, win, WIN_X, WIN_Y); /* create graphics context */ gc = XCreateGC(dpy, win, 0, 0); XSetGraphicsExposures(dpy, gc, False); /* load image */ { XpmAttributes attr; attr.valuemask = 0; if (XpmCreatePixmapFromData(dpy, win, USE_XPM_NAME, &pix, NULL, &attr)) { fprintf(stderr, "Error not load xpm."); return 1; } /* get xpm width and height */ xpm_w = attr.width; xpm_h = attr.height; /* free xpm attributes */ XpmFreeAttributes(&attr); } /* create Pixmap. Use scalling. */ XGetWindowAttributes(dpy, win, &xgwa); buf = XCreatePixmap(dpy, win, display_w, display_h, xgwa.depth); XSetForeground(dpy, gc, get_color(dpy, "green")); XFillRectangle(dpy, buf, gc, 0, 0, display_w, display_h); outbuf = XCreatePixmap(dpy, win, OUT_W, OUT_H, xgwa.depth); XSetForeground(dpy, gc, get_color(dpy, "black")); XFillRectangle(dpy, outbuf, gc, 0, 0, OUT_W, OUT_H); count = 0; /* main loop */ busy_loop = 1; while (busy_loop) { struct timespec start, end; double diff; timespec_get(&start, TIME_UTC); /* event */ while (XPending(dpy)) { XNextEvent(dpy, &evt); switch (evt.type) { /* case Expose: if (evt.xexpose.count == 0) { } break; */ case KeyPress: busy_loop = 0; break; default: break; } } update(dpy, win, gc, pix, buf, outbuf, xpm_w, xpm_h, OUT_W, OUT_H, count); count++; XFlush(dpy); timespec_get(&end, TIME_UTC); diff = (end.tv_sec + (double)end.tv_nsec / 1000000000) - (start.tv_sec + (double)start.tv_nsec / 1000000000); printf("%lf msec\n", diff * 1000); usleep(16 * 1000); /* wait */ } XFreePixmap(dpy, pix); XFreePixmap(dpy, buf); XFreePixmap(dpy, outbuf); XFreeGC(dpy, gc); XDestroyWindow(dpy, win); XCloseDisplay(dpy); return 0; }