idraw.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:14k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * Idraw Output
  3.  *
  4.  * Beorn Johnson
  5.  * Alan Kramer
  6.  * David Harrison
  7.  */
  8. #include <stdio.h>
  9. #include <X11/Xlib.h>
  10. #include "hard_devices.h"
  11. #include "xgout.h"
  12. #define HEIGHT 792
  13. #define FIX(X) X = HEIGHT - X;
  14. typedef struct {
  15.     char   *title_font;
  16.     char   *axis_font;
  17.     int     title_size;
  18.     int     axis_size;
  19.     FILE   *strm;
  20. }       Info;
  21. char   *idraw_prologue[] =
  22. {
  23.     "%I Idraw 4",
  24.     "Begin",
  25.     "%I b u",
  26.     "%I cfg u",
  27.     "%I cbg u",
  28.     "%I f u",
  29.     "%I p u",
  30.     "%I t",
  31.     "[ 1 0 0 1 0 0 ] concat",
  32.     "/originalCTM matrix currentmatrix def",
  33.     0
  34. };
  35. /*
  36.  * Hardcopy Interface for Xgraph
  37.  *
  38.  * Major differences from first version:
  39.  *   Four new parameters are passed to the device initialization routine:
  40.  *   title_family, title_size, axis_family, and axis_size.  See the
  41.  *   description of xg_init() for details.
  42.  *
  43.  *   Clipping is done automatically by xgraph.  The xg_clip() routine
  44.  *   is obsolete.
  45.  *
  46.  *   The xg_line() routine has become the xg_seg() routine.  It now
  47.  *   draws segments rather than a series of lines.
  48.  *
  49.  *   A new field (max_segs) in the device structure now specifies
  50.  *   the maximum number of segments the device can handle in a group.
  51.  */
  52. /*
  53.  * Adding an output device to xgraph
  54.  *
  55.  * Step 1
  56.  *   Write versions of the following routines for your device:
  57.  *   xg_init(), xg_text(), xg_seg(), xg_dot(), and xg_end().
  58.  *   The interface and function of these routines are described
  59.  *   in detail below.  These routines should be named according
  60.  *   to your device.  For example,  the initialization routine
  61.  *   for the Postscript output device is psInit().  Also,  name
  62.  *   your source file after your device (e.g. the postscript
  63.  *   routines are in the file ps.c).  Instructions continue
  64.  *   after the description of the interface routines.
  65.  */
  66. void    idrawText();
  67. void    idrawDot();
  68. void    idrawSeg();
  69. void    idrawEnd();
  70. int 
  71. idrawInit(strm, width, height, title_family, title_size,
  72.   axis_family, axis_size, flags, out_info, errmsg)
  73. FILE   *strm; /* Output stream              */
  74. int     width,
  75.         height; /* Size of space (microns)    */
  76. char   *title_family; /* Name of title font family  */
  77. double  title_size; /* Title font height (points) */
  78. char   *axis_family; /* Name of axis font family   */
  79. double  axis_size; /* Axis font height (points)  */
  80. int     flags; /* Flags                      */
  81. xgOut  *out_info; /* Device info (RETURN)       */
  82. char    errmsg[ERRBUFSIZE]; /* Error message area         */
  83. /*
  84.  * This routine is called by xgraph just before drawing is to
  85.  * begin.  The desired size of the plot is given by `width'
  86.  * and `height'.  The parameters `title_family', `title_size',
  87.  * `axis_family', and `axis_size' specify the names of the
  88.  * title and axis fonts and their vertical sizes (in points).
  89.  * These parameters can be ignored if your device does not
  90.  * support multiple fonts.  Binary flags are specified in
  91.  * the `flags' field.  These include:
  92.  *  D_DOCU:
  93.  *      If this flag is set,  it indicates the user has specified that
  94.  * the output will be included in some larger document.  Devices
  95.  * may choose to use this information to produce output that
  96.  * can be integrated into documents with less effort.  For example,
  97.  * the Postscript output routines produce bounding box information
  98.  * when this flag is set.
  99.  * The routine should fill in all of the fields of `out_info' with
  100.  * appropriate values.  The values are described below:
  101.  *  area_w, area_h:
  102.  *  Size of the drawing space in device coordinates.
  103.  * This should take in account the requested area
  104.  * given by `width', and `height'.
  105.  *  bdr_pad:
  106.  *  Xgraph will leave this number of device coordinates around
  107.  * all of the outer edges of the graph.
  108.  *  axis_pad:
  109.  * Additional space around axis labels (in devcoords)
  110.  * so that the labels do not appear crowded.
  111.  *  legend_pad:
  112.  * Space (in devcoords) from the top of legend text to
  113.  * the representative line drawn above the legend text.
  114.  *  tick_len:
  115.  * Size of a tick mark placed on axis (in devcoords)
  116.  *  axis_width:
  117.  * An estimate of the width of a large character in
  118.  *      the axis font (in devcoords).  This can be an overestimate.  An
  119.  *      underestimate may produce bad results.
  120.  *  axis_height:
  121.  * An estimate of the height of a large character in
  122.  *      the axis labeling font (in devcoords).
  123.  *  title_width, title_height:
  124.  * Same as above except for the title font.
  125.  *  max_segs:
  126.  * Due to buffering constraints,  some devices may not be able to
  127.  * handle massive segment lists.  This parameter tells xgraph not
  128.  * to send more than `max_segs' segments in one request.
  129.  * Output to the device should be written to the stream `strm'.
  130.  * The functions are described individually below.  After filling
  131.  * in the parameters and setting the function pointers,  the routine
  132.  * should initialize its drawing state and store any extra needed
  133.  * information in `user_state'.  This value will be passed to all
  134.  * other routines during the drawing sequence.  If the device
  135.  * cannot initialize,  it should return a zero status and fill
  136.  * `errmsg' with an informative error message.
  137.  */
  138. {
  139.     Info   *idraw_info;
  140.     char  **l;
  141.     double  scx,
  142.             scy;
  143.     idraw_info = (Info *) Malloc(sizeof(*idraw_info));
  144.     for (l = idraw_prologue; *l; l++)
  145. fprintf(strm, "%sn", *l);
  146.     out_info->dev_flags = 0;
  147.     scx = width / 612;
  148.     scy = height / 792.0;
  149.     if (scx > scy) {
  150. scy /= scx;
  151. scx = 1;
  152.     }
  153.     else {
  154. scx /= scy;
  155. scy = 1;
  156.     }
  157.     out_info->bdr_pad = title_size / 4;
  158.     out_info->axis_pad = 2.0 * axis_size;
  159.     out_info->legend_pad = 0;
  160.     out_info->area_w = width * 0.00283; /* pts per micron */
  161.     out_info->area_h = height * 0.00283;
  162.     out_info->tick_len = axis_size;
  163.     out_info->axis_height = axis_size;
  164.     out_info->title_height = title_size;
  165.     out_info->axis_width = (axis_size * 5.0) / 12.0;
  166.     out_info->title_width = (title_size * 5.0) / 12.0;
  167.     out_info->max_segs = 100;
  168.     out_info->xg_text = idrawText;
  169.     out_info->xg_seg = idrawSeg;
  170.     out_info->xg_dot = idrawDot;
  171.     out_info->xg_end = idrawEnd;
  172.     out_info->user_state = (char *) idraw_info;
  173.     idraw_info->title_font = title_family;
  174.     idraw_info->axis_font = axis_family;
  175.     idraw_info->title_size = title_size;
  176.     idraw_info->axis_size = axis_size;
  177.     idraw_info->strm = strm;
  178.     return 1;
  179. }
  180. /* Text justifications */
  181. #define T_CENTER 0
  182. #define T_LEFT 1
  183. #define T_UPPERLEFT 2
  184. #define T_TOP 3
  185. #define T_UPPERRIGHT 4
  186. #define T_RIGHT 5
  187. #define T_LOWERRIGHT 6
  188. #define T_BOTTOM 7
  189. #define T_LOWERLEFT 8
  190. /* Text styles */
  191. #define T_AXIS 0
  192. #define T_TITLE 1
  193. static void 
  194. idraw_just(x, y, just, size, len)
  195. int    *x,
  196.        *y; /* Given location (lower left) */
  197. int     just; /* Justification */
  198. int     size; /* Size in points */
  199. int     len; /* Number of chars */
  200. /*
  201.  * Unfortunately, idraw really can't display text with a justification.
  202.  * This is a horrible hack to try to get around the problem.  It tries
  203.  * to compute a rough bounding box for the text based on the text height
  204.  * and the string length and offset `x,y' appropriately for the justification.
  205.  * This is only a hack...
  206.  */
  207. {
  208.     int     t_width,
  209.             t_height;
  210.     t_height = size;
  211.     t_width = (size * len * 5) / 12; /* Horrible estimate */
  212.     switch (just) {
  213.     case T_CENTER:
  214. *x -= t_width / 2;
  215. *y += t_height / 2;
  216. break;
  217.     case T_LEFT:
  218. *y += t_height / 2;
  219. break;
  220.     case T_UPPERLEFT:
  221. /* nothing */
  222. break;
  223.     case T_TOP:
  224. *x -= t_width / 2;
  225. break;
  226.     case T_UPPERRIGHT:
  227. *x -= t_width;
  228. break;
  229.     case T_RIGHT:
  230. *x -= t_width;
  231. *y += t_height / 2;
  232. break;
  233.     case T_LOWERRIGHT:
  234. *x -= t_width;
  235. *y += t_height;
  236. break;
  237.     case T_BOTTOM:
  238. *x -= t_width / 2;
  239. *y += t_height;
  240. break;
  241.     case T_LOWERLEFT:
  242. *y += t_height;
  243. break;
  244.     }
  245.     /*
  246.      * Also, idraw seems to put a space above all text it draws. The
  247.      * computation below compensates for this.
  248.      */
  249.     *y += (size / 3);
  250. }
  251. void 
  252. idrawText(user_state, x, y, text, just, style)
  253. char   *user_state; /* Value set in xg_init   */
  254. int     x,
  255.         y; /* Text position (pixels) */
  256. char   *text; /* Null terminated text   */
  257. int     just; /* Justification (above)  */
  258. int     style; /* Text style (above)     */
  259. /*
  260.  * This routine should draw text at the indicated position using
  261.  * the indicated justification and style.  The justification refers
  262.  * to the location of the point in reference to the text.  For example,
  263.  * if just is T_LOWERLEFT,  (x,y) should be located at the lower left
  264.  * edge of the text string.
  265.  */
  266. {
  267.     char   *font;
  268.     int     size;
  269.     Info   *idraw = (Info *) user_state;
  270.     FIX(y);
  271.     font = style == T_AXIS ? idraw->axis_font :
  272. idraw->title_font;
  273.     size = style == T_AXIS ? idraw->axis_size :
  274. idraw->title_size;
  275.     idraw_just(&x, &y, just, size, strlen(text));
  276.     fprintf(idraw->strm, "Begin %%I Textn");
  277.     fprintf(idraw->strm, "%%I cfg Blackn");
  278.     fprintf(idraw->strm, "0 0 0 SetCFgn");
  279.     fprintf(idraw->strm, "%%I f *%s*-%d-*n", font, size);
  280.     fprintf(idraw->strm, "/%s %d SetFn", font, size);
  281.     fprintf(idraw->strm, "%%I tn");
  282.     fprintf(idraw->strm, "[ 1 0 0 1 %d %d ] concatn", x, y);
  283.     fprintf(idraw->strm, "%%In");
  284.     fprintf(idraw->strm, "[n");
  285.     fprintf(idraw->strm, "(%s)n", text);
  286.     fprintf(idraw->strm, "] Textn");
  287.     fprintf(idraw->strm, "Endn");
  288. }
  289. /* Line Styles */
  290. #define L_AXIS 0
  291. #define L_ZERO 1
  292. #define L_VAR 2
  293. void 
  294. idrawSeg(user_state, ns, seglist, width, style, lappr, color)
  295. char   *user_state; /* Value set in xg_init */
  296. int     ns; /* Number of segments   */
  297. XSegment *seglist; /* X array of segments  */
  298. int     width; /* Width of lines       */
  299. int     style; /* See above            */
  300. int     lappr; /* Line appearence      */
  301. int     color; /* Line color (if any)  */
  302. /*
  303.  * This routine draws a number of line segments at the points
  304.  * given in `seglist'.  Note that contiguous segments need not share
  305.  * endpoints but often do.  All segments should be `width' devcoords wide
  306.  * and drawn in style `style'.  If `style' is L_VAR,  the parameters
  307.  * `color' and `lappr' should be used to draw the line.  Both
  308.  * parameters vary from 0 to 7.  If the device is capable of
  309.  * color,  `color' varies faster than `style'.  If the device
  310.  * has no color,  `style' will vary faster than `color' and
  311.  * `color' can be safely ignored.  However,  if the
  312.  * the device has more than 8 line appearences,  the two can
  313.  * be combined to specify 64 line style variations.
  314.  * Xgraph promises not to send more than the `max_segs' in the
  315.  * xgOut structure passed back from xg_init().
  316.  */
  317. {
  318.     Info   *idraw = (Info *) user_state;
  319.     short   to_style;
  320.     int     i,
  321.             j,
  322.             k;
  323.     static unsigned short style_list[] =
  324.     {
  325. 0xffff, 0xf0f0, 0xcccc, 0xaaaa,
  326. 0xf060, 0xf198, 0x7f55, 0x0000,
  327.     };
  328.     to_style = style == L_AXIS ? 65535
  329. : style == L_ZERO ? 65535
  330. : style_list[lappr];
  331.     for (i = 0; i < ns; i++) {
  332. FIX(seglist[i].y1);
  333. FIX(seglist[i].y2);
  334.     }
  335.     for (i = 0; i < ns; i = j) {
  336. for (j = i + 1; j < ns
  337.      && seglist[j - 1].x2 == seglist[j].x1
  338.      && seglist[j - 1].y2 == seglist[j].y1;
  339.      j++);
  340. fprintf(idraw->strm, "Begin %%I MLinen");
  341. fprintf(idraw->strm, "%%I b %dn", to_style);
  342. fprintf(idraw->strm, "%d 0 0 [", width);
  343. /* fprintf(idraw -> strm, "%d"); */
  344. fprintf(idraw->strm, "] 0 SetBn");
  345. fprintf(idraw->strm, "%%I cfg Blackn");
  346. fprintf(idraw->strm, "0 0 0 SetCFgn");
  347. fprintf(idraw->strm, "%%I cbg Whiten");
  348. fprintf(idraw->strm, "1 1 1 SetCBgn");
  349. fprintf(idraw->strm, "none SetP %%I p nn");
  350. fprintf(idraw->strm, "%%I t un");
  351. fprintf(idraw->strm, "%%I %dn", j - i + 1);
  352. for (k = i; k < j; k++)
  353.     fprintf(idraw->strm, "%d %dn",
  354.     seglist[k].x1, seglist[k].y1);
  355. fprintf(idraw->strm, "%d %dn",
  356. seglist[k - 1].x2, seglist[k - 1].y2);
  357. fprintf(idraw->strm, "%d MLinen", j - i + 1);
  358. fprintf(idraw->strm, "Endn");
  359.     }
  360. }
  361. /* Marker styles */
  362. #define P_PIXEL 0
  363. #define P_DOT 1
  364. #define P_MARK 2
  365. void 
  366. idrawDot(user_state, x, y, style, type, color)
  367. char   *user_state; /* Value set in xg_init    */
  368. int     x,
  369.         y; /* Location in pixel units */
  370. int     style; /* Dot style               */
  371. int     type; /* Type of marker          */
  372. int     color; /* Marker color (if any)   */
  373. /*
  374.  * This routine should draw a marker at location `x,y'.  If the
  375.  * style is P_PIXEL,  the dot should be a single pixel.  If
  376.  * the style is P_DOT,  the dot should be a reasonably large
  377.  * dot.  If the style is P_MARK,  it should be a distinguished
  378.  * mark which is specified by `type' (0-7).  If the output
  379.  * device is capable of color,  the marker should be drawn in
  380.  * `color' (0-7) which corresponds with the color for xg_line.
  381.  */
  382. {
  383. }
  384. void 
  385. idrawEnd(user_state)
  386. char   *user_state;
  387. /*
  388.  * This routine is called after a drawing sequence is complete.
  389.  * It can be used to clean up the user state and set the device
  390.  * state appropriately.  This routine is optional in the structure.
  391.  */
  392. {
  393.     Info   *idraw = (Info *) user_state;
  394.     fprintf(idraw->strm, "End %%I eopn");
  395.     fclose(idraw->strm);
  396. }
  397. /*
  398.  * Adding an output device to xgraph
  399.  *
  400.  * Step 2
  401.  *   Edit the file hard_devices.c.  Declare your initialization
  402.  *   function and add your device to the list of devices,
  403.  *   hard_devices[].  The structure hard_dev is described below:
  404.  */
  405. #ifdef notdef
  406. extern int idrawInit();
  407. struct hard_dev idraw =
  408. {
  409.     "idraw format", idrawInit,
  410.     0, ".clipboard", 0,
  411.     25, "Times-Bold", 18, "Times", 12
  412. };
  413. #endif
  414. /*
  415.  * dev_spec:
  416.  *    The dev_spec field should be a command that directly outputs to
  417.  *    your device.  The command should contain one %s directive that
  418.  *    will be filled in with the name of the device from the hardcopy
  419.  *    dialog.
  420.  * dev_file:
  421.  *    The default file to write output to if the user selects `To File'.
  422.  * dev_printer:
  423.  *    The default printer to write output to if the user selects
  424.  *    `To Device'.
  425.  * dev_max_dim:
  426.  *    The default maximum dimension for the device in centimeters.
  427.  * dev_title_font, dev_title_size:
  428.  *    The default title font and size.  Sizes are specified in
  429.  *    points (1/72 inch).
  430.  * dev_axis_font, dev_axis_size:
  431.  *    The default axis font and size.
  432.  */
  433. /*
  434.  * Adding an output device to xgraph
  435.  *
  436.  * Step 3
  437.  *   Edit the file Makefile.  Add your source file to the SRC variable
  438.  *   and the corresponding object file to the OBJ variable.  Finally,
  439.  *   remake xgraph.  Your device should now be available in the
  440.  *   hardcopy dialog.
  441.  */