Annotation of OpenXM_contrib/gnuplot/term/latex.trm, Revision 1.1.1.3
1.1 maekawa 1: /*
1.1.1.3 ! ohara 2: * $Id: latex.trm,v 1.9.2.2 2002/12/11 19:24:27 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: "",
1.1 maekawa 865: " Examples:",
866: " About label positioning:",
867: " Use gnuplot defaults (mostly sensible, but sometimes not really best):",
868: " set title '\\LaTeX\\ -- $ \\gamma $'",
869: " Force centering both horizontally and vertically:",
870: " set label '{\\LaTeX\\ -- $ \\gamma $}' at 0,0",
871: " Specify own positioning (top here):",
872: " set xlabel '[t]{\\LaTeX\\ -- $ \\gamma $}'",
873: " The other label -- account for long ticlabels:",
1.1.1.3 ! ohara 874: " set ylabel '[r]{\\LaTeX\\ -- $ \\gamma $\\rule{7mm}{0pt}}'"
1.1 maekawa 875: END_HELP(latex)
876: #endif /* TERM_TABLE */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>