Graphviz  2.29.20120524.0446
plugin/core/gvrender_core_mif.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 /* FIXME - incomplete replacement for codegen */
00015 
00016 #ifdef HAVE_CONFIG_H
00017 #include "config.h"
00018 #endif
00019 
00020 #include <stdarg.h>
00021 #include <stdlib.h>
00022 #include <string.h>
00023 #include <ctype.h>
00024 
00025 #include "macros.h"
00026 #include "const.h"
00027 
00028 #include "gvio.h"
00029 #include "gvplugin_render.h"
00030 #include "gvplugin_device.h"
00031 #include "gvcint.h"
00032 
00033 typedef enum { FORMAT_MIF, } format_type;
00034 
00035 /* MIF font modifiers */
00036 #define REGULAR 0
00037 #define BOLD    1
00038 #define ITALIC  2
00039 
00040 /* MIF patterns */
00041 #define P_SOLID 0
00042 #define P_NONE  15
00043 #define P_DOTTED 4              /* i wasn't sure about this */
00044 #define P_DASHED 11             /* or this */
00045 
00046 /* MIF bold line constant */
00047 #define WIDTH_NORMAL 1
00048 #define WIDTH_BOLD 3
00049 
00050 static char *FillStr = "<Fill 3>";
00051 static char *NoFillStr = "<Fill 15>";
00052 
00053 static void mif_ptarray(GVJ_t * job, pointf * A, int n)
00054 {
00055     int i;
00056 
00057     gvprintf(job, " <NumPoints %d>\n", n);
00058     for (i = 0; i < n; i++)
00059         gvprintf(job, " <Point %.2f %.2f>\n", A[i].x, A[i].y);
00060 }
00061 
00062 typedef struct {
00063     char *name;
00064     int CMYK[4];
00065 } mif_color_t;
00066 
00067 static mif_color_t mif_colors[] = {
00068     {"Black", {0, 0, 0, 100}},
00069     {"White", {0, 0, 0, 0}},
00070     {"Red", {0, 100, 100, 0}},
00071     {"Green", {100, 0, 100, 0}},
00072     {"Blue", {100, 100, 0, 0}},
00073     {"Cyan", {100, 0, 0, 0}},
00074     {"Magenta", {0, 100, 0, 0}},
00075     {"Yellow", {0, 0, 100, 0}},
00076     {"aquamarine", {100, 0, 0, 18}},
00077     {"plum", {0, 100, 0, 33}},
00078     {"peru", {0, 24, 100, 32}},
00079     {"pink", {0, 50, 0, 0}},
00080     {"mediumpurple", {10, 100, 0, 0}},
00081     {"grey", {0, 0, 0, 50}},
00082     {"lightgrey", {0, 0, 0, 25}},
00083     {"lightskyblue", {38, 33, 0, 0}},
00084     {"lightcoral", {0, 50, 60, 0}},
00085     {"yellowgreen", {31, 0, 100, 0}},
00086 };
00087 
00088 static void mif_color(GVJ_t * job, int i)
00089 {
00090     if (isupper(mif_colors[i].name[0]))
00091         gvprintf(job, "<Separation %d>\n", i);
00092     else
00093         gvprintf(job, "<ObColor `%s'>\n", mif_colors[i].name);
00094 }
00095 
00096 #if 0
00097 static void mif_style(GVJ_t * job, int filled)
00098 {
00099     obj_state_t *obj = job->obj;
00100 
00101     gvputs(job, "style=\"fill:");
00102     if (filled)
00103         mif_color(job->obj->fillcolor);
00104     else
00105         gvputs(job, "none");
00106 
00107     gvputs(job, ";stroke:");
00108      
00109 
00110 
00111     while ((line = *s++)) {
00112         if (streq(line, "solid"))
00113             pen = P_SOLID;
00114         else if (streq(line, "dashed"))
00115             pen = P_DASHED;
00116         else if (streq(line, "dotted"))
00117             pen = P_DOTTED;
00118         else if (streq(line, "invis"))
00119             pen = P_NONE;
00120         else if (streq(line, "bold"))
00121             penwidth = WIDTH_BOLD;
00122         else if (streq(line, "filled"))
00123             fill = P_SOLID;
00124         else if (streq(line, "unfilled"))
00125             fill = P_NONE;
00126         else {
00127             agerr(AGERR,
00128                   "mif_style: unsupported style %s - ignoring\n",
00129                   line);
00130         }
00131     }
00132 
00133     fw = fa = "Regular";
00134     switch (cp->fontopt) {
00135     case BOLD:
00136         fw = "Bold";
00137         break;
00138     case ITALIC:
00139         fa = "Italic";
00140         break;
00141     }
00142     gvprintf(job, 
00143             "<Font <FFamily `%s'> <FSize %.1f pt> <FWeight %s> <FAngle %s>>\n",
00144             cp->fontfam, job->scale.x * cp->fontsz, fw, fa);
00145 
00146     gvprintf(job, "<Pen %d> <Fill %d> <PenWidth %d>\n",
00147             job->pen, job->fill, job->penwidth);
00148 }
00149 #endif
00150 
00151 static void mif_comment(GVJ_t * job, char *str)
00152 {
00153     gvprintf(job, "# %s\n", str);
00154 }
00155 
00156 static void mif_color_declaration(GVJ_t * job, char *str, int CMYK[4])
00157 {
00158     gvputs(job, " <Color \n");
00159     gvprintf(job, "  <ColorTag `%s'>\n", str);
00160     gvprintf(job, "  <ColorCyan  %d.000000>\n", CMYK[0]);
00161     gvprintf(job, "  <ColorMagenta  %d.000000>\n", CMYK[1]);
00162     gvprintf(job, "  <ColorYellow  %d.000000>\n", CMYK[2]);
00163     gvprintf(job, "  <ColorBlack  %d.000000>\n", CMYK[3]);
00164     if (isupper(str[0])) {
00165         gvprintf(job, "  <ColorAttribute ColorIs%s>\n", str);
00166         gvputs(job, "  <ColorAttribute ColorIsReserved>\n");
00167     }
00168     gvputs(job, " > # end of Color\n");
00169 }
00170 
00171 static void
00172 mif_begin_job(GVJ_t * job)
00173 {
00174     gvprintf(job,
00175         "<MIFFile 3.00> # Generated by %s version %s (%s)\n",
00176         job->common->info[0], job->common->info[1], job->common->info[2]);
00177 }
00178 
00179 static void mif_end_job(GVJ_t * job)
00180 {
00181     gvputs(job, "# end of MIFFile\n");
00182 }
00183 
00184 static void mif_begin_graph(GVJ_t * job)
00185 {
00186     int i;
00187 
00188     gvprintf(job, "# Title: %s\n", job->obj->u.g->name);
00189     gvprintf(job, "# Pages: %d\n",
00190         job->pagesArraySize.x * job->pagesArraySize.y);
00191     gvputs(job, "<Units Upt>\n");
00192     gvputs(job, "<ColorCatalog \n");
00193     for (i = 0; i < (sizeof(mif_colors) / sizeof(mif_color_t)); i++)
00194         mif_color_declaration(job, mif_colors[i].name, mif_colors[i].CMYK);
00195     gvputs(job, "> # end of ColorCatalog\n");
00196     gvprintf(job, "<BRect %g %g %g %g>\n",
00197         job->canvasBox.LL.x,
00198         job->canvasBox.UR.y,
00199         job->canvasBox.UR.x - job->canvasBox.LL.x,
00200         job->canvasBox.UR.y - job->canvasBox.LL.y);
00201 }
00202 
00203 static void
00204 mif_begin_page(GVJ_t *job)
00205 {
00206     gvprintf(job,
00207             " <ArrowStyle <TipAngle 15> <BaseAngle 90> <Length %.1f> <HeadType Filled>>\n",
00208             14 * job->scale.x);
00209 }
00210 
00211 static void mif_set_color(GVJ_t * job, char *name)
00212 {
00213     int i;
00214 
00215     for (i = 0; i < (sizeof(mif_colors)/sizeof(mif_color_t)); i++) {
00216         if (strcasecmp(mif_colors[i].name, name) == 0)
00217             mif_color(job, i);
00218     }
00219     agerr(AGERR, "color %s not supported in MIF\n", name);
00220 }
00221 
00222 static char *mif_string(GVJ_t * job, char *s)
00223 {
00224     static char *buf = NULL;
00225     static int bufsize = 0;
00226     int pos = 0;
00227     char *p, esc;
00228 
00229     if (!buf) {
00230         bufsize = 64;
00231         buf = malloc(bufsize);
00232     }
00233 
00234     p = buf;
00235     while (*s) {
00236         if (pos > (bufsize - 8)) {
00237             bufsize *= 2;
00238             buf = realloc(buf, bufsize);
00239             p = buf + pos;
00240         }
00241         esc = 0;
00242         switch (*s) {
00243         case '\t':
00244             esc = 't';
00245             break;
00246         case '>':
00247         case '\'':
00248         case '`':
00249         case '\\':
00250             esc = *s;
00251             break;
00252         }
00253         if (esc) {
00254             *p++ = '\\';
00255             *p++ = esc;
00256             pos += 2;
00257         } else {
00258             *p++ = *s;
00259             pos++;
00260         }
00261         s++;
00262     }
00263     *p = '\0';
00264     return buf;
00265 }
00266 
00267 static void mif_textpara(GVJ_t * job, pointf p, textpara_t * para)
00268 {
00269     char *anchor;
00270 
00271 //    p.y -= para->font.size / 2 + 2;
00272     switch (para->just) {
00273     case 'l':
00274         anchor = "Left";
00275         break;
00276     case 'r':
00277         anchor = "Right";
00278         break;
00279     default:
00280     case 'n':
00281         anchor = "Center";
00282         break;
00283     }
00284     gvprintf(job,
00285             "<TextLine <Angle %d> <TLOrigin %.2f %.2f> <TLAlignment %s>",
00286             job->rotation, p.x, p.y, anchor);
00287     gvprintf(job, " <String `%s'>>\n", mif_string(job, para->str));
00288 }
00289 
00290 static void mif_bezier(GVJ_t * job, pointf * A, int n, int arrow_at_start,
00291                        int arrow_at_end, int filled)
00292 {
00293     gvprintf(job,
00294             "<PolyLine <Fill 15> <Smoothed Yes> <HeadCap Square>\n");
00295     mif_ptarray(job, A, n);
00296     gvputs(job, ">\n");
00297 }
00298 
00299 static void mif_polygon(GVJ_t * job, pointf * A, int n, int filled)
00300 {
00301     gvprintf(job, "<Polygon %s\n", (filled ? FillStr : NoFillStr));
00302     mif_ptarray(job, A, n);
00303     gvputs(job, ">\n");
00304 }
00305 
00306 static void mif_ellipse(GVJ_t * job, pointf * A, int filled)
00307 {
00308     pointf dia;
00309 
00310     dia.x = (A[1].x - A[0].x) * 2;
00311     dia.y = (A[1].y - A[0].y) * 2;
00312 
00313     gvprintf(job, "<Ellipse %s <BRect %.2f %.2f %.1f %.1f>>\n",
00314             filled ? FillStr : NoFillStr,
00315             A[1].x - dia.x, A[1].y, dia.x, -dia.y);
00316 }
00317 
00318 static void mif_polyline(GVJ_t * job, pointf * A, int n)
00319 {
00320     gvputs(job, "<PolyLine <HeadCap Square>\n");
00321     mif_ptarray(job, A, n);
00322     gvputs(job, ">\n");
00323 }
00324 
00325 gvrender_engine_t mif_engine = {
00326     mif_begin_job,
00327     mif_end_job,
00328     mif_begin_graph,
00329     0,                          /* mif_end_graph */
00330     0,                          /* mif_begin_layer */
00331     0,                          /* mif_end_layer */
00332     mif_begin_page,
00333     0,                          /* mif_end_page */
00334     0,                          /* mif_begin_cluster */
00335     0,                          /* mif_end_cluster */
00336     0,                          /* mif_begin_nodes */
00337     0,                          /* mif_end_nodes */
00338     0,                          /* mif_begin_edges */
00339     0,                          /* mif_end_edges */
00340     0,                          /* mif_begin_node */
00341     0,                          /* mif_end_node */
00342     0,                          /* mif_begin_edge */
00343     0,                          /* mif_end_edge */
00344     0,                          /* mif_begin_anchor */
00345     0,                          /* mif_end_anchor */
00346     0,                          /* mif_begin_label */
00347     0,                          /* mif_end_label */
00348     mif_textpara,
00349     0,                          /* mif_resolve_color */
00350     mif_ellipse,
00351     mif_polygon,
00352     mif_bezier,
00353     mif_polyline,
00354     mif_comment,
00355     0,                          /* mif_library_shape */
00356 };
00357 
00358 gvrender_features_t mif_features = {
00359     GVRENDER_Y_GOES_DOWN,       /* flags */
00360     4.,                         /* default pad - graph units */
00361     NULL,                       /* knowncolors */
00362     0,                          /* sizeof knowncolors */
00363     CMYK_BYTE,                  /* color_type */
00364 };
00365 
00366 static gvdevice_features_t device_features_mif = {
00367     0,                          /* flags */
00368     {0.,0.},                    /* default margin - points */
00369     {0.,0.},                    /* default page width, height - points */
00370     {72.,72.},                  /* default dpi */
00371 };
00372 
00373 gvplugin_installed_t gvrender_mif_types[] = {
00374     {FORMAT_MIF, "mif", -1, &mif_engine, &mif_features},
00375     {0, NULL, 0, NULL, NULL}
00376 };
00377 
00378 gvplugin_installed_t gvdevice_mif_types[] = {
00379     {FORMAT_MIF, "mif:mif", -1, NULL, &device_features_mif},
00380     {0, NULL, 0, NULL, NULL}
00381 };