1/* 2 * Hardcopy Interface for Xgraph 3 * 4 * Major differences from first version: 5 * A flags argument has been added to xg_init(). This new argument 6 * is used to specify a new binary option: D_DOCU. See below 7 * for details. 8 * 9 * Four new parameters are passed to the device initialization routine: 10 * title_family, title_size, axis_family, and axis_size. See the 11 * description of xg_init() for details. 12 * 13 * Clipping is done automatically by xgraph. The xg_clip() routine 14 * is obsolete. 15 * 16 * The xg_line() routine has become the xg_seg() routine. It now 17 * draws segments rather than a series of lines. 18 * 19 * A new field (max_segs) in the device structure now specifies 20 * the maximum number of segments the device can handle in a group. 21 */ 22 23 24/* 25 * Adding an output device to xgraph 26 * 27 * Step 1 28 * Write versions of the following routines for your device: 29 * xg_init(), xg_text(), xg_seg(), xg_dot(), and xg_end(). 30 * The interface and function of these routines are described 31 * in detail below. These routines should be named according 32 * to your device. For example, the initialization routine 33 * for the Postscript output device is psInit(). Also, name 34 * your source file after your device (e.g. the postscript 35 * routines are in the file ps.c). Instructions continue 36 * after the description of the interface routines. 37 * 38 * The definitions below are quoted here as a convenience. In 39 * your output module, you can include "xgout.h" to obtain these 40 * definitions. 41 */ 42 43#define D_COLOR 0x01 44#define ERRBUFSIZE 2048 45 46#define D_DOCU 0x01 47 48typedef struct xg_out { 49 int dev_flags; /* Device characteristic flags */ 50 int area_w, area_h; /* Width and height in pixels */ 51 int bdr_pad; /* Padding from border */ 52 int axis_pad; /* Extra space around axis labels */ 53 int tick_len; /* Length of a tick mark */ 54 int legend_pad; /* Top of legend text to legend line */ 55 int axis_width; /* Width of big character of axis font */ 56 int axis_height; /* Height of big character of axis font */ 57 int title_width; /* Width of big character of title font */ 58 int title_height; /* Height of big character of title font */ 59 int max_segs; /* Maximum number of segments in group */ 60 61 void (*xg_text)(); /* Draws text at a location */ 62 void (*xg_seg)(); /* Draws a series of segments */ 63 void (*xg_dot)(); /* Draws a dot or marker at a location */ 64 void (*xg_end)(); /* Stops the drawing sequence */ 65 66 char *user_state; /* User supplied state information */ 67} xgOut; 68 69 70int xg_init(strm, width, height, title_family, title_size, 71 axis_family, axis_size, out_info, errmsg) 72FILE *strm; /* Output stream */ 73int width, height; /* Size of space (microns) */ 74char *title_family; /* Name of title font family */ 75double title_size; /* Title font height (points) */ 76char *axis_family; /* Name of axis font family */ 77double axis_size; /* Axis font height (points) */ 78int flags; /* Flags (see below) */ 79xgOut *out_info; /* Device info (RETURN) */ 80char errmsg[ERRBUFSIZE]; /* Error message area */ 81/* 82 * This routine is called by xgraph just before drawing is to 83 * begin. The desired size of the plot is given by `width' 84 * and `height'. The parameters `title_family', `title_size', 85 * `axis_family', and `axis_size' specify the names of the 86 * title and axis fonts and their vertical sizes (in points). 87 * These parameters can be ignored if your device does not 88 * support multiple fonts. The `flags' argument specifies 89 * certain binary flags to the output routines. These 90 * flags are: 91 * D_DOCU: 92 * If this flag is set, it indicates the user has specified that 93 * the output will be included in some larger document. Devices 94 * may choose to use this information to produce output that 95 * can be integrated into documents with less effort. For example, 96 * the Postscript output routines produce bounding box information 97 * when this flag is set. 98 * The routine should fill in all of the fields of `out_info' with 99 * appropriate values. The values are described below: 100 * area_w, area_h: 101 * Size of the drawing space in device coordinates. 102 * This should take in account the requested area 103 * given by `width', and `height'. 104 * bdr_pad: 105 * Xgraph will leave this number of device coordinates around 106 * all of the outer edges of the graph. 107 * axis_pad: 108 * Additional space around axis labels (in devcoords) 109 * so that the labels do not appear crowded. 110 * legend_pad: 111 * Space (in devcoords) from the top of legend text to 112 * the representative line drawn above the legend text. 113 * tick_len: 114 * Size of a tick mark placed on axis (in devcoords) 115 * axis_width: 116 * An estimate of the width of a large character in 117 * the axis font (in devcoords). This can be an overestimate. An 118 * underestimate may produce bad results. 119 * axis_height: 120 * An estimate of the height of a large character in 121 * the axis labeling font (in devcoords). 122 * title_width, title_height: 123 * Same as above except for the title font. 124 * max_segs: 125 * Due to buffering constraints, some devices may not be able to 126 * handle massive segment lists. This parameter tells xgraph not 127 * to send more than `max_segs' segments in one request. 128 * Output to the device should be written to the stream `strm'. 129 * The functions are described individually below. After filling 130 * in the parameters and setting the function pointers, the routine 131 * should initialize its drawing state and store any extra needed 132 * information in `user_state'. This value will be passed to all 133 * other routines during the drawing sequence. If the device 134 * cannot initialize, it should return a zero status and fill 135 * `errmsg' with an informative error message. 136 */ 137 138/* Text justifications */ 139#define T_CENTER 0 140#define T_LEFT 1 141#define T_UPPERLEFT 2 142#define T_TOP 3 143#define T_UPPERRIGHT 4 144#define T_RIGHT 5 145#define T_LOWERRIGHT 6 146#define T_BOTTOM 7 147#define T_LOWERLEFT 8 148 149/* Text styles */ 150#define T_AXIS 0 151#define T_TITLE 1 152 153void xg_text(user_state, x, y, text, just, style) 154char *user_state; /* Value set in xg_init */ 155int x, y; /* Text position (pixels) */ 156char *text; /* Null terminated text */ 157int just; /* Justification (above) */ 158int style; /* Text style (above) */ 159/* 160 * This routine should draw text at the indicated position using 161 * the indicated justification and style. The justification refers 162 * to the location of the point in reference to the text. For example, 163 * if just is T_LOWERLEFT, (x,y) should be located at the lower left 164 * edge of the text string. 165 */ 166 167/* Line Styles */ 168#define L_AXIS 0 169#define L_ZERO 1 170#define L_VAR 2 171 172void xg_seg(user_state, ns, seglist, width, style, lappr, color) 173char *user_state; /* Value set in xg_init */ 174int ns; /* Number of segments */ 175XSegment *seglist; /* X array of segments */ 176int width; /* Width of lines */ 177int style; /* See above */ 178int lappr; /* Line appearence */ 179int color; /* Line color (if any) */ 180/* 181 * This routine draws a number of line segments at the points 182 * given in `seglist'. Note that contiguous segments need not share 183 * endpoints but often do. All segments should be `width' devcoords wide 184 * and drawn in style `style'. The `width' may be zero meaning that 185 * the line should be drawn as thin as the device allows. If `style' is 186 * L_VAR, the parameters `color' and `lappr' should be used to draw the 187 * line. Both parameters vary from 0 to 7. If the device is capable of 188 * color, `color' varies faster than `style'. If the device 189 * has no color, `style' will vary faster than `color' and 190 * `color' can be safely ignored. However, if the 191 * the device has more than 8 line appearences, the two can 192 * be combined to specify 64 line style variations. 193 * Xgraph promises not to send more than the `max_segs' in the 194 * xgOut structure passed back from xg_init(). 195 */ 196 197/* Marker styles */ 198#define P_PIXEL 0 199#define P_DOT 1 200#define P_MARK 2 201 202void xg_dot(user_state, x, y, style, type, color) 203char *user_state; /* Value set in xg_init */ 204int x, y; /* Location in pixel units */ 205int style; /* Dot style */ 206int type; /* Type of marker */ 207int color; /* Marker color (if any) */ 208/* 209 * This routine should draw a marker at location `x,y'. If the 210 * style is P_PIXEL, the dot should be a single pixel. If 211 * the style is P_DOT, the dot should be a reasonably large 212 * dot. If the style is P_MARK, it should be a distinguished 213 * mark which is specified by `type' (0-7). If the output 214 * device is capable of color, the marker should be drawn in 215 * `color' (0-7) which corresponds with the color for xg_line. 216 */ 217 218void xg_end(user_state) 219char *user_state; 220/* 221 * This routine is called after a drawing sequence is complete. 222 * It can be used to clean up the user state and set the device 223 * state appropriately. This routine is optional in the structure. 224 */ 225 226/* 227 * Adding an output device to xgraph 228 * 229 * Step 2 230 * Edit the file hard_devices.c. Declare your initialization 231 * function and add your device to the list of devices, 232 * hard_devices[]. The structure hard_dev is described below 233 * and is defined in hard_devices.h: 234 */ 235 236#define MFNAME 25 237 238typedef enum hard_dev_docu_defn { NONE, NO, YES } hard_dev_docu; 239 240typedef struct hard_dev { 241 char *dev_name; /* Device name */ 242 int (*dev_init)(); /* Initialization function */ 243 char *dev_spec; /* Default pipe program */ 244 char dev_file[MFNAME]; /* Default file name */ 245 char dev_printer[MFNAME]; /* Default printer name */ 246 double dev_max_dim; /* Default maximum dimension (cm) */ 247 char dev_title_font[MFNAME];/* Default name of title font */ 248 double dev_title_size; /* Default size of title font (pnts) */ 249 char dev_axis_font[MFNAME]; /* Default name of axis font */ 250 double dev_axis_size; /* Default size of axis font (pnts) */ 251 hard_dev_docu dev_docu; /* Document predicate */ 252}; 253 254/* 255 * dev_spec: 256 * The dev_spec field should be a command that directly outputs to 257 * your device. The command should contain one %s directive that 258 * will be filled in with the name of the device from the hardcopy 259 * dialog. 260 * dev_file: 261 * The default file to write output to if the user selects `To File'. 262 * dev_printer: 263 * The default printer to write output to if the user selects 264 * `To Device'. 265 * dev_max_dim: 266 * The default maximum dimension for the device in centimeters. 267 * dev_title_font, dev_title_size: 268 * The default title font and size. Sizes are specified in 269 * points (1/72 inch). 270 * dev_axis_font, dev_axis_size: 271 * The default axis font and size. 272 * dev_docu 273 * Some devices may require extra preparation when including xgraph 274 * output in a document. This parameter indicates the default 275 * value of the Document predicate in the hardcopy dialog. If 276 * the value is NONE, the device doesn't need any special preparation 277 * for producing output for inclusion in documents. 278 */ 279 280/* 281 * Adding an output device to xgraph 282 * 283 * Step 3 284 * Edit the file Makefile. Add your source file to the SRC variable 285 * and the corresponding object file to the OBJ variable. Finally, 286 * remake xgraph. Your device should now be available in the 287 * hardcopy dialog. 288 */ 289