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>