📄 graphics.c
字号:
XMapWindow(display, button[bnum].win); XSelectInput(display, button[bnum].win, ButtonPressMask); button[bnum].ispressed = 1;}static voidunmap_button(int bnum){/* Unmaps a button from the screen. */ XUnmapWindow(display, button[bnum].win);}voidcreate_button(char *prev_button_text, char *button_text, void (*button_func) (void (*drawscreen) (void))){/* Creates a new button below the button containing prev_button_text. * * The text and button function are set according to button_text and * * button_func, respectively. */ int i, bnum, space; space = 8;/* Only allow new buttons that are text (not poly) types. */ bnum = -1; for(i = 4; i < num_buttons; i++) { if(button[i].istext == 1 && strcmp(button[i].text, prev_button_text) == 0) { bnum = i + 1; break; } } if(bnum == -1) { printf ("Error in create_button: button with text %s not found.\n", prev_button_text); exit(1); } num_buttons++; button = (t_button *) my_realloc(button, num_buttons * sizeof(t_button));/* NB: Requirement that you specify the button that this button goes under * * guarantees that button[num_buttons-2] exists and is a text button. */ button[num_buttons - 1].xleft = button[num_buttons - 2].xleft; button[num_buttons - 1].ytop = button[num_buttons - 2].ytop + button[num_buttons - 2].height + space; button[num_buttons - 1].height = button[num_buttons - 2].height; button[num_buttons - 1].width = button[num_buttons - 2].width; map_button(num_buttons - 1); for(i = num_buttons - 1; i > bnum; i--) { button[i].ispoly = button[i - 1].ispoly;/* No poly copy for now, as I'm only providing the ability to create text * * buttons. */ button[i].istext = button[i - 1].istext; strcpy(button[i].text, button[i - 1].text); button[i].fcn = button[i - 1].fcn; button[i].ispressed = button[i - 1].ispressed; } button[bnum].istext = 1; button[bnum].ispoly = 0; my_strncpy(button[bnum].text, button_text, BUTTON_TEXT_LEN); button[bnum].fcn = button_func; button[bnum].ispressed = 1;}voiddestroy_button(char *button_text){/* Destroys the button with text button_text. */ int i, bnum; bnum = -1; for(i = 4; i < num_buttons; i++) { if(button[i].istext == 1 && strcmp(button[i].text, button_text) == 0) { bnum = i; break; } } if(bnum == -1) { printf ("Error in destroy_button: button with text %s not found.\n", button_text); exit(1); } for(i = bnum + 1; i < num_buttons; i++) { button[i - 1].ispoly = button[i].ispoly;/* No poly copy for now, as I'm only providing the ability to create text * * buttons. */ button[i - 1].istext = button[i].istext; strcpy(button[i - 1].text, button[i].text); button[i - 1].fcn = button[i].fcn; button[i - 1].ispressed = button[i].ispressed; } unmap_button(num_buttons - 1); num_buttons--; button = (t_button *) my_realloc(button, num_buttons * sizeof(t_button));}voidinit_graphics(char *window_name){ /* Open the toplevel window, get the colors, 2 graphics * * contexts, load a font, and set up the toplevel window * * Calls build_default_menu to set up the default menu. */ char *display_name = NULL; int x, y; /* window position */ unsigned int border_width = 2; /* ignored by OpenWindows */ XTextProperty windowName;/* X Windows' names for my colours. */ char *cnames[NUM_COLOR] = { "white", "black", "grey55", "grey75", "blue", "green", "yellow", "cyan", "red", "RGBi:0.0/0.5/0.0", "magenta" }; XColor exact_def; Colormap cmap; int i; unsigned long valuemask = 0; /* ignore XGCvalues and use defaults */ XGCValues values; XEvent event; disp_type = SCREEN; /* Graphics go to screen, not ps */ for(i = 0; i <= MAX_FONT_SIZE; i++) font_is_loaded[i] = 0; /* No fonts loaded yet. */ /* connect to X server */ if((display = XOpenDisplay(display_name)) == NULL) { fprintf(stderr, "Cannot connect to X server %s\n", XDisplayName(display_name)); exit(-1); } /* get screen size from display structure macro */ screen_num = DefaultScreen(display); display_width = DisplayWidth(display, screen_num); display_height = DisplayHeight(display, screen_num); x = y = 0; top_width = 2 * display_width / 3; top_height = 4 * display_height / 5; cmap = DefaultColormap(display, screen_num); private_cmap = None; for(i = 0; i < NUM_COLOR; i++) { if(!XParseColor(display, cmap, cnames[i], &exact_def)) { fprintf(stderr, "Color name %s not in database", cnames[i]); exit(-1); } if(!XAllocColor(display, cmap, &exact_def)) { fprintf(stderr, "Couldn't allocate color %s.\n", cnames[i]); if(private_cmap == None) { fprintf(stderr, "Will try to allocate a private colourmap.\n"); fprintf(stderr, "Colours will only display correctly when your " "cursor is in the graphics window.\n" "Exit other colour applications and rerun this " "program if you don't like that.\n\n"); private_cmap = XCopyColormapAndFree(display, cmap); cmap = private_cmap; if(!XAllocColor(display, cmap, &exact_def)) { fprintf(stderr, "Couldn't allocate color %s as private.\n", cnames[i]); exit(1); } } else { fprintf(stderr, "Couldn't allocate color %s as private.\n", cnames[i]); exit(1); } } colors[i] = exact_def.pixel; } toplevel = XCreateSimpleWindow(display, RootWindow(display, screen_num), x, y, top_width, top_height, border_width, colors[BLACK], colors[WHITE]); if(private_cmap != None) XSetWindowColormap(display, toplevel, private_cmap); /* hints stuff deleted. */ XSelectInput(display, toplevel, ExposureMask | StructureNotifyMask | ButtonPressMask); /* Create default Graphics Contexts. valuemask = 0 -> use defaults. */ gc = XCreateGC(display, toplevel, valuemask, &values); gc_menus = XCreateGC(display, toplevel, valuemask, &values); /* Create XOR graphics context for Rubber Banding */ values.function = GXxor; values.foreground = colors[BLACK]; gcxor = XCreateGC(display, toplevel, (GCFunction | GCForeground), &values); /* specify font for menus. */ load_font(menu_font_size); font_is_loaded[menu_font_size] = 1; XSetFont(display, gc_menus, font_info[menu_font_size]->fid);/* Set drawing defaults for user-drawable area. Use whatever the * * initial values of the current stuff was set to. */ force_setfontsize(currentfontsize); force_setcolor(currentcolor); force_setlinestyle(currentlinestyle); force_setlinewidth(currentlinewidth); XStringListToTextProperty(&window_name, 1, &windowName); XSetWMName(display, toplevel, &windowName);/* Uncomment to set icon name *//* XSetWMIconName (display, toplevel, &windowName); *//* XStringListToTextProperty copies the window_name string into * * windowName.value. Free this memory now. */ free(windowName.value); XMapWindow(display, toplevel); build_textarea(); build_default_menu();/* The following is completely unnecessary if the user is using the * * interactive (event_loop) graphics. It waits for the first Expose * * event before returning so that I can tell the window manager has got * * the top-level window up and running. Thus the user can start drawing * * into this window immediately, and there's no danger of the window not * * being ready and output being lost. */ XPeekIfEvent(display, &event, test_if_exposed, NULL);}static Booltest_if_exposed(Display * disp, XEvent * event_ptr, XPointer dummy){/* Returns True if the event passed in is an exposure event. Note that * * the bool type returned by this function is defined in Xlib.h. */ if(event_ptr->type == Expose) { return (True); } return (False);}static voidmenutext(Window win, int xc, int yc, char *text){/* draws text center at xc, yc -- used only by menu drawing stuff */ int len, width; len = strlen(text); width = XTextWidth(font_info[menu_font_size], text, len); XDrawString(display, win, gc_menus, xc - width / 2, yc + (font_info[menu_font_size]->ascent - font_info[menu_font_size]->descent) / 2, text, len);}static voiddrawbut(int bnum){/* Draws button bnum in either its pressed or unpressed state. */ int width, height, thick, i, ispressed; XPoint mypoly[6]; ispressed = button[bnum].ispressed; thick = 2; width = button[bnum].width; height = button[bnum].height;/* Draw top and left edges of 3D box. */ if(ispressed) { XSetForeground(display, gc_menus, colors[BLACK]); } else { XSetForeground(display, gc_menus, colors[WHITE]); }/* Note: X Windows doesn't appear to draw the bottom pixel of * * a polygon with XFillPolygon, so I make this 1 pixel thicker * * to compensate. */ mypoly[0].x = 0; mypoly[0].y = height; mypoly[1].x = 0; mypoly[1].y = 0; mypoly[2].x = width; mypoly[2].y = 0; mypoly[3].x = width - thick; mypoly[3].y = thick; mypoly[4].x = thick; mypoly[4].y = thick; mypoly[5].x = thick; mypoly[5].y = height - thick; XFillPolygon(display, button[bnum].win, gc_menus, mypoly, 6, Convex, CoordModeOrigin);/* Draw bottom and right edges of 3D box. */ if(ispressed) { XSetForeground(display, gc_menus, colors[WHITE]); } else { XSetForeground(display, gc_menus, colors[BLACK]); } mypoly[0].x = 0; mypoly[0].y = height; mypoly[1].x = width; mypoly[1].y = height; mypoly[2].x = width; mypoly[2].y = 0; mypoly[3].x = width - thick; mypoly[3].y = thick; mypoly[4].x = width - thick; mypoly[4].y = height - thick; mypoly[5].x = thick; mypoly[5].y = height - thick; XFillPolygon(display, button[bnum].win, gc_menus, mypoly, 6, Convex, CoordModeOrigin);/* Draw background */ if(ispressed) { XSetForeground(display, gc_menus, colors[DARKGREY]); } else { XSetForeground(display, gc_menus, colors[LIGHTGREY]); }/* Give x,y of top corner and width and height */ XFillRectangle(display, button[bnum].win, gc_menus, thick, thick, width - 2 * thick, height - 2 * thick);/* Draw polygon, if there is one */ if(button[bnum].ispoly) { for(i = 0; i < 3; i++) { mypoly[i].x = button[bnum].poly[i][0]; mypoly[i].y = button[bnum].poly[i][1]; } XSetForeground(display, gc_menus, colors[BLACK]); XFillPolygon(display, button[bnum].win, gc_menus, mypoly, 3, Convex, CoordModeOrigin); }/* Draw text, if there is any */ if(button[bnum].istext) { XSetForeground(display, gc_menus, colors[BLACK]); menutext(button[bnum].win, button[bnum].width / 2, button[bnum].height / 2, button[bnum].text); }}static voidturn_on_off(int pressed){/* Shows when the menu is active or inactive by colouring the * * buttons. */ int i; for(i = 0; i < num_buttons; i++) { button[i].ispressed = pressed; drawbut(i); }}static intwhich_button(Window win){ int i; for(i = 0; i < num_buttons; i++) { if(button[i].win == win) return (i); } printf("Error: Unknown button ID in which_button.\n"); return (0);}static voiddrawmenu(void){ int i; for(i = 0; i < num_buttons; i++) { drawbut(i); }}static voidupdate_transform(void){/* Set up the factors for transforming from the user world to X Windows * * coordinates. */ float mult, y1, y2, x1, x2;/* X Window coordinates go from (0,0) to (width-1,height-1) */ xmult = ((float)top_width - 1. - MWIDTH) / (xright - xleft); ymult = ((float)top_height - 1. - T_AREA_HEIGHT) / (ybot - ytop);/* Need to use same scaling factor to preserve aspect ratio */ if(fabs(xmult) <= fabs(ymult)) { mult = fabs(ymult / xmult); y1 = ytop - (ybot - ytop) * (mult - 1.) / 2.; y2 = ybot + (ybot - ytop) * (mult - 1.) / 2.; ytop = y1; ybot = y2; } else { mult = fabs(xmult / ymult); x1 = xleft - (xright - xleft) * (mult - 1.) / 2.; x2 = xright + (xright - xleft) * (mult - 1.) / 2.; xleft = x1; xright = x2; } xmult = ((float)top_width - 1. - MWIDTH) / (xright - xleft); ymult = ((float)top_height - 1. - T_AREA_HEIGHT) / (ybot - ytop);}static voidupdate_ps_transform(void){/* Postscript coordinates start at (0,0) for the lower left hand corner * * of the page and increase upwards and to the right. For 8.5 x 11 * * sheet, coordinates go from (0,0) to (612,792). Spacing is 1/72 inch.* * I'm leaving a minimum of half an inch (36 units) of border around * * each edge. */ float ps_width, ps_height; ps_width = 540.; /* 72 * 7.5 */ ps_height = 720.; /* 72 * 10 */ ps_xmult = ps_width / (xright - xleft); ps_ymult = ps_height / (ytop - ybot);/* Need to use same scaling factor to preserve aspect ratio. * * I show exactly as much on paper as the screen window shows, * * or the user specifies. */ if(fabs(ps_xmult) <= fabs(ps_ymult)) { ps_left = 36.; ps_right = 36. + ps_width; ps_bot = 396. - fabs(ps_xmult * (ytop - ybot)) / 2.; ps_top = 396. + fabs(ps_xmult * (ytop - ybot)) / 2.;/* Maintain aspect ratio but watch signs */ ps_ymult = (ps_xmult * ps_ymult < 0) ? -ps_xmult : ps_xmult; } else { ps_bot = 36.; ps_top = 36. + ps_height; ps_left = 306. - fabs(ps_ymult * (xright - xleft)) / 2.; ps_right = 306. + fabs(ps_ymult * (xright - xleft)) / 2.;/* Maintain aspect ratio but watch signs */ ps_xmult = (ps_xmult * ps_ymult < 0) ? -ps_ymult : ps_ymult; }}voidevent_loop(void (*act_on_button) (float x, float y), void (*drawscreen) (void)){/* The program's main event loop. Must be passed a user routine * * drawscreen which redraws the screen. It handles all window resizing * * zooming etc. itself. If the user clicks a button in the graphics * * (toplevel) area, the act_on_button routine passed in is called. */ XEvent report; int bnum; float x, y;#define OFF 1#define ON 0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -