VPR-6.0

vpr/SRC/base/graphics.c File Reference

#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "util.h"
#include "graphics.h"
#include "vpr_types.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>
Include dependency graph for graphics.c:

Go to the source code of this file.

Data Structures

struct  t_button

Defines

#define max(a, b)   (((a) > (b))? (a) : (b))
#define min(a, b)   ((a) > (b)? (b) : (a))
#define MWIDTH   104
#define T_AREA_HEIGHT   24
#define MAX_FONT_SIZE   40
#define PI   3.141592654
#define BUTTON_TEXT_LEN   20
#define MAXPIXEL   15000
#define MINPIXEL   -15000
#define OFF   1
#define ON   0
#define XPOST(worldx)   (((worldx)-xleft)*ps_xmult + ps_left)
#define YPOST(worldy)   (((worldy)-ybot)*ps_ymult + ps_bot)
#define XTOWORLD(x)   (((float) x)/xmult + xleft)
#define YTOWORLD(y)   (((float) y)/ymult + ytop)

Functions

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)
static int xcoord (float worldx)
static int ycoord (float worldy)
static void load_font (int pointsize)
static void force_setcolor (int cindex)
void setcolor (int cindex)
int getcolor ()
static void force_setlinestyle (int linestyle)
void setlinestyle (int linestyle)
static void force_setlinewidth (int linewidth)
void setlinewidth (int linewidth)
static void force_setfontsize (int pointsize)
void setfontsize (int pointsize)
static void build_textarea (void)
static void setpoly (int bnum, int xc, int yc, int r, float theta)
static void build_default_menu (void)
void create_button (char *prev_button_text, char *button_text, void(*button_func)(void(*drawscreen)(void)))
void destroy_button (char *button_text)
void init_graphics (char *window_name)
static void menutext (Window win, int xc, int yc, char *text)
static void drawbut (int bnum)
static void turn_on_off (int pressed)
static int which_button (Window win)
static void drawmenu (void)
static void update_transform (void)
static void update_ps_transform (void)
void event_loop (void(*act_on_button)(float x, float y), void(*drawscreen)(void))
void clearscreen (void)
static int rect_off_screen (float x1, float y1, float x2, float y2)
void drawline (float x1, float y1, float x2, float y2)
void drawrect (float x1, float y1, float x2, float y2)
void fillrect (float x1, float y1, float x2, float y2)
static float angnorm (float ang)
void drawarc (float xc, float yc, float rad, float startang, float angextent)
void fillarc (float xc, float yc, float rad, float startang, float angextent)
void fillpoly (t_point *points, int npoints)
void drawtext (float xc, float yc, const char *text, float boundx)
void flushinput (void)
void init_world (float x1, float y1, float x2, float y2)
void draw_message (void)
void update_message (char *msg)
static void update_win (int x[2], int y[2], void(*drawscreen)(void))
void close_graphics (void)
int init_postscript (char *fname)
void close_postscript (void)

Variables

static const int menu_font_size = 14
static t_buttonbutton
static int num_buttons
static int disp_type
static Display * display
static int screen_num
static GC gc
static GC gcxor
static GC gc_menus
static XFontStruct * font_info [MAX_FONT_SIZE+1]
static int font_is_loaded [MAX_FONT_SIZE+1]
static unsigned int display_width
static unsigned int display_height
static unsigned int top_width
static unsigned int top_height
static Window toplevel
static Window menu
static Window textarea
static float xleft
static float xright
static float ytop
static float ybot
static float saved_xleft
static float saved_xright
static float saved_ytop
static float saved_ybot
static float ps_left
static float ps_right
static float ps_top
static float ps_bot
static float ps_xmult
static float ps_ymult
static float xmult
static float ymult
static Colormap private_cmap
static char message [BUFSIZE] = "\0"
static int colors [NUM_COLOR]
static FILE * ps
static int currentcolor = BLACK
static int currentlinestyle = SOLID
static int currentlinewidth = 0
static int currentfontsize = 10

Detailed Description

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.

Definition in file graphics.c.


Define Documentation

#define BUTTON_TEXT_LEN   20

Definition at line 101 of file graphics.c.

#define max (   a,
 
)    (((a) > (b))? (a) : (b))

Definition at line 93 of file graphics.c.

#define MAX_FONT_SIZE   40

Largest point size of text

Definition at line 98 of file graphics.c.

#define MAXPIXEL   15000

MAXPIXEL and MINPIXEL are set to prevent what appears to be overflow with very large pixel values on the Sun X Server.

Definition at line 167 of file graphics.c.

#define min (   a,
 
)    ((a) > (b)? (b) : (a))

Definition at line 94 of file graphics.c.

#define MINPIXEL   -15000

Definition at line 168 of file graphics.c.

#define MWIDTH   104

width of menu window

Definition at line 96 of file graphics.c.

#define OFF   1
#define ON   0
#define PI   3.141592654

Definition at line 99 of file graphics.c.

#define T_AREA_HEIGHT   24

Height of text window

Definition at line 97 of file graphics.c.

#define XPOST (   worldx)    (((worldx)-xleft)*ps_xmult + ps_left)

Macros for translation from world to PostScript coordinates

Definition at line 80 of file graphics.c.

#define XTOWORLD (   x)    (((float) x)/xmult + xleft)

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).

Definition at line 89 of file graphics.c.

#define YPOST (   worldy)    (((worldy)-ybot)*ps_ymult + ps_bot)

Macros for translation from world to PostScript coordinates

Definition at line 81 of file graphics.c.

#define YTOWORLD (   y)    (((float) y)/ymult + ytop)

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).

Definition at line 90 of file graphics.c.


Function Documentation

static void adjustwin ( void(*)(void)  drawscreen) [static]

The window button was pressed. Let the user click on the two diagonally opposed corners, and zoom in on this area.

Definition at line 1787 of file graphics.c.

