📄 graphics.c
字号:
#include <math.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include "util.h"#include "graphics.h"#include "vpr_types.h"/*#include "draw.h" */#ifndef NO_GRAPHICS#include <X11/Xlib.h>#include <X11/Xutil.h>#include <X11/Xos.h>#include <X11/Xatom.h>#endif/* Written by Vaughn Betz at the University of Toronto, Department of * * Electrical and Computer Engineering. Graphics package Version 1.3. * * All rights reserved by U of T, etc. * * * * You may freely use this graphics interface for non-commercial purposes * * as long as you leave the written by Vaughn Betz message in it -- who * * knows, maybe someday an employer will see it and give me a job or large * * sums of money :). * * * * Revision History: * * * * Sept. 19, 1997: Incorporated Zoom Fit code of Haneef Mohammed at * * Cypress. Makes it easy to zoom to a full view of the graphics. * * * * Sept. 11, 1997: Added the create_button and delete_button interface to * * make it easy to add and destroy buttons from user code. Removed the * * bnum parameter to the button functions, since it wasn't really needed. * * * * June 28, 1997: Added filled arc drawing primitive. Minor modifications * * to PostScript driver to make the PostScript output slightly smaller. * * * * April 15, 1997: Added code to init_graphics so it waits for a window * * to be exposed before returning. This ensures that users of non- * * interactive graphics can never draw to a window before it is available. * * * * Feb. 24, 1997: Added code so the package will allocate a private * * colormap if the default colormap doesn't have enough free colours. * * * * June 28, 1996: Converted all internal functions in graphics.c to have * * internal (static) linkage to avoid any conflicts with user routines in * * the rest of the program. * * * * June 12, 1996: Added setfontsize and setlinewidth attributes. Added * * pre-clipping of objects for speed (and compactness of PS output) when * * graphics are zoomed in. Rewrote PostScript engine to shrink the output * * and make it easier to read. Made drawscreen a callback function passed * * in rather than a global. Graphics attribute calls are more efficient -- * * they check if they have to change anything before doing it. * * * * October 27, 1995: Added the message area, a callback function for * * interacting with user button clicks, and implemented a workaround for a * * Sun X Server bug that misdisplays extremely highly zoomed graphics. * * * * Jan. 13, 1995: Modified to incorporate PostScript Support. *//****************** Types and defines local to this module ******************/#ifndef NO_GRAPHICS/* Uncomment the line below if your X11 header files don't define XPointer *//* typedef char *XPointer; *//* Macros for translation from world to PostScript coordinates */#define XPOST(worldx) (((worldx)-xleft)*ps_xmult + ps_left)#define YPOST(worldy) (((worldy)-ybot)*ps_ymult + ps_bot)/* Macros to convert from X Windows Internal Coordinates to my * * World Coordinates. (This macro is used only rarely, so * * the divides don't hurt speed). */#define XTOWORLD(x) (((float) x)/xmult + xleft)#define YTOWORLD(y) (((float) y)/ymult + ytop)#define max(a,b) (((a) > (b))? (a) : (b))#define min(a,b) ((a) > (b)? (b) : (a))#define MWIDTH 104 /* width of menu window */#define T_AREA_HEIGHT 24 /* Height of text window */#define MAX_FONT_SIZE 40 /* Largest point size of text */#define PI 3.141592654#define BUTTON_TEXT_LEN 20typedef struct {int width; int height; int xleft; int ytop; void (*fcn) (void (*drawscreen) (void)); Window win; int istext; char text[BUTTON_TEXT_LEN]; int ispoly; int poly[3][2]; int ispressed;} t_button;/********************* Static variables local to this module ****************/static const int menu_font_size = 14; /* Font for menus and dialog boxes. */static t_button *button; /* [0..num_buttons-1] */static int num_buttons; /* Number of menu buttons */static int disp_type; /* Selects SCREEN or POSTSCRIPT */static Display *display;static int screen_num;static GC gc, gcxor, gc_menus;static XFontStruct *font_info[MAX_FONT_SIZE+1]; /* Data for each size */static int font_is_loaded[MAX_FONT_SIZE + 1]; /* 1: loaded, 0: not */static unsigned int display_width, display_height; /* screen size */static unsigned int top_width, top_height; /* window size */static Window toplevel, menu, textarea; /* various windows */static float xleft, xright, ytop, ybot; /* world coordinates *//* Initial world coordinates */static float saved_xleft, saved_xright, saved_ytop, saved_ybot; static float ps_left, ps_right, ps_top, ps_bot; /* Figure boundaries for * * PostScript output, in PostScript coordinates. */static float ps_xmult, ps_ymult; /* Transformation for PostScript. */static float xmult, ymult; /* Transformation factors */static Colormap private_cmap; /* "None" unless a private cmap was allocated. *//* Graphics state. Set start-up defaults here. */static int currentcolor = BLACK;static int currentlinestyle = SOLID;static int currentlinewidth = 0;static int currentfontsize = 10;static char message[BUFSIZE] = "\0"; /* User message to display *//* Color indices passed back from X Windows. */static int colors[NUM_COLOR];/* For PostScript output */static FILE *ps;/* MAXPIXEL and MINPIXEL are set to prevent what appears to be * * overflow with very large pixel values on the Sun X Server. */#define MAXPIXEL 15000 #define MINPIXEL -15000 /********************** Subroutines local to this module ********************//* Function declarations for button responses */static void translate_up (void (*drawscreen) (void)); static void translate_left (void (*drawscreen) (void)); static void translate_right (void (*drawscreen) (void)); static void translate_down (void (*drawscreen) (void)); static void zoom_in (void (*drawscreen) (void));static void zoom_out (void (*drawscreen) (void));static void zoom_fit (void (*drawscreen) (void));static void adjustwin (void (*drawscreen) (void)); static void postscript (void (*drawscreen) (void));static void proceed (void (*drawscreen) (void));static void quit (void (*drawscreen) (void)); static Bool test_if_exposed (Display *disp, XEvent *event_ptr, XPointer dummy);static void map_button (int bnum); static void unmap_button (int bnum); /********************** Subroutine definitions ******************************/static int xcoord (float worldx) {/* Translates from my internal coordinates to X Windows coordinates * * in the x direction. Add 0.5 at end for extra half-pixel accuracy. */ int winx; winx = (int) ((worldx-xleft)*xmult + 0.5); /* Avoid overflow in the X Window routines. This will allow horizontal * * and vertical lines to be drawn correctly regardless of zooming, but * * will cause diagonal lines that go way off screen to change their * * slope as you zoom in. The only way I can think of to completely fix * * this problem is to do all the clipping in advance in floating point, * * then convert to integers and call X Windows. This is a lot of extra * * coding, and means that coordinates will be clipped twice, even though * * this "Super Zoom" problem won't occur unless users zoom way in on * * the graphics. */ winx = max (winx, MINPIXEL); winx = min (winx, MAXPIXEL); return (winx);}static int ycoord (float worldy) {/* Translates from my internal coordinates to X Windows coordinates * * in the y direction. Add 0.5 at end for extra half-pixel accuracy. */ int winy; winy = (int) ((worldy-ytop)*ymult + 0.5); /* Avoid overflow in the X Window routines. */ winy = max (winy, MINPIXEL); winy = min (winy, MAXPIXEL); return (winy);}static void load_font(int pointsize) {/* Makes sure the font of the specified size is loaded. Point_size * * MUST be between 1 and MAX_FONT_SIZE -- no check is performed here. *//* Use proper point-size medium-weight upright helvetica font */ char fontname[44]; sprintf(fontname,"-*-helvetica-medium-r-*--*-%d0-*-*-*-*-*-*", pointsize); #ifdef VERBOSE printf ("Loading font: point size: %d, fontname: %s\n",pointsize, fontname);#endif/* Load font and get font information structure. */ if ((font_info[pointsize] = XLoadQueryFont(display,fontname)) == NULL) { fprintf( stderr, "Cannot open desired font\n"); exit( -1 ); }}static void force_setcolor (int cindex) { static char *ps_cnames[NUM_COLOR] = {"white", "black", "grey55", "grey75", "blue", "green", "yellow", "cyan", "red", "darkgreen", "magenta"}; currentcolor = cindex; if (disp_type == SCREEN) { XSetForeground (display, gc,colors[cindex]); } else { fprintf (ps,"%s\n", ps_cnames[cindex]); }}void setcolor (int cindex) { if (currentcolor != cindex) force_setcolor (cindex);}static void force_setlinestyle (int linestyle) {/* Note SOLID is 0 and DASHED is 1 for linestyle. *//* PostScript and X commands needed, respectively. */ static char *ps_text[2] = {"linesolid", "linedashed"}; static int x_vals[2] = {LineSolid, LineOnOffDash}; currentlinestyle = linestyle; if (disp_type == SCREEN) { XSetLineAttributes (display, gc, currentlinewidth, x_vals[linestyle], CapButt, JoinMiter); } else { fprintf(ps,"%s\n", ps_text[linestyle]); }}void setlinestyle (int linestyle) { if (linestyle != currentlinestyle) force_setlinestyle (linestyle);}static void force_setlinewidth (int linewidth) {/* linewidth should be greater than or equal to 0 to make any sense. *//* Note SOLID is 0 and DASHED is 1 for linestyle. */ static int x_vals[2] = {LineSolid, LineOnOffDash}; currentlinewidth = linewidth; if (disp_type == SCREEN) { XSetLineAttributes (display, gc, linewidth, x_vals[currentlinestyle], CapButt, JoinMiter); } else { fprintf(ps,"%d setlinewidth\n", linewidth); }}void setlinewidth (int linewidth) { if (linewidth != currentlinewidth) force_setlinewidth (linewidth);}static void force_setfontsize (int pointsize) {/* Valid point sizes are between 1 and MAX_FONT_SIZE */ if (pointsize < 1) pointsize = 1; else if (pointsize > MAX_FONT_SIZE) pointsize = MAX_FONT_SIZE; currentfontsize = pointsize; if (disp_type == SCREEN) { if (!font_is_loaded[pointsize]) { load_font (pointsize); font_is_loaded[pointsize] = 1; } XSetFont(display, gc, font_info[pointsize]->fid); } else { /* PostScript: set up font and centering function */ fprintf(ps,"%d setfontsize\n",pointsize); } }void setfontsize (int pointsize) {/* For efficiency, this routine doesn't do anything if no change is * * implied. If you want to force the graphics context or PS file * * to have font info set, call force_setfontsize (this is necessary * * in initialization and X11 / Postscript switches). */ if (pointsize != currentfontsize) force_setfontsize (pointsize);}static void build_textarea (void) {/* Creates a small window at the top of the graphics area for text messages */ XSetWindowAttributes menu_attributes; unsigned long valuemask; textarea = XCreateSimpleWindow(display,toplevel, 0, top_height-T_AREA_HEIGHT, display_width, T_AREA_HEIGHT-4, 2, colors[BLACK], colors[LIGHTGREY]); menu_attributes.event_mask = ExposureMask; /* ButtonPresses in this area are ignored. */ menu_attributes.do_not_propagate_mask = ButtonPressMask; /* Keep text area on bottom left */ menu_attributes.win_gravity = SouthWestGravity; valuemask = CWWinGravity | CWEventMask | CWDontPropagate; XChangeWindowAttributes(display, textarea, valuemask, &menu_attributes); XMapWindow (display, textarea);}static void setpoly (int bnum, int xc, int yc, int r, float theta) {/* Puts a triangle in the poly array for button[bnum] */ int i; button[bnum].istext = 0; button[bnum].ispoly = 1; for (i=0;i<3;i++) { button[bnum].poly[i][0] = (int) (xc + r*cos(theta) + 0.5); button[bnum].poly[i][1] = (int) (yc + r*sin(theta) + 0.5); theta += 2*PI/3; }}static void build_default_menu (void) {/* Sets up the default menu buttons on the right hand side of the window. */ XSetWindowAttributes menu_attributes; unsigned long valuemask; int i, xcen, x1, y1, bwid, bheight, space; menu = XCreateSimpleWindow(display,toplevel, top_width-MWIDTH, 0, MWIDTH-4, display_height, 2, colors[BLACK], colors[LIGHTGREY]); menu_attributes.event_mask = ExposureMask; /* Ignore button presses on the menu background. */ menu_attributes.do_not_propagate_mask = ButtonPressMask; /* Keep menu on top right */ menu_attributes.win_gravity = NorthEastGravity; valuemask = CWWinGravity | CWEventMask | CWDontPropagate; XChangeWindowAttributes(display, menu, valuemask, &menu_attributes); XMapWindow (display, menu); num_buttons = 11; button = (t_button *) my_malloc (num_buttons * sizeof (t_button));/* Now do the arrow buttons */ bwid = 28; space = 3; y1 = 10; xcen = 51; x1 = xcen - bwid/2; button[0].xleft = x1; button[0].ytop = y1; setpoly (0, bwid/2, bwid/2, bwid/3, -PI/2.); /* Up */ button[0].fcn = translate_up; y1 += bwid + space; x1 = xcen - 3*bwid/2 - space; button[1].xleft = x1; button[1].ytop = y1; setpoly (1, bwid/2, bwid/2, bwid/3, PI); /* Left */ button[1].fcn = translate_left; x1 = xcen + bwid/2 + space; button[2].xleft = x1; button[2].ytop = y1; setpoly (2, bwid/2, bwid/2, bwid/3, 0); /* Right */ button[2].fcn = translate_right; y1 += bwid + space; x1 = xcen - bwid/2; button[3].xleft = x1; button[3].ytop = y1; setpoly (3, bwid/2, bwid/2, bwid/3, +PI/2.); /* Down */ button[3].fcn = translate_down; for (i=0;i<4;i++) { button[i].width = bwid; button[i].height = bwid; } /* Rectangular buttons */ y1 += bwid + space + 6; space = 8; bwid = 90; bheight = 26; x1 = xcen - bwid/2; for (i=4;i<num_buttons;i++) { button[i].xleft = x1; button[i].ytop = y1; y1 += bheight + space; button[i].istext = 1; button[i].ispoly = 0; button[i].width = bwid; button[i].height = bheight; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -