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