/* rotate-pm.c 1.1 */ /* Copyright 1992, 1993 O'Reilly and Associates, Inc. Permission to use, copy, and modify this program is hereby granted, as long as this copyright notice appears in each copy of the program source code. */ #include "book_utils.h" static Display *dpy; static Window window; static PEXRenderer renderer; static Pixmap pixmap; static XWindowAttributes wattrs; static GC gc; /* The triangle's coordinates. */ static PEXCoord2D points[] = {{.4,.5},{.6,.5},{.5,.9}}; static void redraw( angle ) double angle; { PEXColor color; PEXMatrix3x3 xform; static PEXCoord2D center = {0.5, 0.5}; static PEXVector2D shift = {0,0}, scale = {1,1}; /* Clear the off-screen pixmap. */ XFillRectangle( dpy, pixmap, gc, 0, 0, wattrs.width, wattrs.height ); /* Redraw into the off-screen pixmap. */ PEXBeginRendering( dpy, pixmap, renderer ); { /* Build the transform for the new angle. */ PEXBuildTransform2D( ¢er, &shift, angle, &scale, xform ); PEXSetLocalTransform2D( dpy, renderer, PEXOCRender, PEXReplace, xform ); /* Create the primitive. */ PEXSetInteriorStyle( dpy, renderer, PEXOCRender, PEXInteriorStyleSolid ); SET_COLOR( 1, 0, 0, color ); /* red */ PEXSetSurfaceColor( dpy, renderer, PEXOCRender, PEXColorTypeRGB, &color ); PEXFillArea2D( dpy, renderer, PEXOCRender, PEXShapeConvex, True, 3, points ); } PEXEndRendering( dpy, renderer, True ); /* Copy the entire pixmap to the window. */ XCopyArea( dpy, pixmap, window, gc, 0, 0, wattrs.width, wattrs.height, 0, 0 ); XFlush( dpy ); } static void resize( event ) XEvent *event; { /* Compare the old size to the new size. */ if ( event->xconfigure.width != wattrs.width || event->xconfigure.height != wattrs.height ) { /* The size changed. Destroy the old pixmap. */ XFreePixmap( dpy, pixmap ); /* Create a new pixmap at the new window size. */ XGetWindowAttributes( dpy, window, &wattrs ); pixmap = XCreatePixmap( dpy, window, wattrs.width, wattrs.height, wattrs.depth ); } } #define WIN_GEOM "500x500+50+50" main( argc, argv ) int argc; char *argv[]; { XEvent event; XVisualInfo vis_info; XColor bkgd_color; XStandardColormap cmap_info; PEXColorApproxEntry capx_info; PEXRendererAttributes rattrs; PEXExtensionInfo *pexinfo; int done = 0; double angle = 0; XGCValues gcattrs; /* Open a display and initialize PEX. */ dpy = ora_init_pex( argv, &pexinfo ); if ( !dpy ) exit(1); /* Determine the best visual to use. */ ora_find_best_visual( dpy, &vis_info ); /* Get a standard colormap for the visual. */ if ( !ora_get_standard_colormap( dpy, &vis_info, &cmap_info ) ) { fprintf ( stderr, "Cannot find a standard colormap\n" ); exit(1); } ora_set_stdcmap_approx( &vis_info, &cmap_info, &capx_info ); /* Create the window, giving it a gray background. */ bkgd_color.red = bkgd_color.green = bkgd_color.blue = 0x5555; bkgd_color.flags = DoRed | DoGreen | DoBlue; window = ora_create_window( dpy, &vis_info, &cmap_info, WIN_GEOM, &bkgd_color ); /* Set up the PEX renderer. */ if ( IMMED_MODE_SPT( pexinfo ) ) { renderer = ora_setup_renderer( dpy, window, &capx_info, &rattrs ); } else { fprintf( stderr, "No immediate mode.\n" ); exit(1); } /* Set up the PEX renderer. */ if ( IMMED_MODE_SPT( pexinfo ) ) { renderer = ora_setup_renderer( dpy, window, &capx_info, &rattrs ); } else { fprintf( stderr, "No immediate mode.\n" ); exit(1); } /* Create a pixmap for double buffering. */ XGetWindowAttributes( dpy, window, &wattrs ); pixmap = XCreatePixmap( dpy, window, wattrs.width, wattrs.height, wattrs.depth ); if ( pixmap == NULL ) { fprintf( stderr, "Can't allocate a pixmap.\n" ); exit(1); } /* Create a graphics context and set the foreground color. */ gcattrs.foreground = bkgd_color.pixel; gc = XCreateGC( dpy, window, GCForeground, &gcattrs ); /* Read and respond to X events. */ XSelectInput( dpy, window, ExposureMask | ButtonPressMask | StructureNotifyMask ); while ( !done ) { XNextEvent( dpy, &event ); switch ( event.type ) { case Expose: /* Flush remaining Expose events, then redraw. */ while ( XCheckTypedWindowEvent( dpy, window, Expose, &event ) ) ; /* empty statement */ redraw( angle ); break; case ConfigureNotify: resize( &event ); break; case ButtonPress: switch( event.xbutton.button ) { case Button1: /* Rotate. */ for ( angle = 2*M_PI - M_PI/60; angle > 0; angle -= M_PI/60 ) { redraw( angle ); } /* Reset to initial position. */ redraw( angle = 0 ); break; default: done = 1; break; } break; } } XCloseDisplay( dpy ); return 0; }