[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.2

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

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