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