Graphviz  2.29.20120524.0446
plugin/core/gvrender_core_dia.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 "gvplugin_render.h"
00029 #include "gvplugin_device.h"
00030 #include "gvio.h"
00031 #include "gvcint.h"
00032 
00033 typedef enum { FORMAT_DIA, } format_type;
00034 
00035 extern char *xml_string(char *str);
00036 
00037 /* DIA font modifiers */
00038 #define REGULAR 0
00039 #define BOLD    1
00040 #define ITALIC  2
00041 
00042 /* DIA patterns */
00043 #define P_SOLID 0
00044 #define P_NONE  15
00045 #define P_DOTTED 4              /* i wasn't sure about this */
00046 #define P_DASHED 11             /* or this */
00047 
00048 /* DIA bold line constant */
00049 #define WIDTH_NORMAL 1
00050 #define WIDTH_BOLD 3
00051 
00052 #define DIA_RESOLUTION 1.0
00053 #define SCALE (DIA_RESOLUTION/15.0)
00054 
00055 static double Scale;
00056 static pointf Offset;
00057 static int Rot;
00058 static box PB;
00059 static int onetime = TRUE;
00060 
00061 typedef struct context_t {
00062     char *pencolor, *fillcolor, *fontfam, fontopt, font_was_set;
00063     char pen, fill, penwidth, style_was_set;
00064     double fontsz;
00065 } context_t;
00066 
00067 #define MAXNEST 4
00068 static context_t cstk[MAXNEST];
00069 static int SP;
00070 
00071 #define SVG_COLORS_P 0
00072 
00073 static int dia_comparestr(const void *s1, const void *s2)
00074 {
00075         return strcmp(*(char **) s1, *(char **) s2);
00076 }
00077 
00078 static char *dia_resolve_color(char *name)
00079 {
00080 /* color names from http://www.w3.org/TR/SVG/types.html */
00081 /* NB.  List must be LANG_C sorted */
00082     static char *svg_known_colors[] = {
00083         "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure",
00084         "beige", "bisque", "black", "blanchedalmond", "blue",
00085         "blueviolet", "brown", "burlywood",
00086         "cadetblue", "chartreuse", "chocolate", "coral",
00087         "cornflowerblue", "cornsilk", "crimson", "cyan",
00088         "darkblue", "darkcyan", "darkgoldenrod", "darkgray",
00089         "darkgreen", "darkgrey", "darkkhaki", "darkmagenta",
00090         "darkolivegreen", "darkorange", "darkorchid", "darkred",
00091         "darksalmon", "darkseagreen", "darkslateblue", "darkslategray",
00092         "darkslategrey", "darkturquoise", "darkviolet", "deeppink",
00093         "deepskyblue", "dimgray", "dimgrey", "dodgerblue",
00094         "firebrick", "floralwhite", "forestgreen", "fuchsia",
00095         "gainsboro", "ghostwhite", "gold", "goldenrod", "gray",
00096         "green", "greenyellow", "grey",
00097         "honeydew", "hotpink", "indianred",
00098         "indigo", "ivory", "khaki",
00099         "lavender", "lavenderblush", "lawngreen", "lemonchiffon",
00100         "lightblue", "lightcoral", "lightcyan", "lightgoldenrodyellow",
00101         "lightgray", "lightgreen", "lightgrey", "lightpink",
00102         "lightsalmon", "lightseagreen", "lightskyblue",
00103         "lightslategray", "lightslategrey", "lightsteelblue",
00104         "lightyellow", "lime", "limegreen", "linen",
00105         "magenta", "maroon", "mediumaquamarine", "mediumblue",
00106         "mediumorchid", "mediumpurple", "mediumseagreen",
00107         "mediumslateblue", "mediumspringgreen", "mediumturquoise",
00108         "mediumvioletred", "midnightblue", "mintcream",
00109         "mistyrose", "moccasin",
00110         "navajowhite", "navy", "oldlace",
00111         "olive", "olivedrab", "orange", "orangered", "orchid",
00112         "palegoldenrod", "palegreen", "paleturquoise",
00113         "palevioletred", "papayawhip", "peachpuff", "peru", "pink",
00114         "plum", "powderblue", "purple",
00115         "red", "rosybrown", "royalblue",
00116         "saddlebrown", "salmon", "sandybrown", "seagreen", "seashell",
00117         "sienna", "silver", "skyblue", "slateblue", "slategray",
00118         "slategrey", "snow", "springgreen", "steelblue",
00119         "tan", "teal", "thistle", "tomato", "turquoise",
00120         "violet",
00121         "wheat", "white", "whitesmoke",
00122         "yellow", "yellowgreen",
00123     };
00124 
00125     static char buf[SMALLBUF];
00126     char *tok;
00127     gvcolor_t color;
00128 
00129 //    tok = canontoken(name);
00130 tok = name;
00131     if (!SVG_COLORS_P || (bsearch(&tok, svg_known_colors,
00132                               sizeof(svg_known_colors) / sizeof(char *),
00133                               sizeof(char *), dia_comparestr) == NULL)) {
00134         /* if tok was not found in known_colors */
00135         if (streq(tok, "transparent")) {
00136             tok = "none";
00137         } else {
00138 //            colorxlate(name, &color, RGBA_BYTE);
00139             sprintf(buf, "#%02x%02x%02x",
00140                     color.u.rgba[0], color.u.rgba[1], color.u.rgba[2]);
00141             tok = buf;
00142         }
00143     }
00144     return tok;
00145 }
00146 
00147 
00148 static void dia_reset(void)
00149 {
00150     onetime = TRUE;
00151 }
00152 
00153 
00154 static void init_dia(void)
00155 {
00156     SP = 0;
00157     cstk[0].pencolor = DEFAULT_COLOR;   /* DIA pencolor */
00158     cstk[0].fillcolor = "";     /* DIA fillcolor */
00159     cstk[0].fontfam = DEFAULT_FONTNAME; /* font family name */
00160     cstk[0].fontsz = DEFAULT_FONTSIZE;  /* font size */
00161     cstk[0].fontopt = REGULAR;  /* modifier: REGULAR, BOLD or ITALIC */
00162     cstk[0].pen = P_SOLID;      /* pen pattern style, default is solid */
00163     cstk[0].fill = P_NONE;
00164     cstk[0].penwidth = WIDTH_NORMAL;
00165 }
00166 
00167 static pointf dia_pt(pointf p)
00168 {
00169     pointf rv;
00170 
00171     if (Rot == 0) {
00172         rv.x = PB.LL.x + p.x * Scale + Offset.x;
00173         rv.y = PB.UR.y - 1 - p.y * Scale - Offset.y;
00174     } else {
00175         rv.x = PB.UR.x - 1 - p.y * Scale - Offset.x;
00176         rv.y = PB.UR.y - 1 - p.x * Scale - Offset.y;
00177     }
00178     return rv;
00179 }
00180 
00181 static void dia_style(GVJ_t * job, context_t * cp)
00182 {
00183     if (cp->pencolor != DEFAULT_COLOR) {
00184         gvputs(job, "      <dia:attribute name=\"border_color\">\n");
00185         gvprintf(job, "        <dia:color val=\"%s\"/>\n",
00186                    dia_resolve_color(cp->pencolor));
00187         gvputs(job, "      </dia:attribute>\n");
00188     }
00189     if (cp->penwidth != WIDTH_NORMAL) {
00190         gvputs(job, "      <dia:attribute name=\"line_width\">\n");
00191         gvprintf(job, "        <dia:real val=\"%g\"/>\n",
00192                    Scale * (cp->penwidth));
00193         gvputs(job, "      </dia:attribute>\n");
00194     }
00195     if (cp->pen == P_DASHED) {
00196         gvputs(job, "      <dia:attribute name=\"line_style\">\n");
00197         gvprintf(job, "        <dia:real val=\"%d\"/>\n", 1);
00198         gvputs(job, "      </dia:attribute>\n");
00199 #if 0
00200     } else if (cp->pen == P_DOTTED) {
00201         gvprintf(job, "stroke-dasharray:%s;", sdotarray);
00202 #endif
00203     }
00204 }
00205 
00206 static void dia_stylefill(GVJ_t * job, context_t * cp, int filled)
00207 {
00208     if (filled) {
00209         gvputs(job, "      <dia:attribute name=\"inner_color\">\n");
00210         gvprintf(job, "        <dia:color val=\"%s\"/>\n",
00211                    dia_resolve_color(cp->fillcolor));
00212         gvputs(job, "      </dia:attribute>\n");
00213     } else {
00214         gvputs(job, "      <dia:attribute name=\"show_background\">\n");
00215         gvprintf(job, "        <dia:boolean val=\"%s\"/>\n", "true");
00216         gvputs(job, "      </dia:attribute>\n");
00217     }
00218 }
00219 
00220 static void dia_comment(GVJ_t * job, char *str)
00221 {
00222     gvputs(job, "<!-- ");
00223     gvputs(job, xml_string(str));
00224     gvputs(job, " -->\n");
00225 }
00226 
00227 static void
00228 dia_begin_job(GVJ_t *job)
00229 {
00230     gvprintf(job, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
00231 }
00232 
00233 static void dia_end_job(GVJ_t *job)
00234 {
00235 }
00236 
00237 static void dia_begin_graph(GVJ_t * job)
00238 {
00239     gvprintf(job, "<dia:diagram xmlns:dia=\"http://www.lysator.liu.se/~alla/dia/\">\n");
00240 #if 0
00241     Rootgraph = g;
00242     PB.LL.x = PB.LL.y = 0;
00243     PB.UR.x = (bb.UR.x - bb.LL.x + 2 * GD_drawing(g)->margin.x) * SCALE;
00244     PB.UR.y = (bb.UR.y - bb.LL.y + 2 * GD_drawing(g)->margin.y) * SCALE;
00245     Offset.x = GD_drawing(g)->margin.x * SCALE;
00246     Offset.y = GD_drawing(g)->margin.y * SCALE;
00247     if (onetime) {
00248         init_dia();
00249         onetime = FALSE;
00250     }
00251 #endif
00252     gvputs(job, "  <dia:diagramdata>\n");
00253 
00254     gvputs(job, "    <dia:attribute name=\"background\">\n");
00255     gvputs(job, "      <dia:color val=\"#ffffff\"/>\n");
00256     gvputs(job, "    </dia:attribute>\n");
00257 
00258     gvputs(job, "    <dia:attribute name=\"paper\">\n");
00259     gvputs(job, "      <dia:composite type=\"paper\">\n");
00260     gvputs(job, "        <dia:attribute name=\"name\">\n");
00261     gvputs(job, "          <dia:string>#A4#</dia:string>\n");
00262     gvputs(job, "        </dia:attribute>\n");
00263     gvputs(job, "        <dia:attribute name=\"tmargin\">\n");
00264     gvputs(job, "          <dia:real val=\"2.8222\"/>\n");
00265     gvputs(job, "        </dia:attribute>\n");
00266     gvputs(job, "        <dia:attribute name=\"bmargin\">\n");
00267     gvputs(job, "          <dia:real val=\"2.8222\"/>\n");
00268     gvputs(job, "        </dia:attribute>\n");
00269     gvputs(job, "        <dia:attribute name=\"lmargin\">\n");
00270     gvputs(job, "          <dia:real val=\"2.8222\"/>\n");
00271     gvputs(job, "        </dia:attribute>\n");
00272     gvputs(job, "        <dia:attribute name=\"rmargin\">\n");
00273     gvputs(job, "          <dia:real val=\"2.8222\"/>\n");
00274     gvputs(job, "        </dia:attribute>\n");
00275     gvputs(job, "        <dia:attribute name=\"is_portrait\">\n");
00276     gvputs(job, "          <dia:boolean val=\"true\"/>\n");
00277     gvputs(job, "        </dia:attribute>\n");
00278     gvputs(job, "        <dia:attribute name=\"scaling\">\n");
00279     gvputs(job, "          <dia:real val=\"1\"/>\n");
00280     gvputs(job, "        </dia:attribute>\n");
00281     gvputs(job, "        <dia:attribute name=\"fitto\">\n");
00282     gvputs(job, "          <dia:boolean val=\"false\"/>\n");
00283     gvputs(job, "        </dia:attribute>\n");
00284     gvputs(job, "      </dia:composite>\n");
00285     gvputs(job, "    </dia:attribute>\n");
00286 
00287     gvputs(job, "    <dia:attribute name=\"grid\">\n");
00288     gvputs(job, "      <dia:composite type=\"grid\">\n");
00289     gvputs(job, "        <dia:attribute name=\"width_x\">\n");
00290     gvputs(job, "          <dia:real val=\"1\"/>\n");
00291     gvputs(job, "        </dia:attribute>\n");
00292     gvputs(job, "        <dia:attribute name=\"width_y\">\n");
00293     gvputs(job, "          <dia:real val=\"1\"/>\n");
00294     gvputs(job, "        </dia:attribute>\n");
00295     gvputs(job, "        <dia:attribute name=\"visible_x\">\n");
00296     gvputs(job, "          <dia:int val=\"1\"/>\n");
00297     gvputs(job, "        </dia:attribute>\n");
00298     gvputs(job, "        <dia:attribute name=\"visible_y\">\n");
00299     gvputs(job, "          <dia:int val=\"1\"/>\n");
00300     gvputs(job, "        </dia:attribute>\n");
00301     gvputs(job, "      </dia:composite>\n");
00302     gvputs(job, "    </dia:attribute>\n");
00303 
00304     gvputs(job, "    <dia:attribute name=\"guides\">\n");
00305     gvputs(job, "      <dia:composite type=\"guides\">\n");
00306     gvputs(job, "        <dia:attribute name=\"hguides\"/>\n");
00307     gvputs(job, "        <dia:attribute name=\"vguides\"/>\n");
00308     gvputs(job, "      </dia:composite>\n");
00309     gvputs(job, "    </dia:attribute>\n");
00310 
00311     gvputs(job, "  </dia:diagramdata>\n");
00312 }
00313 
00314 static void dia_end_graph(GVJ_t * job)
00315 {
00316     gvprintf(job, "</dia:diagram>\n");
00317 }
00318 
00319 static void
00320 dia_begin_page(GVJ_t * job)
00321 {
00322     gvprintf(job, "  <dia:layer name=\"Background\" visible=\"true\">\n");
00323 }
00324 
00325 static void dia_end_page(GVJ_t * job)
00326 {
00327     gvputs(job, "  </dia:layer>\n");
00328 }
00329 
00330 static void dia_begin_cluster(GVJ_t * job)
00331 {
00332 //    obj_state_t *obj = job->obj;
00333 
00334     gvprintf(job, "    <dia:group>\n");
00335 }
00336 
00337 static void dia_end_cluster(GVJ_t * job)
00338 {
00339     gvprintf(job, "    </dia:group>\n");
00340 }
00341 
00342 static void dia_begin_node(GVJ_t * job)
00343 {
00344     gvprintf(job, "    <dia:group>\n");
00345 }
00346 
00347 static void dia_end_node(GVJ_t * job)
00348 {
00349     gvprintf(job, "    </dia:group>\n");
00350 }
00351 
00352 static void dia_begin_edge(GVJ_t * job)
00353 {
00354     gvprintf(job, "    <dia:group>\n");
00355 }
00356 
00357 static void dia_end_edge(GVJ_t * job)
00358 {
00359     gvprintf(job, "    </dia:group>\n");
00360 }
00361 
00362 static void dia_begin_context(void)
00363 {
00364     assert(SP + 1 < MAXNEST);
00365     cstk[SP + 1] = cstk[SP];
00366     SP++;
00367 }
00368 
00369 static void dia_end_context(void)
00370 {
00371     int psp = SP - 1;
00372     assert(SP > 0);
00373     /*free(cstk[psp].fontfam); */
00374     SP = psp;
00375 }
00376 
00377 static void dia_set_font(char *name, double size)
00378 {
00379     char *p;
00380     context_t *cp;
00381 
00382     cp = &(cstk[SP]);
00383     cp->font_was_set = TRUE;
00384     cp->fontsz = size;
00385     p = strdup(name);
00386     cp->fontfam = p;
00387 }
00388 
00389 static void dia_set_pencolor(char *name)
00390 {
00391     cstk[SP].pencolor = name;
00392 }
00393 
00394 static void dia_set_fillcolor(char *name)
00395 {
00396     cstk[SP].fillcolor = name;
00397 }
00398 
00399 static void dia_set_style(char **s)
00400 {
00401 #if 0
00402     char *line, *p;
00403     context_t *cp;
00404 
00405     cp = &(cstk[SP]);
00406     while ((p = line = *s++)) {
00407         if (streq(line, "solid"))
00408             cp->pen = P_SOLID;
00409         else if (streq(line, "dashed"))
00410             cp->pen = P_DASHED;
00411         else if (streq(line, "dotted"))
00412             cp->pen = P_DOTTED;
00413         else if (streq(line, "invis"))
00414             cp->pen = P_NONE;
00415         else if (streq(line, "bold"))
00416             cp->penwidth = WIDTH_BOLD;
00417         else if (streq(line, "setlinewidth")) {
00418             while (*p)
00419                 p++;
00420             p++;
00421             cp->penwidth = atol(p);
00422         } else if (streq(line, "filled"))
00423             cp->fill = P_SOLID;
00424         else if (streq(line, "unfilled"))
00425             cp->fill = P_NONE;
00426         else {
00427             agwarn("dia_set_style: unsupported style %s - ignoring\n",
00428                   line);
00429         }
00430         cp->style_was_set = TRUE;
00431     }
00432     /* if (cp->style_was_set) dia_style(cp); */
00433 #endif
00434 }
00435 
00436 static void dia_textpara(GVJ_t * job, pointf p, textpara_t * para)
00437 {
00438     obj_state_t *obj = job->obj;
00439     PostscriptAlias *pA;
00440     int anchor;
00441     double size;
00442     char *family=NULL, *weight=NULL, *stretch=NULL, *style=NULL;
00443 
00444     switch (para->just) {
00445     case 'l':
00446         anchor = 0;
00447         break;
00448     case 'r':
00449         anchor = 2;
00450         break;
00451     default:
00452     case 'n':
00453         anchor = 1;
00454         break;
00455     }
00456     p.y += para->yoffset_centerline;
00457 
00458     pA = para->postscript_alias;
00459     if (pA) {
00460         switch(GD_fontnames(job->gvc->g)) {
00461                 case PSFONTS:
00462                     family = pA->name;
00463                     weight = pA->weight;
00464                     style = pA->style;
00465                     break;
00466                 case SVGFONTS:
00467                     family = pA->svg_font_family;
00468                     weight = pA->svg_font_weight;
00469                     style = pA->svg_font_style;
00470                     break;
00471                 default:
00472                 case NATIVEFONTS:
00473                     family = pA->family;
00474                     weight = pA->weight;
00475                     style = pA->style;
00476                     break;
00477         }
00478         stretch = pA->stretch;
00479 #if 0
00480         gvprintf(job, " font-family=\"%s", family);
00481         if (pA->svg_font_family) gvprintf(job, ",%s", pA->svg_font_family);
00482         gvputs(job, "\"");
00483         if (weight) gvprintf(job, " font-weight=\"%s\"", weight);
00484         if (stretch) gvprintf(job, " font-stretch=\"%s\"", stretch);
00485         if (style) gvprintf(job, " font-style=\"%s\"", style);
00486 #endif
00487     }
00488     else
00489         family = para->fontname;
00490     size = para->fontsize;
00491 
00492 #if 0
00493     switch (obj->pencolor.type) {
00494     case COLOR_STRING:
00495         if (strcasecmp(obj->pencolor.u.string, "black"))
00496             gvprintf(job, " fill=\"%s\"", obj->pencolor.u.string);
00497         break;
00498     case RGBA_BYTE:
00499         gvprintf(job, " fill=\"#%02x%02x%02x\"",
00500                 obj->pencolor.u.rgba[0], obj->pencolor.u.rgba[1], obj->pencolor.u.rgba[2]);
00501         break;
00502     default:
00503         assert(0);              /* internal error */
00504     }
00505 #endif
00506 
00507     gvprintf(job,
00508         "    <dia:object type=\"Standard - Text\" version=\"0\" id=\"%s\">\n",
00509          "0");
00510     gvputs(job, "      <dia:attribute name=\"text\">\n");
00511     gvputs(job, "        <dia:composite type=\"text\">\n");
00512     gvputs(job, "          <dia:attribute name=\"string\">\n");
00513     gvputs(job, "            <dia:string>#");
00514     gvputs(job, xml_string(para->str));
00515     gvputs(job, "#</dia:string>\n");
00516     gvputs(job, "          </dia:attribute>\n");
00517     gvputs(job, "          <dia:attribute name=\"font\">\n");
00518     gvprintf(job, "            <dia:font name=\"%s\"/>\n", family);
00519     gvputs(job, "          </dia:attribute>\n");
00520     gvputs(job, "          <dia:attribute name=\"height\">\n");
00521     gvprintf(job, "            <dia:real val=\"%g\"/>\n", size);
00522     gvputs(job, "          </dia:attribute>\n");
00523     gvputs(job, "          <dia:attribute name=\"pos\">\n");
00524     gvprintf(job, "            <dia:point val=\"%g,%g\"/>\n", p.x, p.y);
00525     gvputs(job, "          </dia:attribute>\n");
00526     gvputs(job, "          <dia:attribute name=\"color\">\n");
00527 #if 0
00528     gvprintf(job, "            <dia:color val=\"%s\"/>\n",
00529                dia_resolve_color(cp->pencolor));
00530 #else
00531     gvprintf(job, "            <dia:color val=\"%s\"/>\n",
00532                "black");
00533 #endif
00534     gvputs(job, "          </dia:attribute>\n");
00535     gvputs(job, "          <dia:attribute name=\"alignment\">\n");
00536     gvprintf(job, "            <dia:enum val=\"%d\"/>\n", anchor);
00537     gvputs(job, "          </dia:attribute>\n");
00538     gvputs(job, "        </dia:composite>\n");
00539     gvputs(job, "      </dia:attribute>\n");
00540     gvputs(job, "      <dia:attribute name=\"obj_pos\">\n");
00541     gvprintf(job, "        <dia:point val=\"%g,%g\"/>\n", p.x, p.y);
00542     gvputs(job, "      </dia:attribute>\n");
00543 #if 0
00544     gvputs(job, "      <dia:attribute name=\"obj_bb\">\n");
00545     gvprintf(job, "        <dia:rectangle val=\"%g,%g;%g,%g\"/>\n",
00546                p.x - (Scale * (para->width) / 2.), p.y - 0.4,
00547                p.x + (Scale * (para->width) / 2.), p.y + 0.4);
00548     gvputs(job, "      </dia:attribute>\n");
00549 #endif
00550     gvputs(job, "    </dia:object>\n");
00551 }
00552 
00553 static void dia_ellipse(GVJ_t * job, pointf *A, int filled)
00554 {
00555 #if 0
00556     pointf cp, rp;
00557     int nodeId;
00558 
00559     switch (Obj) {
00560     case NODE:
00561         nodeId = Curnode->id;
00562         break;
00563     default:
00564         nodeId = -1;
00565         break;
00566     }
00567 
00568     if (cstk[SP].pen == P_NONE) {
00569         /* its invisible, don't draw */
00570         return;
00571     }
00572     cp = dia_pt(p);
00573 
00574     if (Rot) {
00575         int t;
00576         t = rx;
00577         rx = ry;
00578         ry = t;
00579     }
00580     rp.x = Scale * rx;
00581     rp.y = Scale * ry;
00582 
00583     gvprintf(job,
00584         "    <dia:object type=\"Standard - Ellipse\" version=\"0\" id=\"%d\">\n",
00585          nodeId);
00586     gvputs(job, "      <dia:attribute name=\"elem_corner\">\n");
00587     gvprintf(job, "        <dia:point val=\"%g,%g\"/>\n", cp.x - rp.x,
00588                cp.y - rp.y);
00589     gvputs(job, "      </dia:attribute>\n");
00590     gvputs(job, "      <dia:attribute name=\"elem_width\">\n");
00591     gvprintf(job, "        <dia:real val=\"%g\"/>\n", rp.x + rp.x);
00592     gvputs(job, "      </dia:attribute>\n");
00593     gvputs(job, "      <dia:attribute name=\"elem_height\">\n");
00594     gvprintf(job, "        <dia:real val=\"%g\"/>\n", rp.y + rp.y);
00595     gvputs(job, "      </dia:attribute>\n");
00596     gvputs(job, "      <dia:attribute name=\"obj_pos\">\n");
00597     gvprintf(job, "        <dia:point val=\"%g,%g\"/>\n", cp.x - rp.x,
00598                cp.y - rp.y);
00599     gvputs(job, "      </dia:attribute>\n");
00600     gvputs(job, "      <dia:attribute name=\"obj_bb\">\n");
00601     gvprintf(job, "        <dia:rectangle val=\"%g,%g;%g,%g\"/>\n",
00602                cp.x - rp.x - .11, cp.y - rp.y - .11, cp.x + rp.x + .11,
00603                cp.y + rp.y + .11);
00604     gvputs(job, "      </dia:attribute>\n");
00605     dia_style(job, &cstk[SP]);
00606     dia_stylefill(job, &cstk[SP], filled);
00607     gvputs(job, "    </dia:object>\n");
00608 #endif
00609 }
00610 
00611 
00612 int ellipse_connection(pointf cp, pointf p)
00613 {
00614     int conn = 0;
00615 #if 0
00616     if (cp.x == p.x) {
00617         if (cp.y > p.y)
00618             conn = 1;
00619         else
00620             conn = 6;
00621     } else if (cp.y == p.y) {
00622         if (cp.x > p.x)
00623             conn = 3;
00624         else
00625             conn = 4;
00626     } else if (cp.x < p.x) {
00627         if (cp.y < p.y)
00628             conn = 7;
00629         else
00630             conn = 2;
00631     } else if (cp.x > p.x) {
00632         if (cp.y < p.y)
00633             conn = 5;
00634         else
00635             conn = 0;
00636     }
00637 #endif
00638     return conn;
00639 }
00640 
00641 
00642 int box_connection(node_t * n, pointf p)
00643 {
00644     int conn = 0;
00645 #if 0
00646     int i = 0, j, sides, conn = 0, peripheries, z;
00647     double xsize, ysize, mindist2 = 0.0, dist2;
00648     polygon_t *poly;
00649     pointf P, *vertices;
00650     static point *A;
00651     static int A_size;
00652 
00653     poly = (polygon_t *) ND_shape_info(n);
00654     vertices = poly->vertices;
00655     sides = poly->sides;
00656     peripheries = poly->peripheries;
00657 
00658     if (A_size < sides) {
00659         A_size = sides + 5;
00660         A = malloc(A_size*sizeof(pointf));
00661     }
00662 
00663     xsize = ((ND_lw(n) + ND_rw(n)) / POINTS(ND_width(n))) * 16.0;
00664     ysize = ((ND_ht(n)) / POINTS(ND_height(n))) * 16.0;
00665 
00666     for (j = 0; j < peripheries; j++) {
00667         for (i = 0; i < sides; i++) {
00668             P = vertices[i + j * sides];
00669 /* simple rounding produces random results around .5 
00670  * this trick should clip off the random part. 
00671  * (note xsize/ysize prescaled by 16.0 above) */
00672             A[i].x = ROUND(P.x * xsize) / 16;
00673             A[i].y = ROUND(P.y * ysize) / 16;
00674             if (sides > 2) {
00675                 A[i].x += ND_coord_i(n).x;
00676                 A[i].y += ND_coord_i(n).y;
00677             }
00678         }
00679     }
00680 
00681     z = 0;
00682     while (z < i) {
00683         dist2 = DIST2(p, dia_pt(A[z]));
00684         if (z == 0) {
00685             mindist2 = dist2;
00686             conn = 0;
00687         }
00688         if (dist2 < mindist2) {
00689             mindist2 = dist2;
00690             conn = 2 * z;
00691         }
00692         z++;
00693     }
00694 
00695     z = 0;
00696     while (z < i) {
00697         P.x = (dia_pt(A[z]).x + dia_pt(A[z + 1]).x) / 2;
00698         P.y = (dia_pt(A[z]).y + dia_pt(A[z + 1]).y) / 2;
00699         dist2 = DIST2(p, P);
00700         if (dist2 < mindist2) {
00701             mindist2 = dist2;
00702             conn = 2 * z + 1;
00703         }
00704         z++;
00705     }
00706 #endif
00707     return conn;
00708 }
00709 
00710 
00711 static void
00712 dia_bezier(GVJ_t *job, pointf * A, int n, int arrow_at_start, int arrow_at_end, int filled)
00713 {
00714 #if 0
00715     int i, conn_h, conn_t;
00716     pointf p, firstp = { 0, 0 }, llp = {
00717     0, 0}, urp = {
00718     0, 0};
00719     node_t *head, *tail;
00720     char *shape_t;
00721     pointf cp_h, cp_t;
00722 
00723     if (cstk[SP].pen == P_NONE) {
00724         /* its invisible, don't draw */
00725         return;
00726     }
00727 
00728     gvprintf(job,
00729         "    <dia:object type=\"Standard - BezierLine\" version=\"0\" id=\"%s\">\n",
00730          "00");
00731     gvputs(job, "       <dia:attribute name=\"bez_points\">\n");
00732     for (i = 0; i < n; i++) {
00733         p = dia_pt(A[i]);
00734         if (!i)
00735             llp = urp = firstp = p;
00736         if (p.x < llp.x || p.y < llp.y)
00737             llp = p;
00738         if (p.x > urp.x || p.y > urp.y)
00739             urp = p;
00740         gvprintf(job, "        <dia:point val=\"%g,%g\"/>\n", p.x, p.y);
00741     }
00742     gvputs(job, "      </dia:attribute>\n");
00743     dia_style(job, &cstk[SP]);
00744     gvputs(job, "      <dia:attribute name=\"obj_pos\">\n");
00745     gvprintf(job, "        <dia:point val=\"%g,%g\"/>\n", firstp.x, firstp.y);
00746     gvputs(job, "      </dia:attribute>\n");
00747     gvputs(job, "      <dia:attribute name=\"obj_bb\">\n");
00748     gvprintf(job, "        <dia:rectangle val=\"%g,%g;%g,%g\"/>\n",
00749                llp.x - .11, llp.y - .11, urp.x + .11, urp.y + .11);
00750     gvputs(job, "      </dia:attribute>\n");
00751     if (!Curedge) return;
00752 
00753     conn_h = conn_t = -1;
00754 
00755     head = Curedge->head;
00756     tail = Curedge->tail;
00757 
00758     shape_t = ND_shape(tail)->name;
00759 
00760     /* arrowheads */
00761     if (arrow_at_start) {
00762         gvputs(job, "      <dia:attribute name=\"start_arrow\">\n");
00763         gvputs(job, "          <dia:enum val=\"3\"/>\n");
00764         gvputs(job, "      </dia:attribute>\n");
00765         gvputs(job, "      <dia:attribute name=\"start_arrow_length\">\n");
00766         gvputs(job, "           <dia:real val=\"0.8\"/>\n");
00767         gvputs(job, "      </dia:attribute>\n");
00768         dia_fputs
00769             ("           <dia:attribute name=\"start_arrow_width\">\n");
00770         gvputs(job, "                   <dia:real val=\"0.8\"/>\n");
00771         gvputs(job, "      </dia:attribute>\n");
00772     }
00773     if (arrow_at_end) {
00774         gvputs(job, "      <dia:attribute name=\"end_arrow\">\n");
00775         gvputs(job, "          <dia:enum val=\"3\"/>\n");
00776         gvputs(job, "      </dia:attribute>\n");
00777         gvputs(job, "      <dia:attribute name=\"end_arrow_length\">\n");
00778         gvputs(job, "           <dia:real val=\"0.8\"/>\n");
00779         gvputs(job, "      </dia:attribute>\n");
00780         dia_fputs
00781             ("           <dia:attribute name=\"end_arrow_width\">\n");
00782         gvputs(job, "                   <dia:real val=\"0.8\"/>\n");
00783         gvputs(job, "      </dia:attribute>\n");
00784     }
00785 
00786     gvputs(job, "      <dia:attribute name=\"conn_endpoints\">\n");
00787     gvprintf(job, "        <dia:point val=\"%g,%g\"/>\n", dia_pt(A[0]).x,
00788                dia_pt(A[0]).y);
00789     gvprintf(job, "        <dia:point val=\"%g,%g\"/>\n", dia_pt(A[n - 1]).x,
00790                dia_pt(A[n - 1]).y);
00791     gvputs(job, "      </dia:attribute>\n");
00792     gvputs(job, "      <dia:connections>\n");
00793 
00794     if ((strcmp(shape_t, "ellipse") == 0)
00795         || (strcmp(shape_t, "circle") == 0)
00796         || (strcmp(shape_t, "doublecircle") == 0)) {
00797         cp_h = dia_pt(ND_coord_i(head));
00798         if (AG_IS_DIRECTED(Rootgraph))
00799             conn_h = ellipse_connection(cp_h, dia_pt(A[n - 1]));
00800         else
00801             conn_h = ellipse_connection(cp_h, dia_pt(A[0]));
00802     } else {
00803         if (AG_IS_DIRECTED(Rootgraph))
00804             conn_h = box_connection(head, dia_pt(A[n - 1]));
00805         else
00806             conn_h = box_connection(head, dia_pt(A[0]));
00807     }
00808 
00809     if ((strcmp(shape_t, "ellipse") == 0)
00810         || (strcmp(shape_t, "circle") == 0)
00811         || (strcmp(shape_t, "doublecircle") == 0)) {
00812         cp_t = dia_pt(ND_coord_i(tail));
00813         if (AG_IS_DIRECTED(Rootgraph))
00814             conn_t = ellipse_connection(cp_t, dia_pt(A[0]));
00815         else
00816             conn_t = ellipse_connection(cp_t, dia_pt(A[n - 1]));
00817     } else {
00818         if (AG_IS_DIRECTED(Rootgraph))
00819             conn_t = box_connection(tail, dia_pt(A[0]));
00820         else
00821             conn_t = box_connection(tail, dia_pt(A[n - 1]));
00822     }
00823 
00824     if (arrow_at_start) {
00825         gvprintf(job,
00826             "        <dia:connection handle=\"0\" to=\"%d\" connection=\"%d\"/>\n",
00827              head->id, conn_h);
00828         gvprintf(job,
00829             "        <dia:connection handle=\"%d\" to=\"%d\" connection=\"%d\"/>\n",
00830              (n - 1), tail->id, conn_t);
00831     } else {
00832         gvprintf(job,
00833             "        <dia:connection handle=\"0\" to=\"%d\" connection=\"%d\"/>\n",
00834              tail->id, conn_t);
00835         gvprintf(job,
00836             "        <dia:connection handle=\"%d\" to=\"%d\" connection=\"%d\"/>\n",
00837              (n - 1), head->id, conn_h);
00838     }
00839 
00840     gvputs(job, "      </dia:connections>\n");
00841     gvputs(job, "    </dia:object>\n");
00842 #endif
00843 }
00844 
00845 
00846 
00847 static void dia_polygon(GVJ_t * job, pointf * A, int n, int filled)
00848 {
00849 #if 0
00850     int i;
00851     pointf p, firstp = { 0, 0 }, llp = {
00852     0, 0}, urp = {
00853     0, 0};
00854 
00855     if (cstk[SP].pen == P_NONE) {
00856         /* its invisible, don't draw */
00857         return;
00858     }
00859 
00860     switch (Obj) {
00861     case NODE:
00862         gvprintf(job,
00863             "    <dia:object type=\"Standard - Polygon\" version=\"0\" id=\"%d\">\n",
00864              Curnode->id);
00865         break;
00866     case EDGE:
00867         return;
00868         break;
00869     case CLST:
00870         gvprintf(job,
00871             "    <dia:object type=\"Standard - Polygon\" version=\"0\" id=\"%s\">\n",
00872              Curgraph->name);
00873         break;
00874     default:
00875         gvprintf(job,
00876             "    <dia:object type=\"Standard - Polygon\" version=\"0\" id=\"%s\">\n",
00877              "polygon");
00878         break;
00879     }
00880     gvputs(job, "       <dia:attribute name=\"poly_points\">\n");
00881     for (i = 0; i < n; i++) {
00882         p = dia_pt(A[i]);
00883         if (!i)
00884             llp = urp = firstp = p;
00885         if (p.x < llp.x || p.y < llp.y)
00886             llp = p;
00887         if (p.x > urp.x || p.y > urp.y)
00888             urp = p;
00889         gvprintf(job, "        <dia:point val=\"%g,%g\"/>\n", p.x, p.y);
00890     }
00891     gvputs(job, "      </dia:attribute>\n");
00892     gvputs(job, "      <dia:attribute name=\"obj_pos\">\n");
00893     gvprintf(job, "        <dia:point val=\"%g,%g\"/>\n", firstp.x, firstp.y);
00894     gvputs(job, "      </dia:attribute>\n");
00895     gvputs(job, "      <dia:attribute name=\"obj_bb\">\n");
00896     gvprintf(job, "        <dia:rectangle val=\"%g,%g;%g,%g\"/>\n",
00897                llp.x - .11, llp.y - .11, urp.x + .11, urp.y + .11);
00898     gvputs(job, "      </dia:attribute>\n");
00899     dia_style(job, &cstk[SP]);
00900     dia_stylefill(job, &cstk[SP], filled);
00901     gvputs(job, "    </dia:object>\n");
00902 #endif
00903 }
00904 
00905 static void dia_polyline(GVJ_t * job, pointf * A, int n)
00906 {
00907 #if 0
00908     int i;
00909     pointf p, firstp = { 0, 0 }, llp = {
00910     0, 0}, urp = {
00911     0, 0};
00912 
00913     if (cstk[SP].pen == P_NONE) {
00914         /* its invisible, don't draw */
00915         return;
00916     }
00917     gvprintf(job,
00918         "    <dia:object type=\"Standard - PolyLine\" version=\"0\" id=\"%s\">\n",
00919          "0");
00920     gvputs(job, "      <dia:attribute name=\"poly_points\">\n");
00921     for (i = 0; i < n; i++) {
00922         p = dia_pt(A[i]);
00923         if (!i)
00924             llp = urp = firstp = p;
00925         if (p.x < llp.x || p.y < llp.y)
00926             llp = p;
00927         if (p.x > urp.x || p.y > urp.y)
00928             urp = p;
00929         gvprintf(job, "<dia:point val=\"%g,%g\"/>\n", p.x, p.y);
00930     }
00931     gvputs(job, "      </dia:attribute>\n");
00932     dia_style(job, &cstk[SP]);
00933     gvputs(job, "      <dia:attribute name=\"obj_pos\">\n");
00934     gvprintf(job, "        <dia:point val=\"%g,%g\"/>\n", firstp.x, firstp.y);
00935     gvputs(job, "      </dia:attribute>\n");
00936     gvputs(job, "      <dia:attribute name=\"obj_bb\">\n");
00937     gvprintf(job, "        <dia:rectangle val=\"%g,%g;%g,%g\"/>\n",
00938                llp.x - .11, llp.y - .11, urp.x + .11, urp.y + .11);
00939     gvputs(job, "      </dia:attribute>\n");
00940     gvputs(job, "    </dia:object>\n");
00941 #endif
00942 }
00943 
00944 gvrender_engine_t dia_engine = {
00945     dia_begin_job, dia_end_job,
00946     dia_begin_graph, dia_end_graph,
00947     0, /* dia_begin_layer */ 0, /* dia_end_layer */
00948     dia_begin_page, dia_end_page,
00949     dia_begin_cluster, dia_end_cluster,
00950     0, /* dia_begin_nodes */ 0, /* dia_end_nodes */
00951     0, /* dia_begin_edges */ 0, /* dia_end_edges */
00952     dia_begin_node, dia_end_node,
00953     dia_begin_edge, dia_end_edge,
00954     0, /* dia_begin_anchor */ 0, /* dia_end_anchor */
00955     0, /* dia_begin_label */ 0, /* dia_end_label */
00956     dia_textpara, dia_resolve_color,
00957     dia_ellipse, dia_polygon,
00958     dia_bezier, dia_polyline,
00959     dia_comment,
00960     0,                  /* dia_library_shape */
00961 };
00962 
00963 static gvrender_features_t render_features_dia = {
00964     0,                          /* flags */
00965     4.,                         /* default pad - graph units */
00966     NULL,                       /* knowncolors */
00967     0,                          /* sizeof knowncolors */
00968     HSVA_DOUBLE,                /* color_type */
00969 };
00970 
00971 static gvdevice_features_t device_features_dia = {
00972     GVDEVICE_BINARY_FORMAT
00973       | GVDEVICE_COMPRESSED_FORMAT, /* flags */
00974     {0.,0.},                    /* default margin - points */
00975     {0.,0.},                    /* default page width, height - points */
00976     {72.,72.},                  /* default dpi */
00977 };
00978 
00979 gvplugin_installed_t gvrender_dia_types[] = {
00980     {FORMAT_DIA, "dia", -1, &dia_engine, &render_features_dia},
00981     {0, NULL, 0, NULL, NULL}
00982 };
00983 
00984 gvplugin_installed_t gvdevice_dia_types[] = {
00985     {FORMAT_DIA, "dia:dia", -1, NULL, &device_features_dia},
00986     {0, NULL, 0, NULL, NULL}
00987 };
00988