home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume26 / psgraph / part02 / output.c < prev   
Encoding:
C/C++ Source or Header  |  1992-09-06  |  20.4 KB  |  897 lines

  1. /* $Header: output.c,v 1.10 92/08/04 17:55:10 mogul Exp $ */
  2.  
  3. /*
  4.  *               Copyright 1989, 1992 Digital Equipment Corporation
  5.  *                          All Rights Reserved
  6.  * 
  7.  * 
  8.  * Permission to use, copy, and modify this software and its documentation
  9.  * is hereby granted only under the following terms and conditions.  Both
  10.  * the above copyright notice and this permission notice must appear in
  11.  * all copies of the software, derivative works or modified versions, and
  12.  * any portions threof, and both notices must appear in supporting
  13.  * documentation.
  14.  * 
  15.  * Users of this software agree to the terms and conditions set forth
  16.  * herein, and hereby grant back to Digital a non-exclusive, unrestricted,
  17.  * royalty-free right and license under any changes, enhancements or
  18.  * extensions made to the core functions of the software, including but
  19.  * not limited to those affording compatibility with other hardware or
  20.  * software environments, but excluding applications which incorporate
  21.  * this software.  Users further agree to use their best efforts to return
  22.  * to Digital any such changes, enhancements or extensions that they make
  23.  * and inform Digital of noteworthy uses of this software.  Correspondence
  24.  * should be provided to Digital at:
  25.  * 
  26.  *                       Director of Licensing
  27.  *                       Western Research Laboratory
  28.  *                       Digital Equipment Corporation
  29.  *                       250 University Avenue
  30.  *                       Palo Alto, California  94301  
  31.  * 
  32.  * This software may be distributed (but not offered for sale or
  33.  * transferred for compensation) to third parties, provided such third
  34.  * parties agree to abide by the terms and conditions of this notice.
  35.  * 
  36.  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS
  37.  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
  38.  * WARRANTIES OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL
  39.  * EQUIPMENT CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
  40.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
  41.  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  42.  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  43.  * PERFORMANCE OF THIS SOFTWARE.
  44.  */
  45.  
  46. /* 
  47.  * output.c - Spit out the PostScript
  48.  * 
  49.  * Author:    Christopher A. Kent
  50.  *         Western Research Laboratory
  51.  *         Digital Equipment Corporation
  52.  * Date:    Wed Jan  4 1989
  53.  */
  54.  
  55. /*
  56.  * $Log:    output.c,v $
  57.  * Revision 1.10  92/08/04  17:55:10  mogul
  58.  * undo RCS botch
  59.  * 
  60.  * Revision 1.9  1992/07/16  20:07:09  cak
  61.  * Fix markergray implementation so it doesn't blow away the effects of color.
  62.  *
  63.  * Revision 1.8  1992/06/17  22:14:41  kent
  64.  * Make axis specs with max < min work, fix some bugs with centering
  65.  * and multiple args.
  66.  *
  67.  * Revision 1.7  1992/06/16  01:48:11  kent
  68.  * Make y positioning and centering and such work right.
  69.  *
  70.  * Revision 1.6  1992/04/06  21:14:03  kent
  71.  * Broke the bounding box computation last time 'round. Fixed.
  72.  *
  73.  * Revision 1.5  1992/04/02  00:45:01  kent
  74.  * Changes to handle lots of points; when using dataticks, the axis
  75.  * routines could get too big and overflow the operand stack. As
  76.  * a result, the output PostScript code is even uglier.
  77.  *
  78.  * Revision 1.4  1992/03/31  02:31:34  kent
  79.  * Added markergray verb and fixed inverted gray values.
  80.  *
  81.  * Revision 1.3  1992/03/31  00:07:39  kent
  82.  * Added markerscale verb.
  83.  *
  84.  * Revision 1.2  1992/03/30  23:33:47  kent
  85.  * Added halfopen, halfticks grid styles, range frames, and gray.
  86.  *
  87.  * Revision 1.1  1992/03/20  21:25:43  kent
  88.  * Initial revision
  89.  *
  90.  * Revision 1.16  92/02/21  17:13:23  mogul
  91.  * Added Digital license info
  92.  * 
  93.  * Revision 1.15  91/02/04  17:03:22  mogul
  94.  * Break up long sets of text commands to avoid producing
  95.  * PostScript with excessively long lines (hard to email).
  96.  * 
  97.  * 
  98.  * Revision 1.14  91/02/04  16:48:27  mogul
  99.  * Don't emit color changes when not necessary (saves space in
  100.  * output file).
  101.  * 
  102.  * Revision 1.13  91/02/04  16:31:05  mogul
  103.  * fixed color support for text, markers
  104.  * 
  105.  * Revision 1.12  90/12/11  20:41:55  reid
  106.  * Added support for new "color" and "linewidth" options.
  107.  * 
  108.  * Revision 1.11  90/11/05  11:11:44  reid
  109.  * Checking in Chris Kent's changes of June 1989
  110.  * 
  111.  * Revision 1.10  89/03/01  10:44:40  kent
  112.  * NORTH and WEST axis text must be adjusted based on point size, since the
  113.  * code in the prologue "unadjusts" it based on the point size.
  114.  * 
  115.  * Revision 1.9  89/02/03  09:33:23  kent
  116.  * Make splines work on log scales.
  117.  * 
  118.  * Revision 1.8  89/01/27  15:56:15  kent
  119.  * Line style "off" has to be handled in code, since there's no way I can
  120.  * cleanly use setdash to draw an "empty" line. Also fixed problems with
  121.  * axisText on axes with non-zero origins.
  122.  * 
  123.  * Revision 1.7  89/01/11  09:14:27  kent
  124.  * Removed some internal knowledge about the semantics of line types. This
  125.  * is all in the PostScript now.
  126.  * 
  127.  * Revision 1.6  89/01/10  18:19:55  kent
  128.  * Moved marker code to prolog, added error checking and messages.
  129.  * 
  130.  * Revision 1.5  89/01/09  22:18:45  kent
  131.  * Added log scales.
  132.  * 
  133.  * Revision 1.4  89/01/04  17:40:56  kent
  134.  * Moved font stuff from main.c to output.c.
  135.  * newfont() sets PS fontsize variable so white background is the right size.
  136.  * 
  137.  * Revision 1.3  89/01/04  17:30:31  kent
  138.  * Made command line arguments override compiled-in defaults for
  139.  * all plots in a run, not just the first one. 
  140.  * 
  141.  * Revision 1.2  89/01/04  15:22:08  kent
  142.  * Massive renaming. No functional change.
  143.  * 
  144.  * Revision 1.1  89/01/04  13:57:59  kent
  145.  * Initial revision
  146.  * 
  147.  */
  148.  
  149. static char rcs_ident[] = "$Header: output.c,v 1.10 92/08/04 17:55:10 mogul Exp $";
  150.  
  151. #include <stdio.h>
  152. #include <assert.h>
  153.  
  154. #include "psgraph.h"
  155.  
  156. typedef struct _plotpoint {
  157.     float x, y;
  158. }plotpoint_t;
  159.  
  160. /*
  161.  * doplot - generate all the output text for the plot.
  162.  *
  163.  * BUG: leaks storage if called multiple times.
  164.  */
  165.  
  166. doplot()
  167. {
  168.     int     i, numpoints, sizeofpoints;
  169.     plotpoint_t    *points;
  170.  
  171.     CurrentPage++;
  172.     printf("%%%%Page: %d %d\n", CurrentPage, CurrentPage);
  173.     printf("StartPSGraph\n");
  174.     printf("/saveIt save def\ngsave\n/solid f\n");
  175.     TextFont = TEXTFONT;
  176.     CurrentFont = NULL;
  177.     newfont(TextFont);
  178.  
  179. /**/
  180.  
  181.     setupAxes();
  182.  
  183.     doXaxis();
  184.  
  185.     doYaxis();
  186.  
  187.     printf("/drawTitle [\n");
  188.     doTitle();
  189.     printf("] cvx bind def\n");
  190.  
  191.     if (Preview)
  192.         printf("1 1 translate\n");
  193.  
  194.     if (Xcenter != 0.0) {        /* do centering */
  195.         printf("%f %f sub 2 div 0 translate\n", 
  196.             Xcenter, Xaxis.size);
  197.         /* must adjust bbox */
  198.         minX += (Xcenter - Xaxis.size) / 2.0;
  199.         maxX += (Xcenter - Xaxis.size) / 2.0;
  200.         /* move Y origin to 0 */
  201.         printf("0 %f translate\n", -minY);
  202.         maxY -= minY; minY = 0.0;
  203.     } else {
  204.         printf("%f %f translate\n",    /* move origin to 0,0 */
  205.             -minX, -minY);
  206.         maxX -= minX; minX = 0.0;
  207.         maxY -= minY; minY = 0.0;
  208.     }
  209.     printf("drawXaxis drawYaxis drawTitle\n");
  210.  
  211.     MinX = MIN(minX, MinX);
  212.     MinY = MIN(minY, MinY);
  213.     MaxX = MAX(maxX, MaxX);
  214.     MaxY = MAX(maxY, MaxY);
  215.  
  216.     sizeofpoints = 10;
  217.     points=(plotpoint_t *)calloc(10,sizeof(plotpoint_t));
  218.     numpoints = 0;
  219.     cliplimits(Xaxis.gmin-ClipDist/Xaxis.size*(Xaxis.gmax-Xaxis.gmin),
  220.            Yaxis.gmin-ClipDist/Yaxis.size*(Yaxis.gmax-Yaxis.gmin),
  221.            Xaxis.gmax+ClipDist/Xaxis.size*(Xaxis.gmax-Xaxis.gmin),
  222.            Yaxis.gmax+ClipDist/Yaxis.size*(Yaxis.gmax-Yaxis.gmin),
  223.            Xaxis.distg < 0, Yaxis.distg < 0);
  224.     for(i=0 ; i<NumTokens; i++) {
  225.         switch(Token[i].type) {
  226.         case TRANS:
  227.             if (numpoints > 0) {
  228.                 dumppoints(points, numpoints);
  229.                 numpoints = 0;
  230.             }
  231.             TransparentLabels = Token[i].ival;
  232.             break;
  233.         case BREAK:
  234.             if ( numpoints > 0 ) {
  235.                 dumppoints(points,numpoints);
  236.                 numpoints = 0;
  237.             }
  238.             break;
  239.         case LINETYPE:
  240.             if ( numpoints > 0 ) {
  241.                 dumppoints(points,numpoints);
  242.                 numpoints = 0;
  243.                 UseSpline = FALSE;
  244.             }
  245.             if ( Token[i].label != NULL )
  246.                 LineType = Token[i].label;
  247.             break;
  248.         case LINECOLOR:
  249.             if ( numpoints > 0 ) {
  250.                 dumppoints(points,numpoints);
  251.                 numpoints = 0;
  252.                 UseSpline = FALSE;
  253.             }
  254.             if ( Token[i].label != NULL ) {
  255.                 LineColor = Token[i].label;
  256.                 TextColor = Token[i].label;
  257.                 MarkColor = Token[i].label;
  258.                 graymarker(0.0);
  259.             }
  260.             break;
  261.         case LINEWIDTH:
  262.             if ( numpoints > 0 ) {
  263.                 dumppoints(points,numpoints);
  264.                 numpoints = 0;
  265.                 UseSpline = FALSE;
  266.             }
  267.             if ( Token[i].label != NULL )
  268.                 LineWidth = Token[i].label;
  269.             break;
  270.         case MARKER:
  271.             UseMarker = Token[i].label;
  272.             setmarker(UseMarker);
  273.             break;
  274.         case MARKERSCALE:
  275.             scalemarker(Token[i].val[0]);
  276.             break;
  277.         case MARKERGRAY:
  278.             graymarker(Token[i].val[0]);
  279.             break;
  280.         case FONT:
  281.             if ( numpoints > 0 ) {
  282.                 dumppoints(points,numpoints);
  283.                 points[0] = points[numpoints-1];
  284.                 numpoints = 1;
  285.             }
  286.             if ( Token[i].label != NULL ) {
  287.                 newfont(Token[i].label);
  288.                 TextFont = Token[i].label;
  289.             }
  290.             break;
  291.         case TEXT:
  292.             if ( numpoints > 0 ) {
  293.                 dumppoints(points,numpoints);
  294.                 numpoints = 0;
  295.             }
  296.             if ( code(Token[i].xval,Token[i].yval)==0 )
  297.                 text(Token[i].label,sx(Token[i].xval),sy(Token[i].yval),"ljust");
  298.             break;
  299.         case SPLINE:
  300.             dumppoints(points,numpoints);
  301.             numpoints = 0;
  302.             UseSpline = TRUE;
  303.             break;
  304.         case POINT:
  305.             if ( numpoints >= sizeofpoints ) {
  306.                 sizeofpoints += 10;
  307.                 points = (plotpoint_t *)realloc((char *)points,sizeofpoints*sizeof(plotpoint_t));
  308.             }
  309.             points[numpoints].x = Token[i].val[0];
  310.             points[numpoints++].y = Token[i].val[1];
  311.             if ( Token[i].label != NULL ) {
  312.                 if ( code(Token[i].xval,Token[i].yval)==0 )
  313.                     if (TransparentLabels)
  314.                         text(Token[i].label,
  315.                         sx(Token[i].val[0])+0.1,
  316.                         sy(Token[i].val[1]),"ljust");
  317.                     else
  318.                         wtext(Token[i].label,
  319.                         sx(Token[i].val[0])+0.1,
  320.                         sy(Token[i].val[1]),"ljust");
  321.                 if (BreakAfterLabel && numpoints > 0) {
  322.                     dumppoints(points,numpoints);
  323.                     numpoints = 0;
  324.                 }
  325.             }
  326.             if ( UseMarker != NULL )
  327.                 domarker(Token[i].val[0],Token[i].val[1]);
  328.             break;
  329.         }
  330.     }
  331.     dumppoints(points,numpoints);
  332.     printf("grestore saveIt restore\n");
  333.     if (Preview)
  334. /*        printf("gsave showpage grestore\n");*/
  335.         printf("showpage\n");
  336.     /*
  337.      * bah ... these can be supplied with command line arguments, but
  338.      * they shouldn't leak through to a second graph...
  339.      */
  340.     
  341.     Title.title = NULL;
  342.     Title.font = NULL;
  343. }
  344.  
  345. /*
  346.  * dumppoints - generate the commands for the data stored in the points array.
  347.  */
  348.  
  349. dumppoints(points, numpoints)
  350. plotpoint_t *points;
  351. int numpoints;
  352. {
  353.     int i;
  354.     float xs, ys, xe, ye;
  355.     float dxi, dyi, dxi1, dyi1;
  356.  
  357.     if (numpoints < 2 ||
  358.         strcmp(LineType, "off") == 0 ||
  359.         strcmp(LineType, "none") == 0)
  360.         return;
  361.     if ( UseSpline ) {
  362.         i = 1;
  363.         while (!clip(points[i-1].x, points[i-1].y,
  364.                 points[i].x, points[i].y,
  365.                 &xs, &ys, &xe, &ye)) 
  366.             i++;        /* remove invisibles at beginning */
  367.  
  368.         startline(xs, ys);
  369.         printf(" %f %f rlineto\n",
  370.             (SX(xe) - SX(xs))/2, (SY(ye) - SY(ys))/2);
  371.  
  372.         for (; i < numpoints - 1; i++){
  373.             if ( clip(points[i-1].x, points[i-1].y,
  374.                   points[i].x, points[i].y,
  375.                   &xs, &ys, &xe, &ye)) {
  376.                 dxi = SX(xe) - SX(xs);
  377.                 dyi = SY(ye) - SY(ys);
  378.             } else {/* handle intermediate clipping */}
  379.             if ( clip(points[i].x, points[i].y,
  380.                   points[i+1].x, points[i+1].y,
  381.                   &xs, &ys, &xe, &ye)) {
  382.                 dxi1 = SX(xe) - SX(xs);
  383.                 dyi1 = SY(ye) - SY(ys);
  384.             } else {/* ditto. it's ugly */}
  385.             printf(" %f %f %f %f %f %f rcurveto\n",
  386.                 dxi/3, dyi/3,
  387.                 (3*dxi+dxi1)/6, (3*dyi+dyi1)/6,
  388.                 (dxi+dxi1)/2, (dyi+dyi1)/2);
  389.         }
  390.         contline(xe, ye);        
  391.     } else for ( i=1 ; i<numpoints ; i++ ) {
  392.         if ( clip(points[i-1].x, points[i-1].y,
  393.               points[i].x,points[i].y, &xs, &ys, &xe, &ye)) {
  394.             if ( i==1 || xs!=points[i-1].x && ys!=points[i-1].y) {
  395.                 if ( i != 1 )
  396.                     printf("\n");
  397.                 startline(xs,ys);
  398.             }
  399.             contline(xe,ye);
  400.         }
  401.     }
  402. }
  403.  
  404. startGridTemp()
  405. {
  406.     assert(!TempOpen);
  407.     printf("/gt%03d[\n", CurrentTemp++);
  408.     TempOpen = TRUE;
  409.     LinesInTemp = 0;
  410. }
  411.  
  412. endGridTemp()
  413. {
  414.     assert(TempOpen);
  415.     printf("]cvx bind def\n");
  416.     TempOpen = FALSE;
  417. }
  418.  
  419. gridLine(x1, y1, x2, y2, g)
  420. float    x1, y1, x2, y2, g;
  421. {
  422.         if (LinesInTemp > 50) { endGridTemp(); startGridTemp(); }
  423.     LinesInTemp++;
  424.         
  425.     putchar('{');
  426.     if (g != 0.0)
  427.         printf("gsave %f setgray ", g);
  428.     stroke(sx(x1), sy(y1), sx(x2), sy(y2));
  429.     if (g != 0.0)
  430.         printf("grestore");
  431.     printf("\t}EX\n");
  432. }
  433.  
  434. tick(x, y, d, big, g)
  435. float    x, y, g;
  436. dir_t    d;
  437. bool    big;
  438. {
  439.     float    len;
  440.  
  441.         if (LinesInTemp > 50) { endGridTemp(); startGridTemp(); }
  442.     LinesInTemp++;
  443.  
  444.     len = big ? TickLen : Tick2Len;
  445.     printf("{ ");
  446.     if (g != 0.0)
  447.         printf("gsave %f setgray ", g);
  448.     switch(d) {
  449.     case    NORTH:
  450.         stroke(sx(x), sy(y), sx(x), sy(y) + len);
  451.         break;
  452.     case    EAST:
  453.         stroke(sx(x), sy(y), sx(x) + len, sy(y));
  454.         break;
  455.     case    SOUTH:
  456.         stroke(sx(x), sy(y) - len, sx(x), sy(y));
  457.         break;
  458.     case    WEST:
  459.         stroke(sx(x) - len, sy(y), sx(x), sy(y));
  460.         break;
  461.     }
  462.     if (g != 0.0)
  463.         printf("grestore");
  464.     printf("\t}EX\n");
  465. }
  466.  
  467. static int    maxWest = 0;    /* most char positions west */
  468.  
  469. tickText(x, y, val, d, font)
  470. float    x, y;
  471. float    val;
  472. dir_t    d;
  473. char    *font;
  474. {
  475.     char    buf[32];
  476.     int    len;
  477.  
  478.         if (LinesInTemp > 50) { endGridTemp(); startGridTemp(); }
  479.     LinesInTemp++;
  480.  
  481.     sprintf(buf, "%g", val);
  482.     printf("{ ");
  483.     newfont(font);
  484.     switch(d){
  485.     case SOUTH:
  486.         text(buf, sx(x), sy(y) - (0.8 * PointSize/72.0), "");
  487.         minY = MIN(minY, sy(Yaxis.gmin)-(0.8*PointSize/72.0));
  488.         break;
  489.     case WEST:
  490.         text(buf, sx(x) - 0.05, sy(y), "rjust");
  491.         len = strlen(buf);
  492.         maxWest = MAX(len, maxWest);
  493.         minX = MIN(minX, -(0.75 * len*PointSize/72.0));
  494.         break;
  495.     }
  496.     printf("\t}EX\n");
  497. }
  498.  
  499. axisText(buf, d, font)
  500. char    *buf;
  501. dir_t    d;
  502. char    *font;
  503. {
  504.     float    xc, yc;
  505.  
  506.     xc = sx(Xaxis.gmin) + (SX(Xaxis.gmax) - SX(Xaxis.gmin)) / 2.0;
  507.     yc = sy(Yaxis.gmin) + (SY(Yaxis.gmax) - SY(Yaxis.gmin)) / 2.0;
  508.  
  509.     printf("{ ");
  510.     newfont(font);
  511.     switch(d) {
  512.     case NORTH:
  513.         printf("%f %f m (%s) /cjust t ", 
  514.             xc, sy(Yaxis.gmax) + 0.1 + 0.3 * PointSize/72.0,
  515.             buf);
  516.         maxY = MAX(maxY, sy(Yaxis.gmax) + 0.1 + 1.3*PointSize/72.0);
  517.         break;
  518.  
  519.     case SOUTH:
  520.         printf("%f %f m (%s) /cjust t ",
  521.             xc, sy(Yaxis.gmin) - 1.8*PointSize/72.0, buf);
  522.         minY = MIN(minY, sy(Yaxis.gmin) - 2.0*PointSize/72.0);
  523.         break;
  524.  
  525.     case WEST:
  526.         printf("%f %f m (%s) /vjust t ", 
  527.             sx(Xaxis.gmin) - (0.75*maxWest * PointSize/72.0
  528.                       + 0.1 + 0.3 * PointSize/72.0),
  529.             yc, 
  530.             buf);
  531.         minX = MIN(minX, sx(Xaxis.gmin) - 
  532.             (0.75*maxWest*PointSize/72.0 
  533.              + 0.1 + 1.3 * PointSize/72.0));
  534.         break;        
  535.     }
  536.     printf("\t}EX\n");
  537. }
  538.  
  539. /*
  540.  * Plot routines -
  541.  *
  542.  * These routines all assume that their input is already scaled to inches
  543.  */
  544.  
  545. stroke(x1,y1,x2,y2)
  546. float x1,y1,x2,y2;
  547. {
  548.     printf("%f %f %f %f l ", x1, y1, x2, y2);
  549. }
  550.  
  551. startline(x,y)
  552. float x,y;
  553. {
  554.     setcolor(LineColor);
  555.     if (LineType != NULL && strlen(LineType)>0)
  556.         printf("/%s f ", LineType);
  557.     else
  558.         printf("/solid f ");
  559.     if (LineWidth != NULL && strlen(LineType)>0)
  560.         printf(" %s fw ", LineWidth);
  561.     else
  562.         printf(" 0.6 setlinewidth ");
  563.     printf("%f %f m\n",sx(x),sy(y));
  564. }
  565.  
  566. contline(x,y)
  567. float x,y;
  568. {
  569.     printf(" %f %f n\n",sx(x),sy(y));
  570. }
  571.  
  572. text(s,x,y,mod)
  573. float x,y;
  574. char *s, *mod;
  575. {
  576.     setcolor(TextColor);
  577.     printf("%f %f m (%s) ", x, y, s);
  578.     if ((strlen(mod) == 0) || (mod == NULL))
  579.         printf("/cjust ");
  580.     else 
  581.         printf ("/%s ", mod);
  582.     printf("t\n");
  583. }
  584.  
  585. wtext(s,x,y,mod)
  586. float x,y;
  587. char *s, *mod;
  588. {
  589.     setcolor(TextColor);
  590.     printf("%f %f m (%s) ", x, y, s);
  591.     if ((strlen(mod) == 0) || (mod == NULL))
  592.         printf("/cjust ");
  593.     else 
  594.         printf ("/%s ", mod);
  595.     printf("w\n");
  596. }
  597.  
  598. newfont(font)
  599. register char *font;
  600. {
  601.     char name[100];
  602.     int size;
  603.     register char *np = name;
  604.     register char *s = font;
  605.     register fontName_t *fp;
  606.  
  607.     while (isascii(*s) && (isalpha(*s) || (*s == '-')))
  608.         *np++ = *s++;
  609.     *np++ = NULL;
  610.     if (isascii(*s) && isdigit(*s)) {
  611.         size = 0;
  612.         do
  613.             size = size * 10 + *s++ - '0';
  614.         while ('0' <= *s && *s <= '9');
  615.     }
  616.     if (*s || !size || !name[0]) {
  617.         fprintf (stderr, "Poorly formed font name: \"%s\"\n", name);
  618.         return;
  619.     }
  620.     if (CurrentFont)
  621.         if (size == PointSize && !strcmp(CurrentFont->name, name))
  622.             return;        /* no change */
  623.     printf("/%s findfont %d scalefont setfont ", name, size);
  624.     printf("/fontsize %d def\n", size);
  625.     PointSize = size;
  626.  
  627.     for (fp = FontList; fp; fp = fp->next)
  628.         if (!strcmp(fp->name, name)) {
  629.             CurrentFont = fp;
  630.             return;        /* already there */
  631.         }
  632.     fp = (fontName_t *) malloc(sizeof (fontName_t));
  633.     fp->name = newstr(name);
  634.     fp->next = FontList;
  635.     FontList = fp;
  636.     CurrentFont = fp;
  637. }
  638.  
  639. /*
  640.  * setmarker - set the current marker type
  641.  */
  642.  
  643. setmarker(m)
  644. char    *m;
  645. {
  646.     printf("/%s sm\n", m);
  647. }
  648.  
  649. /*
  650.  * domarker - print the marker at the given point.
  651.  */
  652.  
  653. domarker(x,y)
  654. float    x,y;
  655. {
  656.     if ( code(x,y) )
  657.     return;
  658.     /*
  659.      * note that the marker gray stuff is done inside mk (in PS), so
  660.      * the color may not actually take effect.
  661.      */
  662.     setcolor(MarkColor);
  663.     printf("%f %f mk\n", sx(x), sy(y));
  664. }
  665.  
  666. /*
  667.  * graymarker - set the marker gray value
  668.  */
  669.  
  670. graymarker(s)
  671. float s;
  672. {
  673.     printf("/mg %f def\n", s);
  674. }
  675.  
  676. /*
  677.  * scalemarker - set the marker scale value
  678.  */
  679.  
  680. scalemarker(s)
  681. float    s;
  682. {
  683.     printf("/ms %f def\n", s);
  684. }
  685.  
  686. /*
  687.  * setcolor - set current color; remembers what is already set
  688.  */
  689.  
  690. char *curColor = NULL;
  691.  
  692. setcolor(color)
  693. char *color;
  694. {
  695.     if (curColor && color && (strcmp(curColor, color) == 0))
  696.         return;
  697.     curColor = color;
  698.     if (color != NULL && strlen(color)>0)
  699.         printf("/%s fc\n",color);
  700.     else
  701.         printf("/black fc\n");
  702. }
  703.  
  704. /*
  705.  *----------------------------------------------------------------------
  706.  *
  707.  * DATA CLIPPING ROUTINES
  708.  *
  709.  *    2D clipper     Cohen-Sutherland clipper from Newman and Sproull(pg 67).
  710.  *
  711.  */
  712.  
  713. #define LEFT    0x1
  714. #define RIGHT   0x2
  715. #define BOTTOM  0x4
  716. #define TOP     0x8
  717.  
  718. float   Clipxl, Clipxr, Clipyb, Clipyt;
  719. int    Clipxf, Clipyf;
  720. unsigned int c;
  721.  
  722.  
  723. cliplimits( xmin, ymin, xmax, ymax, xflip, yflip)
  724. float xmin, ymin, xmax, ymax;
  725. int   xflip, yflip;
  726. {
  727.     extern float Clipxl, Clipxr, CLipyb, Clipyt;
  728.  
  729.     Clipxl = xmin;
  730.     Clipxr = xmax;
  731.     Clipxf = xflip;
  732.     Clipyb = ymin;
  733.     Clipyt = ymax;
  734.     Clipyf = yflip;
  735. }
  736.  
  737.  
  738. code( x, y )
  739. float x,y; /* point to encode */
  740.  
  741. {
  742.  
  743.     c = 0;
  744.  
  745.     if ( Clipxf ? x > Clipxl : x < Clipxl )
  746.         c = LEFT;
  747.     else if ( Clipxf ? x < Clipxr : x > Clipxr )
  748.         c = RIGHT;
  749.  
  750.     if ( Clipyf ? y > Clipyb : y < Clipyb )
  751.         c = c | BOTTOM;
  752.     else if ( Clipyf ? y < Clipyt : y > Clipyt )
  753.         c = c | TOP;
  754.  
  755.     return c;
  756.  
  757. }
  758.  
  759.  
  760. clip( x1, y1, x2, y2, xs, ys, xe, ye )
  761. float x1, y1, x2, y2;      /* line to test against box */
  762. float *xs, *ys, *xe, *ye;  /* returned line within region */ 
  763. /*
  764.  *    Description:    Clips a line against the rectangular clipping region set by
  765.  *            Cliplimits. 
  766.  *
  767.  *    Input:
  768.  *            endpoints of a line to be tested. No order assumed.
  769.  *
  770.  *    Output:
  771.  *            Returns the new endpoints of the line clipped to the edges
  772.  *            of the box in xs, ys, xe, ye.
  773.  *
  774.  *        RETURNS:    0  if the the line does not pass through the clipping region.
  775.  *                1  if the line passes through the clipping region.
  776.  *
  777.  */
  778.  
  779. {
  780.     unsigned int c1,c2;
  781.     float x,y;
  782.  
  783.     c1 = code( x1,y1 );
  784.     c2 = code( x2,y2 );
  785.  
  786.     /*  if both c = 0, then both within window : trivial accept */
  787.     while ( (c1 != 0) || (c2 != 0) ) {
  788.             
  789.  
  790.         /* if intersection of c1 and c2 is non-zero, then the line lies
  791.            completely off of the screen */
  792.         if ( c1 & c2 ) {
  793.             *xs = x1;
  794.             *ys = y1;
  795.             *xe = x2;
  796.             *ye = y2;
  797.             return FALSE;
  798.         }
  799.  
  800.         c = c1;
  801.         if ( c == 0 ) c = c2;
  802.  
  803.  
  804.         if ( c & LEFT ) { /* crosses left edge */
  805.             y = y1 + (y2-y1) * (Clipxl - x1) / (x2-x1);
  806.             x = Clipxl;
  807.         } else if ( c & RIGHT ) { /* crosses right edge */
  808.             y = y1 + (y2-y1) * (Clipxr - x1) / (x2-x1);
  809.             x = Clipxr;
  810.         } else if ( c & BOTTOM ) { /* crosses bottom edge */
  811.             x = x1 + (x2-x1) * ( Clipyb - y1 ) / (y2-y1);
  812.             y = Clipyb;
  813.         } else if ( c & TOP ) { /* crosses top edge */
  814.             x = x1 + (x2-x1) * ( Clipyt - y1 ) / (y2-y1);        
  815.             y = Clipyt;
  816.         }
  817.  
  818.         if ( c = c1 ) {
  819.             x1 = x;
  820.             y1 = y;
  821.             c1 = code(x,y);    
  822.         } else {
  823.             x2 = x;
  824.             y2 = y;
  825.             c2 = code(x,y);
  826.         }
  827.  
  828.     } /* end while */
  829.  
  830.     /* line is visible */
  831.  
  832.     *xs = x1;
  833.     *ys = y1;
  834.     *xe = x2;
  835.     *ye = y2;
  836.     return TRUE;
  837. }
  838.  
  839. /*
  840.  * Scaling routines - these convert user data into inches
  841.  */
  842.  
  843. float 
  844. sx(x)
  845. float x;
  846. {
  847.     register axis_t *argp = &Xaxis;
  848.  
  849.     if (argp->tform == IDENT)
  850.         return (x-argp->gmin)/(argp->gmax-argp->gmin)*argp->size
  851.             + argp->offset;
  852.     else
  853.         return (log10(x)-argp->lgmin)/(argp->lgmax - argp->lgmin)
  854.             * argp->size + argp->offset;
  855. }
  856. float
  857. sy(y)
  858. float y;
  859. {
  860.     register axis_t *argp = &Yaxis;
  861.  
  862.     if (argp->tform == IDENT)
  863.         return (y-argp->gmin)/(argp->gmax-argp->gmin)*argp->size
  864.             + argp->offset;
  865.     else
  866.         return (log10(y)-argp->lgmin)/(argp->lgmax - argp->lgmin)
  867.             * argp->size + argp->offset;
  868. }
  869.  
  870. /* these just scale, don't translate */
  871.  
  872. float 
  873. SX(x)
  874. float x;
  875. {
  876.     register axis_t *argp = &Xaxis;
  877.  
  878.     if (argp->tform == IDENT)
  879.         return (x)/(argp->gmax-argp->gmin)*argp->size;
  880.     else
  881.         return (log10(x)-argp->lgmin)/(argp->lgmax - argp->lgmin)
  882.             * argp->size;
  883. }
  884. float 
  885. SY(y)
  886. float y;
  887. {
  888.     register axis_t *argp = &Yaxis;
  889.  
  890.     if (argp->tform == IDENT)
  891.         return (y)/(argp->gmax-argp->gmin)*argp->size;
  892.     else
  893.         return (log10(y)-argp->lgmin)/(argp->lgmax - argp->lgmin)
  894.             * argp->size;
  895. }
  896.  
  897.