[BACK]Return to latex.trm CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gnuplot / term

Annotation of OpenXM_contrib/gnuplot/term/latex.trm, Revision 1.1.1.1

1.1       maekawa     1: /*
                      2:  * $Id: latex.trm,v 1.63 1998/04/14 00:17:53 drd Exp $
                      3:  *
                      4:  */
                      5:
                      6: /* GNUPLOT - latex.trm */
                      7:
                      8: /*[
                      9:  * Copyright 1990 - 1993, 1998
                     10:  *
                     11:  * Permission to use, copy, and distribute this software and its
                     12:  * documentation for any purpose with or without fee is hereby granted,
                     13:  * provided that the above copyright notice appear in all copies and
                     14:  * that both that copyright notice and this permission notice appear
                     15:  * in supporting documentation.
                     16:  *
                     17:  * Permission to modify the software is granted, but not the right to
                     18:  * distribute the complete modified source code.  Modifications are to
                     19:  * be distributed as patches to the released version.  Permission to
                     20:  * distribute binaries produced by compiling modified sources is granted,
                     21:  * provided you
                     22:  *   1. distribute the corresponding source modifications from the
                     23:  *    released version in the form of a patch file along with the binaries,
                     24:  *   2. add special version identification to distinguish your version
                     25:  *    in addition to the base release version number,
                     26:  *   3. provide your name and address as the primary contact for the
                     27:  *    support of your modified version, and
                     28:  *   4. retain our contact information in regard to use of the base
                     29:  *    software.
                     30:  * Permission to distribute the released version of the source code along
                     31:  * with corresponding source modifications in the form of a patch file is
                     32:  * granted with same provisions 2 through 4 for binary distributions.
                     33:  *
                     34:  * This software is provided "as is" without express or implied warranty
                     35:  * to the extent permitted by applicable law.
                     36: ]*/
                     37:
                     38: /*
                     39:  * This file is included by ../term.c.
                     40:  *
                     41:  * This terminal driver supports:
                     42:  *   LaTeX pictures (latex).
                     43:  *   LaTeX pictures with emTeX specials (emtex).
                     44:  *
                     45:  * AUTHORS
                     46:  *   David Kotz, Russell Lang
                     47:  *
                     48:  * send your comments or suggestions to (info-gnuplot@dartmouth.edu).
                     49:  *
                     50:  */
                     51:
                     52: /* modified to optimize use of \rule for long lines */
                     53: /* TLDC: modified to have nice line types */
                     54:
                     55: /* the following LATEX driver has been modified by
                     56:    Russell Lang, eln272v@monu1.cc.monash.oz from the
                     57:    GnuTeX 1.3 driver by David Kotz, David.Kotz@Dartmouth.edu.
                     58:    Since then it has been further extended by David Kotz.
                     59:    EmTeX driver by Russell Lang. */
                     60:
                     61: /*  9 Dec 1992  LATEX_put_text rewritten to handle \\ newlines
                     62:                 Daniel S. Lewart (d-lewart@uiuc.edu) */
                     63:
                     64: /* Since it took me a little while to figure out what is happening,
                     65:  * I may as well write it down.
                     66:  *  There are three length scales of interest: inches, points
                     67:  * and dots. inches are obvious. points are the usual typesetting
                     68:  * thing (ie approx 72 points per inch). This driver works in
                     69:  * units of dots, which corresponds to pixels on a 300 DPI printer.
                     70:  * We do a \setlength{unitlength}{...pt} to make teX work in
                     71:  * terms of dots.  The ... is called LATEX_UNIT in here.
                     72:  *   The reason I had to get involved in all of this is because
                     73:  * font size (in pts) was not being scaled up by DOTS_PER_POINT
                     74:  * - drd, Sept 1996
                     75:  */
                     76:
                     77: #include "driver.h"
                     78:
                     79: #ifdef TERM_REGISTER
                     80: register_term(latex)
                     81: #ifdef EMTEX
                     82: register_term(emtex)
                     83: #endif
                     84: #endif
                     85:
                     86: #ifdef TERM_PROTO
                     87: TERM_PUBLIC void LATEX_options __PROTO((void));
                     88: TERM_PUBLIC void LATEX_init __PROTO((void));
                     89: TERM_PUBLIC void LATEX_graphics __PROTO((void));
                     90: TERM_PUBLIC void LATEX_text __PROTO((void));
                     91: TERM_PUBLIC void LATEX_put_text __PROTO((unsigned int x, unsigned int y, char str[]));
                     92: TERM_PUBLIC void LATEX_linetype __PROTO((int linetype));
                     93: TERM_PUBLIC void LATEX_move __PROTO((unsigned int x, unsigned int y));
                     94: TERM_PUBLIC void LATEX_point __PROTO((unsigned int x, unsigned int y, int number));
                     95: TERM_PUBLIC void LATEX_vector __PROTO((unsigned int ux, unsigned int uy));
                     96: TERM_PUBLIC void LATEX_arrow __PROTO((unsigned int sx, unsigned int sy, unsigned int ex, unsigned int ey, TBOOLEAN head));
                     97: TERM_PUBLIC int LATEX_justify_text __PROTO((enum JUSTIFY mode));
                     98: TERM_PUBLIC int LATEX_text_angle __PROTO((int ang));
                     99: TERM_PUBLIC void LATEX_reset __PROTO((void));
                    100:
                    101: #ifdef EMTEX
                    102: TERM_PUBLIC void EMTEX_init __PROTO((void));
                    103: TERM_PUBLIC void EMTEX_reset __PROTO((void));
                    104: TERM_PUBLIC void EMTEX_text __PROTO((void));
                    105: #endif
                    106:
                    107: #define TINY_STEP 0.5          /* tiny steps for high quality lines */
                    108:
                    109: #define LATEX_PTS_PER_INCH (72.27)
                    110: #define DOTS_PER_INCH (300)    /* resolution of printer we expect to use */
                    111: #define LATEX_UNIT (LATEX_PTS_PER_INCH/DOTS_PER_INCH)  /* dot size in pt */
                    112:
                    113: /* 5 inches wide by 3 inches high (default) */
                    114: #define LATEX_XMAX (5*DOTS_PER_INCH)   /* (LATEX_PTS_PER_INCH/LATEX_UNIT*5.0) */
                    115: #define LATEX_YMAX (3*DOTS_PER_INCH)   /* (LATEX_PTS_PER_INCH/LATEX_UNIT*3.0) */
                    116:
                    117: #define LATEX_HTIC (5*DOTS_PER_INCH/72)                /* (5 pts) */
                    118: #define LATEX_VTIC (5*DOTS_PER_INCH/72)                /* (5 pts) */
                    119: #define LATEX_HCHAR (DOTS_PER_INCH*53/10/72)   /* (5.3 pts) */
                    120: #define LATEX_VCHAR (DOTS_PER_INCH*11/72)      /* (11 pts) */
                    121: #endif
                    122:
                    123:
                    124: #ifndef TERM_PROTO_ONLY
                    125: #ifdef TERM_BODY
                    126:
                    127: static int LATEX_posx;
                    128: static int LATEX_posy;
                    129: static int LATEX_fontsize = 10;
                    130: static char LATEX_font[MAX_ID_LEN+1] = "cmr";
                    131: static enum JUSTIFY latex_justify = LEFT;
                    132: static int latex_angle = 0;
                    133:
                    134: /* Default line-drawing character */
                    135: /* the definition of plotpoint varies with linetype */
                    136: #define LATEX_DOT "\\usebox{\\plotpoint}"
                    137: #define LATEX_TINY_DOT "\\rule{1pt}{1pt}"      /* for dots plot style */
                    138:
                    139: /* POINTS */
                    140: #define LATEX_POINT_TYPES 12   /* we supply more point types */
                    141: static char GPFAR *GPFAR LATEX_points[] =
                    142: {
                    143:     "\\raisebox{-.8pt}{\\makebox(0,0){$\\Diamond$}}",
                    144:     "\\makebox(0,0){$+$}",
                    145:     "\\raisebox{-.8pt}{\\makebox(0,0){$\\Box$}}",
                    146:     "\\makebox(0,0){$\\times$}",
                    147:     "\\makebox(0,0){$\\triangle$}",
                    148:     "\\makebox(0,0){$\\star$}",
                    149:     "\\circle{12}", "\\circle{18}", "\\circle{24}",
                    150:     "\\circle*{12}", "\\circle*{18}", "\\circle*{24}"
                    151: };
                    152:
                    153: /* LINES */
                    154: static float LATEX_size = 0;   /* current thick of line in points */
                    155: static float LATEX_dotspace = 0;       /* current dotspace of line in points */
                    156: #define LATEX_LINE_TYPES 6     /* number of line types below */
                    157: #define LATEX_THIN_LINE 0      /* the thinnest solid line type */
                    158: static struct {
                    159:     float size;                        /* size of dot, or thick of line in points */
                    160:     float dotspace;            /* inter-dot space in points; 0 for lines */
                    161: } GPFAR LATEX_lines[] =
                    162:
                    163: {
                    164:     {0.4, 0.0},                        /* thin solid line */
                    165:     {0.4, 5.0},                        /* thin dotted line */
                    166:     {0.8, 0.0},                        /* thick solid line */
                    167:     {1.0, 5.0},                        /* thick dotted line */
                    168:     {1.2, 0.0},                        /* Thick solid line */
                    169:     {1.0, 10.0},               /* thick widely dotted line */
                    170: };
                    171:
                    172: /* for drawing dotted and solid lines */
                    173: static void LATEX_dot_line __PROTO((int x1, int x2, int y1, int y2));
                    174: static void LATEX_solid_line __PROTO((int x1, int x2, int y1, int y2));
                    175: static void LATEX_rule __PROTO((int code, double x, double y, double width, double height));
                    176: static void LATEX_flushdot __PROTO((void));
                    177: #define LATEX_flushrule() LATEX_rule(2, 0.,0.,0.,0.)   /* flush old rule */
                    178: static TBOOLEAN LATEX_moved = TRUE;    /* pen is up after move */
                    179: static float LATEX_dotsize;    /* size of LATEX_DOT in units */
                    180: static TBOOLEAN LATEX_needsdot = FALSE;                /* does dotted line need termination? */
                    181:
                    182: #ifdef EMTEX
                    183: TBOOLEAN emtex = FALSE;                /* not currently using emtex */
                    184: static void
                    185: EMTEX_solid_line __PROTO((int x1, int x2, int y1, int y2));
                    186: #endif
                    187:
                    188: /* ARROWS */
                    189: /* the set of non-vertical/non-horizontal LaTeX vector slopes */
                    190: /* except negatives - they are handled specially */
                    191: static struct vslope {
                    192:     int dx, dy;
                    193: } GPFAR LATEX_slopes[] =
                    194:
                    195: {
                    196:     {1, 1},
                    197:     {1, 2},
                    198:     {1, 3},
                    199:     {1, 4},
                    200:     {2, 1},
                    201:     {2, 3},
                    202:     {3, 1},
                    203:     {3, 2},
                    204:     {3, 4},
                    205:     {4, 1},
                    206:     {4, 3},
                    207:     {0, 0}                     /* terminator */
                    208: };
                    209:
                    210: /* figure out the best arrow */
                    211: void best_latex_arrow __PROTO((int, int, int, int, int, TBOOLEAN));
                    212:
                    213: TERM_PUBLIC void LATEX_options()
                    214: {
                    215:     if (!END_OF_COMMAND) {
                    216:        if (almost_equals(c_token, "c$ourier")) {
                    217:            strcpy(LATEX_font, "cmtt");
                    218:            c_token++;
                    219:        } else if (almost_equals(c_token, "r$oman")) {
                    220:            strcpy(LATEX_font, "cmr");
                    221:            c_token++;
                    222:        } else if (almost_equals(c_token, "d$efault")) {
                    223:            strcpy(LATEX_font, "cmr");
                    224:            LATEX_fontsize = 10;
                    225:            c_token++;
                    226:        }
                    227:     }
                    228:     if (!END_OF_COMMAND) {
                    229:        struct value a;
                    230:        LATEX_fontsize = (int) real(const_express(&a));
                    231:     }
                    232:     /* tell gnuplot core about char. sizes. Horizontal spacing
                    233:      * is about half the text pointsize
                    234:      */
                    235:     term->v_char = (unsigned int) (LATEX_fontsize * DOTS_PER_INCH / 72);
                    236:     term->h_char = (unsigned int) (LATEX_fontsize * DOTS_PER_INCH / 144);
                    237:
                    238:     sprintf(term_options, "%s %d", LATEX_font[2] == 't' ? "courier" : "roman",
                    239:            LATEX_fontsize);
                    240: }
                    241:
                    242:
                    243: TERM_PUBLIC void LATEX_init()
                    244: {
                    245: #ifdef EMTEX
                    246:     emtex = FALSE;
                    247: #endif
                    248:     LATEX_posx = LATEX_posy = 0;
                    249:
                    250:     fprintf(gpoutfile, "\
                    251: %% GNUPLOT: LaTeX picture\n\
                    252: \\setlength{\\unitlength}{%fpt}\n\
                    253: \\ifx\\plotpoint\\undefined\\newsavebox{\\plotpoint}\\fi\n",
                    254:            LATEX_UNIT);
                    255:
                    256:     LATEX_linetype(-1);
                    257:     LATEX_size = 0;
                    258: }
                    259:
                    260: TERM_PUBLIC void LATEX_graphics()
                    261: {
                    262:     register struct termentry *t = term;
                    263:
                    264:     /* bounding box */
                    265:     int xscale = xsize * t->xmax;
                    266:     int yscale = ysize * t->ymax;
                    267:
                    268:     fprintf(gpoutfile, "\
                    269: \\begin{picture}(%d,%d)(0,0)\n\
                    270: \\font\\gnuplot=%s10 at %dpt\n\
                    271: \\gnuplot\n",
                    272:            xscale, yscale,
                    273:            LATEX_font, LATEX_fontsize);
                    274: }
                    275:
                    276:
                    277: TERM_PUBLIC void LATEX_text()
                    278: {
                    279:     LATEX_flushrule();
                    280:     LATEX_flushdot();
                    281:     fputs("\\end{picture}\n", gpoutfile);
                    282:     LATEX_posx = LATEX_posy = 0;       /* current position */
                    283:     LATEX_moved = TRUE;                /* pen is up after move */
                    284: }
                    285:
                    286: TERM_PUBLIC void LATEX_linetype(linetype)
                    287: int linetype;
                    288: {
                    289:     float size;
                    290:
                    291:     if (linetype >= LATEX_LINE_TYPES)
                    292:        linetype %= LATEX_LINE_TYPES;
                    293:
                    294: #ifdef EMTEX
                    295:     if (!emtex)
                    296: #endif
                    297:        LATEX_flushrule();
                    298:     LATEX_flushdot();
                    299:
                    300:     /* Find the new desired line thickness. */
                    301:     /* negative linetypes (for axes) use a thin line */
                    302:     /* only relevant for drawing axes/border in 3d */
                    303:     size = (linetype >= 0 ? LATEX_lines[linetype].size
                    304:            : LATEX_lines[LATEX_THIN_LINE].size);
                    305:
                    306:     /* If different from current size, redefine \plotpoint */
                    307:     if (size != LATEX_size) {
                    308:        fprintf(gpoutfile,
                    309:                "\\sbox{\\plotpoint}{\\rule[%.3fpt]{%.3fpt}{%.3fpt}}%%\n",
                    310:                -size / 2, size, size);
                    311: #ifdef EMTEX
                    312:        if (emtex)              /* change line width */
                    313:            fprintf(gpoutfile, "\\special{em:linewidth %.1fpt}%%\n", size);
                    314: #endif
                    315:     }
                    316:     LATEX_size = size;
                    317:     LATEX_dotsize = size / LATEX_UNIT;
                    318:     LATEX_dotspace = (linetype >= 0) ? LATEX_lines[linetype].dotspace : 0;
                    319:     LATEX_moved = TRUE;                /* reset */
                    320: }
                    321:
                    322: TERM_PUBLIC void LATEX_move(x, y)
                    323: unsigned int x, y;
                    324: {
                    325:     LATEX_flushdot();
                    326:
                    327:     LATEX_posx = x;
                    328:     LATEX_posy = y;
                    329:     LATEX_moved = TRUE;                /* reset */
                    330: }
                    331:
                    332:
                    333: TERM_PUBLIC void LATEX_point(x, y, number) /* version of line_and_point */
                    334: unsigned int x, y;
                    335: int number;                    /* type of point */
                    336: {
                    337:     LATEX_move(x, y);
                    338:
                    339:     /* Print the character defined by 'number'; number < 0 means
                    340:        to use a dot, otherwise one of the defined points. */
                    341:     fprintf(gpoutfile, "\\put(%d,%d){%s}\n", x, y,
                    342:            (number < 0 ? LATEX_TINY_DOT
                    343:             : LATEX_points[number % LATEX_POINT_TYPES]));
                    344: }
                    345:
                    346:
                    347: TERM_PUBLIC void LATEX_vector(ux, uy)
                    348: unsigned int ux, uy;
                    349: {
                    350:     if (LATEX_dotspace == 0.0) {
                    351:        /* solid line */
                    352: #ifdef EMTEX
                    353:        if (emtex)
                    354:            EMTEX_solid_line(LATEX_posx, (int) ux, LATEX_posy, (int) uy);
                    355:        else
                    356: #endif
                    357:            LATEX_solid_line(LATEX_posx, (int) ux, LATEX_posy, (int) uy);
                    358:     } else
                    359:        /* dotted line */
                    360:        LATEX_dot_line(LATEX_posx, (int) ux, LATEX_posy, (int) uy);
                    361:
                    362:     LATEX_posx = ux;
                    363:     LATEX_posy = uy;
                    364: }
                    365:
                    366: static void LATEX_solid_line(x1, x2, y1, y2)
                    367: int x1, x2, y1, y2;
                    368: {
                    369:     float slope;
                    370:     int inc;
                    371:     float dx, dy, x, y;
                    372:     float offset, length;
                    373:     int code;                  /* possibly combine with previous rule */
                    374:
                    375:     /* we draw a solid line using the current line thickness (size) */
                    376:     /* we do it with lots of \\rules */
                    377:
                    378:     if (x1 == x2 && y1 == y2) {        /* zero-length line - just a dot */
                    379:        if (LATEX_moved) {
                    380:            LATEX_flushrule();
                    381:            /* plot a dot */
                    382:            fprintf(gpoutfile, "\\put(%u,%u){%s}\n", x1, y1, LATEX_DOT);
                    383:        }
                    384:     } else {
                    385:        code = (LATEX_moved ? 0 : 1);   /* no combine after move */
                    386:        LATEX_moved = FALSE;
                    387:        if (x1 == x2)           /* vertical line - special case */
                    388:            LATEX_rule(code, (double) x1, (double) y1,
                    389:                       LATEX_dotsize, (double) y2 - y1);
                    390:        else if (y1 == y2)      /* horizontal line - special case */
                    391:            LATEX_rule(code, (double) x1, (double) y1, (double) x2 - x1,
                    392:                       LATEX_dotsize);
                    393:        else {
                    394:            dx = (float) x2 - x1;
                    395:            dy = (float) y2 - y1;
                    396:            slope = dy / dx;
                    397:            if (ABS(slope) <= 1.0) {
                    398:                /* longer than high */
                    399:                x = GPMIN(ABS(dx), (0.25 + 1.0 / ABS(slope)) * LATEX_dotsize);
                    400:                offset = sign(dy) * GPMIN(LATEX_dotsize, ABS(dy));
                    401:                dy = dy - offset;
                    402:                length = x * LATEX_UNIT;
                    403:                inc = (x == ABS(dx) ? 1 : GPMAX(1, ABS(dy) / TINY_STEP + 0.5));
                    404:                if (inc == 1) {
                    405:                    fprintf(gpoutfile, "\\put(%u,%.2f){\\rule{%.3fpt}{%.3fpt}}\n",
                    406:                            (x2 >= x1 ? x1 : x2), ((float) y1 + y2 - LATEX_dotsize) / 2,
                    407:                            length, LATEX_dotsize * LATEX_UNIT);
                    408:                } else {
                    409:                    dy = dy / inc;
                    410:                    dx = (dx - sign(dx) * x) / (inc - 1);
                    411:                    fprintf(gpoutfile,
                    412:                            "\\multiput(%.2f,%.2f)(%.3f,%.3f){%u}{\\rule{%.3fpt}{%.3fpt}}\n",
                    413:                            (dx >= 0.0 ? (float) x1 : x1 - x),
                    414:                            (float) y1 - (ABS(dy) - offset) / 2,
                    415:                            dx, dy, inc, length, ABS(dy) * LATEX_UNIT);
                    416:                }
                    417: /* done with one section, now smooth it */
                    418:                x = x / 2;
                    419:                dx = sign(dx) * x;
                    420:                dx = (float) x2 - x1 - dx;
                    421:                dy = (float) y2 - y1;
                    422:                fprintf(gpoutfile, "\\multiput(%.2f,%.2f)(%.3f,%.3f){2}{\\rule{%.3fpt}{%.3fpt}}\n",
                    423:                        (dx >= 0.0 ? (float) x1 : x1 - x), (float) y1 - LATEX_dotsize / 2,
                    424:                        dx, dy, x * LATEX_UNIT, LATEX_dotsize * LATEX_UNIT);
                    425:                LATEX_moved = TRUE;
                    426:            } else {
                    427:                /* higher than long */
                    428:                y = GPMIN(ABS(dy), (0.25 + ABS(slope)) * LATEX_dotsize);
                    429:                offset = sign(dx) * GPMIN(LATEX_dotsize, ABS(dx));
                    430:                dx = dx - offset;
                    431:                length = y * LATEX_UNIT;
                    432:                inc = (y == ABS(dy) ? 1 : GPMAX(1, ABS(dx) / TINY_STEP + 0.5));
                    433:                if (inc == 1) {
                    434:                    fprintf(gpoutfile, "\\put(%.2f,%u){\\rule{%.3fpt}{%.3fpt}}\n",
                    435:                            ((float) x1 + x2 - LATEX_dotsize) / 2, (y2 >= y1 ? y1 : y2),
                    436:                            LATEX_dotsize * LATEX_UNIT, length);
                    437:                } else {
                    438:                    dx = dx / inc;
                    439:                    dy = (dy - sign(dy) * y) / (inc - 1);
                    440:                    fprintf(gpoutfile,
                    441:                            "\\multiput(%.2f,%.2f)(%.3f,%.3f){%u}{\\rule{%.3fpt}{%.3fpt}}\n",
                    442:                            (float) x1 - (ABS(dx) - offset) / 2,
                    443:                            (dy >= 0 ? (float) y1 : y1 - y),
                    444:                            dx, dy, inc, ABS(dx) * LATEX_UNIT, length);
                    445:                }
                    446: /* done with one section, now smooth it */
                    447:                y = y / 2;
                    448:                dx = (float) x2 - x1;
                    449:                dy = sign(dy) * y;
                    450:                dy = (float) y2 - y1 - dy;
                    451:                fprintf(gpoutfile, "\\multiput(%.2f,%.2f)(%.3f,%.3f){2}{\\rule{%.3fpt}{%.3fpt}}\n",
                    452:                        (float) x1 - LATEX_dotsize / 2, (dy >= 0.0 ? (float) y1 : y1 - y),
                    453:                        dx, dy, LATEX_dotsize * LATEX_UNIT, y * LATEX_UNIT);
                    454:                LATEX_moved = TRUE;
                    455:            }
                    456:        }
                    457:     }
                    458: }
                    459:
                    460: /* Draw a \rule. Width or height may be negative; we can correct.
                    461:  * The rule is never output immediately. The previous rule is output
                    462:  * as-is if code is 0, and the previous rule is
                    463:  * combined with the current rule (if possible) if code is 1.
                    464:  * The previous rule is output, and the new one ignored, if code is 2.
                    465:  */
                    466: static void LATEX_rule(code, x, y, width, height)
                    467: int code;                      /* how do we treat this rule? */
                    468: double x, y;
                    469: double width;
                    470: double height;
                    471: {
                    472:     static float lastx, lasty;
                    473:     static float lastw, lasth;
                    474:     static TBOOLEAN isvalid = FALSE;   /* is 'last' data valid? */
                    475:     TBOOLEAN combine = (code == 1);
                    476:     TBOOLEAN flush = (code == 2);
                    477:
                    478:     if (!flush)
                    479:        if (width == 0 || height == 0)
                    480:            return;             /* ignore this rule */
                    481:
                    482:     if (isvalid && combine) {
                    483:        /* try to combine new rule with old rule */
                    484:        if ((int) lastx == (int) x && lastw == width) {         /* vertical rule */
                    485:            if (lasth * height >= 0) {  /* same sign */
                    486:                lasth += height;
                    487:                return;
                    488:            }
                    489:        } else if ((int) lasty == (int) y && lasth == height) {         /* horiz rule */
                    490:            if (lastw * width >= 0) {   /* same sign */
                    491:                lastw += width;
                    492:                return;
                    493:            }
                    494:        }
                    495:        /* oh well, output last and remember the new one */
                    496:     }
                    497:     if (isvalid) {
                    498:        /* output the rule */
                    499:        if (lastw < 0) {
                    500:            lastx += lastw;
                    501:            lastw = -lastw;
                    502:        }
                    503:        if (lasth < 0) {
                    504:            lasty += lasth;
                    505:            lasth = -lasth;
                    506:        }
                    507:        /* if very small use canned dot */
                    508:        if (lastw < LATEX_dotsize || lasth < LATEX_dotsize)
                    509:            fprintf(gpoutfile, "\\put(%.1f,%.1f){%s}\n",
                    510:                    lastx, lasty, LATEX_DOT);
                    511:        else
                    512:            fprintf(gpoutfile, "\\put(%.1f,%.1f){\\rule[%.3fpt]{%.3fpt}{%.3fpt}}\n",
                    513:                    lastx, lasty, -LATEX_dotsize * LATEX_UNIT / 2,
                    514:                    lastw * LATEX_UNIT, lasth * LATEX_UNIT);
                    515:     }
                    516:     if (flush) {
                    517:        isvalid = FALSE;
                    518:     } else {
                    519:        lastx = x;
                    520:        lasty = y;
                    521:        lastw = width;
                    522:        lasth = height;
                    523:        isvalid = TRUE;
                    524:     }
                    525: }
                    526:
                    527: static void LATEX_dot_line(x1, x2, y1, y2)
                    528: int x1, x2, y1, y2;
                    529: {
                    530:     static float LATEX_left;   /* fraction of space left after last dot */
                    531:
                    532:     /* we draw a dotted line using the current dot spacing */
                    533:
                    534:     if (LATEX_moved)
                    535:        LATEX_left = 1.0;       /* reset after a move */
                    536:
                    537:     /* zero-length line? */
                    538:     if (x1 == x2 && y1 == y2) {
                    539:        if (LATEX_moved)
                    540:            /* plot a dot */
                    541:            fprintf(gpoutfile, "\\put(%u,%u){%s}\n", x1, y1, LATEX_DOT);
                    542:     } else {
                    543:        float dotspace = LATEX_dotspace / LATEX_UNIT;
                    544:        float x, y;             /* current position */
                    545:        float xinc, yinc;       /* increments */
                    546:        float slope;            /* slope of line */
                    547:        float lastx = -1;       /* last x point plotted */
                    548:        float lasty = -1;       /* last y point plotted */
                    549:        int numdots = 0;        /* number of dots in this section */
                    550:
                    551:        /* first, figure out increments for x and y */
                    552:        if (x2 == x1) {
                    553:            xinc = 0.0;
                    554:            yinc = (y2 - y1 > 0) ? dotspace : -dotspace;
                    555:        } else {
                    556:            slope = ((float) y2 - y1) / ((float) x2 - x1);
                    557:            xinc = dotspace / sqrt(1 + slope * slope) * sign(x2 - x1);
                    558:            yinc = slope * xinc;
                    559:        }
                    560:
                    561:        /* now draw the dotted line */
                    562:        /* we take into account where we last placed a dot */
                    563:        for (x = x1 + xinc * (1 - LATEX_left), y = y1 + yinc * (1 - LATEX_left);
                    564:             (x2 - x) * xinc >= 0 && (y2 - y) * yinc >= 0;      /* same sign or zero */
                    565:             lastx = x, x += xinc,
                    566:             lasty = y, y += yinc)
                    567:            numdots++;
                    568:        if (numdots == 1)
                    569:            fprintf(gpoutfile, "\\put(%.2f,%.2f){%s}\n",
                    570:                    lastx, lasty, LATEX_DOT);
                    571:        else if (numdots > 0)
                    572:            fprintf(gpoutfile, "\\multiput(%u,%u)(%.3f,%.3f){%u}{%s}\n",
                    573:                    x1, y1, xinc, yinc, numdots, LATEX_DOT);
                    574:
                    575:        /* how much is left over, as a fraction of dotspace? */
                    576:        if (xinc != 0.0)        /* xinc must be nonzero */
                    577:            if (lastx >= 0)
                    578:                LATEX_left = ABS(x2 - lastx) / ABS(xinc);
                    579:            else
                    580:                LATEX_left += ABS(x2 - x1) / ABS(xinc);
                    581:        else if (lasty >= 0)
                    582:            LATEX_left = ABS(y2 - lasty) / ABS(yinc);
                    583:        else
                    584:            LATEX_left += ABS(y2 - y1) / ABS(yinc);
                    585:     }
                    586:
                    587:     LATEX_needsdot = (LATEX_left > 0);
                    588:
                    589:     LATEX_moved = FALSE;
                    590: }
                    591:
                    592: static void LATEX_flushdot()
                    593: {
                    594:     if (LATEX_needsdot)
                    595:        fprintf(gpoutfile, "\\put(%d,%d){%s}\n",
                    596:                LATEX_posx, LATEX_posy, LATEX_DOT);
                    597:     LATEX_needsdot = FALSE;
                    598: }
                    599:
                    600: TERM_PUBLIC void LATEX_arrow(sx, sy, ex, ey, head)
                    601: unsigned int sx, sy, ex, ey;
                    602: TBOOLEAN head;
                    603: {
                    604:     best_latex_arrow(sx, sy, ex, ey, 1, head);
                    605:
                    606:     LATEX_posx = ex;
                    607:     LATEX_posy = ey;
                    608: }
                    609:
                    610: void best_latex_arrow(sx, sy, ex, ey, who, head)
                    611: int sx, sy, ex, ey;            /* start and end points */
                    612: int who;                       /* 1=LATEX, 2=EEPIC */
                    613: TBOOLEAN head;
                    614: {
                    615:     int dx = ex - sx;
                    616:     int dy = ey - sy;
                    617:     float m;                   /* slope of line */
                    618:     float arrowslope;          /* slope of arrow */
                    619:     float minerror = 0;                /* best-case error */
                    620:     struct vslope *slope;      /* one of the slopes */
                    621:     struct vslope *bestslope;  /* the slope with min error */
                    622:
                    623:     /* We try to draw a real arrow (ie, \vector). If we can't get
                    624:        * a slope that is close, we draw a bent arrow.
                    625:      */
                    626:
                    627:     if (dx == 0) {
                    628:        /* vertical arrow */
                    629:        fprintf(gpoutfile, "\\put(%d,%d){\\%s(0,%d){%d}}\n",
                    630:                sx, sy, head ? "vector" : "line",
                    631:                sign(ey - sy), ABS(ey - sy));
                    632:     } else if (dy == 0) {
                    633:        /* horizontal arrow */
                    634:        fprintf(gpoutfile, "\\put(%d,%d){\\%s(%d,0){%d}}\n",
                    635:                sx, sy, head ? "vector" : "line",
                    636:                sign(ex - sx), ABS(ex - sx));
                    637:     } else {
                    638:        /* Slanted arrow. We'll give it a try.
                    639:         * we try to find the closest-slope arrowhead.
                    640:         */
                    641:        bestslope = NULL;
                    642:        minerror = 0;           /* to shut up turbo C */
                    643:        m = ABS((float) dy / dx);       /* the slope we want */
                    644:        for (slope = LATEX_slopes; slope->dx != 0.0; slope++) {
                    645:            /* find the slope of the arrow */
                    646:            arrowslope = (float) slope->dy / slope->dx;
                    647:            if (bestslope == NULL || ABS(m - arrowslope) < minerror) {
                    648:                minerror = ABS(m - arrowslope);
                    649:                bestslope = slope;
                    650:            }
                    651:        }
                    652:
                    653:        /* now we have the best slope arrow */
                    654:        /* maybe it's exactly the right slope! */
                    655:        if (minerror == 0.0)    /* unlikely but possible */
                    656:            fprintf(gpoutfile, "\\put(%d,%d){\\%s(%d,%d){%d}}\n",
                    657:                    sx, sy, head ? "vector" : "line",
                    658:                    bestslope->dx * sign(ex - sx), bestslope->dy * sign(ey - sy),
                    659:                    ABS(ex - sx));
                    660:        else {
                    661:            /* we draw the line the usual way, with thin lines */
                    662: #ifdef EMTEX
                    663:            if (emtex) {
                    664:                LATEX_linetype(LATEX_THIN_LINE);
                    665:                EMTEX_solid_line(sx, ex, sy, ey);
                    666:            } else
                    667: #endif
                    668:            if (who == 1) {
                    669:                LATEX_linetype(LATEX_THIN_LINE);
                    670:                LATEX_solid_line(sx, ex, sy, ey);
                    671:            }
                    672: #ifdef EEPIC
                    673:            else {
                    674:                EEPIC_move(sx, sy);
                    675:                EEPIC_vector(ex, ey);
                    676:            }
                    677: #endif /* EEPIC */
                    678:            /* and then draw an arrowhead (a short vector) there */
                    679:            if (head)
                    680:                fprintf(gpoutfile, "\\put(%d,%d){\\vector(%d,%d){0}}\n",
                    681:                        ex, ey,
                    682:                        bestslope->dx * sign(ex - sx), bestslope->dy * sign(ey - sy));
                    683:        }
                    684:     }
                    685: }
                    686:
                    687: TERM_PUBLIC void LATEX_put_text(x, y, str)
                    688: unsigned int x, y;             /* reference point of string */
                    689: char str[];                    /* the text */
                    690: {
                    691:     static char *justify[] =
                    692:     {"[l]", "", "[r]"};
                    693:     int flag, i;
                    694:
                    695:     /* ignore empty strings */
                    696:     if (str[0] == NUL)
                    697:        return;
                    698:
                    699:     for (flag = FALSE, i = 0; str[i] && !flag;)
                    700:        flag = (str[i++] == '\\') && (str[i++] == '\\');
                    701:
                    702:     fprintf(gpoutfile, "\\put(%d,%d)", x, y);
                    703:     if ((str[0] == '{') || (str[0] == '[')) {
                    704:        fprintf(gpoutfile, "{\\makebox(0,0)%s}\n", str);
                    705:     } else if (flag)
                    706:        fprintf(gpoutfile, "{\\makebox(0,0)%s{\\shortstack{%s}}}\n",
                    707:                justify[latex_justify], str);
                    708:     else
                    709:        fprintf(gpoutfile, "{\\makebox(0,0)%s{%s}}\n",
                    710:                justify[latex_justify], str);
                    711: }
                    712:
                    713: TERM_PUBLIC int LATEX_justify_text(mode)
                    714: enum JUSTIFY mode;
                    715: {
                    716:     latex_justify = mode;
                    717:     return (TRUE);
                    718: }
                    719:
                    720: TERM_PUBLIC int LATEX_text_angle(ang)
                    721: int ang;
                    722: {
                    723:     /* we can't really write text vertically, but this will
                    724:        put the ylabel centred at the left of the plot, and
                    725:        then we'll make a \shortstack */
                    726:     latex_angle = ang;
                    727:     return (TRUE);
                    728: }
                    729:
                    730: TERM_PUBLIC void LATEX_reset()
                    731: {
                    732:     LATEX_posx = LATEX_posy = 0;       /* current position */
                    733:     LATEX_moved = TRUE;                /* pen is up after move */
                    734: }
                    735:
                    736:
                    737: #ifdef EMTEX
                    738:
                    739: TERM_PUBLIC void EMTEX_init()
                    740: {
                    741:     emtex = TRUE;
                    742:     LATEX_posx = LATEX_posy = 0;
                    743:     fprintf(gpoutfile, "\
                    744: %% GNUPLOT: LaTeX picture with emtex specials\n\
                    745: \\setlength{\\unitlength}{%fpt}\n\
                    746: \\ifx\\plotpoint\\undefined\\newsavebox{\\plotpoint}\\fi\n",
                    747:            LATEX_UNIT);
                    748:     LATEX_linetype(-1);
                    749: }
                    750:
                    751:
                    752: TERM_PUBLIC void EMTEX_reset()
                    753: {
                    754:     emtex = FALSE;
                    755:     LATEX_posx = LATEX_posy = 0;
                    756: }
                    757:
                    758:
                    759: TERM_PUBLIC void EMTEX_text()
                    760: {
                    761:     fputs("\\end{picture}\n", gpoutfile);
                    762: }
                    763:
                    764:
                    765: static void EMTEX_solid_line(x1, x2, y1, y2)
                    766: int x1, x2, y1, y2;
                    767: {
                    768:     /* emtex special solid line */
                    769:     if (LATEX_moved)
                    770:        fprintf(gpoutfile, "\\put(%d,%d){\\special{em:moveto}}\n", x1, y1);
                    771:     if ((x1 != x2) || (y1 != y2))
                    772:        fprintf(gpoutfile, "\\put(%d,%d){\\special{em:lineto}}\n", x2, y2);
                    773:     LATEX_posx = x2;
                    774:     LATEX_posy = y2;
                    775:     LATEX_moved = FALSE;
                    776: }
                    777:
                    778:
                    779: #endif /* EMTEX */
                    780:
                    781: #endif /* TERM_BODY */
                    782: #endif /* TERM_PROTO_ONLY */
                    783:
                    784: #ifdef TERM_TABLE
                    785:
                    786: TERM_TABLE_START(latex_driver)
                    787:     "latex", "LaTeX picture environment",
                    788:     LATEX_XMAX, LATEX_YMAX, LATEX_VCHAR, LATEX_HCHAR,
                    789:     LATEX_VTIC, LATEX_HTIC, LATEX_options, LATEX_init, LATEX_reset,
                    790:     LATEX_text, null_scale, LATEX_graphics, LATEX_move, LATEX_vector,
                    791:     LATEX_linetype, LATEX_put_text, LATEX_text_angle,
                    792:     LATEX_justify_text, LATEX_point, LATEX_arrow, set_font_null
                    793: TERM_TABLE_END(latex_driver)
                    794:
                    795: #undef LAST_TERM
                    796: #define LAST_TERM latex_driver
                    797:
                    798:
                    799: #ifdef EMTEX
                    800: TERM_TABLE_START(emtex_driver)
                    801:     "emtex", "LaTeX picture environment with emTeX specials",
                    802:     LATEX_XMAX, LATEX_YMAX, LATEX_VCHAR, LATEX_HCHAR,
                    803:     LATEX_VTIC, LATEX_HTIC, LATEX_options, EMTEX_init, EMTEX_reset,
                    804:     EMTEX_text, null_scale, LATEX_graphics, LATEX_move, LATEX_vector,
                    805:     LATEX_linetype, LATEX_put_text, LATEX_text_angle,
                    806:     LATEX_justify_text, LATEX_point, LATEX_arrow, set_font_null
                    807: TERM_TABLE_END(emtex_driver)
                    808:
                    809: #undef LAST_TERM
                    810: #define LAST_TERM emtex_driver
                    811:
                    812: #endif /* EMTEX */
                    813: #endif /* TERM_TABLE */
                    814:
                    815:
                    816: #ifdef TERM_HELP
                    817: START_HELP(latex)
                    818: "1 latex",
                    819: "?commands set terminal emtex",
                    820: "?set terminal emtex",
                    821: "?set term emtex",
                    822: "?terminal emtex",
                    823: "?term emtex",
                    824: "?latex",
                    825: "?commands set terminal latex",
                    826: "?set terminal latex",
                    827: "?set term latex",
                    828: "?terminal latex",
                    829: "?term latex",
                    830: "?emtex",
                    831: " The `latex` and `emtex` drivers allow two options.",
                    832: "",
                    833: " Syntax:",
                    834: "       set terminal latex | emtex {courier | roman} {<fontsize>}",
                    835: "",
                    836: " `fontsize` may be any size you specify.  The default is 10-point Roman.",
                    837: "",
                    838: " Unless your driver is capable of building fonts at any size (e.g. dvips),",
                    839: " stick to the standard 10, 11 and 12 point sizes.",
                    840: "",
                    841: " METAFONT users beware: METAFONT does not like odd sizes.",
                    842: "",
                    843: " All drivers for LaTeX offer a special way of controlling text positioning:",
                    844: " If any text string begins with '{', you also need to include a '}' at the",
                    845: " end of the text, and the whole text will be centered both horizontally",
                    846: " and vertically by LaTeX. --- If the text string begins with '[', you need",
                    847: " to continue it with: a position specification (up to two out of t,b,l,r),",
                    848: " ']{', the text itself, and finally, '}'. The text itself may be anything",
                    849: " LaTeX can typeset as an LR-box. \\rule{}{}'s may help for best positioning.",
                    850: "",
                    851: " Examples:",
                    852: " About label positioning:",
                    853: " Use gnuplot defaults (mostly sensible, but sometimes not really best):",
                    854: "        set title '\\LaTeX\\ -- $ \\gamma $'",
                    855: " Force centering both horizontally and vertically:",
                    856: "        set label '{\\LaTeX\\ -- $ \\gamma $}' at 0,0",
                    857: " Specify own positioning (top here):",
                    858: "        set xlabel '[t]{\\LaTeX\\ -- $ \\gamma $}'",
                    859: " The other label -- account for long ticlabels:",
                    860: "        set ylabel '[r]{\\LaTeX\\ -- $ \\gamma $\\rule{7mm}{0pt}'"
                    861: END_HELP(latex)
                    862: #endif /* TERM_TABLE */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>