Annotation of OpenXM_contrib/gnuplot/term/latex.trm, Revision 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>