1 /* Hello, Emacs, this is -*-C-*-
2 * $Id: metafont.trm,v 1.20 2006/07/21 02:35:47 sfeam Exp $
5 /* GNUPLOT - metafont.trm */
8 * Copyright 1986 - 1993, 1998, 2004 Thomas Williams, Colin Kelley
10 * Permission to use, copy, and distribute this software and its
11 * documentation for any purpose with or without fee is hereby granted,
12 * provided that the above copyright notice appear in all copies and
13 * that both that copyright notice and this permission notice appear
14 * in supporting documentation.
16 * Permission to modify the software is granted, but not the right to
17 * distribute the complete modified source code. Modifications are to
18 * be distributed as patches to the released version. Permission to
19 * distribute binaries produced by compiling modified sources is granted,
21 * 1. distribute the corresponding source modifications from the
22 * released version in the form of a patch file along with the binaries,
23 * 2. add special version identification to distinguish your version
24 * in addition to the base release version number,
25 * 3. provide your name and address as the primary contact for the
26 * support of your modified version, and
27 * 4. retain our contact information in regard to use of the base
29 * Permission to distribute the released version of the source code along
30 * with corresponding source modifications in the form of a patch file is
31 * granted with same provisions 2 through 4 for binary distributions.
33 * This software is provided "as is" without express or implied warranty
34 * to the extent permitted by applicable law.
40 * This terminal driver supports:
41 * Metafont Plot Commands
43 * Written by : Pl Hedne
45 * Pal.Hedne@termo.unit.no
49 * Improvements and bug fixes by Carsten Steger:
50 * - Set default plot size to 5 by 3 inches as in the latex- and eepic-
52 * - Fixed some bugs concerning resolution dependent output
53 * - Added MF_scale function
54 * - Added MF_justify_text function and modified MF_put_text function and
55 * put_text macro accordingly
56 * - Modified MF_move and MF_vector to make output shorter and modified
58 * - Added various linetypes by plotting dashed lines; had to modify
59 * MF_linetype and MF_vector for this
60 * - Added MF_arrow function
61 * - All global variables and #define'd names begin with MF_ now
62 * As a consequence almost nothing of the original code by Pl Hedne remains
63 * but credit goes to him for the ingenious trick of storing the character
64 * images into picture variables, without which this driver would have been
65 * impossible for me to write.
67 * 10/03/95: Converted to new terminal layout by Carsten Steger.
79 /* resolution of printer we expect to use; the value itself is not
80 * particularly important... it is here only for compatibility to the
81 * LaTeX-driver and to get the spacing right. */
83 /* 5 inches wide by 3 inches high (default) */
86 #define MF_XMAX (MF_XSIZE*MF_DPI)
87 #define MF_YMAX (MF_YSIZE*MF_DPI)
89 #define MF_HTIC (5*MF_DPI/72)
90 #define MF_VTIC (5*MF_DPI/72)
91 #define MF_HCHAR (MF_DPI*53/10/72)
92 #define MF_VCHAR (MF_DPI*11/72)
94 TERM_PUBLIC void MF_init __PROTO((void));
95 TERM_PUBLIC void MF_graphics __PROTO((void));
96 TERM_PUBLIC void MF_text __PROTO((void));
97 TERM_PUBLIC int MF_justify_text __PROTO((enum JUSTIFY mode));
98 TERM_PUBLIC int MF_text_angle __PROTO((int ang));
99 TERM_PUBLIC void MF_linetype __PROTO((int linetype));
100 TERM_PUBLIC void MF_move __PROTO((unsigned int x, unsigned int y));
101 TERM_PUBLIC void MF_vector __PROTO((unsigned int x, unsigned int y));
102 TERM_PUBLIC void MF_arrow __PROTO((unsigned int sx, unsigned int sy,
103 unsigned int ex, unsigned int ey,
105 TERM_PUBLIC void MF_put_text __PROTO((unsigned int x, unsigned int y, const char *str));
106 TERM_PUBLIC void MF_reset __PROTO((void));
110 #endif /* TERM_PROTO */
113 #ifndef TERM_PROTO_ONLY
118 /* Plot size in inches */
119 static double MF_xsize = MF_XSIZE;
120 static double MF_ysize = MF_YSIZE;
121 static int MF_char_code;
123 static int MF_line_type;
124 static enum JUSTIFY MF_justify;
125 static double MF_dist_left;
126 static int MF_is_solid;
127 static int MF_picked_up_pen;
129 * We keep track of where we are with respect to dashed lines by using
130 * the next five variables. MF_dash_index indicates which element of
131 * MF_lines[..].dashlen should be used. The MF_last.. variables keep
132 * track of the position of the pen.
134 static int MF_dash_index;
135 static unsigned int MF_last_x, MF_last_y;
138 int solid; /* Is the line solid? */
139 float thickness; /* Thickness of pen we are going to use */
140 int dashlen[4]; /* Length of individual segments; even: line; odd: gap */
144 1, 1.5, { 0, 0, 0, 0 }
147 0, 1.0, { MF_DPI / 60, MF_DPI / 50, MF_DPI / 60, MF_DPI / 50 }
150 1, 1.5, { 0, 0, 0, 0 }
153 0, 1.5, { MF_DPI / 20, MF_DPI / 30, MF_DPI / 20, MF_DPI / 30 }
156 0, 1.5, { MF_DPI / 30, MF_DPI / 20, MF_DPI / 30, MF_DPI / 20 }
159 0, 1.5, { MF_DPI / 15, MF_DPI / 30, MF_DPI / 60, MF_DPI / 30 }
162 0, 1.5, { MF_DPI / 30, MF_DPI / 50, MF_DPI / 30, MF_DPI / 50 }
165 0, 1.5, { MF_DPI / 20, MF_DPI / 50, MF_DPI / 60, MF_DPI / 30 }
168 0, 1.5, { MF_DPI / 30, MF_DPI / 50, MF_DPI / 30, MF_DPI / 30 }
171 0, 1.5, { MF_DPI / 60, MF_DPI / 50, MF_DPI / 60, MF_DPI / 30 }
173 /* dash: line, gap, line, gap */
185 if unknown cmbase: input cmbase fi\n\n\
188 \ndef openit = openwindow currentwindow\n\
189 from (0,0) to (400,800) at (-50,500) enddef;\n\
190 \nmode_setup;\n", gpoutfile);
193 \n%Include next eight lines if you have problems with the mode on your system..\n\
196 %tracingtitles:=0;\n\
197 %pixels_per_inch:=300;\n\
200 %o_correction:=.6;\n\
201 %fix_units;\n", gpoutfile);
203 /* Next lines must be included if text support is needed (CM base used) */
205 \ndef put_text(expr ts,xstart,ystart,rot,justification) =\n\
207 text_width:=0;text_height:=0;text_depth:=0;\n\
208 for ind:=0 step 1 until length(ts)-1:\n\
209 dec_num:=ASCII substring (ind,ind+1) of ts;\n\
210 if unknown r[dec_num]: dec_num:=32; fi\n\
212 text_width:=text_width+wd[65];\n\
213 text_height:=max(text_height,ht[65]);\n\
214 text_depth:=max(text_depth,dp[65]);\n\
215 elseif dec_num>=0: \n\
216 text_width:=text_width+wd[dec_num];\n\
217 text_height:=max(text_height,ht[dec_num]);\n\
218 text_depth:=max(text_depth,dp[dec_num]);\n\
222 if justification=1: ynext:=ystart;\n\
223 elseif justification=2: ynext:=round(ystart-text_width/2);\n\
224 else: ynext:=round(ystart-text_width);\n\
226 xnext:=xstart+(text_height-text_depth)/2;\n\
228 if justification=1: xnext:=xstart;\n\
229 elseif justification=2: xnext:=round(xstart-text_width/2);\n\
230 else: xnext:=round(xstart-text_width);\n\
232 ynext:=ystart-(text_height-text_depth)/2;\n\
234 for ind:=0 step 1 until length(ts)-1:\n\
235 dec_num:=ASCII substring (ind,ind+1) of ts;\n\
236 if unknown r[dec_num]: dec_num:=32; fi\n\
238 xnext:=xnext+wd[65]*cosd rot;\n\
239 ynext:=ynext+wd[65]*sind rot;\n\
240 elseif dec_num>=0: \n\
241 currentpicture:=currentpicture+r[dec_num] shifted(xnext,ynext)\n\
242 rotatedaround ((xnext,ynext),rot); \n\
243 xnext:=xnext+wd[dec_num]*cosd rot;\n\
244 ynext:=ynext+wd[dec_num]*sind rot;\n\
248 enddef;\n", gpoutfile);
252 r[charcode]:=currentpicture;\n\
253 wd[charcode]:=w;ht[charcode]:=h;dp[charcode]:=d;\n\
254 message \"Picture of charcode no.\" & decimal charcode;\n\
257 let endchar_ = endchar;\n\
258 let generate = relax;\n\
259 let roman = relax;\n", gpoutfile);
263 if ligs>1: font_coding_scheme:=\"TeX text\";\n\
264 spanish_shriek=oct\"074\"; spanish_query=oct\"076\";\n\
265 else: font_coding_scheme:=\n\
266 if ligs=0: \"TeX typewriter text\"\n\
267 else: \"TeX text without f-ligatures\" fi;\n\
268 spanish_shriek=oct\"016\"; spanish_query=oct\"017\"; fi\n\
270 input romanu.mf %Roman uppercase.\n\
271 input romanl.mf %Roman lowercase.\n\
272 input greeku.mf %Greek uppercase.\n\
273 input romand.mf %Numerals.\n\
274 input romanp.mf %Ampersand, question marks, currency sign.\n\
275 input romspl.mf %Lowercase specials (dotless \\i, ligature \\ae, etc.)\n\
276 input romspu.mf %Uppercase specials (\\AE, \\OE, \\O)\n\
277 input punct.mf %Punctuation symbols.\n\
278 \nminus=ASCII\"-\"; cmchar \"Minus sign\";\n\
279 beginarithchar(minus); \n\
281 lft x1=hround 1.5u-eps;\n\
282 x2=w-x1; y1=y2=math_axis;\n\
283 draw z1--z2; % bar\n\
285 endchar;\n", gpoutfile);
288 \ncmchar \"Period\";\n\
289 numeric dot_diam#; dot_diam#:=if monospace: 5/4 fi\\ dot_size#;\n\
290 define_whole_blacker_pixels(dot_diam);\n\
291 beginchar(\".\",5u#,dot_diam#,0);\n\
292 adjust_fit(0,0); pickup fine.nib;\n\
293 pos1(dot_diam,0); pos2(dot_diam,90);\n\
294 lft x1l=hround(.5w-.5dot_diam); bot y2l=0; z1=z2; dot(1,2); % dot\n\
296 endchar;\n", gpoutfile);
300 % Next line should probably be removed if CM base is used\n\
302 %Include the next two lines if you want to\n\
303 %rotate the picture 90 deg.(Portrait to Landscape)\n\
304 %currentpicture:=currentpicture rotated 90 shifted (h,0);\n\
305 %tmp:=charht; charht:=charwd; charwd:=tmp;\n\
306 scantokens extra_endchar;\n\
307 if proofing>0: makebox(proofrule); fi\n\
310 if displaying>0: makebox(screenrule); showit; fi\n\
313 let endchar_ = endchar;\n\
314 let generate = input;\n\
315 let roman = roman;\n", gpoutfile);
317 /* font_size must be bigger than em#/16 by METAFONT rules.
318 * Therefore make it pretty big so big figures will be
319 * handled correctly. Setting font_size to 72pt# lets us
320 * handle characters up to 15.94 by 15.94 inches. */
322 \n\nfont_identifier:=\"GNUPLOT\";\n\
324 th#=0.4pt#; define_whole_pixels(th);\n\
326 arrowhead = (-7pt,-2pt){dir30}..(-6pt,0pt)..\
327 {dir150}(-7pt,2pt) &\n\
328 (-7pt,2pt)--(0pt,0pt)--(-7pt,-2pt) & cycle;\n", gpoutfile);
335 register struct termentry *t = term;
337 fprintf(gpoutfile, "\n\nbeginchar(%d,%gin#,%gin#,0);\n",
338 MF_char_code, MF_xsize, MF_ysize);
340 fprintf(gpoutfile, "a:=w/%d;b:=h/%d;\n", t->xmax, t->ymax);
341 MF_picked_up_pen = 0;
348 fputs("endchar;\n", gpoutfile);
353 MF_justify_text(enum JUSTIFY mode)
361 MF_text_angle(int ang)
372 MF_linetype(int linetype)
379 /* Only output change in pens if it actually affects the pen used */
380 if ((MF_lines[linetype].thickness != MF_lines[MF_line_type].thickness) ||
381 (!MF_picked_up_pen)) {
382 fprintf(gpoutfile, "pickup pencircle scaled %gth;\n",
383 MF_lines[linetype].thickness);
384 MF_picked_up_pen = 1;
386 MF_line_type = linetype;
388 MF_dist_left = MF_lines[MF_line_type].dashlen[MF_dash_index];
389 MF_is_solid = MF_lines[MF_line_type].solid;
394 MF_move(unsigned int x, unsigned int y)
399 MF_dist_left = MF_lines[MF_line_type].dashlen[MF_dash_index];
404 MF_vector(unsigned int x, unsigned int y)
407 if (x == MF_last_x && y == MF_last_y)
408 fprintf(gpoutfile, "drawdot (%da,%db);\n", x, y);
410 fprintf(gpoutfile, "draw (%da,%db)--(%da,%db);\n",
411 MF_last_x, MF_last_y, x, y);
413 double dist_to_go, delta_x, delta_y, inc_x, inc_y;
414 double last_x_d, last_y_d, next_x_d, next_y_d;
415 unsigned int next_x, next_y;
417 if (x == MF_last_x && y == MF_last_y) {
418 if (!(MF_dash_index & 1))
419 fprintf(gpoutfile, "drawdot (%da,%db);\n", x, y);
421 last_x_d = MF_last_x;
422 last_y_d = MF_last_y;
423 delta_x = x - last_x_d;
424 delta_y = y - last_y_d;
425 dist_to_go = sqrt(delta_x * delta_x + delta_y * delta_y);
426 inc_x = delta_x / dist_to_go;
427 inc_y = delta_y / dist_to_go;
428 while (MF_dist_left < dist_to_go) {
429 next_x_d = last_x_d + inc_x * MF_dist_left;
430 next_y_d = last_y_d + inc_y * MF_dist_left;
431 next_x = floor(next_x_d + 0.5);
432 next_y = floor(next_y_d + 0.5);
433 /* MF_dash_index & 1 == 0 means: draw a line; otherwise just move */
434 if (!(MF_dash_index & 1))
435 fprintf(gpoutfile, "draw (%da,%db)--(%da,%db);\n",
436 MF_last_x, MF_last_y, next_x, next_y);
441 dist_to_go -= MF_dist_left;
442 MF_dash_index = (MF_dash_index + 1) & 3;
443 MF_dist_left = MF_lines[MF_line_type].dashlen[MF_dash_index];
445 delta_x = x - last_x_d;
446 delta_y = y - last_y_d;
447 MF_dist_left -= sqrt(delta_x * delta_x + delta_y * delta_y);
448 if (!(MF_dash_index & 1)) {
449 if (x == MF_last_x && y == MF_last_y)
450 fprintf(gpoutfile, "drawdot (%da,%db);\n", x, y);
452 fprintf(gpoutfile, "draw (%da,%db)--(%da,%db);\n",
453 MF_last_x, MF_last_y, x, y);
464 unsigned int sx, unsigned int sy,
465 unsigned int ex, unsigned int ey,
468 int delta_x, delta_y;
475 fprintf(gpoutfile, "fill arrowhead rotated angle(%d,%d) shifted (%da,%db);\n",
476 delta_x, delta_y, ex, ey);
482 MF_put_text(unsigned int x, unsigned int y, const char *str)
487 /* ignore empty strings */
491 /* F***. why do drivers need to modify string args? */
492 text = gp_strdup(str);
494 for (i = 0; i < strlen(text); i++)
496 text[i] = '\''; /* Replace " with ' */
497 switch (MF_justify) {
508 fprintf(gpoutfile, "put_text(\"%s\",%da,%db,%d,%d);\n",
509 text, x, y, MF_ang, j);
517 fputs("end.\n", gpoutfile);
521 #endif /* TERM_BODY */
525 TERM_TABLE_START(mf_driver)
526 "mf", "Metafont plotting standard",
527 MF_XMAX, MF_YMAX, MF_VCHAR, MF_HCHAR,
528 MF_VTIC, MF_HTIC, options_null, MF_init, MF_reset,
529 MF_text, null_scale, MF_graphics, MF_move, MF_vector,
530 MF_linetype, MF_put_text, MF_text_angle,
531 MF_justify_text, line_and_point, MF_arrow, set_font_null
532 TERM_TABLE_END(mf_driver)
535 #define LAST_TERM mf_driver
537 #endif /* TERM_TABLE */
538 #endif /* TERM_PROTO_ONLY */
544 "?commands set terminal mf",
551 " The `mf` terminal driver creates an input file to the METAFONT program. Thus a",
552 " figure may be used in the TeX document in the same way as is a character.",
554 " To use a picture in a document, the METAFONT program must be run with the",
555 " output file from `gnuplot` as input. Thus, the user needs a basic knowledge",
556 " of the font creating process and the procedure for including a new font in a",
557 " document. However, if the METAFONT program is set up properly at the local",
558 " site, an unexperienced user could perform the operation without much trouble.",
560 " The text support is based on a METAFONT character set. Currently the",
561 " Computer Modern Roman font set is input, but the user is in principal free to",
562 " choose whatever fonts he or she needs. The METAFONT source files for the",
563 " chosen font must be available. Each character is stored in a separate",
564 " picture variable in METAFONT. These variables may be manipulated (rotated,",
565 " scaled etc.) when characters are needed. The drawback is the interpretation",
566 " time in the METAFONT program. On some machines (i.e. PC) the limited amount",
567 " of memory available may also cause problems if too many pictures are stored.",
569 " The `mf` terminal has no options.",
570 "2 METAFONT Instructions",
571 "?commands set terminal mf detailed",
572 "?set terminal mf detailed",
573 "?set term mf detailed",
575 "?metafont detailed",
577 " - Set your terminal to METAFONT:",
579 " - Select an output-file, e.g.:",
580 " set output \"myfigures.mf\"",
581 " - Create your pictures. Each picture will generate a separate character. Its",
582 " default size will be 5*3 inches. You can change the size by saying `set size",
583 " 0.5,0.5` or whatever fraction of the default size you want to have.",
585 " - Quit `gnuplot`.",
587 " - Generate a TFM and GF file by running METAFONT on the output of `gnuplot`.",
588 " Since the picture is quite large (5*3 in), you will have to use a version of",
589 " METAFONT that has a value of at least 150000 for memmax. On Unix systems",
590 " these are conventionally installed under the name bigmf. For the following",
591 " assume that the command virmf stands for a big version of METAFONT. For",
594 " - Invoke METAFONT:",
596 " - Select the output device: At the METAFONT prompt ('*') type:",
597 " \\mode:=CanonCX; % or whatever printer you use",
598 " - Optionally select a magnification:",
599 " mag:=1; % or whatever you wish",
600 " - Input the `gnuplot`-file:",
601 " input myfigures.mf",
602 " On a typical Unix machine there will usually be a script called \"mf\" that",
603 " executes virmf '&plain', so you probably can substitute mf for virmf &plain.",
604 " This will generate two files: mfput.tfm and mfput.$$$gf (where $$$ indicates",
605 " the resolution of your device). The above can be conveniently achieved by",
606 " typing everything on the command line, e.g.:",
607 " virmf '&plain' '\\mode:=CanonCX; mag:=1; input myfigures.mf'",
608 " In this case the output files will be named myfigures.tfm and",
611 " - Generate a PK file from the GF file using gftopk:",
612 " gftopk myfigures.300gf myfigures.300pk",
613 " The name of the output file for gftopk depends on the DVI driver you use.",
614 " Ask your local TeX administrator about the naming conventions. Next, either",
615 " install the TFM and PK files in the appropriate directories, or set your",
616 " environment variables properly. Usually this involves setting TEXFONTS to",
617 " include the current directory and doing the same thing for the environment",
618 " variable that your DVI driver uses (no standard name here...). This step is",
619 " necessary so that TeX will find the font metric file and your DVI driver will",
620 " find the PK file.",
622 " - To include your pictures in your document you have to tell TeX the font:",
623 " \\font\\gnufigs=myfigures",
624 " Each picture you made is stored in a single character. The first picture is",
625 " character 0, the second is character 1, and so on... After doing the above",
626 " step, you can use the pictures just like any other characters. Therefore, to",
627 " place pictures 1 and 2 centered in your document, all you have to do is:",
628 " \\centerline{\\gnufigs\\char0}",
629 " \\centerline{\\gnufigs\\char1}",
630 " in plain TeX. For LaTeX you can, of course, use the picture environment and",
631 " place the picture wherever you wish by using the \\makebox and \\put macros.",
633 " This conversion saves you a lot of time once you have generated the font;",
634 " TeX handles the pictures as characters and uses minimal time to place them,",
635 " and the documents you make change more often than the pictures do. It also",
636 " saves a lot of TeX memory. One last advantage of using the METAFONT driver",
637 " is that the DVI file really remains device independent, because no \\special",
638 " commands are used as in the eepic and tpic drivers."
640 #endif /* TERM_HELP */