home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 334_02 / latex.trm < prev    next >
Text File  |  1991-02-05  |  18KB  |  639 lines

  1. /* GNUPLOT - latex.trm */
  2. /*
  3.  * Copyright (C) 1990   
  4.  *
  5.  * Permission to use, copy, and distribute this software and its
  6.  * documentation for any purpose with or without fee is hereby granted, 
  7.  * provided that the above copyright notice appear in all copies and 
  8.  * that both that copyright notice and this permission notice appear 
  9.  * in supporting documentation.
  10.  *
  11.  * Permission to modify the software is granted, but not the right to
  12.  * distribute the modified code.  Modifications are to be distributed 
  13.  * as patches to released version.
  14.  *  
  15.  * This software  is provided "as is" without express or implied warranty.
  16.  * 
  17.  * This file is included by ../term.c.
  18.  *
  19.  * This terminal driver supports:
  20.  *   LaTeX pictures (latex).
  21.  *   LaTeX pictures with emTeX specials (emtex). 
  22.  *
  23.  * AUTHORS
  24.  *   David Kotz, Russell Lang
  25.  *
  26.  * send your comments or suggestions to (pixar!info-gnuplot@sun.com).
  27.  * 
  28.  */
  29.  
  30. /* modified to optimize use of \rule for long lines */
  31.  
  32. /* the following LATEX driver has been modified by 
  33.    Russell Lang, eln272v@monu1.cc.monash.oz from the
  34.    GnuTeX 1.3 driver by David Kotz, dfk@cs.duke.edu
  35.    And further extended by David Kotz  */
  36.  
  37.  
  38. #define LATEX_PTS_PER_INCH (72.27)
  39. #define DOTS_PER_INCH (300)    /* resolution of printer we expect to use */
  40. #define LATEX_UNIT (LATEX_PTS_PER_INCH/DOTS_PER_INCH) /* dot size in pt */
  41.  
  42. /* 5 inches wide by 3 inches high (default) */
  43. #define LATEX_XMAX (5*DOTS_PER_INCH)  /* (LATEX_PTS_PER_INCH/LATEX_UNIT*5.0) */
  44. #define LATEX_YMAX (3*DOTS_PER_INCH)  /* (LATEX_PTS_PER_INCH/LATEX_UNIT*3.0) */
  45.  
  46. #define LATEX_HTIC (5*DOTS_PER_INCH/72)        /* (5./LATEX_UNIT) */
  47. #define LATEX_VTIC (5*DOTS_PER_INCH/72)        /* (5./LATEX_UNIT) */
  48. #define LATEX_HCHAR (DOTS_PER_INCH*53/10/72)    /* (5.3/LATEX_UNIT) */
  49. #define LATEX_VCHAR (DOTS_PER_INCH*11/72)    /* (11./LATEX_UNIT) */
  50.  
  51. static int LATEX_posx;
  52. static int LATEX_posy;
  53. enum JUSTIFY latex_justify=LEFT;
  54. static int latex_angle=0;
  55.  
  56. /* Default line-drawing character */
  57. /* the definition of plotpoint varies with linetype */
  58. #define LATEX_DOT "\\usebox{\\plotpoint}"
  59. #define LATEX_TINY_DOT "\\rule{.1pt}{.1pt}" /* for dots plot style */
  60.  
  61. /* POINTS */
  62. #define LATEX_POINT_TYPES 12    /* we supply more point types */
  63. static char *LATEX_points[] = {
  64.     "\\raisebox{-1.2pt}{\\makebox(0,0){$\\Diamond$}}",
  65.     "\\makebox(0,0){$+$}",
  66.     "\\raisebox{-1.2pt}{\\makebox(0,0){$\\Box$}}",
  67.     "\\makebox(0,0){$\\times$}",
  68.     "\\makebox(0,0){$\\triangle$}",
  69.     "\\makebox(0,0){$\\star$}",
  70.     "\\circle{12}", "\\circle{18}", "\\circle{24}",
  71.     "\\circle*{12}", "\\circle*{18}", "\\circle*{24}"
  72. };
  73.  
  74. /* LINES */
  75. static int LATEX_type;        /* negative types use real lines */
  76. #define LATEX_LINE_TYPES 6    /* number of line types below */
  77. #define LATEX_THIN_LINE 0    /* the thinnest solid line type */
  78. static struct {
  79.     float size;            /* size of dot, or thick of line in points */
  80.     float dotspace;            /* inter-dot space in points; 0 for lines */
  81. } LATEX_lines[] = {
  82.     {.4, 0.0},                /* thin solid line */
  83.     {1.0, 0.0},                /* thick solid line */
  84.     {2.0, 0.0},                /* Thick solid line */
  85.     {.4, 5.0},                /* dotted line */
  86.     {.4, 10.0},                /* widely dotted line */
  87.     {.4, 15.0}                /* really widely dotted line */
  88. };
  89. /* for drawing dotted and solid lines */
  90. static void LATEX_dot_line();
  91. static void LATEX_solid_line();
  92. static void LATEX_rule();
  93. #define LATEX_flushrule() LATEX_rule(2, 0.,0.,0.,0.) /* flush old rule */
  94. static BOOLEAN LATEX_moved = TRUE;    /* pen is up after move */
  95. static float LATEX_dotsize;    /* size of LATEX_DOT in units */
  96.  
  97. #ifdef EMTEX
  98. BOOLEAN emtex=FALSE; /* not currently using emtex */
  99. static void EMTEX_solid_line();
  100. #endif
  101.  
  102. /* ARROWS */
  103. /* the set of non-vertical/non-horizontal LaTeX vector slopes */
  104. /* except negatives - they are handled specially */
  105. static struct vslope {
  106.     int dx, dy;
  107. } LATEX_slopes[] = {
  108.     {1,1}, {1,2}, {1,3}, {1,4},
  109.     {2,1}, {2,3},
  110.     {3,1}, {3,2}, {3,4},
  111.     {4,1}, {4,3},
  112.     {0,0}                    /* terminator */
  113. };
  114. static void best_latex_arrow(); /* figure out the best arrow */
  115.  
  116. LATEX_init()
  117. {
  118. #ifdef EMTEX
  119.     emtex = FALSE;
  120. #endif
  121.     LATEX_posx = LATEX_posy = 0;
  122.     LATEX_linetype(-1);
  123.     fprintf(outfile, "%% GNUPLOT: LaTeX picture\n");
  124.     fprintf(outfile, "\\setlength{\\unitlength}{%fpt}\n", LATEX_UNIT);
  125. }
  126.  
  127.  
  128. LATEX_scale(xs, ys)
  129.     float xs, ys;            /* scaling factors */
  130. {
  131.     register struct termentry *t = &term_tbl[term];
  132.  
  133.     /* we change the table for use in graphics.c and LATEX_graphics */
  134.     t->xmax = (unsigned int)(LATEX_XMAX * xs);
  135.     t->ymax = (unsigned int)(LATEX_YMAX * ys);
  136.  
  137.     return(TRUE);
  138. }
  139.  
  140. LATEX_graphics()
  141. {
  142.     register struct termentry *t = &term_tbl[term];
  143.  
  144.     fprintf(outfile, "\\begin{picture}(%d,%d)(0,0)\n", t->xmax, t->ymax);
  145.     fprintf(outfile, "\\tenrm\n");
  146.     fprintf(outfile, 
  147.           "\\ifx\\plotpoint\\undefined\\newsavebox{\\plotpoint}\\fi\n");
  148. }
  149.  
  150.  
  151. LATEX_text()
  152. {
  153.     LATEX_flushrule();
  154.     fprintf(outfile, "\\end{picture}\n");
  155. }
  156.  
  157.  
  158. LATEX_linetype(linetype)
  159.     int linetype;
  160. {
  161.     if (linetype >= LATEX_LINE_TYPES)
  162.      linetype %= LATEX_LINE_TYPES;
  163.  
  164. #ifdef EMTEX
  165.     if (!emtex)
  166. #endif
  167.     LATEX_flushrule();
  168.  
  169.     if (linetype >= 0 && 
  170.        (LATEX_type < 0 ||
  171.         LATEX_lines[linetype].size != LATEX_lines[LATEX_type].size)) {
  172.         /* redefine \plotpoint */
  173.         fprintf(outfile, 
  174.             "\\sbox{\\plotpoint}{\\rule[%.3fpt]{%.3fpt}{%.3fpt}}%%\n",
  175.             -LATEX_lines[linetype].size/2,
  176.             LATEX_lines[linetype].size,
  177.             LATEX_lines[linetype].size);
  178. #ifdef EMTEX
  179.         if (emtex)         /* change line width */
  180.             fprintf(outfile, "\\special{em:linewidth %.1fpt}%%\n",
  181.                 LATEX_lines[linetype].size);
  182. #endif
  183.     }
  184.     
  185.     LATEX_type = linetype;
  186.     LATEX_dotsize 
  187.      = ((linetype >= 0) ? LATEX_lines[linetype].size / LATEX_UNIT : 0);
  188.     LATEX_moved = TRUE;            /* reset */
  189. }
  190.  
  191.  
  192. LATEX_move(x,y)
  193.     unsigned int x,y;
  194. {
  195.     LATEX_posx = x;
  196.     LATEX_posy = y;
  197.     LATEX_moved = TRUE;            /* reset */
  198. }
  199.  
  200.  
  201. LATEX_point(x,y, number)        /* version of line_and_point */
  202.     unsigned int x,y;
  203.     int number;                /* type of point */
  204. {
  205.     LATEX_move(x,y);
  206.     
  207.     /* Print the character defined by 'number'; number < 0 means 
  208.       to use a dot, otherwise one of the defined points. */
  209.     fprintf(outfile, "\\put(%d,%d){%s}\n", x, y, 
  210.           (number < 0 ? LATEX_TINY_DOT
  211.            : LATEX_points[number % LATEX_POINT_TYPES]));
  212. }
  213.  
  214.  
  215. LATEX_vector(ux,uy)
  216.     unsigned int ux,uy;
  217. {
  218.     /* Negative linestyles are straight lines for frame and axes. */
  219.     /* These are vertical and horizontal lines only. */
  220.     if (LATEX_type < 0) {
  221.        int x=ux, y=uy;
  222.        if (x == LATEX_posx) { /* vertical */
  223.           fprintf(outfile, "\\put(%d,%d){\\line(0,%d){%d}}\n",
  224.                 LATEX_posx, LATEX_posy, 
  225.                 sign(y - LATEX_posy), abs(y - LATEX_posy));
  226.        } else if (y == LATEX_posy) { /* horizontal */
  227.           fprintf(outfile, "\\put(%d,%d){\\line(%d,0){%d}}\n",
  228.                 LATEX_posx, LATEX_posy, 
  229.                 sign(x - LATEX_posx), abs(x - LATEX_posx));
  230.        }
  231.     } else {                /* drawing real curves */
  232.        if (LATEX_lines[LATEX_type].dotspace == 0.0)
  233. #ifdef EMTEX
  234.         if (emtex)
  235.            EMTEX_solid_line(LATEX_posx, (int)ux, LATEX_posy, (int)uy);
  236.         else
  237. #endif
  238.            LATEX_solid_line(LATEX_posx, (int)ux, LATEX_posy, (int)uy);
  239.        else
  240.         LATEX_dot_line(LATEX_posx, (int)ux, LATEX_posy, (int)uy);
  241.     }
  242.     LATEX_posx = ux;
  243.     LATEX_posy = uy;
  244. }
  245.  
  246. static void
  247. LATEX_solid_line(x1,x2, y1,y2)
  248.     int x1,x2, y1,y2;
  249. {
  250.     float slope;
  251.     int inc;
  252.     float next;
  253.     float x,y;
  254.     int code;                /* possibly combine with previous rule */
  255.  
  256.     /* we draw a solid line using the thickness for this linetype */
  257.     /* we do it with lots of \\rules */
  258.  
  259.     if (x1 == x2 && y1 == y2) { /* zero-length line - just a dot */
  260.        if (LATEX_moved) {
  261.           LATEX_flushrule();
  262.           /* plot a dot */
  263.           fprintf(outfile, "\\put(%u,%u){%s}\n", x1, y1, LATEX_DOT);
  264.        }
  265.     } else {
  266.        code = (LATEX_moved ? 0 : 1); /* no combine after move */
  267.        if (x1 == x2)        /* vertical line - special case */
  268.         LATEX_rule(code, (float)x1, (float)y1, LATEX_dotsize, (float)y2-y1);
  269.        else if (y1 == y2)    /* horizontal line - special case */
  270.         LATEX_rule(code, (float)x1, (float)y1, (float)x2-x1, LATEX_dotsize);
  271.        else {
  272.           slope = ((float)y2-y1)/((float)x2-x1);
  273.           if (abs(slope) <= 1.0) {
  274.              /* longer than high */
  275.              inc = sign(y2-y1);
  276.              for (x = x1, y = y1; (y2-y)*inc >= 0; y += inc) {
  277.                 next = inc/slope + x;
  278.                 if ((x2>x1 && next > x2) || (x2<x1 && next < x2)) {
  279.                     LATEX_rule(code, x,y, x2-x, LATEX_dotsize);
  280.                     break;
  281.                 } else {
  282.                     LATEX_rule(code, x,y, next-x, LATEX_dotsize);
  283.                     x = next;
  284.                 }
  285.                 code = 0;
  286.              }
  287.           } else {
  288.              /* higher than long */
  289.              inc = sign(x2-x1);
  290.              for (x = x1, y = y1; (x2-x)*inc >= 0; x += inc) {
  291.                 next = inc*slope + y;
  292.                 if ((y2>y1 && next > y2) || (y2<y1 && next < y2)) {
  293.                     LATEX_rule(code, x,y, LATEX_dotsize, y2-y);
  294.                     break;
  295.                 } else {
  296.                     LATEX_rule(code, x,y, LATEX_dotsize, next-y);
  297.                     y = next;
  298.                 }
  299.                 code = 0;
  300.              }
  301.           }
  302.        }
  303.     }
  304.     LATEX_moved = FALSE;
  305. }
  306.  
  307. /* Draw a \rule. Width or height may be negative; we can correct.
  308.  * The rule is never output immediately. The previous rule is output
  309.  * as-is if code is 0, and the previous rule is
  310.  * combined with the current rule (if possible) if code is 1.
  311.  * The previous rule is output, and the new one ignored, if code is 2.
  312.  */
  313. static void
  314. LATEX_rule(code, x,y, width, height)
  315.     int code;                /* how do we treat this rule? */
  316.     float x, y;
  317.     float width;
  318.     float height;
  319. {  
  320.     static float lastx, lasty;
  321.     static float lastw, lasth;
  322.     static BOOLEAN valid = FALSE; /* is 'last' data valid? */
  323.     BOOLEAN combine = (code == 1);
  324.     BOOLEAN flush = (code == 2);
  325.  
  326.     if (!flush)
  327.      if (width == 0 || height == 0)
  328.        return;            /* ignore this rule */
  329.  
  330.     if (valid && combine) {
  331.        /* try to combine new rule with old rule */
  332.        if ((int)lastx == (int)x && lastw == width) { /* vertical rule */
  333.           if (lasth * height >= 0) { /* same sign */
  334.              lasth += height;
  335.              return;
  336.           }
  337.        } else if ((int)lasty == (int)y && lasth == height){ /* horiz rule */
  338.           if (lastw * width >= 0) { /* same sign */
  339.              lastw += width;
  340.              return;
  341.           }
  342.        }
  343.        /* oh well, output last and remember the new one */
  344.     }
  345.  
  346.     if (valid) {
  347.        /* output the rule */
  348.        if (lastw < 0) {
  349.           lastx += lastw;
  350.           lastw = -lastw;
  351.        }
  352.        if (lasth < 0) {
  353.           lasty += lasth;
  354.           lasth = -lasth;
  355.        }
  356.  
  357.        /* if very small use canned dot */
  358.        if (lastw < LATEX_dotsize || lasth < LATEX_dotsize)
  359.         fprintf(outfile, "\\put(%d,%d){%s}\n",       
  360.                (int)lastx, (int)lasty, LATEX_DOT);
  361.        else
  362.         fprintf(outfile, "\\put(%d,%d){\\rule[%.3fpt]{%.3fpt}{%.3fpt}}\n",
  363.                (int)lastx, (int)lasty, -LATEX_dotsize*LATEX_UNIT/2,
  364.                lastw*LATEX_UNIT, lasth*LATEX_UNIT);
  365.     }
  366.     
  367.     if (flush) {
  368.        valid = FALSE;
  369.     } else {
  370.        lastx = x; lasty = y;
  371.        lastw = width; lasth = height;
  372.        valid = TRUE;
  373.     }
  374. }
  375.  
  376. static void
  377. LATEX_dot_line(x1,x2, y1,y2)
  378.     int x1,x2, y1,y2;
  379. {
  380.     static float LATEX_left;    /* fraction of space left after last dot */
  381.     extern double sqrt();
  382.  
  383.     /* we draw a dotted line using the dot spacing for this linetype */
  384.  
  385.     if (LATEX_moved)
  386.      LATEX_left = 1.0;        /* reset after a move */
  387.  
  388.     /* zero-length line? */
  389.     if (x1 == x2 && y1 == y2) {
  390.        if (LATEX_moved)
  391.         /* plot a dot */
  392.         fprintf(outfile, "\\put(%u,%u){%s}\n", x1, y1, LATEX_DOT);
  393.     } else {
  394.        float dotspace = LATEX_lines[LATEX_type].dotspace / LATEX_UNIT;
  395.        float x,y;            /* current position */
  396.        float xinc, yinc;    /* increments */
  397.        float slope;        /* slope of line */
  398.        float lastx = -1;    /* last x point plotted */
  399.        float lasty = -1;    /* last y point plotted */
  400.  
  401.        /* first, figure out increments for x and y */
  402.        if (x2 == x1) {
  403.           xinc = 0.0;
  404.           yinc = dotspace;
  405.        } else {
  406.           slope = ((float)y2-y1)/((float)x2-x1);
  407.           xinc = dotspace / sqrt(1 + slope*slope) * sign(x2-x1);
  408.           yinc = slope * xinc;
  409.        }
  410.  
  411.        /* now draw the dotted line */
  412.        /* we take into account where we last placed a dot */
  413.        for (x=x1 + xinc*(1-LATEX_left), y=y1 + yinc*(1-LATEX_left);
  414.            (x2-x)*xinc >= 0 && (y2-y)*yinc >= 0; /* same sign or zero */
  415.            lastx = x, x += xinc, 
  416.            lasty = y, y += yinc)
  417.         fprintf(outfile, "\\put(%d,%d){%s}\n", (int)x, (int)y, LATEX_DOT);
  418.  
  419.        /* how much is left over, as a fraction of dotspace? */
  420.        if (xinc != 0.0)            /* xinc must be nonzero */
  421.         if (lastx >= 0)
  422.           LATEX_left = abs(x2 - lastx) / xinc;
  423.         else
  424.           LATEX_left += abs(x2-x1) / xinc;
  425.        else
  426.         if (lasty >= 0)
  427.           LATEX_left = abs(y2 - lasty) / yinc;
  428.         else
  429.           LATEX_left += abs(y2-y1) / yinc;
  430.     }
  431.  
  432.     LATEX_moved = FALSE;
  433. }
  434.  
  435. LATEX_arrow(sx,sy, ex,ey)
  436.     int sx,sy, ex,ey;
  437. {
  438.     best_latex_arrow(sx,sy, ex,ey, 1);
  439.  
  440.     LATEX_posx = ex;
  441.     LATEX_posy = ey;
  442. }
  443.  
  444. static void best_latex_arrow(sx,sy, ex,ey, who)
  445.     int sx,sy, ex,ey;        /* start and end points */
  446.     int who;                /* 1=LATEX, 2=EEPIC */
  447. {
  448.     int dx = ex - sx;
  449.     int dy = ey - sy;
  450.     int x, y;                /* points near sx,sy */
  451.     float m;                /* slope of line */
  452.     float arrowslope;        /* slope of arrow */
  453.     float minerror = 0;        /* best-case error */
  454.     struct vslope *slope;    /* one of the slopes */
  455.     struct vslope *bestslope;    /* the slope with min error */
  456.     BOOLEAN horiz;            /* was it the horiz line that was best? */
  457.  
  458.     /* We try to draw a real arrow (ie, \vector). If we can't get
  459.     * a slope that is close, we draw a bent arrow.
  460.     */
  461.  
  462.     if (dx == 0) {
  463.        /* vertical arrow */
  464.        fprintf(outfile, "\\put(%d,%d){\\vector(0,%d){%d}}\n",
  465.              sx, sy, sign(ey-sy), abs(ey-sy));
  466.     } else if (dy == 0) {
  467.        /* horizontal arrow */
  468.        fprintf(outfile, "\\put(%d,%d){\\vector(%d,0){%d}}\n",
  469.              sx, sy, sign(ex-sx), abs(ex-sx));
  470.     } else {
  471.        /* Slanted arrow. We'll give it a try.
  472.         * we try to find the closest-slope arrowhead.
  473.         */
  474.        bestslope = NULL;
  475.        minerror = 0; /* to shut up turbo C */
  476.        m = abs((float)dy/dx); /* the slope we want */
  477.        for (slope = LATEX_slopes; slope->dx != 0.0; slope++) {
  478.           /* find the slope of the arrow */
  479.           arrowslope = (float) slope->dy / slope->dx;
  480.           if (bestslope == NULL || abs(m-arrowslope) < minerror) {
  481.              minerror = abs(m-arrowslope);
  482.              bestslope = slope;
  483.           }
  484.        }
  485.  
  486.        /* now we have the best slope arrow */
  487.        /* maybe it's exactly the right slope! */
  488.        if (minerror == 0.0)    /* unlikely but possible */
  489.         fprintf(outfile, "\\put(%d,%d){\\vector(%d,%d){%d}}\n",
  490.                sx, sy, 
  491.                bestslope->dx*sign(ex-sx), bestslope->dy*sign(ey-sy),
  492.                abs(ex-sx));
  493.        else {
  494.           /* we draw the line the usual way, with thin lines */
  495. #ifdef EMTEX
  496.           if (emtex) {
  497.              LATEX_linetype(LATEX_THIN_LINE);
  498.              EMTEX_solid_line(sx,ex,sy,ey);
  499.           } else 
  500. #endif
  501.             if (who == 1) {
  502.                LATEX_linetype(LATEX_THIN_LINE);
  503.                LATEX_solid_line(sx,ex,sy,ey);
  504.             }
  505. #ifdef EEPIC
  506.             else {
  507.                EEPIC_move(sx,sy);
  508.                EEPIC_vector(ex,ey);
  509.             }
  510. #endif /* EEPIC */
  511.           /* and then draw an arrowhead (a short vector) there */
  512.           fprintf(outfile, "\\put(%d,%d){\\vector(%d,%d){0}}\n",
  513.                 ex, ey, 
  514.                 bestslope->dx*sign(ex-sx), bestslope->dy*sign(ey-sy));
  515.        }
  516.     }
  517. }
  518.  
  519.  
  520. LATEX_put_text(x, y, str)
  521.     int x,y;                /* reference point of string */
  522.     char str[];            /* the text */
  523. {
  524.     /* ignore empty strings */
  525.     if (str[0] == '\0')
  526.      return;
  527.  
  528.     fprintf(outfile, "\\put(%d,%d)",x,y);
  529.     switch(latex_angle) {  
  530.         case 0: {
  531.           switch(latex_justify) {
  532.              case LEFT: {
  533.                 fprintf(outfile,
  534.                        "{\\makebox(0,0)[l]{%s}}\n", str);
  535.                 break;
  536.              }
  537.              case CENTRE: {
  538.                 fprintf(outfile,
  539.                        "{\\makebox(0,0){%s}}\n", str);
  540.                 break;
  541.              }
  542.              case RIGHT: {
  543.                 fprintf(outfile,
  544.                        "{\\makebox(0,0)[r]{%s}}\n", str);
  545.                 break;
  546.              }
  547.           }
  548.           break;
  549.        }
  550.        case 1: {            /* put text in a short stack */
  551.           switch(latex_justify) {
  552.              case LEFT: {
  553.                 fprintf(outfile,
  554.                        "{\\makebox(0,0)[lb]{\\shortstack{%s}}}\n", str);
  555.                 break;
  556.              }
  557.              case CENTRE: {
  558.                 fprintf(outfile,
  559.                        "{\\makebox(0,0)[l]{\\shortstack{%s}}}\n", str);
  560.                 break;
  561.              }
  562.              case RIGHT: {
  563.                 fprintf(outfile,
  564.                        "{\\makebox(0,0)[lt]{\\shortstack{%s}}}\n", str);
  565.                 break;
  566.              }
  567.           }
  568.           break;
  569.        }    
  570.     }
  571. }
  572.  
  573.  
  574.  
  575. int LATEX_justify_text(mode)
  576.     enum JUSTIFY mode;
  577. {
  578.     latex_justify = mode;
  579.     return (TRUE);
  580. }
  581.  
  582. int LATEX_text_angle(angle)
  583.     int angle;
  584. {
  585.     /* we can't really write text vertically, but this will 
  586.       put the ylabel centred at the left of the plot, and
  587.       then we'll make a \shortstack */
  588.     latex_angle = angle;
  589.     return (TRUE);
  590. }
  591.  
  592. LATEX_reset()
  593. {
  594.     LATEX_posx = LATEX_posy = 0;
  595. }
  596.  
  597.  
  598. #ifdef EMTEX
  599.  
  600. EMTEX_init()
  601. {
  602.     emtex=TRUE;
  603.     LATEX_posx = LATEX_posy = 0;
  604.     fprintf(outfile, "%% GNUPLOT: LaTeX picture with emtex specials\n");
  605.     fprintf(outfile, "\\setlength{\\unitlength}{%fpt}\n", LATEX_UNIT);
  606.     LATEX_linetype(-1);
  607. }
  608.  
  609.  
  610. EMTEX_reset()
  611. {
  612.     emtex=FALSE;
  613.     LATEX_posx = LATEX_posy = 0;
  614. }
  615.  
  616.  
  617. EMTEX_text()
  618. {
  619.     fprintf(outfile, "\\end{picture}\n");
  620. }
  621.  
  622.  
  623. static void
  624. EMTEX_solid_line(x1,x2, y1,y2)
  625.     int x1,x2, y1,y2;
  626. {
  627.     /* emtex special solid line */
  628.     if (LATEX_moved)
  629.         fprintf(outfile, "\\put(%d,%d){\\special{em:moveto}}\n", x1, y1);
  630.     if ( (x1!=x2) || (y1!=y2) )
  631.         fprintf(outfile, "\\put(%d,%d){\\special{em:lineto}}\n", x2, y2);
  632.     LATEX_posx = x2;
  633.     LATEX_posy = y2;
  634.     LATEX_moved = FALSE;
  635. }
  636.  
  637.  
  638. #endif /* EMTEX */
  639.