idraw.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:14k
- /*
- * Idraw Output
- *
- * Beorn Johnson
- * Alan Kramer
- * David Harrison
- */
- #include <stdio.h>
- #include <X11/Xlib.h>
- #include "hard_devices.h"
- #include "xgout.h"
- #define HEIGHT 792
- #define FIX(X) X = HEIGHT - X;
- typedef struct {
- char *title_font;
- char *axis_font;
- int title_size;
- int axis_size;
- FILE *strm;
- } Info;
- char *idraw_prologue[] =
- {
- "%I Idraw 4",
- "Begin",
- "%I b u",
- "%I cfg u",
- "%I cbg u",
- "%I f u",
- "%I p u",
- "%I t",
- "[ 1 0 0 1 0 0 ] concat",
- "/originalCTM matrix currentmatrix def",
- 0
- };
- /*
- * Hardcopy Interface for Xgraph
- *
- * Major differences from first version:
- * Four new parameters are passed to the device initialization routine:
- * title_family, title_size, axis_family, and axis_size. See the
- * description of xg_init() for details.
- *
- * Clipping is done automatically by xgraph. The xg_clip() routine
- * is obsolete.
- *
- * The xg_line() routine has become the xg_seg() routine. It now
- * draws segments rather than a series of lines.
- *
- * A new field (max_segs) in the device structure now specifies
- * the maximum number of segments the device can handle in a group.
- */
- /*
- * Adding an output device to xgraph
- *
- * Step 1
- * Write versions of the following routines for your device:
- * xg_init(), xg_text(), xg_seg(), xg_dot(), and xg_end().
- * The interface and function of these routines are described
- * in detail below. These routines should be named according
- * to your device. For example, the initialization routine
- * for the Postscript output device is psInit(). Also, name
- * your source file after your device (e.g. the postscript
- * routines are in the file ps.c). Instructions continue
- * after the description of the interface routines.
- */
- void idrawText();
- void idrawDot();
- void idrawSeg();
- void idrawEnd();
- int
- idrawInit(strm, width, height, title_family, title_size,
- axis_family, axis_size, flags, out_info, errmsg)
- FILE *strm; /* Output stream */
- int width,
- height; /* Size of space (microns) */
- char *title_family; /* Name of title font family */
- double title_size; /* Title font height (points) */
- char *axis_family; /* Name of axis font family */
- double axis_size; /* Axis font height (points) */
- int flags; /* Flags */
- xgOut *out_info; /* Device info (RETURN) */
- char errmsg[ERRBUFSIZE]; /* Error message area */
- /*
- * This routine is called by xgraph just before drawing is to
- * begin. The desired size of the plot is given by `width'
- * and `height'. The parameters `title_family', `title_size',
- * `axis_family', and `axis_size' specify the names of the
- * title and axis fonts and their vertical sizes (in points).
- * These parameters can be ignored if your device does not
- * support multiple fonts. Binary flags are specified in
- * the `flags' field. These include:
- * D_DOCU:
- * If this flag is set, it indicates the user has specified that
- * the output will be included in some larger document. Devices
- * may choose to use this information to produce output that
- * can be integrated into documents with less effort. For example,
- * the Postscript output routines produce bounding box information
- * when this flag is set.
- * The routine should fill in all of the fields of `out_info' with
- * appropriate values. The values are described below:
- * area_w, area_h:
- * Size of the drawing space in device coordinates.
- * This should take in account the requested area
- * given by `width', and `height'.
- * bdr_pad:
- * Xgraph will leave this number of device coordinates around
- * all of the outer edges of the graph.
- * axis_pad:
- * Additional space around axis labels (in devcoords)
- * so that the labels do not appear crowded.
- * legend_pad:
- * Space (in devcoords) from the top of legend text to
- * the representative line drawn above the legend text.
- * tick_len:
- * Size of a tick mark placed on axis (in devcoords)
- * axis_width:
- * An estimate of the width of a large character in
- * the axis font (in devcoords). This can be an overestimate. An
- * underestimate may produce bad results.
- * axis_height:
- * An estimate of the height of a large character in
- * the axis labeling font (in devcoords).
- * title_width, title_height:
- * Same as above except for the title font.
- * max_segs:
- * Due to buffering constraints, some devices may not be able to
- * handle massive segment lists. This parameter tells xgraph not
- * to send more than `max_segs' segments in one request.
- * Output to the device should be written to the stream `strm'.
- * The functions are described individually below. After filling
- * in the parameters and setting the function pointers, the routine
- * should initialize its drawing state and store any extra needed
- * information in `user_state'. This value will be passed to all
- * other routines during the drawing sequence. If the device
- * cannot initialize, it should return a zero status and fill
- * `errmsg' with an informative error message.
- */
- {
- Info *idraw_info;
- char **l;
- double scx,
- scy;
- idraw_info = (Info *) Malloc(sizeof(*idraw_info));
- for (l = idraw_prologue; *l; l++)
- fprintf(strm, "%sn", *l);
- out_info->dev_flags = 0;
- scx = width / 612;
- scy = height / 792.0;
- if (scx > scy) {
- scy /= scx;
- scx = 1;
- }
- else {
- scx /= scy;
- scy = 1;
- }
- out_info->bdr_pad = title_size / 4;
- out_info->axis_pad = 2.0 * axis_size;
- out_info->legend_pad = 0;
- out_info->area_w = width * 0.00283; /* pts per micron */
- out_info->area_h = height * 0.00283;
- out_info->tick_len = axis_size;
- out_info->axis_height = axis_size;
- out_info->title_height = title_size;
- out_info->axis_width = (axis_size * 5.0) / 12.0;
- out_info->title_width = (title_size * 5.0) / 12.0;
- out_info->max_segs = 100;
- out_info->xg_text = idrawText;
- out_info->xg_seg = idrawSeg;
- out_info->xg_dot = idrawDot;
- out_info->xg_end = idrawEnd;
- out_info->user_state = (char *) idraw_info;
- idraw_info->title_font = title_family;
- idraw_info->axis_font = axis_family;
- idraw_info->title_size = title_size;
- idraw_info->axis_size = axis_size;
- idraw_info->strm = strm;
- return 1;
- }
- /* Text justifications */
- #define T_CENTER 0
- #define T_LEFT 1
- #define T_UPPERLEFT 2
- #define T_TOP 3
- #define T_UPPERRIGHT 4
- #define T_RIGHT 5
- #define T_LOWERRIGHT 6
- #define T_BOTTOM 7
- #define T_LOWERLEFT 8
- /* Text styles */
- #define T_AXIS 0
- #define T_TITLE 1
- static void
- idraw_just(x, y, just, size, len)
- int *x,
- *y; /* Given location (lower left) */
- int just; /* Justification */
- int size; /* Size in points */
- int len; /* Number of chars */
- /*
- * Unfortunately, idraw really can't display text with a justification.
- * This is a horrible hack to try to get around the problem. It tries
- * to compute a rough bounding box for the text based on the text height
- * and the string length and offset `x,y' appropriately for the justification.
- * This is only a hack...
- */
- {
- int t_width,
- t_height;
- t_height = size;
- t_width = (size * len * 5) / 12; /* Horrible estimate */
- switch (just) {
- case T_CENTER:
- *x -= t_width / 2;
- *y += t_height / 2;
- break;
- case T_LEFT:
- *y += t_height / 2;
- break;
- case T_UPPERLEFT:
- /* nothing */
- break;
- case T_TOP:
- *x -= t_width / 2;
- break;
- case T_UPPERRIGHT:
- *x -= t_width;
- break;
- case T_RIGHT:
- *x -= t_width;
- *y += t_height / 2;
- break;
- case T_LOWERRIGHT:
- *x -= t_width;
- *y += t_height;
- break;
- case T_BOTTOM:
- *x -= t_width / 2;
- *y += t_height;
- break;
- case T_LOWERLEFT:
- *y += t_height;
- break;
- }
- /*
- * Also, idraw seems to put a space above all text it draws. The
- * computation below compensates for this.
- */
- *y += (size / 3);
- }
- void
- idrawText(user_state, x, y, text, just, style)
- char *user_state; /* Value set in xg_init */
- int x,
- y; /* Text position (pixels) */
- char *text; /* Null terminated text */
- int just; /* Justification (above) */
- int style; /* Text style (above) */
- /*
- * This routine should draw text at the indicated position using
- * the indicated justification and style. The justification refers
- * to the location of the point in reference to the text. For example,
- * if just is T_LOWERLEFT, (x,y) should be located at the lower left
- * edge of the text string.
- */
- {
- char *font;
- int size;
- Info *idraw = (Info *) user_state;
- FIX(y);
- font = style == T_AXIS ? idraw->axis_font :
- idraw->title_font;
- size = style == T_AXIS ? idraw->axis_size :
- idraw->title_size;
- idraw_just(&x, &y, just, size, strlen(text));
- fprintf(idraw->strm, "Begin %%I Textn");
- fprintf(idraw->strm, "%%I cfg Blackn");
- fprintf(idraw->strm, "0 0 0 SetCFgn");
- fprintf(idraw->strm, "%%I f *%s*-%d-*n", font, size);
- fprintf(idraw->strm, "/%s %d SetFn", font, size);
- fprintf(idraw->strm, "%%I tn");
- fprintf(idraw->strm, "[ 1 0 0 1 %d %d ] concatn", x, y);
- fprintf(idraw->strm, "%%In");
- fprintf(idraw->strm, "[n");
- fprintf(idraw->strm, "(%s)n", text);
- fprintf(idraw->strm, "] Textn");
- fprintf(idraw->strm, "Endn");
- }
- /* Line Styles */
- #define L_AXIS 0
- #define L_ZERO 1
- #define L_VAR 2
- void
- idrawSeg(user_state, ns, seglist, width, style, lappr, color)
- char *user_state; /* Value set in xg_init */
- int ns; /* Number of segments */
- XSegment *seglist; /* X array of segments */
- int width; /* Width of lines */
- int style; /* See above */
- int lappr; /* Line appearence */
- int color; /* Line color (if any) */
- /*
- * This routine draws a number of line segments at the points
- * given in `seglist'. Note that contiguous segments need not share
- * endpoints but often do. All segments should be `width' devcoords wide
- * and drawn in style `style'. If `style' is L_VAR, the parameters
- * `color' and `lappr' should be used to draw the line. Both
- * parameters vary from 0 to 7. If the device is capable of
- * color, `color' varies faster than `style'. If the device
- * has no color, `style' will vary faster than `color' and
- * `color' can be safely ignored. However, if the
- * the device has more than 8 line appearences, the two can
- * be combined to specify 64 line style variations.
- * Xgraph promises not to send more than the `max_segs' in the
- * xgOut structure passed back from xg_init().
- */
- {
- Info *idraw = (Info *) user_state;
- short to_style;
- int i,
- j,
- k;
- static unsigned short style_list[] =
- {
- 0xffff, 0xf0f0, 0xcccc, 0xaaaa,
- 0xf060, 0xf198, 0x7f55, 0x0000,
- };
- to_style = style == L_AXIS ? 65535
- : style == L_ZERO ? 65535
- : style_list[lappr];
- for (i = 0; i < ns; i++) {
- FIX(seglist[i].y1);
- FIX(seglist[i].y2);
- }
- for (i = 0; i < ns; i = j) {
- for (j = i + 1; j < ns
- && seglist[j - 1].x2 == seglist[j].x1
- && seglist[j - 1].y2 == seglist[j].y1;
- j++);
- fprintf(idraw->strm, "Begin %%I MLinen");
- fprintf(idraw->strm, "%%I b %dn", to_style);
- fprintf(idraw->strm, "%d 0 0 [", width);
- /* fprintf(idraw -> strm, "%d"); */
- fprintf(idraw->strm, "] 0 SetBn");
- fprintf(idraw->strm, "%%I cfg Blackn");
- fprintf(idraw->strm, "0 0 0 SetCFgn");
- fprintf(idraw->strm, "%%I cbg Whiten");
- fprintf(idraw->strm, "1 1 1 SetCBgn");
- fprintf(idraw->strm, "none SetP %%I p nn");
- fprintf(idraw->strm, "%%I t un");
- fprintf(idraw->strm, "%%I %dn", j - i + 1);
- for (k = i; k < j; k++)
- fprintf(idraw->strm, "%d %dn",
- seglist[k].x1, seglist[k].y1);
- fprintf(idraw->strm, "%d %dn",
- seglist[k - 1].x2, seglist[k - 1].y2);
- fprintf(idraw->strm, "%d MLinen", j - i + 1);
- fprintf(idraw->strm, "Endn");
- }
- }
- /* Marker styles */
- #define P_PIXEL 0
- #define P_DOT 1
- #define P_MARK 2
- void
- idrawDot(user_state, x, y, style, type, color)
- char *user_state; /* Value set in xg_init */
- int x,
- y; /* Location in pixel units */
- int style; /* Dot style */
- int type; /* Type of marker */
- int color; /* Marker color (if any) */
- /*
- * This routine should draw a marker at location `x,y'. If the
- * style is P_PIXEL, the dot should be a single pixel. If
- * the style is P_DOT, the dot should be a reasonably large
- * dot. If the style is P_MARK, it should be a distinguished
- * mark which is specified by `type' (0-7). If the output
- * device is capable of color, the marker should be drawn in
- * `color' (0-7) which corresponds with the color for xg_line.
- */
- {
- }
- void
- idrawEnd(user_state)
- char *user_state;
- /*
- * This routine is called after a drawing sequence is complete.
- * It can be used to clean up the user state and set the device
- * state appropriately. This routine is optional in the structure.
- */
- {
- Info *idraw = (Info *) user_state;
- fprintf(idraw->strm, "End %%I eopn");
- fclose(idraw->strm);
- }
- /*
- * Adding an output device to xgraph
- *
- * Step 2
- * Edit the file hard_devices.c. Declare your initialization
- * function and add your device to the list of devices,
- * hard_devices[]. The structure hard_dev is described below:
- */
- #ifdef notdef
- extern int idrawInit();
- struct hard_dev idraw =
- {
- "idraw format", idrawInit,
- 0, ".clipboard", 0,
- 25, "Times-Bold", 18, "Times", 12
- };
- #endif
- /*
- * dev_spec:
- * The dev_spec field should be a command that directly outputs to
- * your device. The command should contain one %s directive that
- * will be filled in with the name of the device from the hardcopy
- * dialog.
- * dev_file:
- * The default file to write output to if the user selects `To File'.
- * dev_printer:
- * The default printer to write output to if the user selects
- * `To Device'.
- * dev_max_dim:
- * The default maximum dimension for the device in centimeters.
- * dev_title_font, dev_title_size:
- * The default title font and size. Sizes are specified in
- * points (1/72 inch).
- * dev_axis_font, dev_axis_size:
- * The default axis font and size.
- */
- /*
- * Adding an output device to xgraph
- *
- * Step 3
- * Edit the file Makefile. Add your source file to the SRC variable
- * and the corresponding object file to the OBJ variable. Finally,
- * remake xgraph. Your device should now be available in the
- * hardcopy dialog.
- */