{
    XEvent report;
    int corner, xold, yold, x[2], y[2];

    corner = 0;
    xold = -1;
    yold = -1;                  /* Don't need to init yold, but stops compiler warning. */

    while(corner < 2)
        {
            XNextEvent(display, &report);
            switch (report.type)
                {
                case Expose:
#ifdef VERBOSE
                    printf("Got an expose event.\n");
                    printf("Count is: %d.\n", report.xexpose.count);
                    printf("Window ID is: %d.\n", report.xexpose.window);
#endif
                    if(report.xexpose.count != 0)
                        break;
                    if(report.xexpose.window == menu)
                        drawmenu();
                    else if(report.xexpose.window == toplevel)
                        {
                            drawscreen();
                            xold = -1;  /* No rubber band on screen */
                        }
                    else if(report.xexpose.window == textarea)
                        draw_message();
                    break;
                case ConfigureNotify:
                    top_width = report.xconfigure.width;
                    top_height = report.xconfigure.height;
                    update_transform();
#ifdef VERBOSE
                    printf("Got a ConfigureNotify.\n");
                    printf("New width: %d  New height: %d.\n", top_width,
                           top_height);
#endif
                    break;
                case ButtonPress:
#ifdef VERBOSE
                    printf("Got a buttonpress.\n");
                    printf("Window ID is: %d.\n", report.xbutton.window);
                    printf("Location (%d, %d).\n", report.xbutton.x,
                           report.xbutton.y);
#endif
                    if(report.xbutton.window != toplevel)
                        break;
                    x[corner] = report.xbutton.x;
                    y[corner] = report.xbutton.y;
                    if(corner == 0)
                        {
                            XSelectInput(display, toplevel, ExposureMask |
                                         StructureNotifyMask | ButtonPressMask
                                         | PointerMotionMask);
                        }
                    else
                        {
                            update_win(x, y, drawscreen);
                        }
                    corner++;
                    break;
                case MotionNotify:
#ifdef VERBOSE
                    printf("Got a MotionNotify Event.\n");
                    printf("x: %d    y: %d\n", report.xmotion.x,
                           report.xmotion.y);
#endif
                    if(xold >= 0)
                        {       /* xold set -ve before we draw first box */
                            XDrawRectangle(display, toplevel, gcxor,
                                           min(x[0], xold), min(y[0], yold),
                                           abs(x[0] - xold),
                                           abs(y[0] - yold));
                        }
                    /* Don't allow user to window under menu region */
                    xold = min(report.xmotion.x, top_width - 1 - MWIDTH);
                    yold = report.xmotion.y;
                    XDrawRectangle(display, toplevel, gcxor, min(x[0], xold),
                                   min(y[0], yold), abs(x[0] - xold),
                                   abs(y[0] - yold));
                    break;
                }
        }
    XSelectInput(display, toplevel, ExposureMask | StructureNotifyMask
                 | ButtonPressMask);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static float angnorm ( float  ang) [static]

Normalizes an angle to be between 0 and 360 degrees.

Definition at line 1346 of file graphics.c.

{
    int scale;

    if(ang < 0)
        {
            scale = (int)(ang / 360. - 1);
        }
    else
        {
            scale = (int)(ang / 360.);
        }
    ang = ang - scale * 360.;
    return (ang);
}

Here is the caller graph for this function:

static void build_default_menu ( void  ) [static]

Sets up the default menu buttons on the right hand side of the window.

Definition at line 462 of file graphics.c.

{
    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;
        }

    strcpy(button[4].text, "Zoom In");
    strcpy(button[5].text, "Zoom Out");
    strcpy(button[6].text, "Zoom Fit");
    strcpy(button[7].text, "Window");
    strcpy(button[8].text, "PostScript");
    strcpy(button[9].text, "Proceed");
    strcpy(button[10].text, "Exit");

    button[4].fcn = zoom_in;
    button[5].fcn = zoom_out;
    button[6].fcn = zoom_fit;
    button[7].fcn = adjustwin;
    button[8].fcn = postscript;
    button[9].fcn = proceed;
    button[10].fcn = quit;

    for(i = 0; i < num_buttons; i++)
        map_button(i);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void build_textarea ( void  ) [static]

Creates a small window at the top of the graphics area for text messages

Definition at line 419 of file graphics.c.

{
    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);
}

Here is the caller graph for this function:

void clearscreen ( void  )

Erases the screen

Definition at line 1196 of file graphics.c.

