Graphviz  2.31.20130618.0446
lib/common/mifgen.c
Go to the documentation of this file.
00001 /* $Id$ $Revision$ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /*************************************************************************
00005  * Copyright (c) 2011 AT&T Intellectual Property 
00006  * All rights reserved. This program and the accompanying materials
00007  * are made available under the terms of the Eclipse Public License v1.0
00008  * which accompanies this distribution, and is available at
00009  * http://www.eclipse.org/legal/epl-v10.html
00010  *
00011  * Contributors: See CVS logs. Details at http://www.graphviz.org/
00012  *************************************************************************/
00013 
00014 
00015 #include "render.h"
00016 
00017 #define NONE    0
00018 #define NODE    1
00019 #define EDGE    2
00020 #define CLST    3
00021 
00022 /* MIF font modifiers */
00023 #define REGULAR 0
00024 #define BOLD    1
00025 #define ITALIC  2
00026 
00027 /* MIF patterns */
00028 #define P_SOLID 0
00029 #define P_NONE  15
00030 #define P_DOTTED 4              /* i wasn't sure about this */
00031 #define P_DASHED 11             /* or this */
00032 
00033 /* MIF bold line constant */
00034 #define WIDTH_NORMAL 1
00035 #define WIDTH_BOLD 3
00036 
00037 static int N_pages;
00038 /* static       point   Pages; */
00039 static double Scale;
00040 static int Rot;
00041 static box PB;
00042 static int onetime = TRUE;
00043 
00044 typedef struct context_t {
00045     char color_ix, *fontfam, fontopt, font_was_set;
00046     char pen, fill, penwidth, style_was_set;
00047     double fontsz;
00048 } context_t;
00049 
00050 #define MAXNEST 4
00051 static context_t cstk[MAXNEST];
00052 static int SP;
00053 
00054 static char *FillStr = "<Fill 3>";
00055 static char *NoFillStr = "<Fill 15>";
00056 
00057 static void mif_reset(void)
00058 {
00059     onetime = TRUE;
00060 }
00061 
00062 
00063 static void init_mif(void)
00064 {
00065     SP = 0;
00066     cstk[0].color_ix = 0;       /* MIF color index 0-7 */
00067     cstk[0].fontfam = "Times";  /* font family name */
00068     cstk[0].fontopt = REGULAR;  /* modifier: REGULAR, BOLD or ITALIC */
00069     cstk[0].pen = P_SOLID;      /* pen pattern style, default is solid */
00070     cstk[0].fill = P_NONE;
00071     cstk[0].penwidth = WIDTH_NORMAL;
00072 }
00073 
00074 static pointf mifpt(pointf p)
00075 {
00076     pointf tmp, rv;
00077     tmp.x = p.x * Scale;
00078     tmp.y = Scale * p.y;
00079     if (Rot == 0) {
00080         rv.x = tmp.x;
00081         rv.y = PB.UR.y - PB.LL.y - tmp.y;
00082     } else {
00083         rv.x = PB.UR.x - PB.LL.x - tmp.y;
00084         rv.y = tmp.x;
00085     }
00086     return rv;
00087 }
00088 
00089 static void mifptarray(point * A, int n)
00090 {
00091     int i;
00092     pointf p;
00093 
00094     fprintf(Output_file, " <NumPoints %d>\n", n);
00095     for (i = 0; i < n; i++) {
00096         p.x = A[i].x;
00097         p.y = A[i].y;
00098         p = mifpt(p);
00099         fprintf(Output_file, " <Point %.2f %.2f>\n", p.x, p.y);
00100     }
00101 }
00102 
00103 static void mif_font(context_t * cp)
00104 {
00105     char *fw, *fa;
00106 
00107     fw = fa = "Regular";
00108     switch (cp->fontopt) {
00109     case BOLD:
00110         fw = "Bold";
00111         break;
00112     case ITALIC:
00113         fa = "Italic";
00114         break;
00115     }
00116     fprintf(Output_file,
00117             "<Font <FFamily `%s'> <FSize %.1f pt> <FWeight %s> <FAngle %s>>\n",
00118             cp->fontfam, Scale * cp->fontsz, fw, fa);
00119 }
00120 
00121 static void mif_color(int i)
00122 {
00123     static char *mifcolor[] = {
00124         "black", "white", "red", "green", "blue", "cyan",
00125         "magenta", "yellow", "comment",
00126         "aquamarine", "plum", "peru", "pink", "mediumpurple", "grey",
00127         "lightgrey", "lightskyblue", "lightcoral", "yellowgreen",
00128         (char *) 0
00129     };
00130     if (i <= 8)
00131         fprintf(Output_file, "<Separation %d>\n", i);
00132     if (i > 8)
00133         fprintf(Output_file, "<ObColor `%s'>\n", mifcolor[i]);
00134 }
00135 
00136 static void mif_style(context_t * cp)
00137 {
00138     fprintf(Output_file, "<Pen %d> <Fill %d> <PenWidth %d>\n",
00139             cp->pen, cp->fill, cp->penwidth);
00140 }
00141 
00142 static void mif_comment(char *str)
00143 {
00144     fprintf(Output_file, "# %s\n", str);
00145 }
00146 
00147 static void
00148 mif_begin_job(FILE * ofp, graph_t * g, const char **lib, char *info[], point pages)
00149 {
00150     /* Pages = pages; */
00151     N_pages = pages.x * pages.y;
00152     fprintf(Output_file,
00153             "<MIFFile 3.00> # Generated by %s version %s (%s)\n", info[0],
00154             info[1], info[2]);
00155     fprintf(Output_file, "# Title: %s\n", agnameof(g));
00156     fprintf(Output_file, "# Pages: %d\n", N_pages);
00157     fprintf(Output_file, "<Units Upt>\n");
00158     fprintf(Output_file, "<ColorCatalog \n");
00159     fprintf(Output_file, " <Color \n");
00160     fprintf(Output_file, "  <ColorTag `Black'>\n");
00161     fprintf(Output_file, "  <ColorCyan  0.000000>\n");
00162     fprintf(Output_file, "  <ColorMagenta  0.000000>\n");
00163     fprintf(Output_file, "  <ColorYellow  0.000000>\n");
00164     fprintf(Output_file, "  <ColorBlack  100.000000>\n");
00165     fprintf(Output_file, "  <ColorAttribute ColorIsBlack>\n");
00166     fprintf(Output_file, "  <ColorAttribute ColorIsReserved>\n");
00167     fprintf(Output_file, " > # end of Color\n");
00168     fprintf(Output_file, " <Color \n");
00169     fprintf(Output_file, "  <ColorTag `White'>\n");
00170     fprintf(Output_file, "  <ColorCyan  0.000000>\n");
00171     fprintf(Output_file, "  <ColorMagenta  0.000000>\n");
00172     fprintf(Output_file, "  <ColorYellow  0.000000>\n");
00173     fprintf(Output_file, "  <ColorBlack  0.000000>\n");
00174     fprintf(Output_file, "  <ColorAttribute ColorIsWhite>\n");
00175     fprintf(Output_file, "  <ColorAttribute ColorIsReserved>\n");
00176     fprintf(Output_file, " > # end of Color\n");
00177     fprintf(Output_file, " <Color \n");
00178     fprintf(Output_file, "  <ColorTag `Red'>\n");
00179     fprintf(Output_file, "  <ColorCyan  0.000000>\n");
00180     fprintf(Output_file, "  <ColorMagenta  100.000000>\n");
00181     fprintf(Output_file, "  <ColorYellow  100.000000>\n");
00182     fprintf(Output_file, "  <ColorBlack  0.000000>\n");
00183     fprintf(Output_file, "  <ColorAttribute ColorIsRed>\n");
00184     fprintf(Output_file, "  <ColorAttribute ColorIsReserved>\n");
00185     fprintf(Output_file, " > # end of Color\n");
00186     fprintf(Output_file, " <Color \n");
00187     fprintf(Output_file, "  <ColorTag `Green'>\n");
00188     fprintf(Output_file, "  <ColorCyan  100.000000>\n");
00189     fprintf(Output_file, "  <ColorMagenta  0.000000>\n");
00190     fprintf(Output_file, "  <ColorYellow  100.000000>\n");
00191     fprintf(Output_file, "  <ColorBlack  0.000000>\n");
00192     fprintf(Output_file, "  <ColorAttribute ColorIsGreen>\n");
00193     fprintf(Output_file, "  <ColorAttribute ColorIsReserved>\n");
00194     fprintf(Output_file, " > # end of Color\n");
00195     fprintf(Output_file, " <Color \n");
00196     fprintf(Output_file, "  <ColorTag `Blue'>\n");
00197     fprintf(Output_file, "  <ColorCyan  100.000000>\n");
00198     fprintf(Output_file, "  <ColorMagenta  100.000000>\n");
00199     fprintf(Output_file, "  <ColorYellow  0.000000>\n");
00200     fprintf(Output_file, "  <ColorBlack  0.000000>\n");
00201     fprintf(Output_file, "  <ColorAttribute ColorIsBlue>\n");
00202     fprintf(Output_file, "  <ColorAttribute ColorIsReserved>\n");
00203     fprintf(Output_file, " > # end of Color\n");
00204     fprintf(Output_file, " <Color \n");
00205     fprintf(Output_file, "  <ColorTag `Cyan'>\n");
00206     fprintf(Output_file, "  <ColorCyan  100.000000>\n");
00207     fprintf(Output_file, "  <ColorMagenta  0.000000>\n");
00208     fprintf(Output_file, "  <ColorYellow  0.000000>\n");
00209     fprintf(Output_file, "  <ColorBlack  0.000000>\n");
00210     fprintf(Output_file, "  <ColorAttribute ColorIsCyan>\n");
00211     fprintf(Output_file, "  <ColorAttribute ColorIsReserved>\n");
00212     fprintf(Output_file, " > # end of Color\n");
00213     fprintf(Output_file, " <Color \n");
00214     fprintf(Output_file, "  <ColorTag `Magenta'>\n");
00215     fprintf(Output_file, "  <ColorCyan  0.000000>\n");
00216     fprintf(Output_file, "  <ColorMagenta  100.000000>\n");
00217     fprintf(Output_file, "  <ColorYellow  0.000000>\n");
00218     fprintf(Output_file, "  <ColorBlack  0.000000>\n");
00219     fprintf(Output_file, "  <ColorAttribute ColorIsMagenta>\n");
00220     fprintf(Output_file, "  <ColorAttribute ColorIsReserved>\n");
00221     fprintf(Output_file, " > # end of Color\n");
00222     fprintf(Output_file, " <Color \n");
00223     fprintf(Output_file, "  <ColorTag `Yellow'>\n");
00224     fprintf(Output_file, "  <ColorCyan  0.000000>\n");
00225     fprintf(Output_file, "  <ColorMagenta  0.000000>\n");
00226     fprintf(Output_file, "  <ColorYellow  100.000000>\n");
00227     fprintf(Output_file, "  <ColorBlack  0.000000>\n");
00228     fprintf(Output_file, "  <ColorAttribute ColorIsYellow>\n");
00229     fprintf(Output_file, "  <ColorAttribute ColorIsReserved>\n");
00230     fprintf(Output_file, " > # end of Color\n");
00231     fprintf(Output_file, " <Color \n");
00232     fprintf(Output_file, "  <ColorTag `aquamarine'>\n");
00233     fprintf(Output_file, "  <ColorCyan  100.000000>\n");
00234     fprintf(Output_file, "  <ColorMagenta  0.000000>\n");
00235     fprintf(Output_file, "  <ColorYellow  18.000000>\n");
00236     fprintf(Output_file, "  <ColorBlack  0.000000>\n");
00237     fprintf(Output_file, " > # end of Color\n");
00238     fprintf(Output_file, " <Color \n");
00239     fprintf(Output_file, "  <ColorTag `plum'>\n");
00240     fprintf(Output_file, "  <ColorCyan  0.000000>\n");
00241     fprintf(Output_file, "  <ColorMagenta  100.000000>\n");
00242     fprintf(Output_file, "  <ColorYellow  0.000000>\n");
00243     fprintf(Output_file, "  <ColorBlack  33.000000>\n");
00244     fprintf(Output_file, " > # end of Color\n");
00245     fprintf(Output_file, " <Color \n");
00246     fprintf(Output_file, "  <ColorTag `peru'>\n");
00247     fprintf(Output_file, "  <ColorCyan  0.000000>\n");
00248     fprintf(Output_file, "  <ColorMagenta  24.000000>\n");
00249     fprintf(Output_file, "  <ColorYellow  100.000000>\n");
00250     fprintf(Output_file, "  <ColorBlack  32.000000>\n");
00251     fprintf(Output_file, " > # end of Color\n");
00252     fprintf(Output_file, " <Color \n");
00253     fprintf(Output_file, "  <ColorTag `pink'>\n");
00254     fprintf(Output_file, "  <ColorCyan  0.000000>\n");
00255     fprintf(Output_file, "  <ColorMagenta  50.000000>\n");
00256     fprintf(Output_file, "  <ColorYellow  0.000000>\n");
00257     fprintf(Output_file, "  <ColorBlack  0.000000>\n");
00258     fprintf(Output_file, " > # end of Color\n");
00259     fprintf(Output_file, " <Color \n");
00260     fprintf(Output_file, "  <ColorTag `mediumpurple'>\n");
00261     fprintf(Output_file, "  <ColorCyan  40.000000>\n");
00262     fprintf(Output_file, "  <ColorMagenta  100.000000>\n");
00263     fprintf(Output_file, "  <ColorYellow  0.000000>\n");
00264     fprintf(Output_file, "  <ColorBlack  0.000000>\n");
00265     fprintf(Output_file, " > # end of Color\n");
00266     fprintf(Output_file, " <Color \n");
00267     fprintf(Output_file, "  <ColorTag `grey'>\n");
00268     fprintf(Output_file, "  <ColorCyan  0.000000>\n");
00269     fprintf(Output_file, "  <ColorMagenta  0.000000>\n");
00270     fprintf(Output_file, "  <ColorYellow  0.000000>\n");
00271     fprintf(Output_file, "  <ColorBlack  50.000000>\n");
00272     fprintf(Output_file, " > # end of Color\n");
00273     fprintf(Output_file, " <Color \n");
00274     fprintf(Output_file, "  <ColorTag `lightgrey'>\n");
00275     fprintf(Output_file, "  <ColorCyan  0.000000>\n");
00276     fprintf(Output_file, "  <ColorMagenta  0.000000>\n");
00277     fprintf(Output_file, "  <ColorYellow  0.000000>\n");
00278     fprintf(Output_file, "  <ColorBlack  25.000000>\n");
00279     fprintf(Output_file, " > # end of Color\n");
00280     fprintf(Output_file, " <Color \n");
00281     fprintf(Output_file, "  <ColorTag `lightskyblue'>\n");
00282     fprintf(Output_file, "  <ColorCyan  38.000000>\n");
00283     fprintf(Output_file, "  <ColorMagenta  33.000000>\n");
00284     fprintf(Output_file, "  <ColorYellow  0.000000>\n");
00285     fprintf(Output_file, "  <ColorBlack  0.000000>\n");
00286     fprintf(Output_file, " > # end of Color\n");
00287     fprintf(Output_file, " <Color \n");
00288     fprintf(Output_file, "  <ColorTag `lightcoral'>\n");
00289     fprintf(Output_file, "  <ColorCyan  0.000000>\n");
00290     fprintf(Output_file, "  <ColorMagenta  50.000000>\n");
00291     fprintf(Output_file, "  <ColorYellow  60.000000>\n");
00292     fprintf(Output_file, "  <ColorBlack  0.000000>\n");
00293     fprintf(Output_file, " > # end of Color\n");
00294     fprintf(Output_file, " <Color \n");
00295     fprintf(Output_file, "  <ColorTag `yellowgreen'>\n");
00296     fprintf(Output_file, "  <ColorCyan  31.000000>\n");
00297     fprintf(Output_file, "  <ColorMagenta  0.000000>\n");
00298     fprintf(Output_file, "  <ColorYellow  100.000000>\n");
00299     fprintf(Output_file, "  <ColorBlack  0.000000>\n");
00300     fprintf(Output_file, " > # end of Color\n");
00301     fprintf(Output_file, "> # end of ColorCatalog\n");
00302 }
00303 
00304 static void mif_end_job(void)
00305 {
00306     fprintf(Output_file, "# end of MIFFile\n");
00307 }
00308 
00309 static void mif_begin_graph(GVC_t * gvc, graph_t * g, box bb, point pb)
00310 {
00311     PB = bb;
00312     if (onetime) {
00313         fprintf(Output_file, "<BRect %d %d %d %d>\n",
00314                 PB.LL.x, PB.UR.y, PB.UR.x - PB.LL.x, PB.UR.y - PB.LL.y);
00315         init_mif();
00316         onetime = FALSE;
00317     }
00318 }
00319 
00320 static void
00321 mif_begin_page(graph_t * g, point page, double scale, int rot,
00322                point offset)
00323 {
00324     /* int          page_number; */
00325     /* point        sz; */
00326 
00327     Scale = scale;
00328     Rot = rot;
00329     /* page_number =  page.x + page.y * Pages.x + 1; */
00330     /* sz = sub_points(PB.UR,PB.LL); */
00331     fprintf(Output_file,
00332             " <ArrowStyle <TipAngle 15> <BaseAngle 90> <Length %.1f> <HeadType Filled>>\n",
00333             14 * Scale);
00334 }
00335 
00336 static void mif_begin_context(void)
00337 {
00338     assert(SP + 1 < MAXNEST);
00339     cstk[SP + 1] = cstk[SP];
00340     SP++;
00341 }
00342 
00343 static void mif_end_context(void)
00344 {
00345     int c, psp = SP - 1;
00346     assert(SP > 0);
00347     if (cstk[SP].color_ix != (c = cstk[psp].color_ix))
00348         mif_color(c);
00349     if (cstk[SP].font_was_set)
00350         mif_font(&(cstk[psp]));
00351     if (cstk[SP].style_was_set)
00352         mif_style(&(cstk[psp]));
00353     /*free(cstk[psp].fontfam); */
00354     SP = psp;
00355 }
00356 
00357 static void mif_set_font(char *name, double size)
00358 {
00359     char *p, *q;
00360     context_t *cp;
00361 
00362     cp = &(cstk[SP]);
00363     cp->font_was_set = TRUE;
00364     cp->fontsz = size;
00365     p = strdup(name);
00366     if ((q = strchr(p, '-'))) {
00367         *q++ = 0;
00368         if (strcasecmp(q, "italic") == 0)
00369             cp->fontopt = ITALIC;
00370         else if (strcasecmp(q, "bold") == 0)
00371             cp->fontopt = BOLD;
00372     }
00373     cp->fontfam = p;
00374     mif_font(&cstk[SP]);
00375 }
00376 
00377 static void mif_set_color(char *name)
00378 {
00379     int i;
00380     char *tok;
00381 
00382     static char *mifcolor[] = {
00383         "black", "white", "red", "green", "blue", "cyan",
00384         "magenta", "yellow", "comment",
00385         "aquamarine", "plum", "peru", "pink", "mediumpurple", "grey",
00386         "lightgrey", "lightskyblue", "lightcoral", "yellowgreen",
00387         (char *) 0
00388     };
00389 
00390     tok = canontoken(name);
00391     for (i = 0; mifcolor[i]; i++) {
00392         if (strcasecmp(mifcolor[i], tok) == 0) {
00393             cstk[SP].color_ix = i;
00394             mif_color(i);
00395             return;
00396         }
00397     }
00398     agerr(AGERR, "color %s not supported in MIF\n", name);
00399 }
00400 
00401 static void mif_set_style(char **s)
00402 {
00403     char *line;
00404     context_t *cp;
00405 
00406     cp = &(cstk[SP]);
00407     while ((line = *s++)) {
00408         if (streq(line, "solid"))
00409             cp->pen = P_SOLID;
00410         else if (streq(line, "dashed"))
00411             cp->pen = P_DASHED;
00412         else if (streq(line, "dotted"))
00413             cp->pen = P_DOTTED;
00414         else if (streq(line, "invis"))
00415             cp->pen = P_NONE;
00416         else if (streq(line, "bold"))
00417             cp->penwidth = WIDTH_BOLD;
00418         else if (streq(line, "filled"))
00419             cp->fill = P_SOLID;
00420         else if (streq(line, "unfilled"))
00421             cp->fill = P_NONE;
00422         else {
00423             agerr(AGERR,
00424                   "mif_set_style: unsupported style %s - ignoring\n",
00425                   line);
00426         }
00427         cp->style_was_set = TRUE;
00428     }
00429     if (cp->style_was_set)
00430         mif_style(cp);
00431 }
00432 
00433 static char *mif_string(char *s)
00434 {
00435     static char *buf = NULL;
00436     static int bufsize = 0;
00437     int pos = 0;
00438     char *p, esc;
00439 
00440     if (!buf) {
00441         bufsize = 64;
00442         buf = N_GNEW(bufsize, char);
00443     }
00444 
00445     p = buf;
00446     while (*s) {
00447         if (pos > (bufsize - 8)) {
00448             bufsize *= 2;
00449             buf = grealloc(buf, bufsize);
00450             p = buf + pos;
00451         }
00452         esc = 0;
00453         switch (*s) {
00454         case '\t':
00455             esc = 't';
00456             break;
00457         case '>':
00458         case '\'':
00459         case '`':
00460         case '\\':
00461             esc = *s;
00462             break;
00463         }
00464         if (esc) {
00465             *p++ = '\\';
00466             *p++ = esc;
00467             pos += 2;
00468         } else {
00469             *p++ = *s;
00470             pos++;
00471         }
00472         s++;
00473     }
00474     *p = '\0';
00475     return buf;
00476 }
00477 
00478 static void mif_textpara(point p, textpara_t * para)
00479 {
00480     pointf mp;
00481     char *anchor;
00482 
00483     mp.x = p.x;
00484     mp.y = p.y - cstk[SP].fontsz / 2 + 2;
00485     switch (para->just) {
00486     case 'l':
00487         anchor = "Left";
00488         break;
00489     case 'r':
00490         anchor = "Right";
00491         break;
00492     default:
00493     case 'n':
00494         anchor = "Center";
00495         break;
00496     }
00497     mp = mifpt(mp);
00498     fprintf(Output_file,
00499             "<TextLine <Angle %d> <TLOrigin %.2f %.2f> <TLAlignment %s>",
00500             Rot, mp.x, mp.y, anchor);
00501     fprintf(Output_file, " <String `%s'>>\n", mif_string(para->str));
00502 }
00503 
00504 static void mif_bezier(point * A, int n, int arrow_at_start,
00505                        int arrow_at_end, int filled)
00506 {
00507     fprintf(Output_file,
00508             "<PolyLine <Fill 15> <Smoothed Yes> <HeadCap Square>\n");
00509     mifptarray(A, n);
00510     fprintf(Output_file, ">\n");
00511 }
00512 
00513 static void mif_polygon(point * A, int n, int filled)
00514 {
00515     fprintf(Output_file, "<Polygon %s\n", (filled ? FillStr : NoFillStr));
00516     mifptarray(A, n);
00517     fprintf(Output_file, ">\n");
00518 }
00519 
00520 static void mif_ellipse(point p, int rx, int ry, int filled)
00521 {
00522     pointf tl, mp;
00523     tl.x = p.x - rx;
00524     tl.y = p.y + ry;
00525     if (Rot) {
00526         int t;
00527         t = rx;
00528         rx = ry;
00529         ry = t;
00530     }
00531     mp = mifpt(tl);
00532     fprintf(Output_file, "<Ellipse %s <BRect %.2f %.2f %.1f %.1f>>\n",
00533             filled ? FillStr : NoFillStr,
00534             mp.x, mp.y, Scale * (rx + rx), Scale * (ry + ry));
00535 }
00536 
00537 static void mif_polyline(point * A, int n)
00538 {
00539     fprintf(Output_file, "<PolyLine <HeadCap Square>\n");
00540     mifptarray(A, n);
00541     fprintf(Output_file, ">\n");
00542 }
00543 
00544 static void mif_usershape(usershape_t *us, boxf b, point *A, int n, boolean filled)
00545 {
00546     static boolean onetime = TRUE;
00547     if (onetime) {
00548         agerr(AGERR, "custom shapes not available with this driver\n");
00549         onetime = FALSE;
00550     }
00551 }
00552 
00553 codegen_t MIF_CodeGen = {
00554     mif_reset,
00555     mif_begin_job, mif_end_job,
00556     mif_begin_graph, 0,         /* mif_end_graph */
00557     mif_begin_page, 0,          /* mif_end_page */
00558     0, /* mif_begin_layer */ 0, /* mif_end_layer */
00559     0, /* mif_begin_cluster */ 0, /* mif_end_cluster */
00560     0, /* mif_begin_nodes */ 0, /* mif_end_nodes */
00561     0, /* mif_begin_edges */ 0, /* mif_end_edges */
00562     0, /* mif_begin_node */  0, /* mif_end_node */
00563     0, /* mif_begin_edge */  0, /* mif_end_edge */
00564     mif_begin_context, mif_end_context,
00565     0, /* mif_begin_anchor */ 0,        /* mif_end_anchor */
00566     mif_set_font, mif_textpara,
00567     mif_set_color, mif_set_color, mif_set_style,
00568     mif_ellipse, mif_polygon,
00569     mif_bezier, mif_polyline,
00570     0,                          /* bezier_has_arrows */
00571     mif_comment,
00572     mif_usershape
00573 };