#include #include #include #include #include typedef struct { double x, y; } Point; typedef struct { int n_points; Point *points; } Shape; Point triangle_points[3] = { {-1.0, 0.0}, {1.0, 1.0}, {1.0,-1.0} }; Shape triangle = { 3, triangle_points }; int temporary_shape_points = 0; Shape temporary_shape = { 0, NULL }; Shape *get_temporary_shape(int n_points); Shape *get_temporary_shape(int n_points) { if (n_points > temporary_shape_points) { temporary_shape_points *= 2; if (temporary_shape_points < n_points) temporary_shape_points = n_points; if ((temporary_shape.points = realloc(temporary_shape.points, sizeof(Point) * temporary_shape_points)) == NULL) { fprintf(stderr, "cannot allocate memory\n"); exit(1); } } temporary_shape.n_points = n_points; return &temporary_shape; } int temporary_xpoints_points = 0; XPoint *temporary_xpoints = NULL; XPoint *get_temporary_xpoints(int n_points); XPoint *get_temporary_xpoints(int n_points) { if (n_points > temporary_xpoints_points) { temporary_xpoints_points *= 2; if (temporary_xpoints_points < n_points) temporary_xpoints_points = n_points; if ((temporary_xpoints = realloc(temporary_xpoints, sizeof(XPoint) * temporary_xpoints_points)) == NULL) { fprintf(stderr, "cannot allocate memory\n"); exit(1); } } return temporary_xpoints; } typedef struct { double xx, xy, yx, yy, dx, dy; } Transform; Transform id_trans = { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }; void transform_point(Point *p0, Point *p1, Transform *trans); void transform_point(Point *p0, Point *p1, Transform *trans) { double p0x = p0->x, p0y = p0->y; p1->x = p0x * trans->xx + p0y * trans->yx + trans->dx; p1->y = p0x * trans->xy + p0y * trans->yy + trans->dy; } Shape *transform_shape(Shape *src, Shape *dest, Transform *trans); Shape *transform_shape(Shape *src, Shape *dest, Transform *trans) { int i = 0, n = src->n_points; Point *p0 = src->points, *p1; if (dest == NULL) dest = get_temporary_shape(n); p1 = dest->points; for (; in_points; Point *p0 = src->points; XPoint *p1; if (dest == NULL) dest = get_temporary_xpoints(n); p1 = dest; for (; ix = (int)(p0->x+0.5); p1->y = (int)(p0->y+0.5); } return dest; } void scale_transform(Transform *src, Transform *dest, double mag); void scale_transform(Transform *src, Transform *dest, double mag) { dest->xx = src->xx * mag; dest->xy = src->xy * mag; dest->yx = src->yx * mag; dest->yy = src->yy * mag; dest->dx = src->dx * mag; dest->dy = src->dy * mag; } void translate_transform(Transform *src, Transform *dest, double dx, double dy); void translate_transform(Transform *src, Transform *dest, double dx, double dy) { dest->xx = src->xx; dest->xy = src->xy; dest->yx = src->yx; dest->yy = src->yy; dest->dx = src->dx + dx; dest->dy = src->dy + dy; } void make_rotate_transform(Transform *dest, double angle); void make_rotate_transform(Transform *dest, double angle) { double s = sin(angle), c = cos(angle); dest->xx = c; dest->xy = s; dest->yx = -s; dest->yy = c; dest->dx = 0; dest->dy = 0; } void compose_transform(Transform *src0, Transform *src1, Transform *dest); void compose_transform(Transform *src0, Transform *src1, Transform *dest) { double xx0 = src0->xx, xx1 = src1->xx, xy0 = src0->xy, xy1 = src1->xy, yx0 = src0->yx, yx1 = src1->yx, yy0 = src0->yy, yy1 = src1->yy, dx0 = src0->dx, dx1 = src1->dx, dy0 = src0->dy, dy1 = src1->dy; dest->xx = xx0 * xx1 + yx0 * xy1; dest->xy = xy0 * xx1 + yy0 * xy1; dest->yx = xx0 * yx1 + yx0 * yy1; dest->yy = xy0 * yx1 + yy0 * yy1; dest->dx = xx0 * dx1 + yx0 * dy1 + dx0; dest->dy = xy0 * dx1 + yy0 * dy1 + dy0; } void print_transform(Transform *t); void print_transform(Transform *t) { printf("%7.2f %7.2f\n", t->xx, t->xy); printf("%7.2f %7.2f\n", t->yx, t->yy); printf("%7.2f %7.2f\n", t->dx, t->dy); } typedef struct { Shape *s; double size, angle, x, y; Transform t; } Node; Node node = { &triangle, 30, 0, 50, 50, }; void redraw(void); Display *display; Window window; GC gc; int main(int argc, char **argv) { Window root; Colormap colormap; XColor color; int screen_number; long black, white, red; make_rotate_transform(&node.t, node.angle); scale_transform(&node.t, &node.t, node.size); translate_transform(&node.t, &node.t, node.x, node.y); print_transform(&node.t); if ((display = XOpenDisplay(NULL)) == NULL) { fprintf(stderr, "cannot open display\n"); exit(1); } screen_number = DefaultScreen(display); white = WhitePixel(display, screen_number); black = BlackPixel(display, screen_number); colormap = DefaultColormap(display, screen_number); if (XAllocNamedColor(display, colormap, "red", &color, &color)) { red = color.pixel; } else { red = white; } gc = DefaultGC(display, screen_number); { XGCValues values; values.function = GXxor; values.foreground = red^black; values.cap_style = CapNotLast; values.line_width = 0; XChangeGC(display, gc, GCFunction|GCForeground|GCCapStyle| GCLineWidth, &values); } root = DefaultRootWindow(display); window = XCreateSimpleWindow( display, root, 0, 0, 100, 100, 4, white, black); XSelectInput(display, window, ExposureMask); XMapWindow(display, window); XFlush(display); { XWindowAttributes attr; XGetWindowAttributes(display, window, &attr); printf("my event mask: %08lx\n", attr.your_event_mask); printf("all event mask: %08lx\n", attr.all_event_masks); printf("no prop mask: %08lx\n", attr.do_not_propagate_mask); } { XEvent event; while (1) { XNextEvent(display, &event); if (event.type == Expose) { printf("expose event - count: %d\n", event.xexpose.count); if (event.xexpose.count == 0) redraw(); } else { printf("unknown type of event: %04x\n", event.type); } } } XUnmapWindow(display, window); XFreeColors(display, colormap, (unsigned long *)&red, 1, 0); XSync(display, False); XDestroyWindow(display, window); XCloseDisplay(display); exit(0); } void redraw(void) { int i; XPoint points[] = {{50,50}, {55,70}, {70,75}, {75,50}, {50,50}}; printf("redrawing\n"); XClearWindow(display, window); XDrawPoint(display, window, gc, 20, 20); XDrawLine(display, window, gc, 10, 20, 90, 80); for (i=0; i<1; ++i) { XFillArc(display, window, gc, 10, 50, 40, 40, 0, 64*360); XFillPolygon(display, window, gc, points, 5, Convex, CoordModeOrigin); XDrawRectangle(display, window, gc, 40, 40, 20, 20); XFillRectangle(display, window, gc, 45, 35, 10, 30); XDrawRectangle(display, window, gc, 40, 40, 20, 20); XDrawLines(display, window, gc, points, 5, CoordModeOrigin); XFillRectangle(display, window, gc, 45, 35, 10, 30); XFlush(display); } }