/* Hello, Emacs, this is -*-C-*- * $Id: metapost.trm,v 1.38.2.2 2008/05/31 16:08:26 sfeam Exp $ */ /* GNUPLOT - metapost.trm */ /*[ * Copyright 1990 - 1993, 1998, 2004 * * Permission to use, copy, and distribute this software and its * documentation for any purpose with or without fee is hereby granted, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. * * Permission to modify the software is granted, but not the right to * distribute the complete modified source code. Modifications are to * be distributed as patches to the released version. Permission to * distribute binaries produced by compiling modified sources is granted, * provided you * 1. distribute the corresponding source modifications from the * released version in the form of a patch file along with the binaries, * 2. add special version identification to distinguish your version * in addition to the base release version number, * 3. provide your name and address as the primary contact for the * support of your modified version, and * 4. retain our contact information in regard to use of the base * software. * Permission to distribute the released version of the source code along * with corresponding source modifications in the form of a patch file is * granted with same provisions 2 through 4 for binary distributions. * * This software is provided "as is" without express or implied warranty * to the extent permitted by applicable law. ]*/ /* 1999/04/22 * GNUPLOT -- metapost.trm * * This terminal driver supports: * Metapost Commands * * Based on metafont.trm, written by * Pl Hedne * Trondheim, Norway * Pal.Hedne@termo.unit.no; * with improvements by Carsten Steger * * and pstricks.trm, written by * David Kotz and Raymond Toy * * Adapted to metapost by: * Daniel H. Luecking and * L Srinivasa Mohan */ #include "driver.h" #ifdef TERM_REGISTER register_term(mp) #endif #ifdef TERM_PROTO TERM_PUBLIC void MP_options __PROTO((void)); TERM_PUBLIC void MP_init __PROTO((void)); TERM_PUBLIC void MP_graphics __PROTO((void)); TERM_PUBLIC void MP_text __PROTO((void)); TERM_PUBLIC void MP_linetype __PROTO((int linetype)); TERM_PUBLIC void MP_move __PROTO((unsigned int x, unsigned int y)); TERM_PUBLIC void MP_point __PROTO((unsigned int x, unsigned int y, int number)); TERM_PUBLIC void MP_pointsize __PROTO((double size)); TERM_PUBLIC void MP_linewidth __PROTO((double width)); TERM_PUBLIC void MP_vector __PROTO((unsigned int ux, unsigned int uy)); TERM_PUBLIC void MP_arrow __PROTO((unsigned int sx, unsigned int sy, unsigned int ex, unsigned int ey, int head)); TERM_PUBLIC void MP_put_text __PROTO((unsigned int x, unsigned int y, const char str[])); TERM_PUBLIC int MP_justify_text __PROTO((enum JUSTIFY mode)); TERM_PUBLIC int MP_text_angle __PROTO((int ang)); TERM_PUBLIC void MP_reset __PROTO((void)); TERM_PUBLIC int MP_set_font __PROTO((const char *font)); TERM_PUBLIC void MP_boxfill __PROTO((int style, unsigned int x1, unsigned int y1, unsigned int width, unsigned int height)); TERM_PUBLIC int MP_make_palette __PROTO((t_sm_palette *)); TERM_PUBLIC void MP_previous_palette __PROTO((void)); TERM_PUBLIC void MP_set_color __PROTO((t_colorspec *)); TERM_PUBLIC void MP_filled_polygon __PROTO((int, gpiPoint *)); /* 5 inches wide by 3 inches high (default) */ #define MP_XSIZE 5.0 #define MP_YSIZE 3.0 /* gnuplot units will be one pixel if printing device has this resolution. Too small resolutions (like 300) can give rough appearence to curves when user tries to smooth a curve by choosing high sampling rate. */ #define MP_DPI (2400) #define MP_XMAX (MP_XSIZE*MP_DPI) #define MP_YMAX (MP_YSIZE*MP_DPI) #define MP_HTIC (5*MP_DPI/72) /* nominally 5pt */ #define MP_VTIC (5*MP_DPI/72) /* " 5pt */ #define MP_HCHAR (MP_DPI*53/10/72) /* " 5.3pt */ #define MP_VCHAR (MP_DPI*11/72) /* " 11pt */ #endif /* TERM_PROTO */ #ifndef TERM_PROTO_ONLY #ifdef TERM_BODY static double MP_xsize = MP_XSIZE; static double MP_ysize = MP_YSIZE; /* static double MP_xmax = MP_XMAX; static double MP_ymax = MP_YMAX; * unused, for now */ static int MP_posx; static int MP_posy; static char MP_fontname[MAX_ID_LEN + 1]; static double MP_fontsize; static double MP_textmag; static enum JUSTIFY MP_justify = LEFT; static int MP_ang = 0; static int MP_char_code = 0; /* number of nodes in an output line so far */ static int MP_linecount = 1; /* Number of point types */ #define MP_POINT_TYPES 10 /* Number of line types */ #define MP_LINE_TYPES 8 /* are we in the middle of a MP path? */ static TBOOLEAN MP_inline = FALSE; /* colored or dashed lines? */ static TBOOLEAN MP_color = FALSE; static TBOOLEAN MP_solid = FALSE; /* compatability mode*/ /* static TBOOLEAN MP_notex = FALSE; */ #define MP_NO_TEX 0 #define MP_TEX 1 #define MP_LATEX 2 static int MP_tex = MP_TEX; /* add usepackage instructions for PSNFSS ? */ #define MP_PSNFSS_NONE 0 #define MP_PSNFSS_7 1 #define MP_PSNFSS_8 2 static int MP_psnfss = MP_PSNFSS_NONE; /* should amstex packages be included? */ static int MP_amstex = 0; /* add a4paper option to documentclass */ static int MP_a4paper = 0; /* write a prologues line */ static int MP_prologues = -1; /* has color changed? */ static int MP_color_changed = 0; /* has a font change taken place? */ static TBOOLEAN MP_fontchanged = FALSE; /* The old types */ static int MP_oldline = -2; /* The old sizes */ static double MP_oldptsize = 1.0; static double MP_oldpen = 1.0; /* terminate any path in progress */ static void MP_endline __PROTO((void)); /* max number of path nodes before a newline */ #define MP_LINEMAX 5 enum MP_id { MP_OPT_MONOCHROME, MP_OPT_COLOUR, MP_OPT_SOLID, MP_OPT_DASHED, MP_OPT_NOTEX, MP_OPT_TEX, MP_OPT_LATEX, MP_OPT_A4PAPER, MP_OPT_PSNFSS, MP_OPT_PSNFSS_V7, MP_OPT_NOPSNFSS, MP_OPT_AMSTEX, MP_OPT_FONT, MP_OPT_FONTSIZE, MP_OPT_PROLOGUES, MP_OPT_NOPROLOGUES, MP_OPT_MAGNIFICATION, MP_OPT_OTHER }; static struct gen_table MP_opts[] = { { "mo$nochrome", MP_OPT_MONOCHROME }, { "c$olor", MP_OPT_COLOUR }, { "c$olour", MP_OPT_COLOUR }, { "s$olid", MP_OPT_SOLID }, { "da$shed", MP_OPT_DASHED }, { "n$otex", MP_OPT_NOTEX }, { "t$ex", MP_OPT_TEX }, { "la$tex", MP_OPT_LATEX }, { "a4$paper", MP_OPT_A4PAPER }, { "am$stex", MP_OPT_AMSTEX }, { "ps$nfss", MP_OPT_PSNFSS }, { "psnfss-v$ersion7", MP_OPT_PSNFSS_V7 }, { "nops$nfss", MP_OPT_NOPSNFSS }, { "pro$logues", MP_OPT_PROLOGUES }, { "nopro$logues", MP_OPT_NOPROLOGUES }, { "ma$gnification", MP_OPT_MAGNIFICATION }, { "fo$nt", MP_OPT_FONT }, { NULL, MP_OPT_OTHER } }; TERM_PUBLIC void MP_options() { struct value a; /* Annoying hack to handle the case of 'set termoption' after */ /* we have already initialized the terminal. */ if (c_token != 2) { MP_color = FALSE; MP_solid = FALSE; MP_tex = MP_TEX; MP_a4paper = 0; MP_amstex = 0; MP_psnfss = MP_PSNFSS_NONE; MP_fontsize = 10.0; MP_textmag = 1.0; MP_prologues = -1; strcpy(MP_fontname, "cmr10"); } while (!END_OF_COMMAND) { switch (lookup_table(&MP_opts[0], c_token)) { case MP_OPT_MONOCHROME: MP_color = FALSE; c_token++; break; case MP_OPT_COLOUR: MP_color = TRUE; c_token++; break; case MP_OPT_SOLID: MP_solid = TRUE; c_token++; break; case MP_OPT_DASHED: MP_solid = FALSE; c_token++; break; case MP_OPT_NOTEX: MP_tex = MP_NO_TEX; strcpy(MP_fontname, "pcrr8r"); c_token++; break; case MP_OPT_TEX: MP_tex = MP_TEX; c_token++; break; case MP_OPT_LATEX: MP_tex = MP_LATEX; c_token++; break; case MP_OPT_AMSTEX: MP_tex = MP_LATEX; /* only makes sense when using LaTeX */ MP_amstex = 1; c_token++; break; case MP_OPT_A4PAPER: MP_tex = MP_LATEX; /* only makes sense when using LaTeX */ MP_a4paper = 1; c_token++; break; case MP_OPT_PSNFSS: MP_tex = MP_LATEX; /* only makes sense when using LaTeX */ MP_psnfss = MP_PSNFSS_8; c_token++; break; case MP_OPT_PSNFSS_V7: MP_tex = MP_LATEX; /* only makes sense when using LaTeX */ MP_psnfss = MP_PSNFSS_7; c_token++; break; case MP_OPT_NOPSNFSS: MP_psnfss = MP_PSNFSS_NONE; c_token++; break; case MP_OPT_PROLOGUES: c_token++; if (!(END_OF_COMMAND)) { int dummy_for_prologues; if (sscanf(gp_input_line + token[c_token].start_index, "%d", &dummy_for_prologues) == 1) { MP_prologues = dummy_for_prologues; } c_token++; } break; case MP_OPT_NOPROLOGUES: MP_prologues = -1; c_token++; break; case MP_OPT_MAGNIFICATION: c_token++; if (!END_OF_COMMAND) /* global text scaling */ MP_textmag = (double) real(const_express(&a)); /* c_token++; */ /* Needed ??? */ break; case MP_OPT_FONT: c_token++; if (isstringvalue(c_token)) { char *s = try_to_get_string(); strncpy(MP_fontname, s, sizeof(MP_fontname)); } break; case MP_OPT_OTHER: default: if (isstring(c_token)) { /* font name */ quote_str(MP_fontname, c_token, MAX_ID_LEN); c_token++; } if (!END_OF_COMMAND) { /*font size */ MP_fontsize = (double) real(const_express(&a)); c_token++; } break; } } /* minimal error recovery: */ if (MP_fontsize < 5.0) MP_fontsize = 5.0; if (MP_fontsize > 99.99) MP_fontsize = 99.99; term->v_char = (unsigned int) (MP_DPI * MP_fontsize * MP_textmag * 11 / 720); if (MP_tex == MP_NO_TEX) { /* Courier is a little wider than cmtt */ term->h_char = (unsigned int) (MP_DPI * MP_fontsize * MP_textmag * 6.0 / 720 + 0.5); } else { term->h_char = (unsigned int) (MP_DPI * MP_fontsize * MP_textmag * 5.3 / 720 + 0.5); } if (MP_psnfss == MP_PSNFSS_NONE) { /* using the normal font scheme */ sprintf(term_options, "%s %s %stex%s%s mag %.3f font \"%s\" %.2f %sprologues(%d)", MP_color ? "color" : "monochrome", MP_solid ? "solid" : "dashed", (MP_tex == MP_NO_TEX) ? "no" : (MP_tex == MP_LATEX) ? "la" : "", MP_a4paper ? " a4paper" : "", MP_amstex ? " amstex" : "", MP_textmag, MP_fontname, MP_fontsize, (MP_prologues > -1) ? "" : "no", MP_prologues ); } else { /* using postscript fonts */ sprintf(term_options, "%s %s %stex%s%s mag %.3f %s %sprologues(%d)", MP_color ? "color" : "monochrome", MP_solid ? "solid" : "dashed", (MP_tex == MP_NO_TEX) ? "no" : (MP_tex == MP_LATEX) ? "la" : "", MP_a4paper ? " a4paper" : "", MP_amstex ? " amstex" : "", MP_textmag, (MP_psnfss == MP_PSNFSS_7) ? "psnsfss(v7)" : "psnsfss", (MP_prologues > -1) ? "" : "no", MP_prologues ); }; } TERM_PUBLIC void MP_init() { time_t now; time(&now); MP_posx = MP_posy = 0; fprintf(gpoutfile, "%%GNUPLOT Metapost output: %s\n", asctime(localtime(&now))); if (MP_prologues > -1) { fprintf(gpoutfile, "prologues:=%d;\n", MP_prologues); } if (MP_tex == MP_LATEX) { fputs("\n\ %% Add \\documentclass and \\begin{dcoument} for latex\n\ %% NB you should set the environment variable TEX to the name of your\n\ %% latex executable (normally latex) inorder for metapost to work\n\ %% or run\n\ %% mpost --tex=latex ...\n\ \n\ % BEGPRE\n\ verbatimtex\n", gpoutfile); if (MP_a4paper) { fputs("\\documentclass[a4paper]{article}\n", gpoutfile); } else { fputs("\\documentclass{article}\n", gpoutfile); } switch (MP_psnfss) { case MP_PSNFSS_7:{ fputs("\\usepackage[latin1]{inputenc}\n\ \\usepackage[T1]{fontenc}\n\ \\usepackage{times,mathptmx}\n\ \\usepackage{helvet}\n\ \\usepackage{courier}\n", gpoutfile); } break; case MP_PSNFSS_8:{ fputs("\\usepackage[latin1]{inputenc}\n\ \\usepackage[T1]{fontenc}\n\ \\usepackage{textcomp}\n\ \\usepackage{mathptmx}\n\ \\usepackage[scaled=.92]{helvet}\n\ \\usepackage{courier}\n\ \\usepackage{latexsym}\n", gpoutfile); } break; } if (MP_amstex) { fputs("\\usepackage[intlimits]{amsmath}\n\ \\usepackage{amsfonts}\n", gpoutfile); }; fputs("\\begin{document}\n\ etex\n% ENDPRE\n", gpoutfile); } fputs("\n\ warningcheck:=0;\n\ defaultmpt:=mpt:=4;\n\ th:=.6;\n\ %% Have nice sharp joins on our lines\n\ linecap:=butt;\n\ linejoin:=mitered;\n\ \n\ def scalepen expr n = pickup pencircle scaled (n*th) enddef;\n\ def ptsize expr n = mpt:=n*defaultmpt enddef;\n\ \n", gpoutfile); fprintf(gpoutfile, "\ntextmag:=%6.3f;\n", MP_textmag); fputs("\ vardef makepic(expr str) =\n\ if picture str : str scaled textmag\n\ % otherwise a string\n\ else: str infont defaultfont scaled (defaultscale*textmag)\n\ fi\n\ enddef;\n\ \n\ def infontsize(expr str, size) =\n\ infont str scaled (size / fontsize str)\n\ enddef;\n", gpoutfile); if (MP_tex == MP_NO_TEX) { fprintf(gpoutfile, "\n\ defaultfont:= \"%s\";\n\ defaultscale := %6.3f/fontsize defaultfont;\n", MP_fontname, MP_fontsize); } else { if (MP_tex != MP_LATEX) { fputs("\n\ %font changes\n\ verbatimtex\n\ \\def\\setfont#1#2{%.\n\ \\font\\gpfont=#1 at #2pt\n\ \\gpfont}\n", gpoutfile); fprintf(gpoutfile, "\\setfont{%s}{%5.2f}\netex\n", MP_fontname, MP_fontsize); } } fputs("\n\ color currentcolor; currentcolor:=black;\n\ color fillcolor;\n\ boolean colorlines,dashedlines;\n", gpoutfile); if (MP_color) { fputs("colorlines:=true;\n", gpoutfile); } else { fputs("colorlines:=false;\n", gpoutfile); } if (MP_solid) { fputs("dashedlines:=false;\n", gpoutfile); } else { fputs("dashedlines:=true;\n", gpoutfile); } fputs("\n\ def _wc = withpen currentpen withcolor currentcolor enddef;\n\ def _ac = addto currentpicture enddef;\n\ def _sms = scaled mpt shifted enddef;\n\ % drawing point-types\n\ def gpdraw (expr n, x, y) =\n\ if n<0: _ac contour fullcircle _sms (x,y)\n\ elseif (n=1) or (n=3):\n\ _ac doublepath ptpath[n] _sms (x,y) _wc;\n\ _ac doublepath ptpath[n] rotated 90 _sms (x,y) _wc\n\ elseif n<6: _ac doublepath ptpath[n] _sms (x,y) _wc\n\ else: _ac contour ptpath[n] _sms (x,y) _wc\n\ fi\n\ enddef;\n\ \n\ % the point shapes\n\ path ptpath[];\n\ %diamond\n\ ptpath0 = ptpath6 = (-1/2,0)--(0,-1/2)--(1/2,0)--(0,1/2)--cycle;\n\ % plus sign\n\ ptpath1 = (-1/2,0)--(1/2,0);\n\ % square\n\ ptpath2 = ptpath7 = (-1/2,-1/2)--(1/2,-1/2)--(1/2,1/2)--(-1/2,1/2)--cycle;\n\ % cross\n\ ptpath3 := (-1/2,-1/2)--(1/2,1/2);\n\ % circle:\n\ ptpath4 = ptpath8:= fullcircle;\n\ % triangle\n\ ptpath5 = ptpath9 := (0,1/2)--(-1/2,-1/2)--(1/2,-1/2)--cycle;\n\ \n\ def linetype expr n =\n\ currentcolor:= if colorlines : col[n] else: black fi;\n\ if n = -1 :\n\ drawoptions(withcolor currentcolor withpen (currentpen scaled .5));\n\ elseif n < 1 :\n\ drawoptions(_wc);\n\ else :\n\ drawoptions( if dashedlines: dashed lt[n] fi _wc);\n\ fi\n\ enddef;\n\ \n\ % dash patterns\n\ picture lt[];\n\ lt1=dashpattern(on 2 off 2); % dashes\n\ lt2=dashpattern(on 2 off 2 on 0.2 off 2); %dash-dot\n\ lt3=lt1 scaled 1.414;\n\ lt4=lt2 scaled 1.414;\n\ lt5=lt1 scaled 2;\n\ lt6:=lt2 scaled 2;\n\ lt7=dashpattern(on 0.2 off 2); %dots\n\ \n\ color col[],cyan, magenta, yellow;\n\ cyan=blue+green; magenta=red+blue;yellow=green+red;\n\ col[-2]:=col[-1]:=col0:=black;\n\ col1:=red;\n\ col2:=(.2,.2,1); %blue\n\ col3:=(1,.66,0); %orange\n\ col4:=.85*green;\n\ col5:=.9*magenta;\n\ col6:=0.85*cyan;\n\ col7:=.85*yellow;\n\ \n\ %placing text\n\ picture GPtext;\n\ def put_text(expr pic, x, y, r, j) =\n\ GPtext:=makepic(pic);\n\ GPtext:=GPtext shifted\n\ if j = 1: (-(ulcorner GPtext + llcorner GPtext)/2)\n\ elseif j = 2: (-center GPtext)\n\ else: (-(urcorner GPtext + lrcorner GPtext)/2)\n\ fi\n\ rotated r;\n\ draw GPtext shifted (x,y)\n\ enddef;\n", gpoutfile); } TERM_PUBLIC void MP_graphics() { /* initialize "remembered" drawing parameters */ MP_oldline = -2; MP_oldpen = 1.0; MP_oldptsize = pointsize; fprintf(gpoutfile, "\nbeginfig(%d);\nw:=%.3fin;h:=%.3fin;\n", MP_char_code, MP_xsize, MP_ysize); /* MetaPost can only handle numbers up to 4096. When MP_DPI * is larger than 819, this is exceeded by (term->xmax). So we * scale it and all coordinates down by factor of 10.0. And * compensate by scaling a and b up. */ fprintf(gpoutfile, "a:=w/%.1f;b:=h/%.1f;\n", (term->xmax) / 10.0, (term->ymax) / 10.0); fprintf(gpoutfile, "scalepen 1; ptsize %.3f;linetype -2;\n", pointsize); MP_char_code++; /* reset MP_color_changed */ MP_color_changed = 0; } TERM_PUBLIC void MP_text() { if (MP_inline) MP_endline(); fputs("endfig;\n", gpoutfile); } TERM_PUBLIC void MP_linetype(int lt) { int linetype = lt; if (linetype >= MP_LINE_TYPES) linetype %= MP_LINE_TYPES; if (MP_inline) MP_endline(); /* reset the color in case it has been changed in MP_set_color() */ if (MP_color_changed) { MP_oldline = linetype + 1; MP_color_changed = 0; } if (MP_oldline != linetype) { fprintf(gpoutfile, "linetype %d;\n", linetype); MP_oldline = linetype; } } TERM_PUBLIC void MP_move(unsigned int x, unsigned int y) { if ((x != MP_posx) || (y != MP_posy)) { if (MP_inline) MP_endline(); MP_posx = x; MP_posy = y; } /* else we seem to be there already */ } TERM_PUBLIC void MP_point(unsigned int x, unsigned int y, int pt) { int pointtype = pt; if (MP_inline) MP_endline(); /* Print the shape defined by 'number'; number < 0 means to use a dot, otherwise one of the defined points. */ if (pointtype >= MP_POINT_TYPES) pointtype %= MP_POINT_TYPES; /* Change %d to %f, divide x,y by 10 */ fprintf(gpoutfile, "gpdraw(%d,%.1fa,%.1fb);\n", pointtype, x / 10.0, y / 10.0); } TERM_PUBLIC void MP_pointsize(double ps) { if (ps < 0) ps = 1; if (MP_oldptsize != ps) { if (MP_inline) MP_endline(); fprintf(gpoutfile, "ptsize %.3f;\n", ps); MP_oldptsize = ps; } } TERM_PUBLIC void MP_linewidth(double lw) { if (MP_oldpen != lw) { if (MP_inline) MP_endline(); fprintf(gpoutfile, "scalepen %.3f;\n", lw); MP_oldpen = lw; } } TERM_PUBLIC void MP_vector(unsigned int ux, unsigned int uy) { if ((ux == MP_posx) && (uy == MP_posy)) return; /* Zero length line */ if (MP_inline) { if (MP_linecount++ >= MP_LINEMAX) { fputs("\n", gpoutfile); MP_linecount = 1; } } else { MP_inline = TRUE; fprintf(gpoutfile, "draw (%.1fa,%.1fb)", MP_posx / 10.0, MP_posy / 10.0); MP_linecount = 2; } MP_posx = ux; MP_posy = uy; fprintf(gpoutfile, "--(%.1fa,%.1fb)", MP_posx / 10.0, MP_posy / 10.0); } static void MP_endline() { MP_inline = FALSE; fprintf(gpoutfile, ";\n"); } TERM_PUBLIC void MP_arrow(unsigned int sx, unsigned int sy, unsigned int ex, unsigned int ey, int head) { MP_move(sx, sy); if (head) { fprintf(gpoutfile, "%s (%.1fa,%.1fb)--(%.1fa,%.1fb);\n", head == 1 ? "drawarrow" : "drawdblarrow", sx / 10.0, sy / 10.0, ex / 10.0, ey / 10.0); } else if ((sx != ex) || (sy != ey)) { fprintf(gpoutfile, "draw (%.1fa,%.1fb)--(%.1fa,%.1fb);\n", sx / 10.0, sy / 10.0, ex / 10.0, ey / 10.0); } /* else: arrow with no length and no head = sound of one hand clapping? */ MP_posx = ex; MP_posy = ey; } TERM_PUBLIC void MP_put_text(unsigned int x, unsigned int y, const char str[]) { int i, j = 0; char *text; /* ignore empty strings */ if (!str || !*str) return; /* F***. why do drivers need to modify string args? */ text = gp_strdup(str); if (MP_inline) MP_endline(); switch (MP_justify) { case LEFT: j = 1; break; case CENTRE: j = 2; break; case RIGHT: j = 3; break; } if (MP_tex == MP_NO_TEX) { for (i = 0; i < strlen(text); i++) if (text[i] == '"') text[i] = '\''; /* Replace " with ' */ if (MP_fontchanged) { fprintf(gpoutfile, "\ put_text(\"%s\" infontsize(\"%s\",%5.2f), %.1fa, %.1fb, %d, %d);\n", text, MP_fontname, MP_fontsize, x / 10.0, y / 10.0, MP_ang, j); } else { fprintf(gpoutfile, "put_text(\"%s\", %.1fa, %.1fb, %d, %d);\n", text, x / 10.0, y / 10.0, MP_ang, j); } } else if (MP_fontchanged) { if (MP_tex != MP_LATEX) { fprintf(gpoutfile, "\ put_text( btex \\setfont{%s}{%5.2f} %s etex, %.1fa, %.1fb, %d, %d);\n", MP_fontname, MP_fontsize, text, x / 10.0, y / 10.0, MP_ang, j); } else { fprintf(gpoutfile, "put_text( btex %s etex, %.1fa, %.1fb, %d, %d);\n", text, x / 10.0, y / 10.0, MP_ang, j); } } else { fprintf(gpoutfile, "put_text( btex %s etex, %.1fa, %.1fb, %d, %d);\n", text, x / 10.0, y / 10.0, MP_ang, j); } free(text); } TERM_PUBLIC int MP_justify_text(enum JUSTIFY mode) { MP_justify = mode; return (TRUE); } TERM_PUBLIC int MP_text_angle(int ang) { /* Metapost code does the conversion */ MP_ang = ang; return (TRUE); } TERM_PUBLIC int MP_set_font(const char *font) { if (*font) { size_t sep = strcspn(font, ","); strncpy(MP_fontname, font, sep); MP_fontname[sep] = NUL; sscanf(&(font[sep + 1]), "%lf", &MP_fontsize); if (MP_fontsize < 5) MP_fontsize = 5.0; if (MP_fontsize >= 100) MP_fontsize = 99.99; /* */ MP_fontchanged = TRUE; } else { MP_fontchanged = FALSE; } return TRUE; } TERM_PUBLIC void MP_reset() { if (MP_tex == MP_LATEX) { fputs("% BEGPOST\n",gpoutfile); fputs("verbatimtex\n",gpoutfile); fputs(" \\end{document}\n",gpoutfile); fputs("etex\n",gpoutfile); fputs("% ENDPOST\n",gpoutfile); }; fputs("end.\n", gpoutfile); } TERM_PUBLIC void MP_boxfill( int style, unsigned int x1, unsigned int y1, unsigned int wd, unsigned int ht) { /* fillpar: * - solid : 0 - 100% intensity * - pattern : 0 - n pattern number */ int fillpar = style >> 4; style &= 0xf; if (MP_inline) MP_endline(); switch (style) { case FS_EMPTY: /* fill with background color */ fprintf(gpoutfile, "\ fill (%.1fa,%.1fb)--(%.1fa,%.1fb)--(%.1fa,%.1fb)--(%.1fa,%.1fb)--cycle withcolor background;\n", x1 / 10.0, y1 / 10.0, (x1 + wd) / 10.0, y1 / 10.0, (x1 + wd) / 10.0, (y1 + ht) / 10.0, x1 / 10.0, (y1 + ht) / 10.0); break; case FS_PATTERN: /* pattern fill */ /* FIXME: not yet implemented, dummy it up as fill density */ fillpar *= 12; default: case FS_SOLID: /* solid fill */ if (fillpar < 100) { double density = (100-fillpar) * 0.01; fprintf(gpoutfile,"fillcolor:=currentcolor*%.2f+background*%.2f;\n", 1.0-density, density); MP_color_changed = 1; } else fprintf(gpoutfile,"fillcolor:=currentcolor;\n"); fprintf(gpoutfile, "\ fill (%.1fa,%.1fb)--(%.1fa,%.1fb)--(%.1fa,%.1fb)--(%.1fa,%.1fb)--cycle withpen (pencircle scaled 0pt) withcolor fillcolor;\n", x1 / 10.0, y1 / 10.0, (x1 + wd) / 10.0, y1 / 10.0, (x1 + wd) / 10.0, (y1 + ht) / 10.0, x1 / 10.0, (y1 + ht) / 10.0); break; } } TERM_PUBLIC int MP_make_palette(t_sm_palette *palette) { /* metapost can do continuous number of colours */ return 0; } TERM_PUBLIC void MP_set_color(t_colorspec *colorspec) { double gray = colorspec->value; rgb_color color; /* remeber that we changed the color, needed to reset color in MP_linetype()*/ MP_color_changed = 1; if (MP_inline) MP_endline(); if (!MP_color) { /* gray mode */ if (gray < 1e-3) gray = 0; fprintf(gpoutfile, "currentcolor:=%.3gwhite;\n", gray); } else { /* color mode */ if (colorspec->type == TC_LT) { int linecolor = colorspec->lt; if (linecolor >= MP_LINE_TYPES) linecolor %= MP_LINE_TYPES; if (linecolor == -1) fprintf(gpoutfile, "currentcolor:=black;\n"); else if (linecolor >= 0) fprintf(gpoutfile, "currentcolor:=col%d;\n",linecolor); } if (colorspec->type == TC_FRAC) { if (sm_palette.colors != 0) /* finite nb of colors explicitly requested */ gray = (gray >= ((double)(sm_palette.colors-1)) / sm_palette.colors) ? 1 : floor(gray * sm_palette.colors) / sm_palette.colors; rgb1_from_gray( gray, &color ); } else if (colorspec->type == TC_RGB) { color.r = (double)((colorspec->lt >> 16 ) & 255) / 255.; color.g = (double)((colorspec->lt >> 8 ) & 255) / 255.; color.b = (double)(colorspec->lt & 255) / 255.; } else return; if (color.r < 1e-4) color.r = 0; if (color.g < 1e-4) color.g = 0; if (color.b < 1e-4) color.b = 0; fprintf(gpoutfile, "currentcolor:=%.4g*red+%.4g*green+%.4g*blue;\n", color.r, color.g, color.b); } return; } TERM_PUBLIC void MP_filled_polygon(int points, gpiPoint *corners) { int i; int fillpar = corners->style >> 4; int style = corners->style & 0xf; if (MP_inline) MP_endline(); switch (style) { case FS_EMPTY: /* fill with background color */ fprintf(gpoutfile,"fillcolor:=background;\n"); break; case FS_PATTERN: /* pattern fill implemented as partial density */ fillpar *= 12; case FS_SOLID: /* solid fill */ if (fillpar < 100) { double density = (100-fillpar) * 0.01; fprintf(gpoutfile,"fillcolor:=currentcolor*%.2f+background*%.2f;\n", 1.0-density, density); } else { fprintf(gpoutfile,"fillcolor:=currentcolor;\n"); } default: break; } fprintf(gpoutfile, "fill "); for (i = 0; i < points; i++) fprintf(gpoutfile, "(%.1fa,%.1fb)%s", corners[i].x / 10.0, corners[i].y / 10.0, (i < points - 1 && (i + 1) % MP_LINEMAX == 0) ? "\n--" : "--"); fprintf(gpoutfile, "cycle withcolor fillcolor;\n"); } TERM_PUBLIC void MP_previous_palette() { return; } #endif /* TERM_BODY */ #ifdef TERM_TABLE TERM_TABLE_START(mp_driver) "mp", "MetaPost plotting standard", MP_XMAX, MP_YMAX, MP_VCHAR, MP_HCHAR, MP_VTIC, MP_HTIC, MP_options, MP_init, MP_reset, MP_text, null_scale, MP_graphics, MP_move, MP_vector, MP_linetype, MP_put_text, MP_text_angle, MP_justify_text, MP_point, MP_arrow, MP_set_font, MP_pointsize, TERM_BINARY|TERM_CAN_CLIP /*flags*/, 0, 0, MP_boxfill, MP_linewidth #ifdef USE_MOUSE , 0, 0, 0, 0, 0 /* no mouse support for metapost */ #endif , MP_make_palette, MP_previous_palette, /* write grestore */ MP_set_color, MP_filled_polygon TERM_TABLE_END(mp_driver) #undef LAST_TERM #define LAST_TERM mp_driver #endif /* TERM_TABLE */ #endif /* TERM_PROTO_ONLY */ #ifdef TERM_HELP START_HELP(mp) "1 mp", "?commands set terminal mpost", "?set terminal mp", "?set term mp", "?terminal mp", "?term mp", "?mp", "?metapost", "", " The `mp` driver produces output intended to be input to the Metapost program.", " Running Metapost on the file creates EPS files containing the plots. By", " default, Metapost passes all text through TeX. This has the advantage of", " allowing essentially any TeX symbols in titles and labels.", "", " Syntax:", " set term mp {color | colour | monochrome}", " {solid | dashed}", " {notex | tex | latex}", " {magnification }", " {psnfss | psnfss-version7 | nopsnfss}", " {prologues }", " {a4paper}", " {amstex}", " {\"\"} {}", "", " The option `color` causes lines to be drawn in color (on a printer or display", " that supports it), `monochrome` (or nothing) selects black lines. The option", " `solid` draws solid lines, while `dashed` (or nothing) selects lines with", " different patterns of dashes. If `solid` is selected but `color` is not,", " nearly all lines will be identical. This may occasionally be useful, so it is", " allowed.", "", " The option `notex` bypasses TeX entirely, therefore no TeX code can be used in", " labels under this option. This is intended for use on old plot files or files", " that make frequent use of common characters like `$` and `%` that require", " special handling in TeX.", "", " The option `tex` sets the terminal to output its text for TeX to process.", "", " The option `latex` sets the terminal to output its text for processing by", " LaTeX. This allows things like \\frac for fractions which LaTeX knows about", " but TeX does not. Note that you must set the environment variable TEX to the", " name of your LaTeX executable (normally latex) if you use this option or use", " `mpost --tex= ...`. Otherwise metapost will try and", " use TeX to process the text and it won't work.", "", " Changing font sizes in TeX has no effect on the size of mathematics, and there", " is no foolproof way to make such a change, except by globally setting a", " magnification factor. This is the purpose of the `magnification` option. It", " must be followed by a scaling factor. All text (NOT the graphs) will be scaled", " by this factor. Use this if you have math that you want at some size other", " than the default 10pt. Unfortunately, all math will be the same size, but see", " the discussion below on editing the MP output. `mag` will also work under", " `notex` but there seems no point in using it as the font size option (below)", " works as well.", "", " The option `psnfss` uses postscript fonts in combination with LaTeX. Since", " this option only makes sense, if LaTeX is being used, the `latex` option is selected", " automatically. This option includes the following packages for LaTeX:", " inputenc(latin1), fontenc(T1), mathptmx, helvet(scaled=09.2), courier, latexsym ", " and textcomp.", "", " The option `psnfss-version7` uses also postscript fonts in LaTeX (option `latex`", " is also automatically selected), but uses the following packages with LaTeX:", " inputenc(latin1), fontenc(T1), times, mathptmx, helvet and courier.", "", " The option `nopsnfss` is the default and uses the standard font (cmr10 if not", " otherwise specified).", "", " The option `prologues` takes a value as an additional argument and adds the line", " `prologues:=` to the metapost file. If a value of `2` is specified metapost", " uses postscript fonts to generate the eps-file, so that the result can be viewed", " using e.g. ghostscript. Normally the output of metapost uses TeX fonts and therefore", " has to be included in a (La)TeX file before you can look at it.", "", " The option `noprologues` is the default. No additional line specifying the prologue", " will be added.", "", " The option `a4paper` adds a `[a4paper]` to the documentclass. Normally letter paper", " is used (default). Since this option is only used in case of LaTeX, the `latex` option", " is selected automatically.", "", " The option `amstex` automatically selects the `latex` option and includes the following", " LaTeX packages: amsfonts, amsmath(intlimits). By default these packages are not", " included.", "", " A name in quotes selects the font that will be used when no explicit font is", " given in a `set label` or `set title`. A name recognized by TeX (a TFM file", " exists) must be used. The default is \"cmr10\" unless `notex` is selected,", " then it is \"pcrr8r\" (Courier). Even under `notex`, a TFM file is needed by", " Metapost. The file `pcrr8r.tfm` is the name given to Courier in LaTeX's psnfss", " package. If you change the font from the `notex` default, choose a font that", " matches the ASCII encoding at least in the range 32-126. `cmtt10` almost", " works, but it has a nonblank character in position 32 (space).", "", " The size can be any number between 5.0 and 99.99. If it is omitted, 10.0 is", " used. It is advisable to use `magstep` sizes: 10 times an integer or", " half-integer power of 1.2, rounded to two decimals, because those are the most", " available sizes of fonts in TeX systems.", "", " All the options are optional. If font information is given, it must be at the", " end, with size (if present) last. The size is needed to select a size for the", " font, even if the font name includes size information. For example,", " `set term mp \"cmtt12\"` selects cmtt12 shrunk to the default size 10. This", " is probably not what you want or you would have used cmtt10.", "", " The following common ascii characters need special treatment in TeX:", " $, &, #, %, _; |, <, >; ^, ~, \\, {, and }", " The five characters $, #, &, _, and % can simply be escaped, e.g., `\\$`.", " The three characters <, >, and | can be wrapped in math mode, e.g., `$<$`.", " The remainder require some TeX work-arounds. Any good book on TeX will give", " some guidance.", "", " If you type your labels inside double quotes, backslashes in TeX code need to", " be escaped (doubled). Using single quotes will avoid having to do this, but", " then you cannot use `\\n` for line breaks. As of this writing, version 3.7 of", " gnuplot processes titles given in a `plot` command differently than in other", " places, and backslashes in TeX commands need to be doubled regardless of the", " style of quotes.", "", " Metapost pictures are typically used in TeX documents. Metapost deals with", " fonts pretty much the same way TeX does, which is different from most other", " document preparation programs. If the picture is included in a LaTeX document", " using the graphics package, or in a plainTeX document via epsf.tex, and then", " converted to PostScript with dvips (or other dvi-to-ps converter), the text in", " the plot will usually be handled correctly. However, the text may not appear", " if you send the Metapost output as-is to a PostScript interpreter.", "", "2 Metapost Instructions", "?commands set terminal mp detailed", "?set terminal mp detailed", "?set term mp detailed", "?mp detailed", "?metapost detailed", "", " - Set your terminal to Metapost, e.g.:", " set terminal mp mono \"cmtt12\" 12", "", " - Select an output-file, e.g.:", " set output \"figure.mp\"", "", " - Create your pictures. Each plot (or multiplot group) will generate a", " separate Metapost beginfig...endfig group. Its default size will be 5 by 3", " inches. You can change the size by saying `set size 0.5,0.5` or whatever", " fraction of the default size you want to have.", "", " - Quit gnuplot.", "", " - Generate EPS files by running Metapost on the output of gnuplot:", " mpost figure.mp OR mp figure.mp", " The name of the Metapost program depends on the system, typically `mpost` for", " a Unix machine and `mp` on many others. Metapost will generate one EPS file", " for each picture.", "", " - To include your pictures in your document you can use the graphics package", " in LaTeX or epsf.tex in plainTeX:", " \\usepackage{graphics} % LaTeX", " \\input epsf.tex % plainTeX", " If you use a driver other than dvips for converting TeX DVI output to PS, you", " may need to add the following line in your LaTeX document:", " \\DeclareGraphicsRule{*}{eps}{*}{}", " Each picture you made is in a separate file. The first picture is in, e.g.,", " figure.0, the second in figure.1, and so on.... To place the third picture in", " your document, for example, all you have to do is:", " \\includegraphics{figure.2} % LaTeX", " \\epsfbox{figure.2} % plainTeX", "", " The advantage, if any, of the mp terminal over a postscript terminal is", " editable output. Considerable effort went into making this output as clean as", " possible. For those knowledgeable in the Metapost language, the default line", " types and colors can be changed by editing the arrays `lt[]` and `col[]`.", " The choice of solid vs dashed lines, and color vs black lines can be change by", " changing the values assigned to the booleans `dashedlines` and `colorlines`.", " If the default `tex` option was in effect, global changes to the text of", " labels can be achieved by editing the `vebatimtex...etex` block. In", " particular, a LaTeX preamble can be added if desired, and then LaTeX's", " built-in size changing commands can be used for maximum flexibility. Be sure", " to set the appropriate MP configuration variable to force Metapost to run", " LaTeX instead of plainTeX." END_HELP(mp) #endif /* TERM_HELP */