]> granicus.if.org Git - graphviz/commitdiff
clean up
authorellson <devnull@localhost>
Tue, 27 Jun 2006 17:04:19 +0000 (17:04 +0000)
committerellson <devnull@localhost>
Tue, 27 Jun 2006 17:04:19 +0000 (17:04 +0000)
lib/common/Makefile.am
lib/common/gdgen.c [deleted file]
lib/common/mapgen.c [deleted file]
lib/common/psgen.c [deleted file]
lib/common/svggen.c [deleted file]
lib/common/vrmlgen.c [deleted file]

index e2928810e6f683199fd3abdbf245453f26863e33..e27043d307408929e7ca2360c5acad0de5c6acd4 100644 (file)
@@ -17,7 +17,7 @@ noinst_HEADERS = render.h utils.h memory.h \
 noinst_LTLIBRARIES = libcommon_C.la
 
 if WITH_CODEGENS
-CODEGENS = $(GD_CODEGENS) diagen.c figgen.c hpglgen.c mapgen.c mifgen.c mpgen.c \
+CODEGENS = $(GD_CODEGENS) diagen.c figgen.c hpglgen.c mifgen.c mpgen.c \
        picgen.c vtxgen.c xdgen.c
 endif
 
diff --git a/lib/common/gdgen.c b/lib/common/gdgen.c
deleted file mode 100644 (file)
index e67cf3e..0000000
+++ /dev/null
@@ -1,969 +0,0 @@
-/* $Id$ $Revision$ */
-/* vim:set shiftwidth=4 ts=8: */
-
-/**********************************************************
-*      This software is part of the graphviz package      *
-*                http://www.graphviz.org/                 *
-*                                                         *
-*            Copyright (c) 1994-2004 AT&T Corp.           *
-*                and is licensed under the                *
-*            Common Public License, Version 1.0           *
-*                      by AT&T Corp.                      *
-*                                                         *
-*        Information and Software Systems Research        *
-*              AT&T Research, Florham Park NJ             *
-**********************************************************/
-
-#include "render.h"
-#include "gd.h"
-
-#include <fcntl.h>
-#ifdef MSWIN32
-#include <io.h>
-#endif
-
-static gdImagePtr im;
-static int external_surface;
-
-#ifdef _UWIN
-#ifndef DEFAULT_FONTPATH
-#define                DEFAULT_FONTPATH        "/win/fonts"
-#endif                         /* DEFAULT_FONTPATH */
-#else
-#ifndef MSWIN32
-#ifndef DEFAULT_FONTPATH
-#define                DEFAULT_FONTPATH        "/usr/share/ttf:/usr/local/share/ttf:/usr/share/fonts/ttf:/usr/local/share/fonts/ttf:/usr/lib/fonts:/usr/local/lib/fonts:/usr/lib/fonts/ttf:/usr/local/lib/fonts/ttf:/usr/common/graphviz/lib/fonts/ttf:/windows/fonts:/dos/windows/fonts:/usr/add-on/share/ttf:."
-#endif                         /* DEFAULT_FONTPATH */
-#else
-#ifndef DEFAULT_FONTPATH
-#define                DEFAULT_FONTPATH        "%WINDIR%/FONTS;C:/WINDOWS/FONTS;C:/WINNT/Fonts;C:/winnt/fonts"
-#endif                         /* DEFAULT_FONTPATH */
-#endif                         /* MSWIN32 */
-#endif                         /* _UWIN */
-
-#define BEZIERSUBDIVISION 10
-
-/* font modifiers */
-#define REGULAR                0
-#define BOLD           1
-#define ITALIC         2
-
-/* patterns */
-#define P_SOLID                0
-#define P_DOTTED       4
-#define P_DASHED       11
-#define P_NONE         15
-
-/* bold line constant */
-#define WIDTH_NORMAL   1
-#define WIDTH_BOLD     2
-
-/* static int  N_pages; */
-/* static point        Pages; */
-static pointf Dpi;
-static point Margin;
-static pointf CompScale;
-static int Rot;
-
-static point Viewport;
-static pointf GraphFocus;
-static double Zoom;
-
-typedef struct context_t {
-    int pencolor, fillcolor;
-    char *fontfam, fontopt, font_was_set, pen, fill, penwidth;
-    double fontsz;
-} context_t;
-
-#define MAXNEST        4
-static context_t cstk[MAXNEST];
-static int SP;
-static node_t *Curnode;
-
-static int white, black, transparent;
-
-static int gd_resolve_color(char *name)
-{
-    gvcolor_t color;
-
-    if (!(strcmp(name, "transparent"))) {
-       /* special case for "transparent" color */
-       return transparent;
-    } else {
-       colorxlate(name, &color, RGBA_BYTE);
-       /* seems gd alpha is "transparency" rather than the usual "opacity" */
-       return gdImageColorResolveAlpha(im,
-                                       color.u.rgba[0],
-                                       color.u.rgba[1],
-                                       color.u.rgba[2],
-                                       (255 -
-                                        color.u.rgba[3]) * gdAlphaMax /
-                                       255);
-    }
-}
-
-static pointf gdpt(pointf p)
-{
-    pointf rv;
-
-    if (Rot == 0) {
-       rv.x = (p.x - GraphFocus.x) * CompScale.x + Viewport.x / 2. + Margin.x;
-       rv.y = -(p.y - GraphFocus.y) * CompScale.y + Viewport.y / 2. + Margin.y;
-    } else {
-       rv.x = -(p.y - GraphFocus.y) * CompScale.x + Viewport.x / 2. + Margin.x;
-       rv.y = -(p.x - GraphFocus.x) * CompScale.y + Viewport.y / 2. + Margin.y;
-    }
-    return rv;
-}
-
-static void gd_begin_job(FILE * ofp, graph_t * g, char **lib, char *user,
-                        char *info[], point pages)
-{
-/*     Pages = pages; */
-/*     N_pages = pages.x * pages.y; */
-#ifdef MYTRACE
-    fprintf(stderr, "gd_begin_job\n");
-#endif
-}
-
-static void gd_end_job(void)
-{
-#ifdef MYTRACE
-    fprintf(stderr, "gd_end_job\n");
-#endif
-}
-
-static void init1_gd(GVC_t * gvc, graph_t * g, box bb, point pb)
-{
-    Dpi = gvc->job->dpi;
-    Margin.x = ROUND(gvc->job->margin.x * Dpi.x / POINTS_PER_INCH);
-    Margin.y = ROUND(gvc->job->margin.y * Dpi.y / POINTS_PER_INCH);
-    Viewport.x = gvc->job->width;
-    Viewport.y = gvc->job->height;
-    Zoom = gvc->job->zoom;
-    GraphFocus = gvc->job->focus;
-    CompScale.x = Zoom *  Dpi.x / POINTS_PER_INCH;
-    CompScale.y = Zoom *  Dpi.y / POINTS_PER_INCH;
-}
-
-static void init2_gd(gdImagePtr im)
-{
-    SP = 0;
-
-    white = gdImageColorResolveAlpha(im,
-                                    gdRedMax, gdGreenMax, gdBlueMax,
-                                    gdAlphaOpaque);
-    black = gdImageColorResolveAlpha(im, 0, 0, 0, gdAlphaOpaque);
-    transparent = gdImageColorResolveAlpha(im,
-                                          gdRedMax - 1, gdGreenMax,
-                                          gdBlueMax, gdAlphaTransparent);
-    gdImageColorTransparent(im, transparent);
-
-    cstk[0].pencolor = black;  /* set pen black */
-    cstk[0].fontfam = "times"; /* font family name */
-    cstk[0].fontopt = REGULAR; /* modifier: REGULAR, BOLD or ITALIC */
-    cstk[0].pen = P_SOLID;     /* pen pattern style, default is solid */
-    cstk[0].fill = P_NONE;
-    cstk[0].penwidth = WIDTH_NORMAL;
-}
-
-static bool is_format_truecolor_capable(int Output_lang)
-{
-    bool rv = FALSE;
-
-    if (Output_lang == GD) {
-       rv = TRUE;
-#ifdef HAVE_LIBZ
-    } else if (Output_lang == GD2) {
-       rv = TRUE;
-#endif
-#ifdef HAVE_GD_GIF
-    } else if (Output_lang == GIF) {
-       rv = FALSE;
-#endif
-#ifdef HAVE_GD_JPEG
-    } else if (Output_lang == JPEG) {
-       rv = TRUE;
-#endif
-#ifdef HAVE_GD_PNG
-    } else if (Output_lang == PNG) {
-       rv = TRUE;
-#endif
-    } else if (Output_lang == WBMP) {
-       rv = FALSE;
-#ifdef HAVE_GD_XPM
-    } else if (Output_lang == XBM) {
-       rv = FALSE;
-#endif
-    }
-    return rv;
-}
-
-static void gd_begin_graph(GVC_t * gvc, graph_t * g, box bb, point pb)
-{
-    char *bgcolor_str = NULL;
-    char *truecolor_str;
-    bool truecolor_p = FALSE;  /* try to use cheaper paletted mode */
-    bool bg_transparent_p = FALSE;
-    int bgcolor;
-
-    external_surface = gvc->job->external_surface;
-
-    init1_gd(gvc, g, bb, pb);
-
-    if (external_surface) {
-       im = (gdImagePtr)gvc->job->surface;
-    } else {
-       int width, height;
-
-        truecolor_str = agget(g, "truecolor"); /* allow user to force truecolor */
-        bgcolor_str = agget(g, "bgcolor");
-
-        if (truecolor_str && truecolor_str[0])
-           truecolor_p = mapbool(truecolor_str);
-
-        if (bgcolor_str && strcmp(bgcolor_str, "transparent") == 0) {
-           bg_transparent_p = TRUE;
-           if (is_format_truecolor_capable(Output_lang))
-               truecolor_p = TRUE;     /* force truecolor */
-        }
-
-       if (GD_has_images(g))
-           truecolor_p = TRUE; /* force truecolor */
-
-       /* device size with margins all around */
-       width = Viewport.x + 2 * Margin.x;
-       height = Viewport.y + 2 * Margin.y;
-
-        if (truecolor_p) {
-           if (Verbose)
-               fprintf(stderr, "%s: allocating a %dK TrueColor GD image\n",
-                       gvc->common.cmdname, ROUND(width * height * 4 / 1024.));
-           im = gdImageCreateTrueColor(width, height);
-        } else {
-           if (Verbose)
-               fprintf(stderr, "%s: allocating a %dK PaletteColor GD image\n",
-                       gvc->common.cmdname, ROUND(width * height / 1024.));
-           im = gdImageCreate(width, height);
-        }
-        if (!im) {
-           agerr(AGERR, "gdImageCreate returned NULL. Malloc problem?\n");
-           return;
-        }
-    }
-
-    init2_gd(im);
-
-    if (! external_surface) {
-        if (bgcolor_str && bgcolor_str[0])
-           if (bg_transparent_p)
-               bgcolor = transparent;
-           else
-               bgcolor = gd_resolve_color(bgcolor_str);
-        else
-           bgcolor = white;
-    
-        cstk[0].fillcolor = bgcolor;
-    
-        /* Blending must be off to lay a transparent bgcolor.
-           Nothing to blend with anyway. */
-        gdImageAlphaBlending(im, FALSE);
-    
-        gdImageFill(im, im->sx / 2, im->sy / 2, bgcolor);
-    
-        /* Blend everything else together,
-           especially fonts over non-transparent backgrounds */
-        gdImageAlphaBlending(im, TRUE);
-    }    
-
-#ifdef MYTRACE
-    fprintf(stderr, "gd_begin_graph\n");
-#endif
-}
-
-static void gd_end_graph(void)
-{
-    if (!im || external_surface)
-       return;
-
-/*
- * Windows will do \n -> \r\n  translations on stdout unless told otherwise.
- */
-#ifdef HAVE_SETMODE
-#ifdef O_BINARY
-    setmode(fileno(Output_file), O_BINARY);
-#endif
-#endif
-
-    /* Only save the alpha channel in outputs that support it if
-       the base color was transparent.   Otherwise everything
-       was blended so there is no useful alpha info */
-    if (im->trueColor) {
-       if (is_format_truecolor_capable(Output_lang))
-           gdImageSaveAlpha(im, TRUE);
-       else
-           gdImageTrueColorToPalette(im, 0, 256);
-    }
-    if (Output_lang == GD) {
-       gdImageGd(im, Output_file);
-#ifdef HAVE_LIBZ
-    } else if (Output_lang == GD2) {
-#define GD2_CHUNKSIZE 128
-#define GD2_RAW 1
-#define GD2_COMPRESSED 2
-       gdImageGd2(im, Output_file, GD2_CHUNKSIZE, GD2_COMPRESSED);
-#endif
-#ifdef HAVE_GD_GIF
-    } else if (Output_lang == GIF) {
-       gdImageGif(im, Output_file);
-#endif
-#ifdef HAVE_GD_JPEG
-    } else if (Output_lang == JPEG) {
-       /*
-        * Write IM to OUTFILE as a JFIF-formatted JPEG image, using
-        * quality JPEG_QUALITY.  If JPEG_QUALITY is in the range
-        * 0-100, increasing values represent higher quality but
-        * also larger image size.  If JPEG_QUALITY is negative, the
-        * IJG JPEG library's default quality is used (which should
-        * be near optimal for many applications).  See the IJG JPEG
-        * library documentation for more details.
-        */
-#define JPEG_QUALITY -1
-       gdImageJpeg(im, Output_file, JPEG_QUALITY);
-#endif
-#ifdef HAVE_GD_PNG
-    } else if (Output_lang == PNG) {
-       gdImagePng(im, Output_file);
-#endif
-    } else if (Output_lang == WBMP) {
-       /* Use black for the foreground color for the B&W wbmp image. */
-       gdImageWBMP(im, black, Output_file);
-#ifdef HAVE_GD_XPM
-    } else if (Output_lang == XBM) {
-       gdImageXbm(im, Output_file);
-#endif
-    }
-    gdImageDestroy(im);
-#ifdef MYTRACE
-    fprintf(stderr, "gd_end_graph_to_file\n");
-#endif
-}
-
-static void
-gd_begin_page(graph_t * g, point page, double scale, int rot, point offset)
-{
-    if (!im)
-       return;
-
-/*     int             page_number; */
-/*     point           sz; */
-
-    Rot = rot;
-
-/*     page_number = page.x + page.y * Pages.x + 1; */
-#ifdef MYTRACE
-    fprintf(stderr, "gd_begin_page\n");
-    fprintf(stderr, " page=%d,%d offset=%d,%d\n", page.x, page.y, offset.x,
-           offset.y);
-    fprintf(stderr, " page_number=%d\n", page_number);
-#endif
-}
-
-void gd_end_page(void)
-{
-#ifdef MYTRACE
-    fprintf(stderr, "gd_end_page\n");
-#endif
-}
-
-static void gd_begin_node(node_t * n)
-{
-    Curnode = n;
-}
-
-static void gd_end_node(void)
-{
-    Curnode = NULL;
-}
-
-static void gd_begin_context(void)
-{
-    assert(SP + 1 < MAXNEST);
-    cstk[SP + 1] = cstk[SP];
-    SP++;
-}
-
-static void gd_end_context(void)
-{
-    int psp = SP - 1;
-    assert(SP > 0);
-    SP = psp;
-}
-
-static void gd_set_font(char *fontname, double fontsize)
-{
-    context_t *cp;
-#if 0
-    char *p;
-    char *q;
-#endif
-
-    cp = &(cstk[SP]);
-    cp->fontsz = fontsize;
-#if 0
-    p = strdup(fontname);
-    if ((q = strchr(p, '-'))) {
-       *q++ = 0;
-       if (strcasecmp(q, "italic") == 0)
-           cp->fontopt = ITALIC;
-       else if (strcasecmp(q, "bold") == 0)
-           cp->fontopt = BOLD;
-    }
-#endif
-    cp->fontfam = fontname;
-}
-
-static void gd_set_pencolor(char *name)
-{
-    if (!im)
-       return;
-
-    cstk[SP].pencolor = gd_resolve_color(name);
-}
-
-static void gd_set_fillcolor(char *name)
-{
-    if (!im)
-       return;
-
-    cstk[SP].fillcolor = gd_resolve_color(name);
-}
-
-static void gd_set_style(char **s)
-{
-    char *line, *p;
-    context_t *cp;
-
-    cp = &(cstk[SP]);
-    while ((p = line = *s++)) {
-       if (streq(line, "solid"))
-           cp->pen = P_SOLID;
-       else if (streq(line, "dashed"))
-           cp->pen = P_DASHED;
-       else if (streq(line, "dotted"))
-           cp->pen = P_DOTTED;
-       else if (streq(line, "invis"))
-           cp->pen = P_NONE;
-       else if (streq(line, "bold"))
-           cp->penwidth = WIDTH_BOLD;
-       else if (streq(line, "setlinewidth")) {
-           while (*p)
-               p++;
-           p++;
-           cp->penwidth = atol(p);
-       } else if (streq(line, "filled"))
-           cp->fill = P_SOLID;
-       else if (streq(line, "unfilled"))
-           cp->fill = P_NONE;
-       else
-           agerr(AGWARN,
-                 "gd_set_style: unsupported style %s - ignoring\n", line);
-    }
-}
-
-void gd_missingfont(char *err, char *fontreq)
-{
-    static char *lastmissing = 0;
-    static int n_errors = 0;
-
-    if (n_errors >= 20)
-       return;
-    if ((lastmissing == 0) || (strcmp(lastmissing, fontreq))) {
-#if HAVE_GD_FONTCONFIG
-       agerr(AGERR, "%s : %s\n", err, fontreq);
-#else
-       char *p = getenv("GDFONTPATH");
-       if (!p)
-           p = DEFAULT_FONTPATH;
-       agerr(AGERR, "%s : %s in %s\n", err, fontreq, p);
-#endif
-       if (lastmissing)
-           free(lastmissing);
-       lastmissing = strdup(fontreq);
-       n_errors++;
-       if (n_errors >= 20)
-           agerr(AGWARN, "(font errors suppressed)\n");
-    }
-}
-
-extern gdFontPtr gdFontTiny, gdFontSmall, gdFontMediumBold, gdFontLarge, gdFontGiant;
-
-static void gd_textpara(point p, textpara_t * para)
-{
-    pointf mp, ep;
-    double fontsz;
-    gdFTStringExtra strex;
-    int pencolor;
-#ifdef HAVE_GD_FREETYPE
-    char *err;
-    int brect[8];
-#endif
-
-    if (!im)
-       return;
-
-    strex.flags = gdFTEX_RESOLUTION;
-    strex.hdpi = strex.vdpi = Dpi.x * Zoom;
-
-    if (cstk[SP].pen == P_NONE)
-       return;
-
-    pencolor = cstk[SP].pencolor;
-    if (!im->trueColor && cstk[SP].fillcolor == transparent)
-       pencolor = -pencolor;   /* disable antialiasing */
-
-    if (strstr(cstk[SP].fontfam, "/"))
-       strex.flags |= gdFTEX_FONTPATHNAME;
-    else
-       strex.flags |= gdFTEX_FONTCONFIG;
-
-    fontsz = cstk[SP].fontsz;
-
-    switch (para->just) {
-    case 'l':
-       mp.x = p.x;
-       break;
-    case 'r':
-       mp.x = p.x - para->width;
-       break;
-    default:
-    case 'n':
-       mp.x = p.x - para->width / 2;
-       break;
-    }
-    ep.y = mp.y = p.y;
-    ep.x = mp.x + para->width;
-
-    mp = gdpt(mp);
-    if (fontsz <= FONTSIZE_MUCH_TOO_SMALL) {
-       /* ignore entirely */
-    } else if (fontsz <= FONTSIZE_TOO_SMALL) {
-       /* draw line in place of text */
-       ep = gdpt(ep);
-       gdImageLine(im, ROUND(mp.x), ROUND(mp.y),
-                   ROUND(ep.x), ROUND(ep.y), cstk[SP].pencolor);
-    } else {
-#ifdef HAVE_GD_FREETYPE
-       gdFTUseFontConfig(1); /* use fontconfig if possible */
-       err = gdImageStringFTEx(im, brect, pencolor,
-                               para->fontname, fontsz, Rot ? (PI / 2) : 0,
-                               ROUND(mp.x), ROUND(mp.y), para->str, &strex);
-#if 0
-       gdImagePolygon(im, (gdPointPtr) brect, 4, cstk[SP].pencolor);
-#endif
-#if 0
-       fprintf(stderr,
-               "textpara: font=%s size=%g pos=%g,%g width=%g dpi=%d width/dpi=%g\n",
-               para->fontname, fontsz, mp.x, mp.y, (double) (brect[4] - brect[0]),
-               strex.hdpi,
-               (((double) (brect[4] - brect[0])) / strex.hdpi));
-#endif
-       if (err) {
-           /* revert to builtin fonts */
-           gd_missingfont(err, cstk[SP].fontfam);
-#endif
-           mp.y += 2;
-           if (fontsz <= 8.5) {
-               gdImageString(im, gdFontTiny,
-                             ROUND(mp.x), ROUND(mp.y - 9.),
-                             (unsigned char *) para->str, cstk[SP].pencolor);
-           } else if (fontsz <= 9.5) {
-               gdImageString(im, gdFontSmall,
-                             ROUND(mp.x), ROUND(mp.y - 12.),
-                             (unsigned char *) para->str, cstk[SP].pencolor);
-           } else if (fontsz <= 10.5) {
-               gdImageString(im, gdFontMediumBold,
-                             ROUND(mp.x), ROUND(mp.y - 13.),
-                             (unsigned char *) para->str, cstk[SP].pencolor);
-           } else if (fontsz <= 11.5) {
-               gdImageString(im, gdFontLarge,
-                             ROUND(mp.x), ROUND(mp.y - 14.),
-                             (unsigned char *) para->str, cstk[SP].pencolor);
-           } else {
-               gdImageString(im, gdFontGiant,
-                             ROUND(mp.x), ROUND(mp.y - 15.),
-                             (unsigned char *) para->str, cstk[SP].pencolor);
-           }
-#ifdef HAVE_GD_FREETYPE
-       }
-#endif
-    }
-}
-
-static void
-gd_bezier(point * A, int n, int arrow_at_start, int arrow_at_end, int filled)
-{
-    pointf p, p0, p1, V[4];
-    int i, j, step;
-    int style[20];
-    int pen, width;
-    gdImagePtr brush = NULL;
-    gdPoint F[4];
-
-    if (!im)
-       return;
-
-    if (cstk[SP].pen != P_NONE) {
-       if (cstk[SP].pen == P_DASHED) {
-           for (i = 0; i < 10; i++)
-               style[i] = cstk[SP].pencolor;
-           for (; i < 20; i++)
-               style[i] = transparent;
-           gdImageSetStyle(im, style, 20);
-           pen = gdStyled;
-       } else if (cstk[SP].pen == P_DOTTED) {
-           for (i = 0; i < 2; i++)
-               style[i] = cstk[SP].pencolor;
-           for (; i < 12; i++)
-               style[i] = transparent;
-           gdImageSetStyle(im, style, 12);
-           pen = gdStyled;
-       } else {
-           pen = cstk[SP].pencolor;
-       }
-       width = cstk[SP].penwidth * CompScale.x;
-       if (width < WIDTH_NORMAL)
-           width = WIDTH_NORMAL;  /* gd can't do thin lines */
-       gdImageSetThickness(im, width);
-       if (width > WIDTH_NORMAL) {
-           brush = gdImageCreate(width, width);
-           gdImagePaletteCopy(brush, im);
-           gdImageFilledRectangle(brush,
-                                  0, 0, width - 1, width - 1,
-                                  cstk[SP].pencolor);
-           gdImageSetBrush(im, brush);
-           if (pen == gdStyled)
-               pen = gdStyledBrushed;
-           else
-               pen = gdBrushed;
-       }
-       p.x = A[0].x;
-       p.y = A[0].y;
-       p = gdpt(p);
-       F[0].x = ROUND(p.x);
-       F[0].y = ROUND(p.y);
-       p.x = A[n-1].x;
-       p.y = A[n-1].y;
-       p = gdpt(p);
-       F[3].x = ROUND(p.x);
-       F[3].y = ROUND(p.y);
-       V[3].x = A[0].x;
-       V[3].y = A[0].y;
-       for (i = 0; i + 3 < n; i += 3) {
-           V[0] = V[3];
-           for (j = 1; j <= 3; j++) {
-               V[j].x = A[i + j].x;
-               V[j].y = A[i + j].y;
-           }
-           p0 = gdpt(V[0]);
-           for (step = 1; step <= BEZIERSUBDIVISION; step++) {
-               p1 = gdpt(Bezier
-                         (V, 3, (double) step / BEZIERSUBDIVISION, NULL,
-                          NULL));
-               gdImageLine(im, ROUND(p0.x), ROUND(p0.y), ROUND(p1.x),
-                           ROUND(p1.y), pen);
-               if (filled) {
-                   F[1].x = ROUND(p0.x);
-                   F[1].y = ROUND(p0.y);
-                   F[2].x = ROUND(p1.x);
-                   F[2].y = ROUND(p1.y);
-                   gdImageFilledPolygon(im, F, 4, cstk[SP].fillcolor);
-               }
-               p0 = p1;
-           }
-       }
-       if (brush)
-           gdImageDestroy(brush);
-    }
-}
-
-static void gd_polygon(point * A, int n, int filled)
-{
-    pointf p;
-    int i;
-    gdPoint *points;
-    int style[20];
-    int pen, width;
-    gdImagePtr brush = NULL;
-
-    if (!im)
-       return;
-
-    if (cstk[SP].pen != P_NONE) {
-       if (cstk[SP].pen == P_DASHED) {
-           for (i = 0; i < 10; i++)
-               style[i] = cstk[SP].pencolor;
-           for (; i < 20; i++)
-               style[i] = transparent;
-           gdImageSetStyle(im, style, 20);
-           pen = gdStyled;
-       } else if (cstk[SP].pen == P_DOTTED) {
-           for (i = 0; i < 2; i++)
-               style[i] = cstk[SP].pencolor;
-           for (; i < 12; i++)
-               style[i] = transparent;
-           gdImageSetStyle(im, style, 12);
-           pen = gdStyled;
-       } else {
-           pen = cstk[SP].pencolor;
-       }
-       width = cstk[SP].penwidth * CompScale.x;
-       if (width < WIDTH_NORMAL)
-           width = WIDTH_NORMAL;  /* gd can't do thin lines */
-       gdImageSetThickness(im, width);
-       /* use brush instead of Thickness to improve end butts */
-       if (width > WIDTH_NORMAL) {
-           brush = gdImageCreate(width, width);
-           gdImagePaletteCopy(brush, im);
-           gdImageFilledRectangle(brush,
-                                  0, 0, width - 1, width - 1,
-                                  cstk[SP].pencolor);
-           gdImageSetBrush(im, brush);
-           if (pen == gdStyled)
-               pen = gdStyledBrushed;
-           else
-               pen = gdBrushed;
-       }
-       points = N_GNEW(n, gdPoint);
-       for (i = 0; i < n; i++) {
-           p.x = A[i].x;
-           p.y = A[i].y;
-           p = gdpt(p);
-           points[i].x = ROUND(p.x);
-           points[i].y = ROUND(p.y);
-       }
-       if (filled) {
-           gdImageFilledPolygon(im, points, n, cstk[SP].fillcolor);
-       }
-
-       gdImagePolygon(im, points, n, pen);
-       free(points);
-       if (brush)
-           gdImageDestroy(brush);
-    }
-}
-
-static void gd_ellipse(point p, int rx, int ry, int filled)
-{
-    pointf mp;
-    int i;
-    int style[40];             /* need 2* size for arcs, I don't know why */
-    int pen, width;
-    gdImagePtr brush = NULL;
-
-    if (!im)
-       return;
-
-    if (cstk[SP].pen != P_NONE) {
-       if (cstk[SP].pen == P_DASHED) {
-           for (i = 0; i < 20; i++)
-               style[i] = cstk[SP].pencolor;
-           for (; i < 40; i++)
-               style[i] = transparent;
-           gdImageSetStyle(im, style, 40);
-           pen = gdStyled;
-       } else if (cstk[SP].pen == P_DOTTED) {
-           for (i = 0; i < 2; i++)
-               style[i] = cstk[SP].pencolor;
-           for (; i < 24; i++)
-               style[i] = transparent;
-           gdImageSetStyle(im, style, 24);
-           pen = gdStyled;
-       } else {
-           pen = cstk[SP].pencolor;
-       }
-       width = cstk[SP].penwidth * CompScale.x;
-       if (width < WIDTH_NORMAL)
-           width = WIDTH_NORMAL;  /* gd can't do thin lines */
-       gdImageSetThickness(im, width);
-       /* use brush instead of Thickness to improve outline appearance */
-       if (width > WIDTH_NORMAL) {
-           brush = gdImageCreate(width, width);
-           gdImagePaletteCopy(brush, im);
-           gdImageFilledRectangle(brush,
-                                  0, 0, width - 1, width - 1,
-                                  cstk[SP].pencolor);
-           gdImageSetBrush(im, brush);
-           if (pen == gdStyled)
-               pen = gdStyledBrushed;
-           else
-               pen = gdBrushed;
-       }
-       if (Rot) {
-           int t;
-           t = rx;
-           rx = ry;
-           ry = t;
-       }
-       mp.x = p.x;
-       mp.y = p.y;
-       mp = gdpt(mp);
-       if (filled) {
-           gdImageFilledEllipse(im, ROUND(mp.x), ROUND(mp.y),
-                                ROUND(CompScale.x * (rx + rx)),
-                                ROUND(CompScale.y * (ry + ry)),
-                                cstk[SP].fillcolor);
-       }
-       gdImageArc(im, ROUND(mp.x), ROUND(mp.y),
-                  ROUND(CompScale.x * (rx + rx)),
-                  ROUND(CompScale.y * (ry + ry)), 0, 360, pen);
-       if (brush)
-           gdImageDestroy(brush);
-    }
-}
-
-static void gd_polyline(point * A, int n)
-{
-    pointf p, p1;
-    int i;
-    int style[20];
-    int pen, width;
-    gdImagePtr brush = NULL;
-
-    if (!im)
-       return;
-
-    if (cstk[SP].pen != P_NONE) {
-       if (cstk[SP].pen == P_DASHED) {
-           for (i = 0; i < 10; i++)
-               style[i] = cstk[SP].pencolor;
-           for (; i < 20; i++)
-               style[i] = transparent;
-           gdImageSetStyle(im, style, 20);
-           pen = gdStyled;
-       } else if (cstk[SP].pen == P_DOTTED) {
-           for (i = 0; i < 2; i++)
-               style[i] = cstk[SP].pencolor;
-           for (; i < 12; i++)
-               style[i] = transparent;
-           gdImageSetStyle(im, style, 12);
-           pen = gdStyled;
-       } else {
-           pen = cstk[SP].pencolor;
-       }
-       width = cstk[SP].penwidth * CompScale.x;
-       if (width < WIDTH_NORMAL)
-           width = WIDTH_NORMAL;  /* gd can't do thin lines */
-       gdImageSetThickness(im, width);
-       if (width != WIDTH_NORMAL) {
-           brush = gdImageCreate(width, width);
-           gdImagePaletteCopy(brush, im);
-           gdImageFilledRectangle(brush,
-                                  0, 0, width - 1, width - 1,
-                                  cstk[SP].pencolor);
-           gdImageSetBrush(im, brush);
-           if (pen == gdStyled)
-               pen = gdStyledBrushed;
-           else
-               pen = gdBrushed;
-       }
-       p.x = A[0].x;
-       p.y = A[0].y;
-       p = gdpt(p);
-       for (i = 1; i < n; i++) {
-           p1.x = A[i].x;
-           p1.y = A[i].y;
-           p1 = gdpt(p1);
-           gdImageLine(im, ROUND(p.x), ROUND(p.y),
-                       ROUND(p1.x), ROUND(p1.y), pen);
-           p.x = p1.x;
-           p.y = p1.y;
-       }
-       if (brush)
-           gdImageDestroy(brush);
-    }
-}
-
-static void gd_freeimage(usershape_t *us)
-{
-    gdImageDestroy((gdImagePtr)us->data);
-}
-
-static void gd_usershape(usershape_t *us, boxf b, point *A, int n, bool filled)
-{
-    gdImagePtr im2 = NULL, im3;
-
-    if (!us->f)
-       return;
-
-    if (us->data) {
-        if (us->datafree == gd_freeimage)
-             im2 = (gdImagePtr)(us->data);  /* use cached data */
-        else {
-             us->datafree(us);        /* free incompatible cache data */
-             us->data = NULL;
-        }
-    }
-    if (!im2) { /* read file into cache */
-        fseek(us->f, 0, SEEK_SET);
-        switch (us->type) {
-#ifdef HAVE_GD_PNG
-            case FT_PNG:
-                im2 = gdImageCreateFromPng(us->f);
-                break;
-#endif
-#ifdef HAVE_GD_GIF
-            case FT_GIF:
-                im2 = gdImageCreateFromGif(us->f);
-                break;
-#endif
-#ifdef HAVE_GD_JPEG
-            case FT_JPEG:
-                im2 = gdImageCreateFromJpeg(us->f);
-                break;
-#endif
-            default:
-                im2 = NULL;
-        }
-        if (im2) {
-            us->data = (void*)im2;
-            us->datafree = gd_freeimage;
-        }
-    }
-    if (im2) {
-       if (Rot) {
-           im3 = gdImageCreate(im2->sy, im2->sx); /* scratch image for rotation */
-           gdImageCopyRotated(im3, im2, im3->sx / 2., im3->sy / 2.,
-               0, 0, im2->sx, im2->sy, Rot);
-            gdImageCopyResized(im, im3, ROUND(b.LL.x), ROUND(b.LL.y), 0, 0,
-                ROUND(b.UR.y - b.LL.y), ROUND(b.UR.x - b.LL.x), im3->sx, im3->sy);
-           gdImageDestroy(im3);
-       }
-       else {
-            gdImageCopyResized(im, im2, ROUND(b.LL.x), ROUND(b.LL.y), 0, 0,
-                ROUND(b.UR.x - b.LL.x), ROUND(b.UR.y - b.LL.y), im2->sx, im2->sy);
-       }
-    }
-}
-
-codegen_t GD_CodeGen = {
-    0,                         /* gd_reset */
-    gd_begin_job, gd_end_job,
-    gd_begin_graph, gd_end_graph,
-    gd_begin_page, gd_end_page,
-    0, /* gd_begin_layer */ 0, /* gd_end_layer */
-    0, /* gd_begin_cluster */ 0,       /* gd_end_cluster */
-    0, /* gd_begin_nodes */ 0, /* gd_end_nodes */
-    0, /* gd_begin_edges */ 0, /* gd_end_edges */
-    gd_begin_node, gd_end_node,
-    0, /* gd_begin_edge */ 0,  /* gd_end_edge */
-    gd_begin_context, gd_end_context,
-    0, /* gd_begin_anchor */ 0,        /* gd_end_anchor */
-    gd_set_font, gd_textpara,
-    gd_set_pencolor, gd_set_fillcolor, gd_set_style,
-    gd_ellipse, gd_polygon,
-    gd_bezier, gd_polyline,
-    0,                         /* bezier_has_arrows */
-    0,                         /* gd_comment */
-    gd_usershape
-};
diff --git a/lib/common/mapgen.c b/lib/common/mapgen.c
deleted file mode 100644 (file)
index 4147a58..0000000
+++ /dev/null
@@ -1,1157 +0,0 @@
-/* $Id$ $Revision$ */
-/* vim:set shiftwidth=4 ts=8: */
-
-/**********************************************************
-*      This software is part of the graphviz package      *
-*                http://www.graphviz.org/                 *
-*                                                         *
-*            Copyright (c) 1994-2004 AT&T Corp.           *
-*                and is licensed under the                *
-*            Common Public License, Version 1.0           *
-*                      by AT&T Corp.                      *
-*                                                         *
-*        Information and Software Systems Research        *
-*              AT&T Research, Florham Park NJ             *
-**********************************************************/
-
-#define NEWANCHORS 0
-
-#include "render.h"
-#include "htmltable.h"
-
-/* IMAP font modifiers */
-#define REGULAR 0
-#define BOLD            1
-#define ITALIC          2
-
-/* IMAP patterns */
-#define P_SOLID         0
-#define P_NONE  15
-#define P_DOTTED 4             /* i wasn't sure about this */
-#define P_DASHED 11            /* or this */
-
-/* IMAP bold line constant */
-#define WIDTH_NORMAL 1
-#define WIDTH_BOLD 3
-
-/* static int        N_pages; */
-/* static point    Pages; */
-static int onetime = TRUE;
-static int isLatin1;
-
-typedef struct context_t {
-    char color_ix, *fontfam, fontopt, font_was_set;
-    char pen, fill, penwidth, style_was_set;
-    double fontsz;
-} context_t;
-
-#ifdef OLD
-#define MAXNEST 4
-static context_t cstk[MAXNEST];
-static int SP;
-#endif
-
-static double Dpi;
-static double DevScale;
-static double CompScale;
-static int Rot;
-
-static point Viewport;
-static pointf GraphFocus;
-static double Zoom;
-
-/* isRect:
- * isRect function returns true when polygon has 
- * regular rectangular shape. Rectangle is regular when
- * it is not skewed and distorted and orientation is almost zero     
- */
-bool isRect(polygon_t * p)
-{
-    return (p->sides == 4 && (ROUND(p->orientation) % 90) == 0
-           && p->distortion == 0.0 && p->skew == 0.0);
-}
-
-/* pEllipse:
- * pEllipse function returns 'np' points from the circumference
- * of ellipse described by radii 'a' and 'b'. 
- * Assumes 'np' is greater than zero.
- * 'np' should be at least 4 to sample polygon from ellipse
- */
-static pointf *pEllipse(double a, double b, int np)
-{
-    double theta = 0.0;
-    double deltheta = 2 * M_PI / np;
-    int i;
-    pointf *ps;
-
-    ps = N_NEW(np, pointf);
-    for (i = 0; i < np; i++) {
-       ps[i].x = a * cos(theta);
-       ps[i].y = b * sin(theta);
-       theta += deltheta;
-    }
-    return ps;
-}
-
-static pointf mapptf(pointf p)
-{
-    pointf rv;
-
-    if (Rot == 0) {
-       rv.x = (p.x - GraphFocus.x) * CompScale + Viewport.x / 2.;
-       rv.y = -(p.y - GraphFocus.y) * CompScale + Viewport.y / 2.;
-    } else {
-       rv.x = -(p.y - GraphFocus.y) * CompScale + Viewport.x / 2.;
-       rv.y = -(p.x - GraphFocus.x) * CompScale + Viewport.y / 2.;
-    }
-    /* apply clipping */
-    if (rv.x < 0)
-       rv.x = 0;
-    if (rv.x > (double) Viewport.x)
-       rv.x = (double) (Viewport.x - 1);
-    if (rv.y < 0)
-       rv.y = 0;
-    if (rv.y > (double) Viewport.y)
-       rv.y = (double) (Viewport.y - 1);
-    return rv;
-}
-
-/*
- * isFilled function returns 1 if filled style has been set for node 'n'
- * otherwise returns 0. it accepts pointer to node_t as an argument 
- */
-static int ifFilled(node_t * n)
-{
-    char *style, *p, **pp;
-    int r = 0;
-    style = late_nnstring(n, N_style, "");
-    if (style[0]) {
-       pp = parse_style(style);
-       while ((p = *pp)) {
-           if (strcmp(p, "filled") == 0)
-               r = 1;
-           pp++;
-       }
-    }
-    return r;
-}
-
-#if ! NEWANCHORS
-static void mapOutput (map_shape_t map_shape, point* pp, int nump,
-               char* url, char *target, char *label, char *tooltip)
-{
-    int i;
-
-    if (Output_lang == IMAP && url && url[0]) {
-       switch (map_shape) {
-       case MAP_RECTANGLE:
-           fprintf(Output_file, "rectangle %s %d %d %d %d\n", url,
-               pp[0].x, pp[0].y, pp[1].x, pp[1].y);
-           break;
-       case MAP_CIRCLE:
-           fprintf(Output_file, "circle %s %d %d %d %d\n", url,
-               pp[0].x, pp[0].y, (pp[1].x+pp[0].x), pp[0].y);
-           break;
-       case MAP_POLYGON:
-           fprintf(Output_file, "poly %s", url);
-           for (i = 0; i < nump; i++)
-               fprintf(Output_file, " %d,%d", pp[i].x, pp[i].y);
-           fprintf(Output_file, "\n");
-           break;
-       default:
-           assert(0);
-           break;
-       }
-
-    } else if (Output_lang == ISMAP && url && url[0]) {
-       switch (map_shape) {
-       case MAP_RECTANGLE:
-           fprintf(Output_file, "rectangle (%d,%d) (%d,%d) %s %s\n",
-               pp[0].x, pp[0].y, pp[1].x, pp[1].y, url, label);
-           break;
-       default:
-           assert(0);
-           break;
-       }
-
-    } else if (Output_lang == CMAP || Output_lang == CMAPX) {
-       switch (map_shape) {
-       case MAP_RECTANGLE:
-           fprintf(Output_file, "<area shape=\"rect\"");
-           break;
-       case MAP_CIRCLE:
-           fprintf(Output_file, "<area shape=\"circle\"");
-           break;
-       case MAP_POLYGON:
-           fprintf(Output_file, "<area shape=\"poly\"");
-           break;
-       default:
-           assert(0);
-           break;
-       }
-       if (url && url[0])
-           fprintf(Output_file, " href=\"%s\"", xml_string(url));
-       if (target && target[0])
-           fprintf(Output_file, " target=\"%s\"", xml_string(target));
-       if (tooltip && tooltip[0])
-           fprintf(Output_file, " title=\"%s\"", xml_string(tooltip));
-       /*
-        * alt text is intended for the visually impaired, but such
-        * folk are not likely to be clicking around on a graph anyway.
-        * IE on the PC platform (but not on Macs) incorrectly
-        * uses (non-empty) alt strings instead of title strings for tooltips.
-        * To make tooltips work and avoid this IE issue,
-        * while still satisfying usability guidelines
-        * that require that there is always an alt string,
-        * we generate just an empty alt string.
-        */
-       fprintf(Output_file, " alt=\"\"");
-       fprintf(Output_file, " coords=\"");
-
-       switch (map_shape) {
-       case MAP_RECTANGLE:
-           fprintf(Output_file, "%d,%d,%d,%d\"", pp[0].x, pp[0].y, pp[1].x, pp[1].y);
-           break;
-       case MAP_CIRCLE:
-           fprintf(Output_file, "%d,%d,%d\"", pp[0].x, pp[0].y, pp[1].x);
-           break;
-       case MAP_POLYGON:
-           fprintf(Output_file, "%d,%d", pp[0].x, pp[0].y);
-           for (i = 1; i < nump; i++)
-               fprintf(Output_file, " %d,%d", pp[i].x, pp[i].y);
-           fprintf(Output_file, "\"");
-           break;
-       default:
-           break;
-       }
-       if (Output_lang == CMAPX)
-           fprintf(Output_file, " /");
-       fprintf(Output_file, ">\n");
-
-    } else if (Output_lang == POSTSCRIPT || Output_lang == PDF) {
-       if (url && url[0]) {
-           fprintf(Output_file, "[ /Rect [ %d %d %d %d ]\n"
-               "  /Border [ 0 0 0 ]\n"
-               "  /Action << /Subtype /URI /URI %s >>\n"
-               "  /Subtype /Link\n"
-               "/ANN pdfmark\n",
-               pp[0].x, pp[0].y, pp[1].x, pp[1].y, ps_string(url, isLatin1));
-       }
-    }
-}
-#endif
-
-/*
- * map_output_poly function generates the map file of requested format 
- * currently imap, cmapx, ismap, cmap, postscipt and pdf formats are supported
- * This function maps the node. 
- */
-static void
-map_output_poly(node_t * n, char *url,
-               char *target, char *label, char *tooltip, int sample)
-{
-    int sides, peri, nump, i, j, filled = 0, rect = 0, nshape;
-    pointf *ppf, *vertices, ldimen;
-    point *pp, coord;
-    map_shape_t map_shape;
-    polygon_t *poly = NULL;
-
-    /* checking shape of node */
-    nshape = shapeOf(n);
-    /* node coordinate */
-    coord = ND_coord_i(n);
-    /* checking if filled style has been set for node */
-    filled = ifFilled(n);
-
-    if (nshape == SH_POLY || nshape == SH_POINT) {
-       poly = (polygon_t *) ND_shape_info(n);
-
-       /* checking if polygon is regular rectangle */
-       if (isRect(poly) && (poly->peripheries || filled))
-           rect = 1;
-    }
-
-    /* When node has polygon shape and requested output format is imap or cmapx,
-     * we have used shape of polygon to map clickable region that is circle, 
-     * ellipse, polygon with n side, or point. For regular rectangular shape 
-     * we have use node's bounding box to map clickable region 
-     */
-    if (poly && !rect && (Output_lang == IMAP || Output_lang == CMAPX)) {
-
-       if (poly->sides < 3)
-           sides = 1;
-       else
-           sides = poly->sides;
-
-       if (poly->peripheries < 2)
-           peri = 1;
-       else
-           peri = poly->peripheries;
-
-       vertices = poly->vertices;
-
-       /* use bounding box of text label for mapping   
-        * when polygon has no peripheries and node is not filled 
-        */
-       if (poly->peripheries == 0 && !filled) {
-           map_shape = MAP_RECTANGLE;
-           nump = 2;
-           ppf = N_NEW(nump, pointf);
-           pp = N_NEW(nump, point);
-           ldimen = ND_label(n)->dimen;
-           ppf[0].x = coord.x - (ldimen.x) / 2.0;
-           ppf[0].y = coord.y + (ldimen.y) / 2.0;
-           ppf[1].x = coord.x + (ldimen.x) / 2.0;
-           ppf[1].y = coord.y - (ldimen.y) / 2.0;
-
-       } 
-       /* circle or ellipse */
-       else if (poly->sides < 3 && poly->skew == 0.0
-                   && poly->distortion == 0.0) {
-           if (poly->regular) {
-               map_shape = MAP_CIRCLE;
-               nump = 2;               /* center of circle and radius */
-               ppf = N_NEW(nump, pointf);
-               pp = N_NEW(nump, point);
-               ppf[0].x = coord.x;
-               ppf[0].y = coord.y;
-               ppf[1].x = vertices[peri - 1].x;
-               ppf[1].y = vertices[peri - 1].y;
-           }
-           else { /* ellipse is treated as polygon */
-               double a, b;
-               map_shape = MAP_POLYGON;
-               a = vertices[peri - 1].x;
-               b = vertices[peri - 1].y;
-               nump = sample;
-               ppf = pEllipse(a, b, nump);
-               pp = N_NEW(nump, point);
-               for (i = 0; i < nump; i++) {
-                   ppf[i].x += coord.x;
-                   ppf[i].y += coord.y;
-               }
-           }
-           /* all other polygonal shape */
-       } else {
-           int offset = (peri - 1)*(poly->sides);
-           map_shape = MAP_POLYGON;
-           /* distorted or skewed ellipses and circles are polygons with 120 
-             * sides. For mapping we convert them into polygon with sample sides
-            */
-           if (poly->sides == 120) {
-               int delta = 120/sample;
-               nump = sample;
-               ppf = N_NEW(nump, pointf);
-               pp = N_NEW(nump, point);
-               for (i = 0, j = 0; j < nump; i += delta, j++) {
-                   ppf[j].x = coord.x + vertices[i + offset].x;
-                   ppf[j].y = coord.y + vertices[i + offset].y;
-               }
-           } else {
-               nump = sides;
-               ppf = N_NEW(nump, pointf);
-               pp = N_NEW(nump, point);
-               for (i = 0; i < nump; i++) {
-                   ppf[i].x = coord.x + vertices[i + offset].x;
-                   ppf[i].y = coord.y + vertices[i + offset].y;
-               }
-           }
-       }
-    } else {
-       /* we have used node's bounding box to map clickable region  
-        * when requested output format is neither imap nor cmapx and for all 
-        * node shapes other than polygon ( except regular rectangle polygon ) 
-        */
-       map_shape = MAP_RECTANGLE;
-       nump = 2;
-       ppf = N_NEW(nump, pointf);
-       pp = N_NEW(nump, point);
-       ppf[0].x = ND_coord_i(n).x - ND_lw_i(n);
-       ppf[0].y = ND_coord_i(n).y + (ND_ht_i(n) / 2);
-       ppf[1].x = ND_coord_i(n).x + ND_rw_i(n);
-       ppf[1].y = ND_coord_i(n).y - (ND_ht_i(n) / 2);
-    }
-
-    /* apply scaling and translation if necessary */
-    if (Output_lang == ISMAP
-       || Output_lang == IMAP
-       || Output_lang == CMAP || Output_lang == CMAPX) {
-       for (i = 0; i < nump; i++) {
-           ppf[i] = mapptf(ppf[i]);
-       }
-    }
-
-    for (i = 0; i < nump; i++) {
-       pp[i].x = ROUND(ppf[i].x);
-       pp[i].y = ROUND(ppf[i].y);
-    }
-
-#if ! NEWANCHORS
-    mapOutput (map_shape, pp, nump, url, target, label, tooltip);
-#endif
-    free(ppf);
-    free(pp);
-}
-
-static void
-map_output_rect(pointf p1, pointf p2, char *url, char *target, char *label,
-               char *tooltip)
-{
-    pointf ppf1, ppf2;
-    point pp[2];
-    double t;
-
-    if (!(url && url[0]) && !(tooltip && tooltip[0]))
-       return;
-
-    /* apply scaling and translation if necessary */
-    if (Output_lang == ISMAP
-       || Output_lang == IMAP
-       || Output_lang == CMAP || Output_lang == CMAPX) {
-       ppf1 = mapptf(p1);
-       ppf2 = mapptf(p2);
-    } else {
-       ppf1 = p1;
-       ppf2 = p2;
-    }
-    pp[0].x = ROUND(ppf1.x);
-    pp[0].y = ROUND(ppf1.y);
-    pp[1].x = ROUND(ppf2.x);
-    pp[1].y = ROUND(ppf2.y);
-
-    /* suppress maps that are totally clipped in either x or y */
-    if (pp[0].x == pp[1].x || pp[0].y == pp[1].y)
-       return;
-
-    /* fix up coordinate order */
-    if (pp[1].x < pp[0].x) {
-       t = pp[1].x;
-       pp[1].x = pp[0].x;
-       pp[0].x = t;
-    }
-    if (pp[1].y < pp[0].y) {
-       t = pp[1].y;
-       pp[1].y = pp[0].y;
-       pp[0].y = t;
-    }
-#if ! NEWANCHORS
-    mapOutput (MAP_RECTANGLE, pp, 2, url, target, label, tooltip);
-#endif
-}
-
-/* radius of mouse-sensitive region around a point */
-#define FUZZ 3
-static void
-map_output_fuzzy_point(pointf p, char *url, char *target, char *label,
-                      char *tooltip)
-{
-    pointf p1, p2;
-
-    p1.x = p.x - FUZZ;
-    p1.y = p.y - FUZZ;
-    p2.x = p.x + FUZZ;
-    p2.y = p.y + FUZZ;
-
-    map_output_rect(p1, p2, url, target, label, tooltip);
-}
-
-static void map_reset(void)
-{
-    onetime = TRUE;
-}
-
-static void init_imap(void)
-{
-#ifdef OLD
-    SP = 0;
-    cstk[0].color_ix = 0;      /* IMAP color index 0-7 */
-    cstk[0].fontfam = "Times"; /* font family name */
-    cstk[0].fontopt = REGULAR; /* modifier: REGULAR, BOLD or ITALIC */
-    cstk[0].pen = P_SOLID;     /* pen pattern style, default is sold */
-    cstk[0].fill = P_NONE;
-    cstk[0].penwidth = WIDTH_NORMAL;
-#endif
-}
-
-static void doHTMLdata(htmldata_t * dp, point p, void *obj)
-{
-    char *url = NULL, *target = NULL, *title = NULL;
-    pointf p1, p2;
-    int havetitle = 0;
-
-    if ((url = dp->href) && url[0]) {
-       switch (agobjkind(obj)) {
-       case AGGRAPH:
-           url = strdup_and_subst_graph(url, (graph_t *) obj);
-           break;
-       case AGNODE:
-           url = strdup_and_subst_node(url, (node_t *) obj);
-           break;
-       case AGEDGE:
-           url = strdup_and_subst_edge(url, (edge_t *) obj);
-           break;
-       }
-    }
-    target = dp->target;
-    if ((title = dp->title) && title[0]) {
-       havetitle++;
-       switch (agobjkind(obj)) {
-       case AGGRAPH:
-           title = strdup_and_subst_graph(title, (graph_t *) obj);
-           break;
-       case AGNODE:
-           title = strdup_and_subst_node(title, (node_t *) obj);
-           break;
-       case AGEDGE:
-           title = strdup_and_subst_edge(title, (edge_t *) obj);
-           break;
-       }
-    }
-    if (url || title) {
-       p1.x = p.x + dp->box.LL.x;
-       p1.y = p.y + dp->box.LL.y;
-       p2.x = p.x + dp->box.UR.x;
-       p2.y = p.y + dp->box.UR.y;
-       map_output_rect(p1, p2, url, target, "", title);
-    }
-    free(url);
-    free(title);
-}
-
-/* forward declaration */
-static void doHTMLcell(htmlcell_t * cp, point p, void *obj);
-
-static void doHTMLtbl(htmltbl_t * tbl, point p, void *obj)
-{
-    htmlcell_t **cells = tbl->u.n.cells;
-    htmlcell_t *cp;
-
-    while ((cp = *cells++))
-       doHTMLcell(cp, p, obj);
-    if (tbl->data.href)
-       doHTMLdata(&tbl->data, p, obj);
-}
-
-static void doHTMLcell(htmlcell_t * cp, point p, void *obj)
-{
-    if (cp->child.kind == HTML_TBL)
-       doHTMLtbl(cp->child.u.tbl, p, obj);
-    if (cp->data.href)
-       doHTMLdata(&cp->data, p, obj);
-}
-
-static void doHTMLlabel(htmllabel_t * lbl, point p, void *obj)
-{
-    if (lbl->kind == HTML_TBL) {
-       doHTMLtbl(lbl->u.tbl, p, obj);
-    }
-}
-
-static void
-map_begin_job(FILE * ofp, graph_t * g, char **lib, char *user,
-             char *info[], point pages)
-{
-    /* Pages = pages; */
-    /* N_pages = pages.x * pages.y; */
-    if (Output_lang == IMAP) {
-       fprintf(Output_file, "base referer\n");
-    } else if (Output_lang == ISMAP) {
-/*             fprintf(Output_file,"base referer\n"); */
-    } else if (Output_lang == CMAP || Output_lang == CMAPX) {
-/*             fprintf(Output_file,"base referer\n"); */
-    } else if (Output_lang == POSTSCRIPT || Output_lang == PDF) {
-/*             fprintf(Output_file,"base referer\n"); */
-    }
-    isLatin1 = (GD_charset(g) == CHAR_LATIN1);
-}
-
-static void map_begin_graph(GVC_t * gvc, graph_t * g, box bb, point pb)
-{
-    Dpi = GD_drawing(g)->dpi;
-    if (Dpi < 1.0)
-       Dpi = DEFAULT_DPI;
-    DevScale = Dpi / POINTS_PER_INCH;
-
-    Viewport.x = gvc->job->width;
-    Viewport.y = gvc->job->height;
-    if (Viewport.x) {
-       Zoom = gvc->job->zoom;
-       GraphFocus = gvc->job->focus;
-    } else {
-       Viewport.x =
-           (bb.UR.x - bb.LL.x + 2 * GD_drawing(g)->margin.x) * DevScale +
-           2;
-       Viewport.y =
-           (bb.UR.y - bb.LL.y + 2 * GD_drawing(g)->margin.y) * DevScale +
-           2;
-       GraphFocus.x = (GD_bb(g).UR.x - GD_bb(g).LL.x) / 2.;
-       GraphFocus.y = (GD_bb(g).UR.y - GD_bb(g).LL.y) / 2.;
-       Zoom = 1.0;
-    }
-    CompScale = Zoom * DevScale;
-
-    if (onetime) {
-       init_imap();
-       onetime = FALSE;
-    }
-}
-
-static graph_t *Root_Graph;
-static char *Default_URL;
-
-static void
-map_begin_page(graph_t * g, point page, double scale, int rot,
-              point offset)
-{
-    char *url, *name;
-
-    Rot = rot;
-    name = xml_string(g->name);
-
-    if (Output_lang == CMAPX) {
-       fprintf(Output_file, "<map id=\"%s\" name=\"%s\">\n", name, name);
-    }
-    Root_Graph = g;
-    Default_URL = NULL;
-    if (((url = agget(g, "href")) && url[0])
-       || ((url = agget(g, "URL")) && url[0])) {
-       if (Output_lang == IMAP) {
-           fprintf(Output_file, "default %s\n", url);
-       } else if (Output_lang == ISMAP) {
-           fprintf(Output_file, "default %s %s\n", url, g->name);
-       } else if (Output_lang == CMAP || Output_lang == CMAPX) {
-           Default_URL = url;
-       }
-    }
-
-}
-
-static void map_end_page(void)
-{
-    pointf Default_p1, Default_p2;
-    char *Default_label;
-    graph_t *g = Root_Graph;
-
-    if (GD_label(g) && GD_label(g)->html)
-       doHTMLlabel(GD_label(g)->u.html, GD_label(g)->p, (void *) g);
-    if (Default_URL) {
-       Default_URL = strdup_and_subst_graph(Default_URL, g);
-       Default_label = g->name;
-       Default_p1.x = GD_bb(g).LL.x;
-       Default_p1.y = GD_bb(g).LL.y;
-       Default_p2.x = GD_bb(g).UR.x;
-       Default_p2.y = GD_bb(g).UR.y;
-       map_output_rect(Default_p1, Default_p2, Default_URL, "",
-                       Default_label, "");
-       free(Default_URL);
-    }
-    if (Output_lang == CMAPX) {
-       fprintf(Output_file, "</map>\n");
-    }
-}
-
-void map_begin_cluster(graph_t * g)
-{
-    char *s, *url = NULL, *target = NULL, *title = NULL, *tooltip = NULL,
-       *m_url = NULL, *m_target = NULL, *m_tooltip = NULL;
-    pointf p1, p2;
-
-    if (GD_label(g)) {
-       if (GD_label(g)->html)
-           doHTMLlabel(GD_label(g)->u.html, GD_label(g)->p, (void *) g);
-       title = GD_label(g)->text;
-    }
-    if (((s = agget(g, "href")) && s[0])
-       || ((s = agget(g, "URL")) && s[0]))
-       m_url = url = strdup_and_subst_graph(s, g);
-    if ((s = agget(g, "target")) && s[0])
-       m_target = target = strdup_and_subst_graph(s, g);
-    if ((s = agget(g, "tooltip")) && s[0])
-       m_tooltip = tooltip = strdup_and_subst_graph(s, g);
-    else
-       tooltip = title;
-    if (url || m_tooltip) {
-       p1.x = GD_bb(g).LL.x;
-       p1.y = GD_bb(g).LL.y;
-       p2.x = GD_bb(g).UR.x;
-       p2.y = GD_bb(g).UR.y;
-       map_output_rect(p1, p2, url, target, title, tooltip);
-    }
-    free(m_target);
-    free(m_tooltip);
-    free(m_url);
-}
-
-void map_begin_node(node_t * n)
-{
-    char *s, *url = NULL, *target = NULL, *tooltip = NULL,
-       *m_url = NULL, *m_target = NULL, *m_tooltip = NULL;
-    
-    if (ND_label(n)->html)
-       doHTMLlabel(ND_label(n)->u.html, ND_coord_i(n), (void *) n);
-    if (((s = agget(n, "href")) && s[0]) || ((s = agget(n, "URL")) && s[0]))
-       m_url = url = strdup_and_subst_node(s, n);
-    if ((s = agget(n, "target")) && s[0])
-       m_target = target = strdup_and_subst_node(s, n);
-    if ((s = agget(n, "tooltip")) && s[0])
-       m_tooltip = tooltip = strdup_and_subst_node(s, n);
-    else
-       tooltip = ND_label(n)->text;
-
-    if (url || m_tooltip) {
-       int sample = 0;
-       char *p = agget(n, "samplepoints");
-       if (p)
-           sample = atoi(p);
-       /* We want at least 4 points. For server-side maps, at most 100
-         * points are allowed. To simplify things to fit with the 120 points
-         * used for skewed ellipses, we set the bound at 60.
-         */
-       if ((sample < 4) || (sample > 60))
-           sample = DFLT_SAMPLE;
-       map_output_poly(n, url, target, ND_label(n)->text, tooltip, sample);
-    }
-
-    free(m_url);
-    free(m_target);
-    free(m_tooltip);
-}
-
-#define HW 2.0   /* maximum distance away from line, in points */
-
-/* check_control_points:
- * check_control_points function checks the size of quadrilateral
- * formed by four control points
- * returns 1 if four points are in line (or close to line)
- * else return 0
- */
-static int check_control_points(pointf *cp)
-{
-    double dis1 = ptToLine2 (cp[0], cp[3], cp[1]);
-    double dis2 = ptToLine2 (cp[0], cp[3], cp[2]);
-    if (dis1 < HW*HW && dis2 < HW*HW)
-       return 1;
-    else 
-       return 0;
-}
-
-#ifdef DEBUG
-void psmapOutput (point* ps, int n)
-{
-   int i;
-   fprintf (stdout, "newpath %d %d moveto\n", ps[0].x, ps[0].y);
-   for (i=1; i < n; i++)
-       fprintf (stdout, "%d %d lineto\n", ps[i].x, ps[i].y);
-   fprintf (stdout, "closepath stroke\n");
-}
-#endif
-
-typedef struct segitem_s {
-    pointf p;
-    struct segitem_s* next;
-} segitem_t;
-
-#define MARK_FIRST_SEG(L) ((L)->next = (segitem_t*)1)
-#define FIRST_SEG(L) ((L)->next == (segitem_t*)1)
-#define INIT_SEG(P,L) {(L)->next = 0; (L)->p = P;} 
-
-static segitem_t*
-appendSeg (pointf p, segitem_t* lp)
-{
-    segitem_t* s = GNEW(segitem_t);
-    INIT_SEG (p, s);
-    lp->next = s;
-    return s;
-}
-
-/* map_bspline_poly:
- * Output the polygon determined by the n points in p1, followed
- * by the n points in p2 in reverse order. Assumes n <= 50.
- *
- * Note: when using psmapOutput for debugging, remove the calls to
- * mapptf, since for postscript the necessary parameters aren't defined and
- * mapptf always returns (0,0).
- */
-static void 
-map_bspline_poly(int n, pointf* p1, pointf* p2, 
-                 char *url, char* target, char* tooltip)
-{
-    int i;
-    pointf ppf;
-    point rp[100];
-    int last = 2*n-1;
-
-    for (i = 0; i < n; i++) {
-       ppf = mapptf(p1[i]);
-       rp[i].x = ROUND(ppf.x);
-       rp[i].y = ROUND(ppf.y);
-    }
-    for (i = 0; i < n; i++) {
-       ppf = mapptf(p2[i]);
-       rp[last-i].x = ROUND(ppf.x);
-       rp[last-i].y = ROUND(ppf.y);
-    }
-    mapOutput (MAP_POLYGON, rp, last+1, url, target, NULL, tooltip);
-#ifdef DEBUG
-    psmapOutput (rp, last+1);
-#endif
-}
-/* approx_bezier:
- * Approximate Bezier by line segments. If the four points are
- * almost colinear, as determined by check_control_points, we store
- * the segment cp[0]-cp[3]. Otherwise we split the Bezier into 2
- * and recurse. 
- * Since 2 contiguous segments share an endpoint, we actually store
- * the segments as a list of points.
- * New points are appended to the list given by lp. The tail of the
- * list is returned.
- */ 
-static segitem_t* 
-approx_bezier (pointf *cp, segitem_t* lp)
-{
-    pointf sub_curves[8];
-
-    if (check_control_points(cp)) {
-       if (FIRST_SEG (lp)) INIT_SEG (cp[0], lp);
-       lp = appendSeg (cp[3], lp);
-    }
-    else {
-       Bezier (cp, 3, 0.5, sub_curves, sub_curves+4);
-       lp = approx_bezier (sub_curves, lp);
-       lp = approx_bezier (sub_curves+4, lp);
-    }
-    return lp;
-}
-
-/* bisect:
- * Return the angle of the bisector between the two rays
- * pp-cp and cp-np. The bisector returned is always to the
- * left of pp-cp-np.
- */
-static double
-bisect (pointf pp, pointf cp, pointf np)
-{
-  double ang, theta, phi;
-  theta = atan2(np.y - cp.y,np.x - cp.x);
-  phi = atan2(pp.y - cp.y,pp.x - cp.x);
-  ang = theta - phi;
-  if (ang > 0) ang -= 2*M_PI;
-
-  return (phi + ang/2.0);
-}
-
-/* mkSegPts:
- * Determine polygon points related to 2 segments prv-cur and cur-nxt.
- * The points lie on the bisector of the 2 segments, passing through cur,
- * and distance HW from cur. The points are stored in p1 and p2.
- * If p1 is NULL, we use the normal to cur-nxt.
- * If p2 is NULL, we use the normal to prv-cur.
- * Assume at least one of prv or nxt is non-NULL.
- */
-static void
-mkSegPts (segitem_t* prv, segitem_t* cur, segitem_t* nxt, 
-       pointf* p1, pointf* p2)
-{
-    pointf cp, pp, np;
-    double theta, delx, dely;
-    pointf p;
-
-    cp = cur->p;
-    /* if prv or nxt are NULL, use the one given to create a collinear
-     * prv or nxt. This could be more efficiently done with special case code, 
-     * but this way is more uniform.
-     */
-    if (prv) {
-       pp = prv->p;
-       if (nxt)
-           np = nxt->p;
-       else {
-           np.x = 2*cp.x - pp.x;
-           np.y = 2*cp.y - pp.y;
-       }
-    }
-    else {
-       np = nxt->p;
-       pp.x = 2*cp.x - np.x;
-       pp.y = 2*cp.y - np.y;
-    }
-    theta = bisect(pp,cp,np);
-    delx = HW*cos(theta);
-    dely = HW*sin(theta);
-    p.x = cp.x + delx;
-    p.y = cp.y + dely;
-    *p1 = p;
-    p.x = cp.x - delx;
-    p.y = cp.y - dely;
-    *p2 = p;
-}
-
-/* map_output_bspline:
- * Construct and output a closed polygon approximating the input
- * B-spline bp. We do this by first approximating bp by a sequence
- * of line segments. We then use the sequence of segments to determine
- * the polygon.
- * In cmapx, polygons are limited to 100 points, so we output polygons
- * in chunks of 100.
- */
-static void
-map_output_bspline (bezier* bp, char *url, char *target, char *tooltip)
-{
-    segitem_t* segl = GNEW(segitem_t);
-    segitem_t* segp = segl;
-    segitem_t* segprev;
-    segitem_t* segnext;
-    int nc, j, k, cnt;
-    pointf pts[4];
-    pointf pt1[50], pt2[50];
-
-    MARK_FIRST_SEG(segl);
-    nc = (bp->size - 1)/3; /* nc is number of bezier curves */
-    for (j = 0; j < nc; j++) { 
-       for (k = 0; k < 4; k++) {
-           pts[k].x = (double)bp->list[3*j + k].x;
-           pts[k].y = (double)bp->list[3*j + k].y;
-       }
-       segp = approx_bezier (pts, segp);
-    }
-
-    segp = segl;
-    segprev = 0;
-    cnt = 0;
-    while (segp) {
-       segnext = segp->next;
-       mkSegPts (segprev, segp, segnext, pt1+cnt, pt2+cnt);
-       cnt++;
-       if ((segnext == NULL) || (cnt == 50)) {
-           map_bspline_poly (cnt, pt1, pt2, url, target, tooltip);
-           pt1[0] = pt1[cnt-1];
-           pt2[0] = pt2[cnt-1];
-           cnt = 1;
-       }
-       segprev = segp;
-       segp = segnext;
-    }
-
-    /* free segl */
-    while (segl) {
-       segp = segl->next;
-       free (segl);
-       segl = segp;
-    }
-}
-
-void map_begin_edge(edge_t* e)
-{
-    /* strings */
-    char *s, *label, *taillabel, *headlabel, *url, *tailurl, *headurl,
-       *target, *tailtarget, *headtarget, *tooltip, *tailtooltip, *headtooltip,
-       *m_url = NULL, *m_tailurl = NULL, *m_headurl = NULL,
-       *m_target = NULL, *m_tailtarget = NULL, *m_headtarget = NULL,
-       *m_tooltip = NULL, *m_tailtooltip = NULL, *m_headtooltip = NULL;
-
-    textlabel_t *lab = NULL, *tlab = NULL, *hlab = NULL;
-    pointf p, p1, p2;
-    bezier bz;
-
-    /*  establish correct text for main edge label, URL, tooltip */
-    label = NULL;
-    if ((lab = ED_label(e))) {
-       if (lab->html)
-           doHTMLlabel(lab->u.html, lab->p, (void *) e);
-       label = lab->text;
-    }
-    url = NULL;
-    if (((s = agget(e, "href")) && s[0]) || ((s = agget(e, "URL")) && s[0]))
-       m_url = url = strdup_and_subst_edge(s, e);
-    tooltip = label;
-    if ((s = agget(e, "tooltip")) && s[0])
-       m_tooltip = tooltip = strdup_and_subst_edge(s, e);
-    target = NULL;
-    if ((s = agget(e, "target")) && s[0])
-       m_target = target = strdup_and_subst_edge(s, e);
-
-    /*  establish correct text for tail label, URL, tooltip */
-    taillabel = label;
-    if ((tlab = ED_tail_label(e))) {
-       if (tlab->html)
-           doHTMLlabel(tlab->u.html, tlab->p, (void *) e);
-       taillabel = tlab->text;
-    }
-    tailurl = url;
-    if (((s = agget(e, "tailhref")) && s[0]) || ((s = agget(e, "tailURL")) && s[0]))
-       m_tailurl = tailurl = strdup_and_subst_edge(s, e);
-    tailtooltip = taillabel;
-    if ((s = agget(e, "tailtooltip")) && s[0])
-       m_tailtooltip = tailtooltip = strdup_and_subst_edge(s, e);
-    tailtarget = target;
-    if ((s = agget(e, "tailtarget")) && s[0])
-       m_tailtarget = tailtarget = strdup_and_subst_edge(s, e);
-
-    /*  establish correct text for head label, URL, tooltip */
-    headlabel = label;
-    if ((hlab = ED_head_label(e))) {
-       if (hlab->html)
-           doHTMLlabel(hlab->u.html, hlab->p, (void *) e);
-       headlabel = hlab->text;
-    }
-    headurl = url;
-    if (((s = agget(e, "headhref")) && s[0]) || ((s = agget(e, "headURL")) && s[0]))
-       m_headurl = headurl = strdup_and_subst_edge(s, e);
-    headtooltip = headlabel;
-    if ((s = agget(e, "headtooltip")) && s[0])
-       m_headtooltip = headtooltip = strdup_and_subst_edge(s, e);
-    headtarget = target;
-    if ((s = agget(e, "headtarget")) && s[0])
-       m_headtarget = headtarget = strdup_and_subst_edge(s, e);
-
-    /* strings are now set  - next we map the three labels */
-
-    if (lab && (url || m_tooltip)) {
-       /* map a rectangle around the edge label */
-       p1.x = lab->p.x - lab->dimen.x / 2;
-       p1.y = lab->p.y - lab->dimen.y / 2;
-       p2.x = lab->p.x + lab->dimen.x / 2;
-       p2.y = lab->p.y + lab->dimen.y / 2;
-       map_output_rect(p1, p2, url, target, label, tooltip);
-    }
-
-    if (tlab && (tailurl || m_tailtooltip)) {
-       /* map a rectangle around the edge taillabel */
-       p1.x = tlab->p.x - tlab->dimen.x / 2;
-       p1.y = tlab->p.y - tlab->dimen.y / 2;
-       p2.x = tlab->p.x + tlab->dimen.x / 2;
-       p2.y = tlab->p.y + tlab->dimen.y / 2;
-       map_output_rect(p1, p2, tailurl, tailtarget, taillabel, tailtooltip);
-    }
-
-    if (hlab && (headurl || m_headtooltip)) {
-       /* map a rectangle around the edge headlabel */
-       p1.x = hlab->p.x - hlab->dimen.x / 2;
-       p1.y = hlab->p.y - hlab->dimen.y / 2;
-       p2.x = hlab->p.x + hlab->dimen.x / 2;
-       p2.y = hlab->p.y + hlab->dimen.y / 2;
-       map_output_rect(p1, p2, headurl, headtarget, headlabel, headtooltip);
-    }
-
-    /* finally we map the two ends of the edge where they touch nodes */
-
-    /* process intersecion with tail node */
-    if (ED_spl(e) && (tailurl || m_tailtooltip)) {
-       bz = ED_spl(e)->list[0];
-       if (bz.sflag) {
-           /* Arrow at start of splines */
-           p.x = bz.sp.x;
-           p.y = bz.sp.y;
-       } else {
-           /* No arrow at start of splines */
-           p.x = bz.list[0].x;
-           p.y = bz.list[0].y;
-       }
-       map_output_fuzzy_point(p, tailurl, tailtarget, taillabel, tailtooltip);
-    }
-
-    /* process intersection with head node */
-    if (ED_spl(e) && (headurl || m_headtooltip)) {
-       bz = ED_spl(e)->list[ED_spl(e)->size - 1];
-       if (bz.eflag) {
-           /* Arrow at end of splines */
-           p.x = bz.ep.x;
-           p.y = bz.ep.y;
-       } else {
-           /* No arrow at end of splines */
-           p.x = bz.list[bz.size - 1].x;
-           p.y = bz.list[bz.size - 1].y;
-       }
-       map_output_fuzzy_point(p, headurl, headtarget, headlabel, headtooltip);
-    }
-    
-    /* map the edge (spline) for format IMAP or CMAPX */  
-    
-    if (ED_spl(e) && (url || m_tooltip) && (Output_lang == IMAP || Output_lang == CMAPX)) 
-    {
-       int i, ns;
-       splines *spl;
-       
-       spl = ED_spl(e);
-       ns = spl->size; /* number of splines */
-       for (i = 0; i < ns; i++) {
-           map_output_bspline (spl->list+i, url, target, tooltip);
-       }
-    }
-    
-    free(m_url);
-    free(m_target);
-    free(m_tailtarget);
-    free(m_headtarget);
-    free(m_tailurl);
-    free(m_headurl);
-    free(m_tooltip);
-    free(m_tailtooltip);
-    free(m_headtooltip);
-}
-
-static void map_begin_anchor(char *href, char *tooltip, char *target)
-{
-#if NEWANCHORS
-    fprintf(Output_file, "<area");
-    if (href && href[0])
-       fprintf(Output_file, " href=\"%s\"", xml_string(href));
-    if (tooltip && tooltip[0])
-       fprintf(Output_file, " title=\"%s\"", xml_string(tooltip));
-    if (target && target[0])
-       fprintf(Output_file, " target=\"%s\"", xml_string(target));
-#endif
-}
-
-static void map_end_anchor(void)
-{
-#if NEWANCHORS
-    fprintf(Output_file, "/>\n");
-#endif
-}
-     
-static void map_polygon(point * A, int n, int filled)
-{
-#if NEWANCHORS
-    int i;
-    point p;
-
-    fprintf(Output_file, " shape=\"polygon\" coords=\"");
-    for (i = 0; i < n; i++) {
-       p = mappt(A[i]);
-       fprintf(Output_file, "%d,%d,", p.x, p.y);
-    }
-    p = mappt(A[0]);
-    fprintf(Output_file, "%d,%d\"", p.x, p.y);
-#endif
-}
-
-static void map_ellipse(point p, int rx, int ry, int filled)
-{
-#if NEWANCHORS
-    fprintf(Output_file, " shape=\"ellipse\"");
-#endif
-}
-
-
-codegen_t MAP_CodeGen = {
-    map_reset,
-    map_begin_job, 0,          /* map_end_job */
-    map_begin_graph, 0,                /* map_end_graph */
-    map_begin_page, map_end_page,
-    0, /* map_begin_layer */ 0,        /* map_end_layer */
-    map_begin_cluster, 0,      /* map_end_cluster */
-    0, /* map_begin_nodes */ 0,        /* map_end_nodes */
-    0, /* map_begin_edges */ 0,        /* map_end_edges */
-    map_begin_node, 0,         /* map_end_node */
-    map_begin_edge, 0,         /* map_end_edge */
-    0, /* map_begin_context */ 0,      /* map_end_context */
-    map_begin_anchor, map_end_anchor,
-    0, /* map_set_font */ 0,   /* map_textpara */
-    0, /* map_set_color */ 0, /* map_set_color */ 0,   /* map_set_style */
-    map_ellipse, map_polygon,
-    0, /* map_bezier */ 0,     /* map_polyline */
-    0,                         /* bezier_has_arrows */
-    0,                         /* map_comment */
-    0                          /* map_usershape */
-};
diff --git a/lib/common/psgen.c b/lib/common/psgen.c
deleted file mode 100644 (file)
index 2c082ba..0000000
+++ /dev/null
@@ -1,707 +0,0 @@
-/* $Id$ $Revision$ */
-/* vim:set shiftwidth=4 ts=8: */
-
-/**********************************************************
-*      This software is part of the graphviz package      *
-*                http://www.graphviz.org/                 *
-*                                                         *
-*            Copyright (c) 1994-2004 AT&T Corp.           *
-*                and is licensed under the                *
-*            Common Public License, Version 1.0           *
-*                      by AT&T Corp.                      *
-*                                                         *
-*        Information and Software Systems Research        *
-*              AT&T Research, Florham Park NJ             *
-**********************************************************/
-
-/*
-    J$: added `pdfmark' URL embedding.  PostScript rendered from
-        dot files with URL attributes will get active PDF links
-        from Adobe's Distiller.
- */
-#define        PDFMAX  14400           /*  Maximum size of PDF page  */
-
-#include "render.h"
-#include "agxbuf.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-#if HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-
-#ifdef HAVE_LIBGD
-#include "gd.h"
-#endif
-
-#ifndef MSWIN32
-#include <unistd.h>
-#endif
-
-extern void epsf_define(FILE * of);
-extern void epsf_emit_body(usershape_t *us, FILE *of);
-extern char *ps_string(char *ins, int latin);
-
-static int N_pages, Cur_page;
-/* static      point   Pages; */
-static box PB;
-static box DBB;
-static int onetime = TRUE;
-static int isLatin1;
-static char setupLatin1;
-static node_t *Curnode;                /* for user shapes */
-
-static char *Fill = "fill\n";
-static char *Stroke = "stroke\n";
-static char *Newpath_Moveto = "newpath %d %d moveto\n";
-static char **U_lib;
-
-typedef struct grcontext_t {
-    char *pencolor, *fillcolor, *font;
-    char invis;
-    double size;
-} grcontext_t;
-
-#define STACKSIZE 8
-static grcontext_t S[STACKSIZE];
-static int SP = 0;
-
-static void ps_reset(void)
-{
-    onetime = TRUE;
-}
-
-static void
-ps_begin_job(FILE * ofp, graph_t * g, char **lib, char *user, char *info[],
-            point pages)
-{
-    /* Pages = pages; */
-    U_lib = lib;
-    /* wrong when drawing more than one than one graph - use (atend) */
-    N_pages = pages.x * pages.y;
-    if (onetime) {
-        Cur_page = 0;
-        fprintf(Output_file, "%%!PS-Adobe-2.0\n");
-        fprintf(Output_file, "%%%%Creator: %s version %s (%s)\n",
-               info[0], info[1], info[2]);
-        fprintf(Output_file, "%%%%For: %s\n", user);
-        fprintf(Output_file, "%%%%Title: %s\n", g->name);
-        fprintf(Output_file, "%%%%Pages: (atend)\n");
-       if (Show_boxes == NULL)
-           fprintf(Output_file, "%%%%BoundingBox: (atend)\n");
-       fprintf(Output_file, "%%%%EndComments\nsave\n");
-    }
-
-    /* remainder is emitted by first begin_graph */
-}
-
-static void ps_end_job(void)
-{
-    fprintf(Output_file, "%%%%Trailer\n");
-    fprintf(Output_file, "%%%%Pages: %d\n", Cur_page);
-    if (Show_boxes == NULL)
-       fprintf(Output_file, "%%%%BoundingBox: %d %d %d %d\n",
-               DBB.LL.x, DBB.LL.y, DBB.UR.x, DBB.UR.y);
-    fprintf(Output_file, "end\nrestore\n");
-    fprintf(Output_file, "%%%%EOF\n");
-    setupLatin1 = FALSE;
-}
-
-static void ps_comment(char *str)
-{
-    fprintf(Output_file, "%% %s\n", str);
-}
-
-static void ps_begin_graph(GVC_t * gvc, graph_t * g, box bb, point pb)
-{
-    char *s;
-
-    PB = bb;
-    if (onetime) {
-       cat_preamble(gvc->job, U_lib);
-       epsf_define(Output_file);
-       if (Show_boxes) {
-           char* args[2];
-           args[0] = Show_boxes[0];
-           args[1] = NULL;
-           cat_libfile(Output_file, NULL, args);
-        }
-
-       /*  Set base URL for relative links (for Distiller >= 3.0)  */
-       if (((s = agget(g, "href")) && s[0])
-           || ((s = agget(g, "URL")) && s[0])) {
-           fprintf(Output_file,
-                   "[ {Catalog} << /URI << /Base (%s) >> >>\n"
-                   "/PUT pdfmark\n", s);
-       }
-    }
-    
-    isLatin1 = (GD_charset(g) == CHAR_LATIN1);
-    if (isLatin1 && !setupLatin1) {
-       fprintf(Output_file, "setupLatin1\n");  /* as defined in ps header */
-       setupLatin1 = TRUE;
-    }
-}
-
-static void ps_end_graph(void)
-{
-    onetime = FALSE;
-}
-
-static void
-ps_begin_page(graph_t * g, point page, double scale, int rot, point offset)
-{
-    point sz;
-    box pbr;
-
-    sz = sub_points(PB.UR,PB.LL);
-    Cur_page++;
-    fprintf(Output_file, "%%%%Page: %d %d\n", Cur_page, Cur_page);
-
-    if (rot) {
-       pbr.LL.x = PB.LL.y;
-       pbr.LL.y = PB.LL.x;
-       pbr.UR.x = PB.UR.y;
-       pbr.UR.y = PB.UR.x;
-    }
-    else {
-       pbr = PB;
-    }
-    if (onetime) {
-       DBB = pbr;
-    }
-    else {
-       EXPANDBB(DBB, pbr);
-    }
-    if (Show_boxes == NULL) {
-       fprintf(Output_file, "%%%%PageBoundingBox: %d %d %d %d\n",
-               pbr.LL.x, pbr.LL.y, pbr.UR.x, pbr.UR.y);
-    }
-    
-    fprintf(Output_file, "%%%%PageOrientation: %s\n",
-           (rot ? "Landscape" : "Portrait"));
-    if (Output_lang == PDF)
-       fprintf(Output_file, "<< /PageSize [%d %d] >> setpagedevice\n",
-           pbr.UR.x, pbr.UR.y);
-    if (Show_boxes == NULL) {
-       fprintf(Output_file, "gsave\n%d %d %d %d boxprim clip newpath\n",
-           pbr.LL.x, pbr.LL.y, pbr.UR.x, pbr.UR.y);
-    }
-    fprintf(Output_file, "%d %d translate\n", PB.LL.x, PB.LL.y);
-    if (rot)
-        fprintf(Output_file, "gsave %d %d translate %d rotate\n",
-                PB.UR.x - PB.LL.x, 0, rot);
-    fprintf(Output_file, "%d %d %d beginpage\n", page.x, page.y, N_pages);
-    if (rot)
-        fprintf(Output_file, "grestore\n");
-    fprintf(Output_file, "%g %g set_scale\n", scale, scale);
-    fprintf(Output_file, "%d %d translate %d rotate\n",
-           offset.x, offset.y, rot);
-    assert(SP == 0);
-    S[SP].font = S[SP].pencolor = S[SP].fillcolor = "";
-    S[SP].size = 0.0;
-
-    /*  Define the size of the PS canvas  */
-    if (Output_lang == PDF) {
-       if (sz.x > PDFMAX || sz.y > PDFMAX)
-           agerr(AGWARN,
-                 "canvas size (%d,%d) exceeds PDF limit (%d)\n"
-                 "\t(suggest setting a bounding box size, see dot(1))\n",
-                 sz.x, sz.y, PDFMAX);
-       fprintf(Output_file, "[ /CropBox [%d %d %d %d] /PAGE pdfmark\n",
-               pbr.LL.x, pbr.LL.y, pbr.UR.x, pbr.UR.y);
-    }
-}
-
-static void ps_end_page(void)
-{
-    if (Show_boxes)
-       cat_libfile(Output_file, NULL, Show_boxes+1);
-
-    /* the showpage is really a no-op, but at least one PS processor
-     * out there needs to see this literal token.  endpage does the real work.
-     */
-    fprintf(Output_file, "endpage\nshowpage\ngrestore\n");
-    fprintf(Output_file, "%%%%PageTrailer\n");
-    fprintf(Output_file, "%%%%EndPage: %d\n", Cur_page);
-    assert(SP == 0);
-}
-
-static void ps_begin_layer(char *s, int n, int Nlayers)
-{
-    fprintf(Output_file, "%d %d setlayer\n", n, Nlayers);
-}
-
-static void ps_begin_cluster(graph_t * g)
-{
-    fprintf(Output_file, "%% %s\n", g->name);
-
-    /*  Embed information for Distiller to generate hyperlinked PDF  */
-    map_begin_cluster(g);
-}
-
-static void ps_begin_node(node_t * n)
-{
-    Curnode = n;
-
-    /*  Embed information for Distiller to generate hyperlinked PDF  */
-    map_begin_node(n);
-}
-
-static void ps_begin_edge(edge_t * e)
-{
-    /*  Embed information for Distiller, so it can generate hyperactive PDF  */
-    map_begin_edge(e);
-}
-
-
-static void ps_begin_context(void)
-{
-    fprintf(Output_file, "gsave 10 dict begin\n");
-    if (SP == STACKSIZE - 1)
-       agerr(AGWARN, "psgen stk ovfl\n");
-    else {
-       SP++;
-       S[SP] = S[SP - 1];
-    }
-}
-
-static void ps_end_context(void)
-{
-    if (SP == 0)
-       agerr(AGWARN, "psgen stk undfl\n");
-    else
-       SP--;
-    fprintf(Output_file, "end grestore\n");
-}
-
-static void ps_set_font(char *name, double size)
-{
-    if (strcmp(S[SP].font, name) || (size != S[SP].size)) {
-       fprintf(Output_file, "%.2f /%s set_font\n", size, name);
-       S[SP].font = name;
-       S[SP].size = size;
-    }
-}
-
-static void ps_set_color(char *name)
-{
-    static char *op[] = { "graph", "node", "edge", "sethsb" };
-    gvcolor_t color;
-
-    colorxlate(name, &color, HSV_DOUBLE);
-    fprintf(Output_file, "%.3f %.3f %.3f %scolor\n",
-           color.u.HSV[0], color.u.HSV[1], color.u.HSV[2], op[Obj]);
-}
-
-static void ps_set_pencolor(char *name)
-{
-    if (streq(name, "transparent"))
-       S[SP].pencolor = "";
-    else if (strcmp(name, S[SP].pencolor)) {
-       ps_set_color(name);     /* change pen color immediately */
-       S[SP].pencolor = name;
-    }
-}
-
-static void ps_set_fillcolor(char *name)
-{
-    /* defer changes to fill color to shape */
-    if (streq(name, "transparent"))
-       S[SP].fillcolor = "";
-    else
-       S[SP].fillcolor = name;
-}
-
-static void ps_set_style(char **s)
-{
-    char *line, *p;
-
-    while ((p = line = *s++)) {
-       while (*p)
-           p++;
-       p++;
-       while (*p) {
-           fprintf(Output_file, "%s ", p);
-           while (*p)
-               p++;
-           p++;
-       }
-       if (streq(line, "invis"))
-           S[SP].invis = TRUE;
-       fprintf(Output_file, "%s\n", line);
-    }
-}
-
-static void ps_textpara(point p, textpara_t * para)
-{
-    double adj;
-
-    if (S[SP].invis)
-       return;
-    if (*S[SP].pencolor == '\0')
-       return;
-    if (para->xshow) {
-       switch (para->just) {
-       case 'l':
-           break;
-       case 'r':
-           p.x -= para->width;
-           break;
-       default:
-       case 'n':
-           p.x -= para->width / 2;
-           break;
-       }
-       fprintf(Output_file, "%d %d moveto\n%s\n[%s]\nxshow\n",
-               p.x, p.y, ps_string(para->str,isLatin1), para->xshow);
-    } else {
-       switch (para->just) {
-       case 'l':
-           adj = 0.0;
-           break;
-       case 'r':
-           adj = -1.0;
-           break;
-       default:
-       case 'n':
-           adj = -0.5;
-           break;
-       }
-       fprintf(Output_file, "%d %d moveto %.1f %.1f %s alignedtext\n",
-               p.x, p.y, para->width, adj, ps_string(para->str,isLatin1));
-    }
-}
-
-static void
-ps_bezier(point * A, int n, int arrow_at_start, int arrow_at_end, int filled)
-{
-    int j;
-    if (S[SP].invis)
-       return;
-    if (filled && *S[SP].fillcolor) {
-       ps_set_color(S[SP].fillcolor);
-       fprintf(Output_file, Newpath_Moveto, A[0].x, A[0].y);
-       for (j = 1; j < n; j += 3)
-           fprintf(Output_file, "%d %d %d %d %d %d curveto\n",
-               A[j].x, A[j].y, A[j + 1].x, A[j + 1].y, A[j + 2].x,
-               A[j + 2].y);
-       fprintf(Output_file, "closepath\n");
-       fprintf(Output_file, Fill);
-       if (*S[SP].pencolor)
-           ps_set_color(S[SP].pencolor);
-    }
-    if (*S[SP].pencolor == '\0')
-       return;
-    if (arrow_at_start || arrow_at_end)
-       agerr(AGERR, "ps_bezier illegal arrow args\n");
-    fprintf(Output_file, Newpath_Moveto, A[0].x, A[0].y);
-    for (j = 1; j < n; j += 3)
-       fprintf(Output_file, "%d %d %d %d %d %d curveto\n",
-               A[j].x, A[j].y, A[j + 1].x, A[j + 1].y, A[j + 2].x,
-               A[j + 2].y);
-    fprintf(Output_file, Stroke);
-}
-
-static void ps_polygon(point * A, int n, int filled)
-{
-    int j;
-
-    if (S[SP].invis)
-       return;
-    if (filled && *S[SP].fillcolor) {
-       ps_set_color(S[SP].fillcolor);
-       fprintf(Output_file, Newpath_Moveto, A[0].x, A[0].y);
-       for (j = 1; j < n; j++)
-           fprintf(Output_file, "%d %d lineto\n", A[j].x, A[j].y);
-       fprintf(Output_file, "closepath\n");
-       fprintf(Output_file, Fill);
-       if (*S[SP].pencolor)
-           ps_set_color(S[SP].pencolor);
-    }
-    if (*S[SP].pencolor == '\0')
-       return;
-    fprintf(Output_file, Newpath_Moveto, A[0].x, A[0].y);
-    for (j = 1; j < n; j++)
-       fprintf(Output_file, "%d %d lineto\n", A[j].x, A[j].y);
-    fprintf(Output_file, "closepath\n");
-    fprintf(Output_file, Stroke);
-}
-
-static void ps_ellipse(point p, int rx, int ry, int filled)
-{
-    if (S[SP].invis)
-       return;
-    if (filled && *S[SP].fillcolor) {
-       ps_set_color(S[SP].fillcolor);
-       fprintf(Output_file, "%d %d %d %d ellipse_path\n", p.x, p.y, rx,
-               ry);
-       fprintf(Output_file, Fill);
-       if (*S[SP].pencolor)
-           ps_set_color(S[SP].pencolor);
-    }
-    if (*S[SP].pencolor == '\0')
-       return;
-    if (!filled || (filled && strcmp(S[SP].fillcolor, S[SP].pencolor))) {
-       fprintf(Output_file, "%d %d %d %d ellipse_path\n", p.x, p.y, rx,
-               ry);
-       fprintf(Output_file, Stroke);
-    }
-}
-
-static void ps_polyline(point * A, int n)
-{
-    int j;
-
-    if (S[SP].invis)
-       return;
-    if (*S[SP].pencolor == '\0')
-       return;
-    fprintf(Output_file, Newpath_Moveto, A[0].x, A[0].y);
-    for (j = 1; j < n; j++)
-       fprintf(Output_file, "%d %d lineto\n", A[j].x, A[j].y);
-    fprintf(Output_file, Stroke);
-}
-
-#ifdef HAVE_LIBGD
-static void writePSBitmap (gdImagePtr im, boxf bb)
-{
-    int X = im->sx, Y = im->sy, x, y, px;
-
-    fprintf(Output_file, "gsave\n");
-
-    /* this sets the position of the image */
-    fprintf(Output_file, "%g %g translate %% lower-left coordinate\n", bb.LL.x, bb.LL.y);
-
-    /* this sets the rendered size to fit the box */
-    fprintf(Output_file,"%g %g scale\n", bb.UR.x - bb.LL.x, bb.UR.y - bb.LL.y);
-
-    /* xsize ysize bits-per-sample [matrix] */
-    fprintf(Output_file, "%d %d 8 [%d 0 0 %d 0 %d]\n", X, Y, X, -Y, Y);
-
-    fprintf(Output_file, "{<\n");
-    if (im->trueColor) {
-        for (y = 0; y < Y; y++) {
-           for (x = 0; x < X; x++) {
-               px = gdImageTrueColorPixel(im, x, y);
-               fprintf(Output_file, "%02x%02x%02x",
-                   gdTrueColorGetRed(px),
-                   gdTrueColorGetGreen(px),
-                   gdTrueColorGetBlue(px));
-           }
-           fprintf(Output_file, "\n");
-        }
-    }
-    else {
-        for (y = 0; y < Y; y++) {
-           for (x = 0; x < X; x++) {
-               px = gdImagePalettePixel(im, x, y);
-               fprintf(Output_file, "%02x%02x%02x",
-                   im->red[px],
-                   im->green[px],
-                   im->blue[px]);
-           }
-           fprintf(Output_file, "\n");
-        }
-    }
-
-    fprintf(Output_file, ">}\n");
-    fprintf(Output_file, "false 3 colorimage\n");
-
-    fprintf(Output_file, "grestore\n");
-}
-#endif
-
-static void ps_freeimage_gd (usershape_t *us)
-{
-#ifdef HAVE_LIBGD
-    gdImageDestroy((gdImagePtr)us->data);
-#endif
-}
-
-static void ps_freeimage_ps (usershape_t *us)
-{
-#if HAVE_SYS_MMAN_H
-    munmap(us->data, us->datasize);
-#else
-    free(us->data);
-#endif
-}
-
-/* ps_usershape:
- * Images for postscript are complicated by the old epsf shape, as
- * well as user-defined shapes using postscript code.
- * If the name is custom, we look for the image stored in the
- * current node's shapefile attribute.
- * Else we see if name is a user-defined postscript function
- * Else we assume name is the name of the image. This occurs when
- * the image is part of an html label.
- */
-static void ps_usershape(usershape_t *us, boxf b, point *A, int n, bool filled)
-{
-    int j;
-    shape_desc *shape;
-
-    assert(us);
-    assert(us->name);
-
-    if (S[SP].invis)
-       return;
-
-    if (!us->f) {
-        if ((shape = (shape_desc*)us->data)) { /* if we found the shape in a library then us->data was set */
-           if (filled) {
-               ps_begin_context();
-               ps_set_color(S[SP].fillcolor);
-               fprintf(Output_file, "[ ");
-               for (j = 0; j < n; j++)
-                   fprintf(Output_file, "%d %d ", A[j].x, A[j].y);
-               fprintf(Output_file, "%d %d ", A[0].x, A[0].y);
-               fprintf(Output_file, "]  %d true %s\n", n, us->name);
-               ps_end_context();
-           }
-           fprintf(Output_file, "[ ");
-           for (j = 0; j < n; j++)
-               fprintf(Output_file, "%d %d ", A[j].x, A[j].y);
-           fprintf(Output_file, "%d %d ", A[0].x, A[0].y);
-           fprintf(Output_file, "]  %d false %s\n", n, us->name);
-        }
-       return;  
-    }
-
-    if (us->data) {
-       if ((us->datafree != ps_freeimage_gd)
-               && (us->datafree != ps_freeimage_ps))  {
-           us->datafree(us);        /* free incompatible cache data */
-           us->data = NULL;
-           us->datafree = NULL;
-           us->datasize = 0;
-       }
-    }
-
-    if (! us->data) { /* read file into cache */
-       int fd = fileno(us->f);
-       struct stat statbuf;
-
-        fseek(us->f, 0, SEEK_SET);
-        switch (us->type) {
-#ifdef HAVE_LIBGD
-#ifdef HAVE_GD_PNG
-            case FT_PNG:
-                us->data = (void*)gdImageCreateFromPng(us->f);
-                us->datafree = ps_freeimage_gd;
-                break;
-#endif
-#ifdef HAVE_GD_GIF
-            case FT_GIF:
-                us->data = (void*)gdImageCreateFromGif(us->f);
-                us->datafree = ps_freeimage_gd;
-                break;
-#endif
-#ifdef HAVE_GD_JPEG
-            case FT_JPEG:
-                us->data = (void*)gdImageCreateFromJpeg(us->f);
-                us->datafree = ps_freeimage_gd;
-                break;
-#endif
-#endif
-           case FT_PS:
-           case FT_EPS:
-                fstat(fd, &statbuf);
-                us->datasize = statbuf.st_size;
-#if HAVE_SYS_MMAN_H
-                us->data = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
-#else
-               us->data = malloc(statbuf.st_size);
-               read(fd, us->data, statbuf.st_size);
-#endif
-                us->datafree = ps_freeimage_ps;
-                us->must_inline = true;
-               break;
-            default:
-               break;
-        }
-    }
-
-    if (us->data) {
-        boxf bb;
-        pointf p;
-        double pw, ph, tw, th;
-        double scalex, scaley;
-        int i;
-        /* compute bb of polygon */
-        P2PF(A[0],p);
-        bb.LL = bb.UR = p;
-        for (i = 1; i < n; i++) {
-            P2PF(A[i],p);
-            EXPANDBP(bb, p);
-        }
-        pw = b.UR.x - b.LL.x;
-        ph = b.UR.y - b.LL.y;
-        scalex = pw / (double) (us->w);
-        scaley = ph / (double) (us->h);
-        /* keep aspect ratio fixed by just using the smaller scale */
-        if (scalex < scaley) {
-             tw = us->w * scalex;
-             th = us->h * scalex;
-         } else {
-             tw = us->w * scaley;
-             th = us->h * scaley;
-         }
-        /* if image is smaller than target area then center it */
-        if (tw < pw) {
-            b.LL.x += (pw - tw) / 2.0;
-            b.UR.x -= (pw - tw) / 2.0;
-        }
-        if (th < ph) {
-            b.LL.y += (ph - th) / 2.0;
-            b.UR.y -= (ph - th) / 2.0;
-       }
-       switch (us->type) {
-#ifdef HAVE_LIBGD
-       case FT_PNG:
-        case FT_GIF:
-        case FT_JPEG:
-           writePSBitmap ((gdImagePtr)us->data, bb);
-           break;
-#endif
-       case FT_PS:
-       case FT_EPS:
-           ps_begin_context();
-           fprintf(Output_file, "%d %d translate newpath\n",
-               ROUND(bb.LL.x - us->x), ROUND(bb.LL.y - us->y));
-           if (us->must_inline)
-               epsf_emit_body(us, Output_file);
-           else
-               fprintf(Output_file, "user_shape_%d\n", us->macro_id);
-           ps_end_context();
-           break;
-       default:
-           agerr(AGERR, "usershape %s is not supported in PostScript output\n", us->name);
-           break;
-       }
-    }
-}
-
-codegen_t PS_CodeGen = {
-    ps_reset,
-    ps_begin_job, ps_end_job,
-    ps_begin_graph, ps_end_graph,
-    ps_begin_page, ps_end_page,
-    ps_begin_layer, 0,         /* ps_end_layer */
-    ps_begin_cluster, 0,       /* ps_end_cluster */
-    0, /* ps_begin_nodes */ 0, /* ps_end_nodes */
-    0, /* ps_begin_edges */ 0, /* ps_end_edges */
-    ps_begin_node, 0,          /* ps_end_node */
-    ps_begin_edge, 0,          /* ps_end_edge */
-    ps_begin_context, ps_end_context,
-    0, /* ps_begin_anchor */ 0,        /* ps_end_anchor */
-    ps_set_font, ps_textpara,
-    ps_set_pencolor, ps_set_fillcolor, ps_set_style,
-    ps_ellipse, ps_polygon,
-    ps_bezier, ps_polyline,
-    0,                         /* bezier_has_arrows */
-    ps_comment,
-    ps_usershape
-};
diff --git a/lib/common/svggen.c b/lib/common/svggen.c
deleted file mode 100644 (file)
index 671a220..0000000
+++ /dev/null
@@ -1,944 +0,0 @@
-/* $Id$ $Revision$ */
-/* vim:set shiftwidth=4 ts=8: */
-
-/**********************************************************
-*      This software is part of the graphviz package      *
-*                http://www.graphviz.org/                 *
-*                                                         *
-*            Copyright (c) 1994-2004 AT&T Corp.           *
-*                and is licensed under the                *
-*            Common Public License, Version 1.0           *
-*                      by AT&T Corp.                      *
-*                                                         *
-*        Information and Software Systems Research        *
-*              AT&T Research, Florham Park NJ             *
-**********************************************************/
-
-
-/* this is a rough start at a working SVG driver.
-you can get image nodes by setting a node's
- [shape=webimage,shapefile="http://www.your.site.com/path/image.png"]
-(of course can also be a file: reference if you run locally.
-which causes a warning (FIX that) but the back end turns this into
-a custom shape.  you can also set
-[ href = "http://some.place.com/whatever" ] 
-to get clickable nodes (and edges for that matter).
-
-some major areas needing work:
-0. fonts including embedded font support.  is SVG finished in this area?
-1. styles, including dotted/dashed lines, also "style function"
-passthrough in SVG similar to what we have in postscript.
-2. look at what happens in landscape mode, pagination? etc.
-3. allow arbitrary user transforms via graph "style" attribute.
-4. javascript hooks.  particularly, look at this in the context
-of SVG animation for dynadag output (n.b. dynadag only in alpha release)
-5. image node improvement, e.g. set clip path to node boundary, and
-support scaling with fixed aspect ratio (this feature seems to be
-broken in the current Adobe SVG plugin for Windows).  
-6. can we support arbitrary HTML for node contents?
-7. encode abstract graph as interleaved XML in some sort of graph XML dialect?
-8. accessibility features
-9. embed directions about getting plugin, if not present in browser
-
-Stephen North
-north@research.att.com
-*/
-
-#include <ctype.h>
-#include "render.h"
-#ifdef HAVE_LIBZ
-#include "zlib.h"
-#endif
-#ifdef MSWIN32
-#include <io.h>
-#include <stdarg.h>
-#endif
-
-/* SVG font modifiers */
-#define REGULAR 0
-#define BOLD   1
-#define ITALIC 2
-
-/* SVG patterns */
-#define P_SOLID        0
-#define P_NONE  15
-#define P_DOTTED 4             /* i wasn't sure about this */
-#define P_DASHED 11            /* or this */
-
-/* SVG bold line constant */
-#define WIDTH_NORMAL 1
-#define WIDTH_BOLD 3
-
-#ifdef TESTFAILED
-/* sodipodi doesn't understand style sheets */
-#define DEFAULT_STYLE\
-"<style type='text/css'>\n" \
-"<![CDATA[\n" \
-".node ellipse {fill:none;filter:URL(#MyFilter)}\n" \
-".node polygon {fill:none;filter:URL(#MyFilter)}\n" \
-".cluster polygon {fill:none;filter:URL(#MyFilter)}\n" \
-".edge path {fill:none;stroke:black;stroke-width:1;}\n" \
-"text {font-family:Times;stroke:black;stroke-width:.4;font-size:12px}\n" \
-"]]>\n" \
-"</style>"
-
-#define DEFAULT_FILTER \
-"<filter id=\"MyFilter\" x=\"-20%\" y=\"-20%\" width=\"160%\" height=\"160%\">\n" \
-"<feGaussianBlur in=\"SourceAlpha\" stdDeviation=\"4\" result=\"blur\"/>\n" \
-"<feOffset in=\"blur\" dx=\"4\" dy=\"4\" result=\"offsetBlur\"/>\n" \
-"<feSpecularLighting in=\"blur\" surfaceScale=\"5\" specularConstant=\"1\"\n" \
-"specularExponent=\"10\" style=\"lighting-color:white\" result=\"specOut\">\n" \
-"<fePointLight x=\"-5000\" y=\"-10000\" z=\"20000\"/>\n" \
-"</feSpecularLighting>\n" \
-"<feComposite in=\"specOut\" in2=\"SourceAlpha\" operator=\"in\" result=\"specOut\"/>\n" \
-"<feComposite in=\"SourceGraphic\" in2=\"specOut\" operator=\"arithmetic\"\n" \
-"k1=\"0\" k2=\"1\" k3=\"1\" k4=\"0\" result=\"litPaint\"/>\n" \
-"<feMerge>\n" \
-"<feMergeNode in=\"offsetBlur\"/>\n" \
-"<feMergeNode in=\"litPaint\"/>\n" \
-"</feMerge>\n" \
-"</filter>"
-#endif
-
-#define SCALE 1
-
-/* SVG dash array */
-static char *sdarray = "5,2";
-/* SVG dot array */
-static char *sdotarray = "1,5";
-
-static int N_pages;
-/* static      point   Pages; */
-static int onetime = TRUE;
-static int isLatin1;
-
-static pointf CompScale;
-static double FontScale;
-static int Rot;
-
-static point Margin;
-static point Viewport;
-static pointf GraphFocus;
-static double Zoom;
-
-static node_t *Curnode;
-
-typedef struct context_t {
-    char *pencolor, *fillcolor, *fontfam, fontopt, font_was_set;
-    char pen, fill, penwidth, style_was_set;
-    double fontsz;
-} context_t;
-
-#define MAXNEST 4
-static context_t cstk[MAXNEST];
-static int SP;
-
-static char *op[] = { "graph", "node", "edge", "graph" };
-
-#ifdef HAVE_LIBZ
-static gzFile Zfile;
-#endif
-
-static void svg_fputs(char *s)
-{
-    int len;
-
-    len = strlen(s);
-    switch (Output_lang) {
-    case SVGZ:
-#ifdef HAVE_LIBZ
-       gzwrite(Zfile, s, (unsigned) len);
-       break;
-#else
-       agerr(AGERR, "No libz support.\n");
-       exit(1);
-#endif
-    case SVG:
-       fwrite(s, sizeof(char), (unsigned) len, Output_file);
-       break;
-    }
-}
-
-/* svg_printf:
- * Note that this function is unsafe due to the fixed buffer size.
- * It should only be used when the caller is sure the input will not
- * overflow the buffer. In particular, it should be avoided for
- * input coming from users. Also, if vsnprintf is available, the
- * code should check for return values to use it safely.
- */
-static void svg_printf(const char *format, ...)
-{
-    char buf[BUFSIZ];
-    va_list argp;
-
-    va_start(argp, format);
-#ifdef HAVE_VSNPRINTF
-    (void) vsnprintf(buf, sizeof(buf), format, argp);
-#else
-    (void) vsprintf(buf, format, argp);
-#endif
-    va_end(argp);
-
-    svg_fputs(buf);
-}
-
-static void svg_reset(void)
-{
-    onetime = TRUE;
-}
-
-static void init_svg(void)
-{
-    SP = 0;
-    cstk[0].pencolor = DEFAULT_COLOR;  /* SVG pencolor */
-    cstk[0].fillcolor = "";    /* SVG fillcolor */
-    cstk[0].fontfam = DEFAULT_FONTNAME;        /* font family name */
-    cstk[0].fontsz = DEFAULT_FONTSIZE; /* font size */
-    cstk[0].fontopt = REGULAR; /* modifier: REGULAR, BOLD or ITALIC */
-    cstk[0].pen = P_SOLID;     /* pen pattern style, default is solid */
-    cstk[0].fill = P_NONE;
-    cstk[0].penwidth = WIDTH_NORMAL;
-}
-
-static point svgpt(point p)
-{
-    point rv;
-
-    if (Rot == 0) {
-        rv.x = (p.x - GraphFocus.x) * CompScale.x + Viewport.x / 2. + Margin.x;
-        rv.y = -(p.y - GraphFocus.y) * CompScale.y + Viewport.y / 2. + Margin.y;
-    } else {
-        rv.x = -(p.y - GraphFocus.y) * CompScale.x + Viewport.x / 2. + Margin.x;
-        rv.y = -(p.x - GraphFocus.x) * CompScale.y + Viewport.y / 2. + Margin.y;
-    }
-    return rv;
-}
-
-static void svgbzptarray(point * A, int n)
-{
-    int i;
-    point p;
-    char *c;
-
-    c = "M";                   /* first point */
-    for (i = 0; i < n; i++) {
-       p = svgpt(A[i]);
-       svg_printf("%s%d,%d", c, p.x, p.y);
-       if (i == 0)
-           c = "C";            /* second point */
-       else
-           c = " ";            /* remaining points */
-    }
-}
-
-static int svg_comparestr(const void *s1, const void *s2)
-{
-    return strcmp(*(char **) s1, *(char **) s2);
-}
-
-char *svg_resolve_color(char *name, int useKnown)
-{
-/* color names from http://www.w3.org/TR/SVG/types.html */
-/* NB.  List must be LANG_C sorted */
-    static char *svg_known_colors[] = {
-       "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure",
-       "beige", "bisque", "black", "blanchedalmond", "blue",
-       "blueviolet", "brown", "burlywood",
-       "cadetblue", "chartreuse", "chocolate", "coral",
-       "cornflowerblue", "cornsilk", "crimson", "cyan",
-       "darkblue", "darkcyan", "darkgoldenrod", "darkgray",
-       "darkgreen", "darkgrey", "darkkhaki", "darkmagenta",
-       "darkolivegreen", "darkorange", "darkorchid", "darkred",
-       "darksalmon", "darkseagreen", "darkslateblue", "darkslategray",
-       "darkslategrey", "darkturquoise", "darkviolet", "deeppink",
-       "deepskyblue", "dimgray", "dimgrey", "dodgerblue",
-       "firebrick", "floralwhite", "forestgreen", "fuchsia",
-       "gainsboro", "ghostwhite", "gold", "goldenrod", "gray",
-       "green", "greenyellow", "grey",
-       "honeydew", "hotpink", "indianred",
-       "indigo", "ivory", "khaki",
-       "lavender", "lavenderblush", "lawngreen", "lemonchiffon",
-       "lightblue", "lightcoral", "lightcyan", "lightgoldenrodyellow",
-       "lightgray", "lightgreen", "lightgrey", "lightpink",
-       "lightsalmon", "lightseagreen", "lightskyblue",
-       "lightslategray", "lightslategrey", "lightsteelblue",
-       "lightyellow", "lime", "limegreen", "linen",
-       "magenta", "maroon", "mediumaquamarine", "mediumblue",
-       "mediumorchid", "mediumpurple", "mediumseagreen",
-       "mediumslateblue", "mediumspringgreen", "mediumturquoise",
-       "mediumvioletred", "midnightblue", "mintcream",
-       "mistyrose", "moccasin",
-       "navajowhite", "navy", "oldlace",
-       "olive", "olivedrab", "orange", "orangered", "orchid",
-       "palegoldenrod", "palegreen", "paleturquoise",
-       "palevioletred", "papayawhip", "peachpuff", "peru", "pink",
-       "plum", "powderblue", "purple",
-       "red", "rosybrown", "royalblue",
-       "saddlebrown", "salmon", "sandybrown", "seagreen", "seashell",
-       "sienna", "silver", "skyblue", "slateblue", "slategray",
-       "slategrey", "snow", "springgreen", "steelblue",
-       "tan", "teal", "thistle", "tomato", "turquoise",
-       "violet",
-       "wheat", "white", "whitesmoke",
-       "yellow", "yellowgreen",
-    };
-
-    static char buf[SMALLBUF];
-    char *tok;
-    gvcolor_t color;
-
-    tok = canontoken(name);
-    if (!useKnown || (bsearch(&tok, svg_known_colors,
-                             sizeof(svg_known_colors) / sizeof(char *),
-                             sizeof(char *), svg_comparestr) == NULL)) {
-       /* if tok was not found in known_colors */
-       if (streq(tok, "transparent")) {
-           tok = "none";
-       } else {
-           colorxlate(name, &color, RGBA_BYTE);
-           sprintf(buf, "#%02x%02x%02x",
-                   color.u.rgba[0], color.u.rgba[1], color.u.rgba[2]);
-           tok = buf;
-       }
-    }
-    return tok;
-}
-
-static void svg_font(context_t * cp)
-{
-    char *color, buf[BUFSIZ];
-    int needstyle = 0;
-
-    strcpy(buf, " style=\"");
-    if (strcasecmp(cp->fontfam, DEFAULT_FONTNAME)) {
-       sprintf(buf + strlen(buf), "font-family:%s;", cp->fontfam);
-       needstyle++;
-    }
-    if (cp->fontsz != DEFAULT_FONTSIZE) {
-       sprintf(buf + strlen(buf), "font-size:%.2fpt;", cp->fontsz * FontScale);
-       needstyle++;
-    }
-    color = svg_resolve_color(cp->pencolor, 1);
-    if ((strcasecmp(color, "black"))) {
-       sprintf(buf + strlen(buf), "fill:%s;", color);
-       needstyle++;
-    }
-    if (needstyle) {
-       strcat(buf, "\"");
-       svg_fputs(buf);
-    }
-}
-
-
-static void svg_grstyle(context_t * cp, int filled)
-{
-    svg_fputs(" style=\"");
-    if (filled)
-       svg_printf("fill:%s;", svg_resolve_color(cp->fillcolor, 1));
-    else
-       svg_fputs("fill:none;");
-    svg_printf("stroke:%s;", svg_resolve_color(cp->pencolor, 1));
-    if (cp->penwidth != WIDTH_NORMAL)
-       svg_printf("stroke-width:%d;", cp->penwidth);
-    if (cp->pen == P_DASHED) {
-       svg_printf("stroke-dasharray:%s;", sdarray);
-    } else if (cp->pen == P_DOTTED) {
-       svg_printf("stroke-dasharray:%s;", sdotarray);
-    }
-    svg_fputs("\"");
-}
-
-/* xml_namestring:
- * Return xml_string applied to input.
- * If input is Latin1, first translate to UTF8
- */
-static char*
-xml_namestring (char* str)
-{
-    if (isLatin1) {
-       char* s = latin1ToUTF8 (str);
-       str = xml_string(s);
-       free (s);
-    }
-    else
-       str = xml_string(str);
-    return str;
-}
-
-/* svg_name_fputs:
- * Do fputs on input.
- * If input is Latin1, first translate to UTF8.
- */
-static void
-svg_name_fputs (char* str)
-{
-    if (isLatin1) {
-       char* s = latin1ToUTF8 (str);
-       svg_fputs(s);
-       free (s);
-    }
-    else
-       svg_fputs(str);
-}
-
-static void svg_comment(char *str)
-{
-
-    svg_fputs("<!-- ");
-    svg_fputs(xml_namestring(str));
-    svg_fputs(" -->\n");
-}
-
-/* isAscii:
- * Return true if all bytes in string are ascii.
- */
-static int isAscii (char* s)
-{
-  int c;
-
-  while ((c = *s++) && isascii(c)) ;
-  return (c == '\0');
-}
-
-static void
-svg_begin_job(FILE * ofp, graph_t * g, char **lib, char *user,
-             char *info[], point pages)
-{
-    char *s;
-#if HAVE_LIBZ
-    int fd;
-#endif
-
-    switch (Output_lang) {
-    case SVGZ:
-#if HAVE_LIBZ
-       fd = dup(fileno(Output_file));  /* open dup so can gzclose 
-                                          independent of FILE close */
-#ifdef HAVE_SETMODE
-#ifdef O_BINARY
-       /*
-        * Windows will do \n -> \r\n  translations on
-        * stdout unless told otherwise.
-        */
-       setmode(fd, O_BINARY);
-#endif
-#endif
-
-       Zfile = gzdopen(fd, "wb");
-       if (!Zfile) {
-           agerr(AGERR, "Error opening compressed output file\n");
-           exit(1);
-       }
-       break;
-#else
-       agerr(AGERR, "No libz support.\n");
-       exit(1);
-#endif
-    case SVG:
-       break;
-    }
-
-/*     Pages = pages; */
-    N_pages = pages.x * pages.y;
-    svg_fputs
-       ("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
-    if ((s = agget(g, "stylesheet")) && s[0]) {
-       svg_fputs("<?xml-stylesheet href=\"");
-       svg_fputs(s);
-       svg_fputs("\" type=\"text/css\"?>\n");
-    }
-    svg_fputs("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\"\n");
-    svg_fputs
-       (" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\"");
-    /* This is to work around a bug in the SVG 1.0 DTD */
-    svg_fputs
-       (" [\n <!ATTLIST svg xmlns:xlink CDATA #FIXED \"http://www.w3.org/1999/xlink\">\n]");
-    svg_fputs(">\n<!-- Generated by ");
-    svg_fputs(xml_string(info[0]));
-    svg_fputs(" version ");
-    svg_fputs(xml_string(info[1]));
-    svg_fputs(" (");
-    svg_fputs(xml_string(info[2]));
-    /* We assume utf-8 output. If user name contains any non-ascii bytes,
-     * we don't put it in the output. Obviously, this could be made more
-     * sophisticated, like checking that the name is utf-8 or doing some
-     * conversion. 
-     */
-    if (isAscii(user)) {
-       svg_fputs(")\n     For user: ");
-       svg_fputs(xml_string(user));
-       svg_fputs(" -->\n");
-    }
-    else
-       svg_fputs(") -->\n");
-}
-
-static void svg_begin_graph(GVC_t * gvc, graph_t * g, box bb, point pb)
-{
-    Viewport.x = gvc->job->width;
-    Viewport.y = gvc->job->height;
-    Margin.x = ROUND(gvc->job->margin.x * gvc->job->dpi.x / POINTS_PER_INCH);
-    Margin.y = ROUND(gvc->job->margin.y * gvc->job->dpi.y / POINTS_PER_INCH);
-
-    Zoom = gvc->job->zoom;
-    GraphFocus = gvc->job->focus;
-
-    CompScale.x = Zoom * gvc->job->dpi.x / POINTS_PER_INCH;
-    CompScale.y = Zoom * gvc->job->dpi.y / POINTS_PER_INCH;
-    FontScale = CompScale.y * 0.72;
-
-    if (onetime) {
-       init_svg();
-       onetime = FALSE;
-    }
-    isLatin1 = (GD_charset(g) == CHAR_LATIN1);
-    svg_fputs("<!-- Title: ");
-    svg_fputs(xml_namestring(g->name));
-    svg_printf(" Pages: %d -->\n", N_pages);
-    if (ROUND(gvc->job->dpi.x) == POINTS_PER_INCH && ROUND(gvc->job->dpi.y) == POINTS_PER_INCH) {
-       svg_printf("<svg width=\"%dpt\" height=\"%dpt\"\n",
-               Viewport.x + Margin.x * 2, Viewport.y + Margin.y * 2);
-    }
-    else {
-       svg_printf("<svg width=\"%dpx\" height=\"%dpx\"\n",
-               ROUND(gvc->job->dpi.x * (Viewport.x + Margin.x * 2) / POINTS_PER_INCH),
-               ROUND(gvc->job->dpi.y * (Viewport.y + Margin.y * 2) / POINTS_PER_INCH));
-    }
-    /* establish absolute units in points */
-    svg_printf(" viewBox = \"%d %d %d %d\"\n", Margin.x, Margin.y, Viewport.x, Viewport.y);
-    /* namespace of svg */
-    svg_fputs(" xmlns=\"http://www.w3.org/2000/svg\"");
-    /* namespace of xlink */
-    svg_fputs(" xmlns:xlink=\"http://www.w3.org/1999/xlink\"");
-    svg_fputs(">\n");
-}
-
-static void svg_end_graph(void)
-{
-    svg_fputs("</svg>\n");
-    switch (Output_lang) {
-    case SVGZ:
-#ifdef HAVE_LIBZ
-       gzclose(Zfile);
-       break;
-#else
-       agerr(AGERR, "No libz support\n");
-       exit(1);
-#endif
-    case SVG:
-       break;
-    }
-}
-
-static void
-svg_begin_page(graph_t * g, point page, double scale, int rot,
-              point offset)
-{
-    Rot = rot;
-
-#if 0
-fprintf(stderr,"Zoom=%g CompScale=%g,%f\n", Zoom, CompScale.x, CompScale.y);
-fprintf(stderr,"font-size=%g  Zoom=%g\n", cstk[0].fontsz, Zoom);
-#endif
-
-    /* its really just a page of the graph, but its still a graph,
-     * and it is the entire graph if we're not currently paging */
-    svg_printf("<g id=\"%s0\" class=\"graph\"", op[Obj]);
-    /* default style */
-    svg_fputs(" style=\"font-family:");
-    svg_fputs(cstk[0].fontfam);
-    svg_printf(";font-size:%.2fpt;\">\n", cstk[0].fontsz * FontScale);
-    svg_fputs("<title>");
-    svg_fputs(xml_namestring(g->name));
-    svg_fputs("</title>\n");
-}
-
-static void svg_end_page(void)
-{
-    svg_fputs("</g>\n");
-}
-
-static void svg_begin_layer(char *layerName, int n, int nLayers)
-{
-    /* svg_printf("<g id=\"%s\" class=\"layer\">\n", xml_string(layerName)); */
-    svg_fputs("<g id=\"");
-    svg_fputs(xml_string(layerName));
-    svg_fputs("\" class=\"layer\">\n");
-}
-
-static void svg_end_layer(void)
-{
-    svg_fputs("</g>\n");
-}
-
-static void svg_begin_cluster(graph_t * g)
-{
-    svg_printf("<g id=\"%s%d\" class=\"cluster\">", op[Obj],
-              g->meta_node->id);
-    svg_fputs("<title>");
-    svg_fputs(xml_namestring(g->name));
-    svg_fputs("</title>\n");
-}
-
-static void svg_end_cluster(void)
-{
-    svg_fputs("</g>\n");
-}
-
-static void svg_begin_node(node_t * n)
-{
-    Curnode = n;
-    svg_printf("<g id=\"%s%d\" class=\"node\">", op[Obj], n->id);
-    svg_fputs("<title>");
-    svg_fputs(xml_namestring(n->name));
-    svg_fputs("</title>\n");
-}
-
-static void svg_end_node(void)
-{
-    svg_fputs("</g>\n");
-}
-
-static void svg_begin_edge(edge_t * e)
-{
-    char *edgeop;
-
-    svg_printf("<g id=\"%s%d\" class=\"edge\">", op[Obj], e->id);
-    if (e->tail->graph->root->kind & AGFLAG_DIRECTED)
-       edgeop = "&#45;&gt;";
-    else
-       edgeop = "&#45;&#45;";
-    svg_fputs("<title>");
-    svg_fputs(xml_namestring(e->tail->name));
-    svg_fputs(edgeop);
-    /* can't do this in single svg_printf because
-     * xml_string's buffer gets reused. */
-    svg_fputs(xml_namestring(e->head->name));
-    svg_fputs("</title>\n");
-}
-
-static void svg_end_edge(void)
-{
-    svg_fputs("</g>\n");
-}
-
-static void svg_begin_context(void)
-{
-    assert(SP + 1 < MAXNEST);
-    cstk[SP + 1] = cstk[SP];
-    SP++;
-}
-
-static void svg_begin_anchor(char *href, char *tooltip, char *target)
-{
-    svg_fputs("<a");
-    if (href && href[0]) {
-        svg_fputs(" xlink:href=\"");
-        svg_fputs(xml_string(href));
-       svg_fputs("\"");
-    }
-    if (tooltip && tooltip[0]) {
-       svg_fputs(" xlink:title=\"");
-       svg_fputs(xml_string(tooltip));
-       svg_fputs("\"");
-    }
-    if (target && target[0]) {
-       svg_fputs(" target=\"");
-       svg_fputs(xml_string(target));
-       svg_fputs("\"");
-    }
-    svg_fputs(">\n");
-}
-
-static void svg_end_anchor(void)
-{
-    svg_fputs("</a>\n");
-}
-
-static void svg_end_context(void)
-{
-    int psp = SP - 1;
-    assert(SP > 0);
-    /*free(cstk[psp].fontfam); */
-    SP = psp;
-}
-
-static void svg_set_font(char *name, double size)
-{
-    char *p;
-#if 0
-/* see below */
-    char *q;
-#endif
-    context_t *cp;
-
-    cp = &(cstk[SP]);
-    cp->font_was_set = TRUE;
-    cp->fontsz = size;
-    p = strdup(name);
-#if 0
-/*
- * this doesn't work as originally intended 
- * fontnames can be things like: "Times-Roman"
- * where "Roman" is not an ITALIC or BOLD indicator.
- */
-    if ((q = strchr(p, '-'))) {
-       *q++ = 0;
-       if (strcasecmp(q, "italic") == 0)
-           cp->fontopt = ITALIC;
-       else if (strcasecmp(q, "bold") == 0)
-           cp->fontopt = BOLD;
-    }
-    cp->fontfam = p;
-#else
-    cp->fontfam = p;
-#endif
-}
-
-static void svg_set_pencolor(char *name)
-{
-    cstk[SP].pencolor = name;
-}
-
-static void svg_set_fillcolor(char *name)
-{
-    cstk[SP].fillcolor = name;
-}
-
-static void svg_set_style(char **s)
-{
-    char *line, *p;
-    context_t *cp;
-
-    cp = &(cstk[SP]);
-    while ((p = line = *s++)) {
-       if (streq(line, "solid"))
-           cp->pen = P_SOLID;
-       else if (streq(line, "dashed"))
-           cp->pen = P_DASHED;
-       else if (streq(line, "dotted"))
-           cp->pen = P_DOTTED;
-       else if (streq(line, "invis"))
-           cp->pen = P_NONE;
-       else if (streq(line, "bold"))
-           cp->penwidth = WIDTH_BOLD;
-       else if (streq(line, "setlinewidth")) {
-           while (*p)
-               p++;
-           p++;
-           cp->penwidth = atol(p);
-       } else if (streq(line, "filled"))
-           cp->fill = P_SOLID;
-       else if (streq(line, "unfilled"))
-           cp->fill = P_NONE;
-       else {
-           agerr(AGERR,
-                 "svg_set_style: unsupported style %s - ignoring\n",
-                 line);
-       }
-       cp->style_was_set = TRUE;
-    }
-    /* if (cp->style_was_set) svg_style(cp); */
-}
-
-static void svg_textpara(point p, textpara_t * para)
-{
-    char *anchor, *string;
-    point mp;
-    context_t *cp;
-
-    string = xml_string(para->str);
-    if (!string[0])
-       return;
-
-    cp = &(cstk[SP]);
-    if (cp->pen == P_NONE) {
-       /* its invisible, don't draw */
-       return;
-    }
-#if 0
-/* adobe svg doesn't like the dx propert */
-    if (para->xshow) {
-       anchor = "start";
-       switch (para->just) {
-       case 'l':
-           break;
-       case 'r':
-           p.x -= para->width;
-           break;
-       default:
-       case 'n':
-           p.x -= para->width / 2;
-           break;
-       }
-    } else {
-#endif
-       switch (para->just) {
-       case 'l':
-           anchor = "start";
-           break;
-       case 'r':
-           anchor = "end";
-           break;
-       default:
-       case 'n':
-           anchor = "middle";
-           break;
-       }
-#if 0
-/* adobe svg doesn't like the dx propert */
-    }
-#endif
-    mp = svgpt(p);
-
-    svg_printf("<text text-anchor=\"%s\"", anchor);
-    if (Rot) {
-       svg_printf(" transform=\"rotate(-90 %d %d)\"", mp.x, mp.y);
-    }
-    svg_printf(" x=\"%d\" y=\"%d\"", mp.x, mp.y);
-    svg_font(cp);
-#if 0
-/* adobe svg doesn't like the dx propert */
-    if (line->xshow) {
-       svg_fputs("\" dx=\"");
-       svg_fputs(para->xshow);
-    }
-#endif
-    svg_fputs(">");
-    svg_fputs(string);
-    svg_fputs("</text>\n");
-}
-
-static void svg_ellipse(point p, int rx, int ry, int filled)
-{
-    point mp;
-
-    if (cstk[SP].pen == P_NONE) {
-       /* its invisible, don't draw */
-       return;
-    }
-    mp.x = p.x;
-    mp.y = p.y;
-    mp = svgpt(mp);
-    svg_fputs("<ellipse");
-    svg_grstyle(&cstk[SP], filled);
-    svg_printf(" cx=\"%d\" cy=\"%d\"", mp.x, mp.y);
-    if (Rot) {
-       int t;
-       t = rx;
-       rx = ry;
-       ry = t;
-    }
-    mp.x = CompScale.x * rx;
-    mp.y = CompScale.y * ry;
-    svg_printf(" rx=\"%d\" ry=\"%d\"/>\n", mp.x, mp.y);
-}
-
-static void
-svg_bezier(point * A, int n, int arrow_at_start, int arrow_at_end, int filled)
-{
-    if (cstk[SP].pen == P_NONE) {
-       /* its invisible, don't draw */
-       return;
-    }
-    svg_fputs("<path");
-    svg_grstyle(&cstk[SP], filled);
-    svg_fputs(" d=\"");
-    svgbzptarray(A, n);
-    svg_fputs("\"/>\n");
-}
-
-static void svg_polygon(point * A, int n, int filled)
-{
-    int i;
-    point p;
-
-    if (cstk[SP].pen == P_NONE) {
-       /* its invisible, don't draw */
-       return;
-    }
-    svg_fputs("<polygon");
-    svg_grstyle(&cstk[SP], filled);
-    svg_fputs(" points=\"");
-    for (i = 0; i < n; i++) {
-       p = svgpt(A[i]);
-       svg_printf("%d,%d ", p.x, p.y);
-    }
-    /* because Adobe SVG is broken */
-    p = svgpt(A[0]);
-    svg_printf("%d,%d", p.x, p.y);
-    svg_fputs("\"/>\n");
-}
-
-static void svg_polyline(point * A, int n)
-{
-    int i;
-    point p;
-
-    if (cstk[SP].pen == P_NONE) {
-       /* its invisible, don't draw */
-       return;
-    }
-    svg_fputs("<polyline");
-    svg_grstyle(&cstk[SP], 0);
-    svg_fputs(" points=\"");
-    for (i = 0; i < n; i++) {
-       p = svgpt(A[i]);
-       svg_printf("%d,%d ", p.x, p.y);
-    }
-    svg_fputs("\"/>\n");
-}
-
-static void svg_usershape(usershape_t *us, boxf b, point *A, int n, bool filled)
-{
-    char *imagefile;
-
-    if (cstk[SP].pen == P_NONE) {
-       /* its invisible, don't draw */
-       return;
-    }
-    if (us->f)
-       imagefile = us->name;
-    else
-       imagefile = NULL;
-    if (! imagefile) {
-       svg_polygon(A, n, filled);
-       return;
-    }
-
-    svg_fputs("<image xlink:href=\"");
-    svg_name_fputs(imagefile);
-    if (Rot) {
-        svg_printf ("\" width=\"%gpx\" height=\"%fpx\" preserveAspectRatio=\"xMidYMid meet\" x=\"%g\" y=\"%g\"",
-           b.UR.y - b.LL.y, b.UR.x - b.LL.x, b.LL.x, b.UR.y);
-       svg_printf (" transform=\"rotate(-%d %g %g)\"",
-           Rot, b.LL.x, b.UR.y);
-    }
-    else {
-        svg_printf ("\" width=\"%gpx\" height=\"%fpx\" preserveAspectRatio=\"xMidYMid meet\" x=\"%g\" y=\"%g\"",
-           b.UR.x - b.LL.x, b.UR.y - b.LL.y, b.LL.x, b.LL.y);
-    }
-    svg_fputs("/>\n");
-}
-
-codegen_t SVG_CodeGen = {
-    svg_reset,
-    svg_begin_job, 0,          /* svg_end_job */
-    svg_begin_graph, svg_end_graph,
-    svg_begin_page, svg_end_page,
-    svg_begin_layer, svg_end_layer,
-    svg_begin_cluster, svg_end_cluster,
-    0, /* svg_begin_nodes */ 0,        /* svg_end_nodes */
-    0, /* svg_begin_edges */ 0,        /* svg_end_edges */
-    svg_begin_node, svg_end_node,
-    svg_begin_edge, svg_end_edge,
-    svg_begin_context, svg_end_context,
-    svg_begin_anchor, svg_end_anchor,
-    svg_set_font, svg_textpara,
-    svg_set_pencolor, svg_set_fillcolor, svg_set_style,
-    svg_ellipse, svg_polygon,
-    svg_bezier, svg_polyline,
-    0,                         /* bezier_has_arrows */
-    svg_comment,
-    svg_usershape
-};
diff --git a/lib/common/vrmlgen.c b/lib/common/vrmlgen.c
deleted file mode 100644 (file)
index 789413f..0000000
+++ /dev/null
@@ -1,1052 +0,0 @@
-/* $Id$ $Revision$ */
-/* vim:set shiftwidth=4 ts=8: */
-
-/**********************************************************
-*      This software is part of the graphviz package      *
-*                http://www.graphviz.org/                 *
-*                                                         *
-*            Copyright (c) 1994-2004 AT&T Corp.           *
-*                and is licensed under the                *
-*            Common Public License, Version 1.0           *
-*                      by AT&T Corp.                      *
-*                                                         *
-*        Information and Software Systems Research        *
-*              AT&T Research, Florham Park NJ             *
-**********************************************************/
-
-
-#include "render.h"
-#include "gd.h"
-#include "pathutil.h"
-
-
-extern char *get_ttf_fontpath(char *fontreq, int warn);
-
-#ifdef HAVE_GD_PNG
-
-#ifndef MAXFLOAT
-#define MAXFLOAT 10000000.
-#endif
-
-#define                NONE            0
-#define                NODE            1
-#define                EDGE            2
-#define                CLST            3
-
-#define BEZIERSUBDIVISION 10
-
-/* font modifiers */
-#define REGULAR 0
-#define BOLD           1
-#define ITALIC         2
-
-/* patterns */
-#define P_SOLID                0
-#define P_NONE  15
-#define P_DOTTED 4             /* i wasn't sure about this */
-#define P_DASHED 11            /* or this */
-
-/* bold line constant */
-#define WIDTH_NORMAL 1
-#define WIDTH_BOLD 3
-
-typedef struct {
-    unsigned char r, g, b;
-} Color;
-
-
-/* static int  N_pages; */
-/* static point        Pages; */
-static double Scale;
-static int Rot;
-static box BB;
-static double MinZ;
-/* static int  onetime = TRUE; */
-static int Saw_skycolor;
-
-static gdImagePtr im;
-static FILE *PNGfile;
-static node_t *Curnode;
-static edge_t *Curedge;
-static int    IsSegment;   /* set true if edge is line segment */
-static double CylHt;       /* height of cylinder part of edge */
-static double EdgeLen;     /* length between centers of endpoints */
-static double HeadHt, TailHt;  /* height of arrows */
-static double Fstz, Sndz;  /* z values of tail and head points */
-
-typedef struct context_t {
-    unsigned char pencolor_ix, fillcolor_ix;
-    char *pencolor, *fillcolor;
-    char *fontfam, fontopt, font_was_set;
-    double r, g, b;     /* fill color values */
-    char pen, fill, penwidth;
-    double fontsz;
-} context_t;
-
-#define MAXNEST 4
-static context_t cstk[MAXNEST];
-static int SP;
-
-static char *nodeURL(node_t * n, char *buf)
-{
-    sprintf(buf, "node%d.png", n->id);
-    return buf;
-}
-
-/* gdirname:
- * Returns directory pathname prefix
- * Code adapted from dgk
- */
-static char *gdirname(char *pathname)
-{
-    char *last;
-
-    /* go to end of path */
-    for (last = pathname; *last; last++);
-    /* back over trailing '/' */
-    while (last > pathname && *--last == '/');
-    /* back over non-slash chars */
-    for (; last > pathname && *last != '/'; last--);
-    if (last == pathname) {
-       /* all '/' or "" */
-       if (*pathname != '/')
-           *last = '.';
-       /* preserve // */
-       else if (pathname[1] == '/')
-           last++;
-    } else {
-       /* back over trailing '/' */
-       for (; *last == '/' && last > pathname; last--);
-       /* preserve // */
-       if (last == pathname && *pathname == '/' && pathname[1] == '/')
-           last++;
-    }
-    last++;
-    *last = '\0';
-
-    return pathname;
-}
-
-static char *nodefilename(node_t * n, char *buf)
-{
-    static char *dir;
-    static char disposable[1024];
-    char junkbuf[1024];
-
-    if (dir == 0) {
-       if (Output_file_name)
-           dir = gdirname(strcpy(disposable, Output_file_name));
-       else
-           dir = ".";
-    }
-    sprintf(buf, "%s/%s", dir, nodeURL(n, junkbuf));
-    return buf;
-}
-
-static FILE *nodefile(node_t * n)
-{
-    FILE *rv;
-    char buf[1024];
-
-    rv = fopen(nodefilename(n, buf), "wb");
-    return rv;
-}
-
-static unsigned char vrml_resolve_color(char *name)
-{
-    gvcolor_t color;
-
-    if (!(strcmp(name, "transparent"))) {
-       /* special case for "transparent" color */
-       return gdImageColorResolve(im, 255, 255, 254);
-    } else {
-       colorxlate(name, &color, RGBA_BYTE);
-       return gdImageColorResolve(im,
-                                  color.u.rgba[0], color.u.rgba[1],
-                                  color.u.rgba[2]);
-    }
-}
-
-static void vrml_set_pencolor(char *name)
-{
-    cstk[SP].pencolor = name;
-}
-
-static void vrml_set_fillcolor(char *name)
-{
-    gvcolor_t color;
-    cstk[SP].fillcolor = name;
-    colorxlate(name, &color, RGBA_BYTE);
-    cstk[SP].r = (double) color.u.rgba[0] / 255.0;
-    cstk[SP].g = (double) color.u.rgba[1] / 255.0;
-    cstk[SP].b = (double) color.u.rgba[2] / 255.0;
-}
-
-static void init_png(gdImagePtr im)
-{
-    int transparent;
-
-    if ((transparent = gdImageGetTransparent(im)) == -1) {
-       transparent = gdImageColorResolve(im, 255, 255, 254);
-       gdImageColorTransparent(im, transparent);
-    }
-}
-
-static pointf vrml_node_point(point p)
-{
-    pointf rv;
-
-    /* make mp relative to PNG canvas */
-    if (Rot == 0) {
-       rv.x = (p.x - ND_coord_i(Curnode).x + ND_lw_i(Curnode)) * Scale;
-       rv.y =
-           (ND_coord_i(Curnode).y - p.y + ND_ht_i(Curnode) / 2) * Scale;
-    } else {
-       rv.x = (p.y - ND_coord_i(Curnode).y + ND_lw_i(Curnode)) * Scale;
-       rv.y =
-           (ND_coord_i(Curnode).x - p.x + ND_ht_i(Curnode) / 2) * Scale;
-    }
-    return rv;
-}
-
-static void vrml_font(context_t * cp)
-{
-/* FIX
-       char               *fw, *fa;
-
-       fw = fa = "Regular";
-       switch (cp->fontopt) {
-       case BOLD:
-               fw = "Bold";
-               break;
-       case ITALIC:
-               fa = "Italic";
-               break;
-       }
-*/
-}
-
-/* warmed over VRML code starts here */
-
-static void vrml_begin_job(FILE * ofp, graph_t * g, char **lib, char *user,
-                          char *info[], point pages)
-{
-    fprintf(Output_file, "#VRML V2.0 utf8\n");
-}
-
-static void vrml_begin_graph(GVC_t * gvc, graph_t * g, box bb, point pb)
-{
-    g = g;
-
-    Saw_skycolor = FALSE;
-    MinZ = MAXDOUBLE;
-    BB = bb;
-    fprintf(Output_file, "Group { children [\n");
-    fprintf(Output_file, "  Transform {\n");
-    fprintf(Output_file, "    scale %.3f %.3f %.3f\n",
-           .0278, .0278, .0278);
-    fprintf(Output_file, "    children [\n");
-
-    SP = 0;
-    cstk[0].fillcolor = "white";
-    cstk[0].fontfam = "times"; /* font family name */
-    cstk[0].fontopt = REGULAR; /* modifier: REGULAR, BOLD or ITALIC */
-    cstk[0].pen = P_SOLID;     /* pen pattern style, default is solid */
-    cstk[0].fill = P_NONE;
-    cstk[0].penwidth = WIDTH_NORMAL;
-}
-
-static void vrml_end_graph(void)
-{
-    double d, z;
-    box bb = BB;
-
-    d = MAX(bb.UR.x - bb.LL.x,bb.UR.y - bb.LL.y);
-    /* Roughly fill 3/4 view assuming FOV angle of PI/4.
-     * Small graphs and non-square aspect ratios will upset this.
-     */
-    z = (0.6667*d)/tan(PI/8.0) + MinZ;  /* fill 3/4 of view */
-
-    if (!Saw_skycolor)
-       fprintf(Output_file, " Background { skyColor 1 1 1 }\n");
-    fprintf(Output_file, "  ] }\n");
-    fprintf(Output_file, "  Viewpoint {position %.3f %.3f %.3f}\n",
-           .0278 * (bb.UR.x + bb.LL.x) / 2.0,
-           .0278 * (bb.UR.y + bb.LL.y) / 2.0, .0278 * z);
-    fprintf(Output_file, "] }\n");
-}
-
-static void vrml_begin_page(graph_t * g, point page, double scale, int rot,
-                           point offset)
-{
-#if 0                          /* scale not used */
-    Scale = scale * (double) DEFAULT_DPI / POINTS_PER_INCH;
-#else
-    Scale = (double) DEFAULT_DPI / POINTS_PER_INCH;
-#endif
-    Rot = rot;
-}
-
-static void vrml_begin_node(node_t * n)
-{
-    int width, height;
-    double z;
-
-    fprintf(Output_file, "# node %s\n", n->name);
-    z = late_double(n, N_z, 0.0, -MAXFLOAT);
-    if (z < MinZ) MinZ = z;
-    if (shapeOf(n) != SH_POINT) {
-       PNGfile = nodefile(n);
-       width = (ND_lw_i(n) + ND_rw_i(n)) * Scale + 3;
-       height = (ND_ht_i(n)) * Scale + 3;
-       im = gdImageCreate(width, height);
-       init_png(im);
-    }
-    Curnode = n;
-}
-
-static void vrml_end_node(void)
-{
-    if (shapeOf(Curnode) != SH_POINT) {
-       gdImagePng(im, PNGfile);
-       gdImageDestroy(im);
-       im = 0;
-       fclose(PNGfile);
-    }
-}
-
-static void vrml_begin_edge(edge_t * e)
-{
-    Curedge = e;
-    IsSegment = 0;
-    fprintf(Output_file, "# edge %s -> %s\n", e->tail->name, e->head->name);
-    fprintf(Output_file, " Group { children [\n");
-}
-
-static void
-finishSegment (void)
-{
-    point p0 = ND_coord_i(Curedge->tail);
-    point p1 = ND_coord_i(Curedge->head);
-    double o_x, o_y, o_z;
-    double x, y, y0, z, theta;
-
-    o_x = ((double)(p0.x + p1.x))/2;
-    o_y = ((double)(p0.y + p1.y))/2;
-    o_z = (Fstz + Sndz)/2;
-    /* Compute rotation */
-    /* Pick end point with highest y */
-    if (p0.y > p1.y) {
-       x = p0.x;
-       y = p0.y;
-        z = Fstz;
-    }
-    else {
-       x = p1.x;
-       y = p1.y;
-        z = Sndz;
-    }
-    /* Translate center to the origin */
-    x -= o_x;
-    y -= o_y;
-    z -= o_z;
-    if (p0.y > p1.y)
-       theta = acos(2*y/EdgeLen) + PI;
-    else
-       theta = acos(2*y/EdgeLen);
-    if (!x && !z)   /* parallel  to y-axis */
-       x = 1;
-
-    y0 = (HeadHt-TailHt)/2.0;
-    fprintf(Output_file, "      ]\n");
-    fprintf(Output_file, "      center 0 %f 0\n", y0);
-    fprintf(Output_file, "      rotation %f 0 %f   %f\n", -z, x, -theta);
-    fprintf(Output_file, "      translation %.3f %.3f %.3f\n", o_x, o_y - y0, o_z);
-    fprintf(Output_file, "    }\n");
-}
-
-static void vrml_end_edge(void)
-{
-    if (IsSegment) {
-       finishSegment();
-    }
-    fprintf(Output_file, "] }\n");
-}
-
-static void vrml_begin_context(void)
-{
-    assert(SP + 1 < MAXNEST);
-    cstk[SP + 1] = cstk[SP];
-    SP++;
-}
-
-static void vrml_end_context(void)
-{
-    int psp = SP - 1;
-    assert(SP > 0);
-    if (cstk[SP].font_was_set)
-       vrml_font(&(cstk[psp]));
-    /* free(cstk[psp].fontfam); */
-    SP = psp;
-}
-
-static void vrml_set_font(char *name, double size)
-{
-    char *p, *q;
-    context_t *cp;
-
-    cp = &(cstk[SP]);
-    cp->font_was_set = TRUE;
-    cp->fontsz = size;
-    p = strdup(name);
-    if ((q = strchr(p, '-'))) {
-       *q++ = 0;
-       if (strcasecmp(q, "italic") == 0)
-           cp->fontopt = ITALIC;
-       else if (strcasecmp(q, "bold") == 0)
-           cp->fontopt = BOLD;
-    }
-    cp->fontfam = p;
-    vrml_font(&cstk[SP]);
-}
-
-static void vrml_set_style(char **s)
-{
-    char *line;
-    context_t *cp;
-
-    cp = &(cstk[SP]);
-    while ((line = *s++)) {
-       if (streq(line, "solid"))
-           cp->pen = P_SOLID;
-       else if (streq(line, "dashed"))
-           cp->pen = P_DASHED;
-       else if (streq(line, "dotted"))
-           cp->pen = P_DOTTED;
-       else if (streq(line, "bold"))
-           cp->penwidth = WIDTH_BOLD;
-       else if (streq(line, "invis"))
-           cp->pen = P_NONE;
-       else if (streq(line, "filled"))
-           cp->fill = P_SOLID;
-       else if (streq(line, "unfilled"))
-           cp->fill = P_NONE;
-       else {
-           agerr(AGWARN,
-                 "vrml_set_style: unsupported style %s - ignoring\n",
-                 line);
-       }
-    }
-}
-
-static void vrml_textpara(point p, textpara_t * para)
-{
-    char *fontlist, *err;
-    pointf mp;
-    int brect[8];
-    extern gdFontPtr gdFontSmall;
-
-    if (Obj != NODE)
-       return;
-    cstk[SP].pencolor_ix = vrml_resolve_color(cstk[SP].pencolor);
-    fontlist = (char*)(para->layout); /* FIXME - kluge */
-
-    switch (para->just) {
-    case 'l':
-       break;
-    case 'r':
-       p.x -= para->width;
-       break;
-    default:
-    case 'n':
-       p.x -= para->width / 2;
-       break;
-    }
-/*     p.y += cstk[SP].fontsz*2/3; */
-
-    mp = vrml_node_point(p);
-
-    err = gdImageStringFT(im, brect, cstk[SP].pencolor_ix, fontlist,
-                         cstk[SP].fontsz, (Rot ? 90.0 : 0.0) * PI / 180.0,
-                         ROUND(mp.x), ROUND(mp.y), para->str);
-    if (err) {
-       /* revert to builtin fonts */
-       gdImageString(im, gdFontSmall, ROUND(mp.x), ROUND(mp.y),
-                     (unsigned char *) para->str, cstk[SP].pencolor_ix);
-    }
-}
-
-/* interpolate_zcoord:
- * Given 2 points in 3D p = (fst.x,fst.y,fstz) and q = (snd.x, snd.y, sndz),
- * and a point p1 in the xy plane lying on the line segment connecting 
- * the projections of the p and q, find the z coordinate of p1 when it
- * is projected up onto the segment (p,q) in 3-space. 
- *
- * Why the special case for ranks? Is the arithmetic really correct?
- */
-static double 
-interpolate_zcoord(pointf p1, point fst, double fstz, point snd, double sndz)
-{
-    double len, d, rv;
-
-    if (fstz == sndz)
-       return fstz;
-    if (ND_rank(Curedge->tail) != ND_rank(Curedge->head)) {
-       if (snd.y == fst.y)
-           rv = (fstz + sndz) / 2.0;
-       else
-           rv = fstz + (sndz - fstz) * (p1.y - fst.y) / (snd.y - fst.y);
-    } 
-    else {
-       len = DIST(fst, snd);
-       d = DIST(p1, fst)/len;
-       rv = fstz + d*(sndz - fstz);
-    }
-    return rv;
-}
-
-/* collinear:
- * Return true if the 3 points starting at A are collinear.
- */
-static int
-collinear (point * A)
-{
-    Ppoint_t a, b, c;
-    double w;
-
-    a.x = A->x;
-    a.y = A->y;
-    A++;
-    b.x = A->x;
-    b.y = A->y;
-    A++;
-    c.x = A->x;
-    c.y = A->y;
-
-    w = wind(a,b,c);
-    return (fabs(w) <= 1);
-}
-
-/* straight:
- * Return true if bezier points are collinear
- * At present, just check with 4 points, the common case.
- */
-static int
-straight (point * A, int n)
-{
-    if (n != 4) return 0;
-    return (collinear(A) && collinear(A+1));
-}
-
-static void
-doSegment (point* A, point p0, double z0, point p1, double z1)
-{
-    double d1, d0;
-    double delx, dely, delz;
-
-    delx = p0.x - p1.x;
-    dely = p0.y - p1.y;
-    delz = z0 - z1;
-    EdgeLen = sqrt(delx*delx + dely*dely + delz*delz);
-    d0 = DIST(A[0],p0);
-    d1 = DIST(A[3],p1);
-    CylHt = EdgeLen - d0 - d1;
-    TailHt = HeadHt = 0;
-
-    IsSegment = 1;
-    fprintf(Output_file, "Transform {\n");
-    fprintf(Output_file, "  children [\n");
-    fprintf(Output_file, "    Shape {\n");
-    fprintf(Output_file, "      geometry Cylinder {\n"); 
-    fprintf(Output_file, "        bottom FALSE top FALSE\n"); 
-    fprintf(Output_file, "        height %f radius %d }\n", CylHt, cstk[SP].penwidth);
-    fprintf(Output_file, "      appearance Appearance {\n");
-    fprintf(Output_file, "        material Material {\n");
-    fprintf(Output_file, "          ambientIntensity 0.33\n");
-    fprintf(Output_file, "          diffuseColor %f %f %f\n", 
-       cstk[SP].r,cstk[SP].g,cstk[SP].b);
-    fprintf(Output_file, "        }\n");
-    fprintf(Output_file, "      }\n");
-    fprintf(Output_file, "    }\n");
-}
-
-static void
-vrml_bezier(point * A, int n, int arrow_at_start, int arrow_at_end, int filled)
-{
-    pointf p1, V[4];
-    int i, j, step;
-    double fstz, sndz;
-    context_t *cp;
-
-    assert(Obj == EDGE);
-
-    cp = &(cstk[SP]);
-    if (cp->pen == P_NONE)
-       return;
-    fstz = Fstz = late_double(Curedge->tail, N_z, 0.0, -1000.0);
-    sndz = Sndz = late_double(Curedge->head, N_z, 0.0, -MAXFLOAT);
-    if (straight(A,n)) {
-       doSegment (A, ND_coord_i(Curedge->tail),Fstz,ND_coord_i(Curedge->head),Sndz);
-       return;
-    }
-
-    fprintf(Output_file, "Shape { geometry Extrusion  {\n");
-    fprintf(Output_file, "  spine [");
-    V[3].x = A[0].x;
-    V[3].y = A[0].y;
-    for (i = 0; i + 3 < n; i += 3) {
-       V[0] = V[3];
-       for (j = 1; j <= 3; j++) {
-           V[j].x = A[i + j].x;
-           V[j].y = A[i + j].y;
-       }
-       for (step = 0; step <= BEZIERSUBDIVISION; step++) {
-           p1 = Bezier(V, 3, (double) step / BEZIERSUBDIVISION, NULL,
-                       NULL);
-           fprintf(Output_file, " %.3f %.3f %.3f", p1.x, p1.y,
-                   interpolate_zcoord(p1, A[0], fstz, A[n - 1], sndz));
-       }
-    }
-    fprintf(Output_file, " ]\n");
-    fprintf(Output_file, "  crossSection [ %d %d, %d %d, %d %d, %d %d ]\n",
-           (cp->penwidth), (cp->penwidth), -(cp->penwidth),
-           (cp->penwidth), -(cp->penwidth), -(cp->penwidth),
-           (cp->penwidth), -(cp->penwidth));
-    fprintf(Output_file, "}\n");
-    fprintf(Output_file, " appearance DEF E%d Appearance {\n",
-           Curedge->id);
-    fprintf(Output_file, "   material Material {\n");
-    fprintf(Output_file, "   ambientIntensity 0.33\n");
-    fprintf(Output_file, "   diffuseColor %.3f %.3f %.3f\n",
-           cstk[SP].r, cstk[SP].g, cstk[SP].b);
-    fprintf(Output_file, "   }\n");
-    fprintf(Output_file, " }\n");
-    fprintf(Output_file, "}\n");
-}
-
-/* doArrowhead:
- * If edge is straight, we attach a cone to the edge as a group.
- */
-static void
-doArrowhead (point* A)
-{
-    double rad, ht, y;
-    pointf p0;      /* center of triangle base */
-    point  tp,hp;
-
-    p0.x = (A[0].x + A[2].x)/2.0;
-    p0.y = (A[0].y + A[2].y)/2.0;
-    rad = DIST(A[0],A[2])/2.0;
-    ht = DIST(p0,A[1]);
-
-    y = (CylHt + ht)/2.0;
-
-    tp = ND_coord_i(Curedge->tail);
-    hp = ND_coord_i(Curedge->head);
-    fprintf(Output_file, "Transform {\n");
-    if (DIST2(A[1], tp) < DIST2(A[1], hp)) {
-       TailHt = ht;
-       fprintf(Output_file, "  translation 0 -%.3f 0\n", y);
-       fprintf(Output_file, "  rotation 0 0 1 %.3f\n", PI);
-    }
-    else {
-       HeadHt = ht;
-       fprintf(Output_file, "  translation 0 %.3f 0\n", y);
-    }
-    fprintf(Output_file, "  children [\n");
-    fprintf(Output_file, "    Shape {\n");
-    fprintf(Output_file, "      geometry Cone {bottomRadius %.3f height %.3f }\n",
-       rad, ht);
-    fprintf(Output_file, "      appearance Appearance {\n");
-    fprintf(Output_file, "        material Material {\n");
-    fprintf(Output_file, "          ambientIntensity 0.33\n");
-    fprintf(Output_file, "          diffuseColor %f %f %f\n", cstk[SP].r,cstk[SP].g,cstk[SP].b);
-    fprintf(Output_file, "        }\n");
-    fprintf(Output_file, "      }\n");
-    fprintf(Output_file, "    }\n");
-    fprintf(Output_file, "  ]\n");
-    fprintf(Output_file, "}\n");
-}
-
-static void vrml_polygon(point * A, int n, int filled)
-{
-    pointf p, mp;
-    int i;
-    gdPoint *points;
-    int style[20];
-    int pen, width;
-    gdImagePtr brush = NULL;
-    double theta, z;
-    node_t *endp;
-    char somebuf[1024];
-
-    switch (Obj) {
-    case NONE:                 /* GRAPH */
-       fprintf(Output_file, " Background { skyColor %.3f %.3f %.3f }\n",
-               cstk[SP].r, cstk[SP].g, cstk[SP].b);
-       Saw_skycolor = TRUE;
-       break;
-
-    case NODE:
-
-       if (cstk[SP].pen != P_NONE) {
-           cstk[SP].pencolor_ix = vrml_resolve_color(cstk[SP].pencolor);
-           cstk[SP].fillcolor_ix = vrml_resolve_color(cstk[SP].fillcolor);
-           if (cstk[SP].pen == P_DASHED) {
-               for (i = 0; i < 10; i++)
-                   style[i] = cstk[SP].pencolor_ix;
-               for (; i < 20; i++)
-                   style[i] = gdTransparent;
-               gdImageSetStyle(im, style, 20);
-               pen = gdStyled;
-           } else if (cstk[SP].pen == P_DOTTED) {
-               for (i = 0; i < 2; i++)
-                   style[i] = cstk[SP].pencolor_ix;
-               for (; i < 12; i++)
-                   style[i] = gdTransparent;
-               gdImageSetStyle(im, style, 12);
-               pen = gdStyled;
-           } else {
-               pen = cstk[SP].pencolor_ix;
-           }
-           if (cstk[SP].penwidth != WIDTH_NORMAL) {
-               width = cstk[SP].penwidth;
-               brush = gdImageCreate(width, width);
-               gdImagePaletteCopy(brush, im);
-               gdImageFilledRectangle(brush,
-                                      0, 0, width - 1, width - 1,
-                                      cstk[SP].pencolor_ix);
-               gdImageSetBrush(im, brush);
-               if (pen == gdStyled)
-                   pen = gdStyledBrushed;
-               else
-                   pen = gdBrushed;
-           }
-           points = N_GNEW(n, gdPoint);
-           for (i = 0; i < n; i++) {
-               mp = vrml_node_point(A[i]);
-               points[i].x = ROUND(mp.x);
-               points[i].y = ROUND(mp.y);
-           }
-           if (filled)
-               gdImageFilledPolygon(im, points, n, cstk[SP].fillcolor_ix);
-           gdImagePolygon(im, points, n, pen);
-           free(points);
-           if (brush)
-               gdImageDestroy(brush);
-       }
-
-       z = late_double(Curnode, N_z, 0.0, -MAXFLOAT);
-
-       fprintf(Output_file, "Shape {\n");
-       fprintf(Output_file, "  appearance Appearance {\n");
-       fprintf(Output_file, "    material Material {\n");
-       fprintf(Output_file, "      ambientIntensity 0.33\n");
-       fprintf(Output_file, "        diffuseColor 1 1 1\n");
-       fprintf(Output_file, "    }\n");
-       fprintf(Output_file, "    texture ImageTexture { url \"%s\" }\n",
-               nodeURL(Curnode, somebuf));
-       fprintf(Output_file, "  }\n");
-       fprintf(Output_file, "  geometry Extrusion {\n");
-       fprintf(Output_file, "    crossSection [");
-       for (i = 0; i < n; i++) {
-           p.x = A[i].x - ND_coord_i(Curnode).x;
-           p.y = A[i].y - ND_coord_i(Curnode).y;
-           fprintf(Output_file, " %.3f %.3f,", p.x, p.y);
-       }
-       p.x = A[0].x - ND_coord_i(Curnode).x;
-       p.y = A[0].y - ND_coord_i(Curnode).y;
-       fprintf(Output_file, " %.3f %.3f ]\n", p.x, p.y);
-       fprintf(Output_file, "    spine [ %d %d %.3f, %d %d %.3f ]\n",
-               ND_coord_i(Curnode).x, ND_coord_i(Curnode).y, z - .01,
-               ND_coord_i(Curnode).x, ND_coord_i(Curnode).y, z + .01);
-       fprintf(Output_file, "  }\n");
-       fprintf(Output_file, "}\n");
-       break;
-
-    case EDGE:
-       if (cstk[SP].pen == P_NONE)
-           return;
-       if (n != 3) {
-           static int flag;
-           if (!flag) {
-               flag++;
-               agerr(AGWARN,
-                 "vrml_polygon: non-triangle arrowheads not supported - ignoring\n");
-           }
-       }
-       if (IsSegment) {
-           doArrowhead (A);
-           return;
-       }
-       p.x = p.y = 0.0;
-       for (i = 0; i < n; i++) {
-           p.x += A[i].x;
-           p.y += A[i].y;
-       }
-       p.x = p.x / n;
-       p.y = p.y / n;
-
-       /* it is bad to know that A[1] is the aiming point, but we do */
-       theta =
-           atan2((A[0].y + A[2].y) / 2.0 - A[1].y,
-                 (A[0].x + A[2].x) / 2.0 - A[1].x) + PI / 2.0;
-
-
-       /* this is gruesome, but how else can we get z coord */
-       if (DIST2(p, ND_coord_i(Curedge->tail)) <
-           DIST2(p, ND_coord_i(Curedge->head)))
-           endp = Curedge->tail;
-       else
-           endp = Curedge->head;
-       z = late_double(endp, N_z, 0.0, -MAXFLOAT);
-
-       /* FIXME: arrow vector ought to follow z coord of bezier */
-       fprintf(Output_file, "Transform {\n");
-       fprintf(Output_file, "  translation %.3f %.3f %.3f\n", p.x, p.y,
-               z);
-       fprintf(Output_file, "  children [\n");
-       fprintf(Output_file, "    Transform {\n");
-       fprintf(Output_file, "      rotation 0 0 1 %.3f\n", theta);
-       fprintf(Output_file, "      children [\n");
-       fprintf(Output_file, "        Shape {\n");
-       fprintf(Output_file,
-               "          geometry Cone {bottomRadius %.3f height %.3f }\n",
-               cstk[SP].penwidth * 2.5, cstk[SP].penwidth * 10.0);
-       fprintf(Output_file, "          appearance USE E%d\n",
-               Curedge->id);
-       fprintf(Output_file, "        }\n");
-       fprintf(Output_file, "      ]\n");
-       fprintf(Output_file, "    }\n");
-       fprintf(Output_file, "  ]\n");
-       fprintf(Output_file, "}\n");
-       break;
-    default:
-       break;
-    }
-}
-
-/* doSphere:
- * Output sphere in VRML for point nodes.
- */
-static void 
-doSphere (point p, int rx, int ry)
-{
-    pointf  mp;
-    double  z;
-
-    if (!(strcmp(cstk[SP].fillcolor, "transparent"))) {
-       return;
-    }
-    mp.x = ND_coord_i(Curnode).x;
-    mp.y = ND_coord_i(Curnode).y;
-
-    z = late_double(Curnode, N_z, 0.0, -MAXFLOAT);
-
-    fprintf(Output_file, "Transform {\n");
-    fprintf(Output_file, "  translation %.3f %.3f %.3f\n", mp.x, mp.y,
-       z);
-    fprintf(Output_file, "  scale %d %d %d\n", rx, rx, rx);
-    fprintf(Output_file, "  children [\n");
-    fprintf(Output_file, "    Transform {\n");
-    fprintf(Output_file, "      children [\n");
-    fprintf(Output_file, "        Shape {\n");
-    fprintf(Output_file,
-       "          geometry Sphere { radius 1.0 }\n");
-    fprintf(Output_file, "          appearance Appearance {\n");
-    fprintf(Output_file, "            material Material {\n");
-    fprintf(Output_file, "              ambientIntensity 0.33\n");
-    fprintf(Output_file, "              diffuseColor %f %f %f\n", 
-       cstk[SP].r,cstk[SP].g,cstk[SP].b);
-    fprintf(Output_file, "            }\n");
-    fprintf(Output_file, "          }\n");
-    fprintf(Output_file, "        }\n");
-    fprintf(Output_file, "      ]\n");
-    fprintf(Output_file, "    }\n");
-    fprintf(Output_file, "  ]\n");
-    fprintf(Output_file, "}\n");
-}
-
-static void vrml_ellipse(point p, int rx, int ry, int filled)
-{
-    pointf mp;
-    int i;
-    node_t *endp;
-    int style[40];             /* need 2* size for arcs, I don't know why */
-    int pen, width;
-    gdImagePtr brush = NULL;
-    double z;
-    char somebuf[1024];
-
-    switch (Obj) {
-    case NODE:
-       if (shapeOf(Curnode) == SH_POINT) {
-           doSphere (p, rx, ry);
-           return;
-       }
-       cstk[SP].pencolor_ix = vrml_resolve_color(cstk[SP].pencolor);
-       cstk[SP].fillcolor_ix = vrml_resolve_color(cstk[SP].fillcolor);
-       if (cstk[SP].pen != P_NONE) {
-           if (cstk[SP].pen == P_DASHED) {
-               for (i = 0; i < 20; i++)
-                   style[i] = cstk[SP].pencolor_ix;
-               for (; i < 40; i++)
-                   style[i] = gdTransparent;
-               gdImageSetStyle(im, style, 40);
-               pen = gdStyled;
-           } else if (cstk[SP].pen == P_DOTTED) {
-               for (i = 0; i < 2; i++)
-                   style[i] = cstk[SP].pencolor_ix;
-               for (; i < 24; i++)
-                   style[i] = gdTransparent;
-               gdImageSetStyle(im, style, 24);
-               pen = gdStyled;
-           } else {
-               pen = cstk[SP].pencolor_ix;
-           }
-           if (cstk[SP].penwidth != WIDTH_NORMAL) {
-               width = cstk[SP].penwidth;
-               brush = gdImageCreate(width, width);
-               gdImagePaletteCopy(brush, im);
-               gdImageFilledRectangle(brush,
-                                      0, 0, width - 1, width - 1,
-                                      cstk[SP].pencolor_ix);
-               gdImageSetBrush(im, brush);
-               if (pen == gdStyled)
-                   pen = gdStyledBrushed;
-               else
-                   pen = gdBrushed;
-           }
-           mp = vrml_node_point(p);
-
-           if (filled) {
-               gdImageFilledEllipse(im, ROUND(mp.x), ROUND(mp.y),
-                                    ROUND(Scale * (rx + rx)),
-                                    ROUND(Scale * (ry + ry)),
-                                    cstk[SP].fillcolor_ix);
-           }
-           gdImageArc(im, ROUND(mp.x), ROUND(mp.y),
-                      ROUND(Scale * (rx + rx)), ROUND(Scale * (ry + ry)),
-                      0, 360, pen);
-           if (brush)
-               gdImageDestroy(brush);
-       }
-
-       mp.x = ND_coord_i(Curnode).x;
-       mp.y = ND_coord_i(Curnode).y;
-
-       z = late_double(Curnode, N_z, 0.0, -MAXFLOAT);
-
-       fprintf(Output_file, "Transform {\n");
-       fprintf(Output_file, "  translation %.3f %.3f %.3f\n", mp.x, mp.y,
-               z);
-       fprintf(Output_file, "  scale %d %d 1\n", rx, ry);
-       fprintf(Output_file, "  children [\n");
-       fprintf(Output_file, "    Transform {\n");
-       fprintf(Output_file, "      rotation 1 0 0   1.57\n");
-       fprintf(Output_file, "      children [\n");
-       fprintf(Output_file, "        Shape {\n");
-       fprintf(Output_file,
-               "          geometry Cylinder { side FALSE }\n");
-       fprintf(Output_file, "          appearance Appearance {\n");
-       fprintf(Output_file, "            material Material {\n");
-       fprintf(Output_file, "              ambientIntensity 0.33\n");
-       fprintf(Output_file, "              diffuseColor 1 1 1\n");
-       fprintf(Output_file, "            }\n");
-       fprintf(Output_file,
-               "            texture ImageTexture { url \"%s\" }\n",
-               nodeURL(Curnode, somebuf));
-       fprintf(Output_file, "          }\n");
-       fprintf(Output_file, "        }\n");
-       fprintf(Output_file, "      ]\n");
-       fprintf(Output_file, "    }\n");
-       fprintf(Output_file, "  ]\n");
-       fprintf(Output_file, "}\n");
-       break;
-    case EDGE:
-       if (cstk[SP].pen == P_NONE)
-           return;
-       mp.x = (double) p.x;
-       mp.y = (double) p.y;
-       /* this is gruesome, but how else can we get z coord */
-       if (DIST2(mp, ND_coord_i(Curedge->tail)) <
-           DIST2(mp, ND_coord_i(Curedge->head)))
-           endp = Curedge->tail;
-       else
-           endp = Curedge->head;
-       z = late_double(endp, N_z, 0.0, -MAXFLOAT);
-
-       fprintf(Output_file, "Transform {\n");
-       fprintf(Output_file, "  translation %.3f %.3f %.3f\n", mp.x, mp.y,
-               z);
-       fprintf(Output_file, "  children [\n");
-       fprintf(Output_file, "    Shape {\n");
-       fprintf(Output_file, "      geometry Sphere {radius %.3f }\n",
-               (double) rx);
-       fprintf(Output_file, "      appearance USE E%d\n", Curedge->id);
-       fprintf(Output_file, "    }\n");
-       fprintf(Output_file, "  ]\n");
-       fprintf(Output_file, "}\n");
-       break;
-    default:
-       break;
-    }
-}
-
-static void vrml_polyline(point * A, int n)
-{
-/*
-       pointf            p, p1;
-       int                      i;
-
-       if (cstk[SP].pen != P_NONE) {
-               p.x = A[0].x;
-               p.y = A[0].y;
-               for (i = 1; i < n; i++) {
-                       p1.x = A[i].x;
-                       p1.y = A[i].y;
-#ifdef NONEOFTHISEITHER
-                       if (cstk[SP].pen == P_DASHED) {
-                               gdImageDashedLine(im, ROUND(p.x), ROUND(p.y),
-                                       ROUND(p1.x), ROUND(p1.y), cstk[SP].color_ix);
-                       } else {
-                               gdImageLine(im, ROUND(p.x), ROUND(p.y),
-                                       ROUND(p1.x), ROUND(p1.y), cstk[SP].color_ix);
-                       }
-#endif
-                       p.x = p1.x;
-                       p.y = p1.y;
-               }
-       }
-*/
-}
-
-static void vrml_usershape(usershape_t *us, boxf b, point *A, int n, bool filled)
-{
-/* FIXME */
-    vrml_polygon(A, n, filled);
-}
-
-codegen_t VRML_CodeGen = {
-    0,                         /* vrml_reset */
-    vrml_begin_job, 0,         /* vrml_end_job */
-    vrml_begin_graph, vrml_end_graph,
-    vrml_begin_page, 0,                /* vrml_end_page */
-    0, /* vrml_begin_layer */ 0,       /* vrml_end_layer */
-    0, /* vrml_begin_cluster */ 0,     /* vrml_end_cluster */
-    0, /* vrml_begin_nodes */ 0,       /* vrml_end_nodes */
-    0, /* vrml_begin_edges */ 0,       /* vrml_end_edges */
-    vrml_begin_node, vrml_end_node,
-    vrml_begin_edge, vrml_end_edge,
-    vrml_begin_context, vrml_end_context,
-    0, /* vrml_begin_anchor */ 0,      /* vrml_end_anchor */
-    vrml_set_font, vrml_textpara,
-    vrml_set_pencolor, vrml_set_fillcolor, vrml_set_style,
-    vrml_ellipse, vrml_polygon,
-    vrml_bezier, vrml_polyline,
-    0,                         /* bezier_has_arrows */
-    0,                         /* comment */
-    vrml_usershape
-};
-#endif                         /* HAVE_GD_PNG */