{
    int savecolor;

    if(disp_type == SCREEN)
        {
            XClearWindow(display, toplevel);
        }
    else
        {
/* erases current page.  Don't use erasepage, since this will erase *
 * everything, (even stuff outside the clipping path) causing       *
 * problems if this picture is incorporated into a larger document. */
            savecolor = currentcolor;
            setcolor(WHITE);
            fprintf(ps, "clippath fill\n\n");
            setcolor(savecolor);
        }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void close_graphics ( void  )

Release all my drawing structures (through the X server) and close down the connection.

Definition at line 1924 of file graphics.c.

{
    int i;

    for(i = 1; i <= MAX_FONT_SIZE; i++)
        if(font_is_loaded[i])
            XFreeFont(display, font_info[i]);

    XFreeGC(display, gc);
    XFreeGC(display, gcxor);
    XFreeGC(display, gc_menus);

    if(private_cmap != None)
        XFreeColormap(display, private_cmap);

    XCloseDisplay(display);
    free(button);
}

Here is the caller graph for this function:

void close_postscript ( void  )

Properly ends postscript output and redirects output to screen.

Definition at line 2081 of file graphics.c.

{
    fprintf(ps, "showpage\n");
    fprintf(ps, "\n%%%%Trailer\n");
    fclose(ps);
    disp_type = SCREEN;
    update_transform();         /* Ensure screen world reflects any changes      *
                                 * made while printing.                          */

/* Need to make sure that we really set up the graphics context --  *
 * don't want the change requested to match the current setting and *
 * do nothing -> force the changes.                                 */

    force_setcolor(currentcolor);
    force_setlinestyle(currentlinestyle);
    force_setlinewidth(currentlinewidth);
    force_setfontsize(currentfontsize);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void create_button ( char *  prev_button_text,
char *  button_text,
void(*)(void(*drawscreen)(void))  button_func 
)

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.

Definition at line 590 of file graphics.c.

{
    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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void destroy_button ( char *  button_text)

Destroys the button with text button_text.

Definition at line 655 of file graphics.c.

{
    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));
}

Here is the call graph for this function:

Here is the caller graph for this function:

void draw_message ( void  )

Draw the current message in the text area at the screen bottom.

Definition at line 1597 of file graphics.c.

{
    int len, width, savefontsize, savecolor;
    float ylow;

    if(disp_type == SCREEN)
        {
            XClearWindow(display, textarea);
            len = strlen(message);
            width = XTextWidth(font_info[menu_font_size], message, len);

            XSetForeground(display, gc_menus, colors[BLACK]);
            XDrawString(display, textarea, gc_menus,
                        (top_width - MWIDTH - width) / 2,
                        (T_AREA_HEIGHT - 4) / 2 +
                        (font_info[menu_font_size]->ascent -
                         font_info[menu_font_size]->descent) / 2, message,
                        len);
        }

    else
        {
/* Draw the message in the bottom margin.  Printer's generally can't  *
 * print on the bottom 1/4" (area with y < 18 in PostScript coords.)  */

            savecolor = currentcolor;
            setcolor(BLACK);
            savefontsize = currentfontsize;
            setfontsize(menu_font_size - 2);    /* Smaller OK on paper */
            ylow = ps_bot - 8.;
            fprintf(ps, "(%s) %.2f %.2f censhow\n", message,
                    (ps_left + ps_right) / 2., ylow);
            setcolor(savecolor);
            setfontsize(savefontsize);
        }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void drawarc ( float  xc,
float  yc,
float  rad,
float  startang,
float  angextent 
)

Draws a circular arc. X11 can do elliptical arcs quite simply, and PostScript could do them by scaling the coordinate axes. Too much work for now, and probably too complex an object for users to draw much, so I'm just doing circular arcs. Startang is relative to the Window's positive x direction. Angles in degrees.

Definition at line 1370 of file graphics.c.

{
    int xl, yt;
    unsigned int width, height;

/* Conservative (but fast) clip test -- check containing rectangle of *
 * a circle.                                                          */

    if(rect_off_screen(xc - rad, yc - rad, xc + rad, yc + rad))
        return;

/* X Windows has trouble with very large angles. (Over 360).    *
 * Do following to prevent its inaccurate (overflow?) problems. */
    if(fabs(angextent) > 360.)
        angextent = 360.;

    startang = angnorm(startang);

    if(disp_type == SCREEN)
        {
            xl = (int)(xcoord(xc) - fabs(xmult * rad));
            yt = (int)(ycoord(yc) - fabs(ymult * rad));
            width = (unsigned int)(2 * fabs(xmult * rad));
            height = width;
            XDrawArc(display, toplevel, gc, xl, yt, width, height,
                     (int)(startang * 64), (int)(angextent * 64));
        }
    else
        {
            fprintf(ps, "%.2f %.2f %.2f %.2f %.2f %s stroke\n", XPOST(xc),
                    YPOST(yc), fabs(rad * ps_xmult), startang,
                    startang + angextent,
                    (angextent < 0) ? "drawarcn" : "drawarc");
        }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void drawbut ( int  bnum) [static]

Draws button bnum in either its pressed or unpressed state.

Definition at line 894 of file graphics.c.

{
    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);
        }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void drawline ( float  x1,
float  y1,
float  x2,
float  y2 
)

Draw a line from (x1,y1) to (x2,y2) in the user-drawable area. Coordinates are in world (user) space.

Definition at line 1255 of file graphics.c.

{
    if(rect_off_screen(x1, y1, x2, y2))
        return;

    if(disp_type == SCREEN)
        {
            /* Xlib.h prototype has x2 and y1 mixed up. */
            XDrawLine(display, toplevel, gc, xcoord(x1), ycoord(y1),
                      xcoord(x2), ycoord(y2));
        }
    else
        {
            fprintf(ps, "%.2f %.2f %.2f %.2f drawline\n", XPOST(x1),
                    YPOST(y1), XPOST(x2), YPOST(y2));
        }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void drawmenu ( void  ) [static]

Definition at line 1025 of file graphics.c.

{
    int i;

    for(i = 0; i < num_buttons; i++)
        {
            drawbut(i);
        }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void drawrect ( float  x1,
float  y1,
float  x2,
float  y2 
)

(x1,y1) and (x2,y2) are diagonally opposed corners, in world coords.

Definition at line 1278 of file graphics.c.

{
    unsigned int width, height;
    int xw1, yw1, xw2, yw2, xl, yt;

    if(rect_off_screen(x1, y1, x2, y2))
        return;

    if(disp_type == SCREEN)
        {
/* translate to X Windows calling convention. */
            xw1 = xcoord(x1);
            xw2 = xcoord(x2);
            yw1 = ycoord(y1);
            yw2 = ycoord(y2);
            xl = min(xw1, xw2);
            yt = min(yw1, yw2);
            width = abs(xw1 - xw2);
            height = abs(yw1 - yw2);
            XDrawRectangle(display, toplevel, gc, xl, yt, width, height);
        }
    else
        {
            fprintf(ps, "%.2f %.2f %.2f %.2f drawrect\n", XPOST(x1),
                    YPOST(y1), XPOST(x2), YPOST(y2));
        }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void drawtext ( float  xc,
float  yc,
const char *  text,
float  boundx 
)

Draws text centered on xc,yc if it fits in boundx

Definition at line 1517 of file graphics.c.

{
    int len, width, xw_off, yw_off;

    len = strlen(text);
    width = XTextWidth(font_info[currentfontsize], text, len);
    if(width > fabs(boundx * xmult))
        return;                 /* Don't draw if it won't fit */

    xw_off = width / (2. * xmult);      /* NB:  sign doesn't matter. */

/* NB:  2 * descent makes this slightly conservative but simplifies code. */
    yw_off = (font_info[currentfontsize]->ascent +
              2 * font_info[currentfontsize]->descent) / (2. * ymult);

/* Note:  text can be clipped when a little bit of it would be visible *
 * right now.  Perhaps X doesn't return extremely accurate width and   *
 * ascent values, etc?  Could remove this completely by multiplying    *
 * xw_off and yw_off by, 1.2 or 1.5.                                   */

    if(rect_off_screen(xc - xw_off, yc - yw_off, xc + xw_off, yc + yw_off))
        return;

    if(disp_type == SCREEN)
        {
            XDrawString(display, toplevel, gc, xcoord(xc) - width / 2,
                        ycoord(yc) + (font_info[currentfontsize]->ascent -
                                      font_info[currentfontsize]->descent) /
                        2, text, len);
        }
    else
        {
            fprintf(ps, "(%s) %.2f %.2f censhow\n", text, XPOST(xc),
                    YPOST(yc));
        }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void event_loop ( void(*)(float x, float y)  act_on_button,
void(*)(void)  drawscreen 
)

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.

Definition at line 1115 of file graphics.c.

{
    XEvent report;
    int bnum;
    float x, y;

#define OFF 1
#define ON 0

    turn_on_off(ON);
    while(1)
        {
            XNextEvent(display, &report);
            switch (report.type)
                {
                case Expose:
#ifdef VERBOSE
                    printf("Got an expose event.\n");
                    printf("Count is: %d.\n", report.xexpose.count);
                    printf("Window ID is: %d.\n", report.xexpose.window);
#endif
                    if(report.xexpose.count != 0)
                        break;
                    if(report.xexpose.window == menu)
                        drawmenu();
                    else if(report.xexpose.window == toplevel)
                        drawscreen();
                    else if(report.xexpose.window == textarea)
                        draw_message();
                    break;
                case ConfigureNotify:
                    top_width = report.xconfigure.width;
                    top_height = report.xconfigure.height;
                    update_transform();
#ifdef VERBOSE
                    printf("Got a ConfigureNotify.\n");
                    printf("New width: %d  New height: %d.\n", top_width,
                           top_height);
#endif
                    break;
                case ButtonPress:
#ifdef VERBOSE
                    printf("Got a buttonpress.\n");
                    printf("Window ID is: %d.\n", report.xbutton.window);
#endif
                    if(report.xbutton.window == toplevel)
                        {
                            x = XTOWORLD(report.xbutton.x);
                            y = YTOWORLD(report.xbutton.y);
                            act_on_button(x, y);
                        }
                    else
                        {       /* A menu button was pressed. */
                            bnum = which_button(report.xbutton.window);
#ifdef VERBOSE
                            printf("Button number is %d\n", bnum);
#endif
                            button[bnum].ispressed = 1;
                            drawbut(bnum);
                            XFlush(display);    /* Flash the button */
                            button[bnum].fcn(drawscreen);
                            button[bnum].ispressed = 0;
                            drawbut(bnum);
                            if(button[bnum].fcn == proceed)
                                {
                                    turn_on_off(OFF);
                                    flushinput();
                                    return;     /* Rather clumsy way of returning *
                                                 * control to the simulator       */
                                }
                        }
                    break;
                }
        }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void fillarc ( float  xc,
float  yc,
float  rad,
float  startang,
float  angextent 
)

Fills a circular arc. Startang is relative to the Window's positive x direction. Angles in degrees.

Definition at line 1415 of file graphics.c.

{

    int xl, yt;
    unsigned int width, height;

/* Conservative (but fast) clip test -- check containing rectangle of *
 * a circle.                                                          */

    if(rect_off_screen(xc - rad, yc - rad, xc + rad, yc + rad))
        return;

/* X Windows has trouble with very large angles. (Over 360).    *
 * Do following to prevent its inaccurate (overflow?) problems. */

    if(fabs(angextent) > 360.)
        angextent = 360.;

    startang = angnorm(startang);

    if(disp_type == SCREEN)
        {
            xl = (int)(xcoord(xc) - fabs(xmult * rad));
            yt = (int)(ycoord(yc) - fabs(ymult * rad));
            width = (unsigned int)(2 * fabs(xmult * rad));
            height = width;
            XFillArc(display, toplevel, gc, xl, yt, width, height,
                     (int)(startang * 64), (int)(angextent * 64));
        }
    else
        {
            fprintf(ps, "%.2f %.2f %.2f %.2f %.2f %s\n", fabs(rad * ps_xmult),
                    startang, startang + angextent, XPOST(xc), YPOST(yc),
                    (angextent < 0) ? "fillarcn" : "fillarc");
        }
}

Here is the call graph for this function:

void fillpoly ( t_point points,
int  npoints 
)

Definition at line 1458 of file graphics.c.

{

    XPoint transpoints[MAXPTS];
    int i;
    float xmin, ymin, xmax, ymax;

    if(npoints > MAXPTS)
        {
            printf
                ("Error in fillpoly:  Only %d points allowed per polygon.\n",
                 MAXPTS);
            printf("%d points were requested.  Polygon is not drawn.\n",
                   npoints);
            return;
        }

/* Conservative (but fast) clip test -- check containing rectangle of *
 * polygon.                                                           */

    xmin = xmax = points[0].x;
    ymin = ymax = points[0].y;

    for(i = 1; i < npoints; i++)
        {
            xmin = min(xmin, points[i].x);
            xmax = max(xmax, points[i].x);
            ymin = min(ymin, points[i].y);
            ymax = max(ymax, points[i].y);
        }

    if(rect_off_screen(xmin, ymin, xmax, ymax))
        return;

    if(disp_type == SCREEN)
        {
            for(i = 0; i < npoints; i++)
                {
                    transpoints[i].x = (short)xcoord(points[i].x);
                    transpoints[i].y = (short)ycoord(points[i].y);
                }
            XFillPolygon(display, toplevel, gc, transpoints, npoints, Complex,
                         CoordModeOrigin);
        }
    else
        {
            fprintf(ps, "\n");

            for(i = npoints - 1; i >= 0; i--)
                fprintf(ps, "%.2f %.2f\n", XPOST(points[i].x),
                        YPOST(points[i].y));

            fprintf(ps, "%d fillpoly\n", npoints);
        }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void fillrect ( float  x1,
float  y1,
float  x2,
float  y2 
)

(x1,y1) and (x2,y2) are diagonally opposed corners in world coords.

Definition at line 1312 of file graphics.c.

{
    unsigned int width, height;
    int xw1, yw1, xw2, yw2, xl, yt;

    if(rect_off_screen(x1, y1, x2, y2))
        return;

    if(disp_type == SCREEN)
        {
/* translate to X Windows calling convention. */
            xw1 = xcoord(x1);
            xw2 = xcoord(x2);
            yw1 = ycoord(y1);
            yw2 = ycoord(y2);
            xl = min(xw1, xw2);
            yt = min(yw1, yw2);
            width = abs(xw1 - xw2);
            height = abs(yw1 - yw2);
            XFillRectangle(display, toplevel, gc, xl, yt, width, height);
        }
    else
        {
            fprintf(ps, "%.2f %.2f %.2f %.2f fillrect\n", XPOST(x1),
                    YPOST(y1), XPOST(x2), YPOST(y2));
        }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void flushinput ( void  )

Empties event queue

Definition at line 1559 of file graphics.c.

{
    if(disp_type != SCREEN)
        return;
    XFlush(display);
}

Here is the caller graph for this function:

static void force_setcolor ( int  cindex) [static]

Definition at line 269 of file graphics.c.

{

    static char *ps_cnames[NUM_COLOR] =
        { "white", "black", "grey55", "grey75",
        "blue", "green", "yellow", "cyan", "red", "darkgreen", "magenta", 
        "bisque", "lightblue", "thistle", "plum", "khaki", 
        "coral", "turquoise", "mediumpurple", "darkslateblue", "darkkhaki"
    };

    currentcolor = cindex;

    if(disp_type == SCREEN)
        {
            XSetForeground(display, gc, colors[cindex]);
        }
    else
        {
            fprintf(ps, "%s\n", ps_cnames[cindex]);
        }
}

Here is the caller graph for this function:

static void force_setfontsize ( int  pointsize) [static]

Definition at line 372 of file graphics.c.

{

/* 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);
        }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void force_setlinestyle ( int  linestyle) [static]

Definition at line 306 of file graphics.c.

{

/* 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]);
        }
}

Here is the caller graph for this function:

static void force_setlinewidth ( int  linewidth) [static]

Definition at line 340 of file graphics.c.

{

/* 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);
        }
}

Here is the caller graph for this function:

int getcolor ( )

Definition at line 300 of file graphics.c.

{
    return currentcolor;
}

Here is the caller graph for this function:

void init_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.

Definition at line 701 of file graphics.c.

{

    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", 
        "bisque", "lightblue", "thistle", "plum", "khaki", 
        "coral", "turquoise", "mediumpurple", "darkslateblue", "darkkhaki"
    };

    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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int init_postscript ( char *  fname)

Opens a file for PostScript output. The header information, clipping path, etc. are all dumped out. If the file could not be opened, the routine returns 0; otherwise it returns 1.

Definition at line 1949 of file graphics.c.

{
    ps = fopen(fname, "w");
    if(ps == NULL)
        {
            printf("Error: could not open %s for PostScript output.\n",
                   fname);
            printf("Drawing to screen instead.\n");
            return (0);
        }
    disp_type = POSTSCRIPT;     /* Graphics go to postscript file now. */

/* Header for minimal conformance with the Adobe structuring convention */
    fprintf(ps, "%%!PS-Adobe-1.0\n");
    fprintf(ps, "%%%%DocumentFonts: Helvetica\n");
    fprintf(ps, "%%%%Pages: 1\n");
/* Set up postscript transformation macros and page boundaries */
    update_ps_transform();
/* Bottom margin is at ps_bot - 15. to leave room for the on-screen message. */
    fprintf(ps, "%%%%BoundingBox: %d %d %d %d\n",
            (int)ps_left, (int)(ps_bot - 15.), (int)ps_right, (int)ps_top);
    fprintf(ps, "%%%%EndComments\n");

    fprintf(ps, "/censhow   %%draw a centered string\n");
    fprintf(ps, " { moveto               %% move to proper spot\n");
    fprintf(ps, "   dup stringwidth pop  %% get x length of string\n");
    fprintf(ps, "   -2 div               %% Proper left start\n");
    fprintf(ps,
            "   yoff rmoveto         %% Move left that much and down half font height\n");
    fprintf(ps, "   show newpath } def   %% show the string\n\n");

    fprintf(ps, "/setfontsize     %% set font to desired size and compute "
            "centering yoff\n");
    fprintf(ps, " { /Helvetica findfont\n");
    fprintf(ps, "   exch scalefont\n");
    fprintf(ps, "   setfont         %% Font size set ...\n\n");
    fprintf(ps, "   0 0 moveto      %% Get vertical centering offset\n");
    fprintf(ps, "   (Xg) true charpath\n");
    fprintf(ps, "   flattenpath pathbbox\n");
    fprintf(ps, "   /ascent exch def pop -1 mul /descent exch def pop\n");
    fprintf(ps, "   newpath\n");
    fprintf(ps, "   descent ascent sub 2 div /yoff exch def } def\n\n");

    fprintf(ps, "%% Next two lines for debugging only.\n");
    fprintf(ps, "/str 20 string def\n");
    fprintf(ps, "/pnum {str cvs print (  ) print} def\n");

    fprintf(ps, "/drawline      %% draw a line from (x2,y2) to (x1,y1)\n");
    fprintf(ps, " { moveto lineto stroke } def\n\n");

    fprintf(ps, "/rect          %% outline a rectangle \n");
    fprintf(ps, " { /y2 exch def /x2 exch def /y1 exch def /x1 exch def\n");
    fprintf(ps, "   x1 y1 moveto\n");
    fprintf(ps, "   x2 y1 lineto\n");
    fprintf(ps, "   x2 y2 lineto\n");
    fprintf(ps, "   x1 y2 lineto\n");
    fprintf(ps, "   closepath } def\n\n");

    fprintf(ps, "/drawrect      %% draw outline of a rectanagle\n");
    fprintf(ps, " { rect stroke } def\n\n");

    fprintf(ps, "/fillrect      %% fill in a rectanagle\n");
    fprintf(ps, " { rect fill } def\n\n");

    fprintf(ps, "/drawarc { arc stroke } def           %% draw an arc\n");
    fprintf(ps, "/drawarcn { arcn stroke } def "
            "        %% draw an arc in the opposite direction\n\n");

    fprintf(ps, "%%Fill a counterclockwise or clockwise arc sector, "
            "respectively.\n");
    fprintf(ps,
            "/fillarc { moveto currentpoint 5 2 roll arc closepath fill } "
            "def\n");
    fprintf(ps,
            "/fillarcn { moveto currentpoint 5 2 roll arcn closepath fill } "
            "def\n\n");

    fprintf(ps,
            "/fillpoly { 3 1 roll moveto         %% move to first point\n"
            "   2 exch 1 exch {pop lineto} for   %% line to all other points\n"
            "   closepath fill } def\n\n");


    fprintf(ps, "%%Color Definitions:\n");
    fprintf(ps, "/white { 1 setgray } def\n");
    fprintf(ps, "/black { 0 setgray } def\n");
    fprintf(ps, "/grey55 { .55 setgray } def\n");
    fprintf(ps, "/grey75 { .75 setgray } def\n");
    fprintf(ps, "/blue { 0 0 1 setrgbcolor } def\n");
    fprintf(ps, "/green { 0 1 0 setrgbcolor } def\n");
    fprintf(ps, "/yellow { 1 1 0 setrgbcolor } def\n");
    fprintf(ps, "/cyan { 0 1 1 setrgbcolor } def\n");
    fprintf(ps, "/red { 1 0 0 setrgbcolor } def\n");
    fprintf(ps, "/darkgreen { 0 0.5 0 setrgbcolor } def\n");
    fprintf(ps, "/magenta { 1 0 1 setrgbcolor } def\n");
        fprintf(ps, "/bisque { 1 0.9 0.8 setrgbcolor } def\n");
        fprintf(ps, "/lightblue { 0.7 0.8 0.9 setrgbcolor } def\n");
        fprintf(ps, "/thistle { 0.8 0.7 0.8 setrgbcolor } def\n");
        fprintf(ps, "/plum {0.8 0.6 0.8 setrgbcolor } def\n");
        fprintf(ps, "/khaki { 1 0.9 0.6 setrgbcolor } def\n");
        fprintf(ps, "/coral { 1 0.7 0.6 setrgbcolor } def\n");
        fprintf(ps, "/turquoise { 0.5 0.6 0.9 setrgbcolor } def\n");
        fprintf(ps, "/mediumpurple { 0.7 0.6 0.7 setrgbcolor } def\n");
        fprintf(ps, "/darkslateblue { 0.7 0.5 0.7 setrgbcolor } def\n");
        fprintf(ps, "/darkkhaki { 0.9 0.7 0.4 setrgbcolor } def\n");

    fprintf(ps, "\n%%Solid and dashed line definitions:\n");
    fprintf(ps, "/linesolid {[] 0 setdash} def\n");
    fprintf(ps, "/linedashed {[3 3] 0 setdash} def\n");

    fprintf(ps, "\n%%%%EndProlog\n");
    fprintf(ps, "%%%%Page: 1 1\n\n");

/* Set up PostScript graphics state to match current one. */
    force_setcolor(currentcolor);
    force_setlinestyle(currentlinestyle);
    force_setlinewidth(currentlinewidth);
    force_setfontsize(currentfontsize);

/* Draw this in the bottom margin -- must do before the clippath is set */
    draw_message();

/* Set clipping on page. */
    fprintf(ps, "%.2f %.2f %.2f %.2f rect ", ps_left, ps_bot, ps_right,
            ps_top);
    fprintf(ps, "clip newpath\n\n");

    return (1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void init_world ( float  x1,
float  y1,
float  x2,
float  y2 
)

Sets the coordinate system the user wants to draw into.

Definition at line 1569 of file graphics.c.

{
    xleft = x1;
    xright = x2;
    ytop = y1;
    ybot = y2;

    saved_xleft = xleft;        /* Save initial world coordinates to allow full */
    saved_xright = xright;      /* view button to zoom all the way out.         */
    saved_ytop = ytop;
    saved_ybot = ybot;

    if(disp_type == SCREEN)
        {
            update_transform();
        }
    else
        {
            update_ps_transform();
        }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void load_font ( int  pointsize) [static]

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

Definition at line 246 of file graphics.c.

{
    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);
        }
}

Here is the caller graph for this function:

static void map_button ( int  bnum) [static]

Maps a button onto the screen and set it up for input, etc.

Definition at line 563 of file graphics.c.

{
    button[bnum].win = XCreateSimpleWindow(display, menu,
                                           button[bnum].xleft,
                                           button[bnum].ytop,
                                           button[bnum].width,
                                           button[bnum].height, 0,
                                           colors[WHITE], colors[LIGHTGREY]);
    XMapWindow(display, button[bnum].win);
    XSelectInput(display, button[bnum].win, ButtonPressMask);
    button[bnum].ispressed = 1;
}

Here is the caller graph for this function:

static void menutext ( Window  win,
int  xc,
int  yc,
char *  text 
) [static]

draws text center at xc, yc -- used only by menu drawing stuff

Definition at line 877 of file graphics.c.

{
    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);
}

Here is the caller graph for this function:

static void postscript ( void(*)(void)  drawscreen) [static]

Takes a snapshot of the screen and stores it in pic?.ps. The first picture goes in pic1.ps, the second in pic2.ps, etc.

Definition at line 1883 of file graphics.c.

{
    static int piccount = 1;
    int success;
    char fname[20];

    sprintf(fname, "pic%d.ps", piccount);
    success = init_postscript(fname);

    if(success == 0)
        return;                 /* Couldn't open file, abort. */

    drawscreen();
    close_postscript();
    piccount++;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void proceed ( void(*)(void)  drawscreen) [static]

Dummy routine. Just exit the event loop.

Definition at line 1903 of file graphics.c.

{

    /* Dummy routine.  Just exit the event loop. */

}

Here is the caller graph for this function:

static void quit ( void(*)(void)  drawscreen) [static]

Definition at line 1912 of file graphics.c.

{

    close_graphics();
    exit(0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int rect_off_screen ( float  x1,
float  y1,
float  x2,
float  y2 
) [static]

Return 1 if I can quarantee no part of this rectangle will lie within the user drawing area. Otherwise return 0. Note: this routine is only used to help speed (and to shrink ps files) -- it will be highly effective when the graphics are zoomed in and lots are off-screen. I don't have to pre-clip for correctness.

Definition at line 1224 of file graphics.c.

{
    float xmin, xmax, ymin, ymax;

    xmin = min(xleft, xright);
    if(x1 < xmin && x2 < xmin)
        return (1);

    xmax = max(xleft, xright);
    if(x1 > xmax && x2 > xmax)
        return (1);

    ymin = min(ytop, ybot);
    if(y1 < ymin && y2 < ymin)
        return (1);

    ymax = max(ytop, ybot);
    if(y1 > ymax && y2 > ymax)
        return (1);

    return (0);
}

Here is the caller graph for this function:

void setcolor ( int  cindex)

Use a constant from clist

Definition at line 293 of file graphics.c.

{

    if(currentcolor != cindex)
        force_setcolor(cindex);
}

Here is the call graph for this function:

Here is the caller graph for this function:

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).

Definition at line 410 of file graphics.c.

{
    if(pointsize != currentfontsize)
        force_setfontsize(pointsize);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void setlinestyle ( int  linestyle)

Definition at line 331 of file graphics.c.

{

    if(linestyle != currentlinestyle)
        force_setlinestyle(linestyle);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void setlinewidth ( int  linewidth)

Definition at line 363 of file graphics.c.

{

    if(linewidth != currentlinewidth)
        force_setlinewidth(linewidth);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void setpoly ( int  bnum,
int  xc,
int  yc,
int  r,
float  theta 
) [static]

Puts a triangle in the poly array for button[bnum]

Definition at line 441 of file graphics.c.

{
    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;
        }
}

Here is the caller graph for this function:

static Bool test_if_exposed ( Display *  disp,
XEvent *  event_ptr,
XPointer  dummy 
) [static]

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.

Definition at line 861 of file graphics.c.

{

    if(event_ptr->type == Expose)
        {
            return (True);
        }

    return (False);
}

Here is the caller graph for this function:

static void translate_down ( void(*)(void)  drawscreen) [static]

Moves view 1/2 screen down.

Definition at line 1713 of file graphics.c.

{
    float ystep;

    ystep = (ybot - ytop) / 2.;
    ytop += ystep;
    ybot += ystep;
    update_transform();
    drawscreen();
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void translate_left ( void(*)(void)  drawscreen) [static]

Moves view 1/2 screen left.

Definition at line 1727 of file graphics.c.

{
    float xstep;

    xstep = (xright - xleft) / 2.;
    xleft -= xstep;
    xright -= xstep;
    update_transform();
    drawscreen();
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void translate_right ( void(*)(void)  drawscreen) [static]

Moves view 1/2 screen right.

Definition at line 1741 of file graphics.c.

{
    float xstep;

    xstep = (xright - xleft) / 2.;
    xleft += xstep;
    xright += xstep;
    update_transform();
    drawscreen();
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void translate_up ( void(*)(void)  drawscreen) [static]

Moves view 1/2 screen up.

Definition at line 1699 of file graphics.c.

{
    float ystep;

    ystep = (ybot - ytop) / 2.;
    ytop -= ystep;
    ybot -= ystep;
    update_transform();
    drawscreen();
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void turn_on_off ( int  pressed) [static]

Shows when the menu is active or inactive by colouring the buttons.

Definition at line 996 of file graphics.c.

{

    int i;

    for(i = 0; i < num_buttons; i++)
        {
            button[i].ispressed = pressed;
            drawbut(i);
        }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void unmap_button ( int  bnum) [static]

Unmaps a button from the screen.

Definition at line 579 of file graphics.c.

{
    XUnmapWindow(display, button[bnum].win);
}

Here is the caller graph for this function:

void update_message ( char *  msg)

Changes the message to be displayed on screen.

Definition at line 1637 of file graphics.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void update_ps_transform ( void  ) [static]

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.

Definition at line 1076 of file graphics.c.

{
    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;
        }
}

Here is the caller graph for this function:

static void update_transform ( void  ) [static]

Set up the factors for transforming from the user world to X Windows coordinates.

Definition at line 1040 of file graphics.c.

{
    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);
}

Here is the caller graph for this function:

static void update_win ( int  x[2],
int  y[2],
void(*)(void)  drawscreen 
) [static]

Definition at line 1754 of file graphics.c.

{
    float x1, x2, y1, y2;

    x[0] = min(x[0], top_width - MWIDTH);       /* Can't go under menu */
    x[1] = min(x[1], top_width - MWIDTH);
    y[0] = min(y[0], top_height - T_AREA_HEIGHT);       /* Can't go under text area */
    y[1] = min(y[1], top_height - T_AREA_HEIGHT);

    if((x[0] == x[1]) || (y[0] == y[1]))
        {
            printf("Illegal (zero area) window.  Window unchanged.\n");
            return;
        }
    x1 = XTOWORLD(min(x[0], x[1]));
    x2 = XTOWORLD(max(x[0], x[1]));
    y1 = YTOWORLD(min(y[0], y[1]));
    y2 = YTOWORLD(max(y[0], y[1]));
    xleft = x1;
    xright = x2;
    ytop = y1;
    ybot = y2;
    update_transform();
    drawscreen();
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int which_button ( Window  win) [static]

Definition at line 1010 of file graphics.c.

{
    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);
}

Here is the caller graph for this function:

static int xcoord ( float  worldx) [static]

Translates from my internal coordinates to X Windows coordinates * in the x direction. Add 0.5 at end for extra half-pixel accuracy.

Definition at line 201 of file graphics.c.

{
    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);
}

Here is the caller graph for this function:

static int ycoord ( float  worldy) [static]

Translates from my internal coordinates to X Windows coordinates in the y direction. Add 0.5 at end for extra half-pixel accuracy.

Definition at line 228 of file graphics.c.

{
    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);
}

Here is the caller graph for this function:

static void zoom_fit ( void(*)(void)  drawscreen) [static]

Sets the view back to the initial view set by init_world (i.e. a full view) of all the graphics.

Definition at line 1684 of file graphics.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void zoom_in ( void(*)(void)  drawscreen) [static]

Zooms in by a factor of 1.666.

Definition at line 1646 of file graphics.c.

{
    float xdiff, ydiff;

    xdiff = xright - xleft;
    ydiff = ybot - ytop;
    xleft += xdiff / 5.;
    xright -= xdiff / 5.;
    ytop += ydiff / 5.;
    ybot -= ydiff / 5.;

    update_transform();
    drawscreen();
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void zoom_out ( void(*)(void)  drawscreen) [static]

Zooms out by a factor of 1.666.

Definition at line 1664 of file graphics.c.

{
    float xdiff, ydiff;

    xdiff = xright - xleft;
    ydiff = ybot - ytop;
    xleft -= xdiff / 3.;
    xright += xdiff / 3.;
    ytop -= ydiff / 3.;
    ybot += ydiff / 3.;

    update_transform();
    drawscreen();
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

t_button* button [static]

[0..num_buttons-1]

Definition at line 126 of file graphics.c.

int colors[NUM_COLOR] [static]

Color indices passed back from X Windows.

Definition at line 160 of file graphics.c.

int currentcolor = BLACK [static]

Graphics state. Set start-up defaults here.

Definition at line 151 of file graphics.c.

int currentfontsize = 10 [static]

Graphics state. Set start-up defaults here.

Definition at line 154 of file graphics.c.

int currentlinestyle = SOLID [static]

Graphics state. Set start-up defaults here.

Definition at line 152 of file graphics.c.

int currentlinewidth = 0 [static]

Graphics state. Set start-up defaults here.

Definition at line 153 of file graphics.c.

int disp_type [static]

Selects SCREEN or POSTSCRIPT

Definition at line 129 of file graphics.c.

Display* display [static]

Definition at line 130 of file graphics.c.

unsigned int display_height

screen size

Definition at line 135 of file graphics.c.

unsigned int display_width [static]

Definition at line 135 of file graphics.c.

XFontStruct* font_info[MAX_FONT_SIZE+1] [static]

Data for each size

Definition at line 133 of file graphics.c.

int font_is_loaded[MAX_FONT_SIZE+1] [static]

1: loaded, 0: not

Definition at line 134 of file graphics.c.

GC gc [static]

Definition at line 132 of file graphics.c.

Definition at line 132 of file graphics.c.

GC gcxor

Definition at line 132 of file graphics.c.

Window menu

Definition at line 137 of file graphics.c.

const int menu_font_size = 14 [static]

Font for menus and dialog boxes.

Definition at line 124 of file graphics.c.

char message[BUFSIZE] = "\0" [static]

User message to display

Definition at line 157 of file graphics.c.

int num_buttons [static]

Number of menu buttons

Definition at line 127 of file graphics.c.

Colormap private_cmap [static]

"None" unless a private cmap was allocated.

Definition at line 147 of file graphics.c.

FILE* ps [static]

For PostScript output

Definition at line 163 of file graphics.c.

float ps_bot

Figure boundaries for PostScript output, in PostScript coordinates.

Definition at line 143 of file graphics.c.

float ps_left [static]

Definition at line 143 of file graphics.c.

float ps_right

Definition at line 143 of file graphics.c.

float ps_top

Definition at line 143 of file graphics.c.

float ps_xmult [static]

Definition at line 145 of file graphics.c.

float ps_ymult

Transformation for PostScript.

Definition at line 145 of file graphics.c.

float saved_xleft [static]

Initial world coordinates

Definition at line 141 of file graphics.c.

float saved_xright

Definition at line 141 of file graphics.c.

float saved_ybot

Definition at line 141 of file graphics.c.

float saved_ytop

Definition at line 141 of file graphics.c.

int screen_num [static]

Definition at line 131 of file graphics.c.

Window textarea

various windows

Definition at line 137 of file graphics.c.

unsigned int top_height

window size

Definition at line 136 of file graphics.c.

unsigned int top_width [static]

Definition at line 136 of file graphics.c.

Window toplevel [static]

Definition at line 137 of file graphics.c.

float xleft [static]

Definition at line 138 of file graphics.c.

float xmult [static]

Definition at line 146 of file graphics.c.

float xright

Definition at line 138 of file graphics.c.

float ybot

world coordinates

Definition at line 138 of file graphics.c.

float ymult

Transformation factors

Definition at line 146 of file graphics.c.

float ytop

Definition at line 138 of file graphics.c.