]> granicus.if.org Git - graphviz/commitdiff
-Tps:core plugin is now feature complete with -Tps:cg
authorellson <devnull@localhost>
Sun, 18 Jun 2006 03:21:20 +0000 (03:21 +0000)
committerellson <devnull@localhost>
Sun, 18 Jun 2006 03:21:20 +0000 (03:21 +0000)
just needs more testing!!

lib/common/psgen.c
lib/common/psusershape.c
lib/common/types.h
lib/common/usershape.h
lib/gvc/gvloadimage.c
lib/gvc/gvusershape.c
plugin/core/gvloadimage_core.c
plugin/core/gvrender_core_ps.c
plugin/gd/gvloadimage_gd.c
plugin/pango/gvloadimage_pango.c

index ed8bef83af0631347544748e0b6665364d6b0442..646113c9fa1c391f62e1b81a0ab6cba1545f12c3 100644 (file)
@@ -23,6 +23,9 @@
 
 #include "render.h"
 #include "agxbuf.h"
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 #ifdef HAVE_LIBGD
 #include "gd.h"
 #include <unistd.h>
 #endif
 
-#include <sys/stat.h>
-
 extern void epsf_define(FILE * of);
-extern void epsf_emit_body(ps_image_t *img, FILE *of);
-extern void ps_freeusershapes(void);
-extern ps_image_t *ps_usershape_to_image(char *shapeimagefile);
+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; */
@@ -142,7 +142,6 @@ static void ps_begin_graph(GVC_t * gvc, graph_t * g, box bb, point pb)
 
 static void ps_end_graph(void)
 {
-    ps_freeusershapes();
     onetime = FALSE;
 }
 
@@ -331,34 +330,6 @@ static void ps_set_style(char **s)
     }
 }
 
-char *ps_string(char *ins, int latin)
-{
-    char *s;
-    char *base;
-    static agxbuf  xb;
-    int rc;
-
-    if (latin)
-       base = utf8ToLatin1 (ins);
-    else
-       base = ins;
-
-    if (xb.buf == NULL)
-       agxbinit (&xb, 0, NULL);
-
-    rc = agxbputc (&xb, LPAREN);
-    s = base;
-    while (*s) {
-       if ((*s == LPAREN) || (*s == RPAREN) || (*s == '\\'))
-           rc = agxbputc (&xb, '\\');
-       rc = agxbputc (&xb, *s++);
-    }
-    agxbputc (&xb, RPAREN);
-    if (base != ins) free (base);
-    s = agxbuse(&xb);
-    return s;
-}
-
 static void ps_textpara(point p, textpara_t * para)
 {
     double adj;
@@ -492,7 +463,7 @@ static void ps_polyline(point * A, int n)
 #ifdef HAVE_LIBGD
 static void writePSBitmap (gdImagePtr im, boxf bb)
 {
-    int x, y, px;
+    int X = im->sx, Y = im->sy, x, y, px;
 
     fprintf(Output_file, "gsave\n");
 
@@ -503,50 +474,51 @@ static void writePSBitmap (gdImagePtr im, boxf bb)
     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", im->sx, im->sy, 
-                       im->sx, -(im->sy), im->sy);
+    fprintf(Output_file, "%d %d 8 [%d 0 0 %d 0 %d]\n", X, Y, X, -Y, Y);
 
     fprintf(Output_file, "{<\n");
-    for (y = 0; y < im->sy; y++) {
-       for (x = 0; x < im->sx; x++) {
-           if (im->trueColor) {
+    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));
            }
-           else {
+           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, ">}\n");
     fprintf(Output_file, "false 3 colorimage\n");
 
     fprintf(Output_file, "grestore\n");
-
 }
 #endif
 
-static void ps_freeimage_gd (void *data)
+static void ps_freeimage_gd (usershape_t *us)
 {
 #ifdef HAVE_LIBGD
-    gdImageDestroy((gdImagePtr)data);
+    gdImageDestroy((gdImagePtr)us->data);
 #endif
 }
 
-static void ps_freeimage_ps (void *data)
+static void ps_freeimage_ps (usershape_t *us)
 {
-#if 0
-    free (data);
-#endif
+    munmap(us->data, us->datasize);
 }
 
 /* ps_usershape:
@@ -561,12 +533,6 @@ static void ps_freeimage_ps (void *data)
 static void ps_usershape(usershape_t *us, boxf b, point *A, int n, bool filled)
 {
     int j;
-#ifdef HAVE_LIBGD
-    gdImagePtr gd_img = NULL;
-#endif
-    ps_image_t *ps_img = NULL;
-    point offset;
-
     if (S[SP].invis)
        return;
 
@@ -593,127 +559,114 @@ static void ps_usershape(usershape_t *us, boxf b, point *A, int n, bool filled)
     }
 
     if (us->data) {
-       if (us->datafree == ps_freeimage_gd) {
-#ifdef HAVE_LIBGD
-           gd_img = (gdImagePtr)(us->data);  /* use cached data */
-#endif
-       }
-       else if (us->datafree == ps_freeimage_ps) {
-#if 0
-           ps_img = (ps_image_t *)(us->data);  /* use cached data */
-#endif
-       }
-       else {
+       if ((us->datafree != (void*)ps_freeimage_gd)
+               && (us->datafree != (void*)ps_freeimage_ps))  {
            us->datafree(us->data);        /* free incompatible cache data */
            us->data = NULL;
+           us->datafree = NULL;
+           us->datasize = 0;
        }
     }
 
-#ifdef HAVE_LIBGD
-    if (!ps_img && !gd_img) { /* read file into cache */
-#else
-    if (!ps_img) { /* read file into cache */
-#endif
+    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:
-                gd_img = gdImageCreateFromPng(us->f);
+                us->data = (void*)gdImageCreateFromPng(us->f);
+                us->datafree = (void*)ps_freeimage_gd;
                 break;
 #endif
 #ifdef HAVE_GD_GIF
             case FT_GIF:
-                gd_img = gdImageCreateFromGif(us->f);
+                us->data = (void*)gdImageCreateFromGif(us->f);
+                us->datafree = (void*)ps_freeimage_gd;
                 break;
 #endif
 #ifdef HAVE_GD_JPEG
             case FT_JPEG:
-                gd_img = gdImageCreateFromJpeg(us->f);
+                us->data = (void*)gdImageCreateFromJpeg(us->f);
+                us->datafree = (void*)ps_freeimage_gd;
                 break;
 #endif
 #endif
            case FT_PS:
            case FT_EPS:
-               ps_img = ps_usershape_to_image(us->name);
+                fstat(fd, &statbuf);
+                us->datasize = statbuf.st_size;
+                us->data = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
+                us->datafree = (void*)ps_freeimage_ps;
+                us->must_inline = true;
                break;
             default:
                break;
         }
-#ifdef HAVE_LIBGD
-        if (gd_img) {
-            us->data = (void*)gd_img;
-            us->datafree = ps_freeimage_gd;
-        }
-#endif
-#if 0
-        if (ps_img) {
-            us->data = (void*)ps_img;
-            us->datafree = ps_freeimage_ps;
-        }
-#endif
-    }
-
-    if (ps_img) {
-       ps_begin_context();
-       offset.x = -ps_img->origin.x - (ps_img->size.x) / 2;
-       offset.y = -ps_img->origin.y - (ps_img->size.y) / 2;
-       fprintf(Output_file, "%d %d translate newpath\n",
-           ND_coord_i(Curnode).x + offset.x,
-           ND_coord_i(Curnode).y + offset.y);
-       if (ps_img->must_inline)
-           epsf_emit_body(ps_img, Output_file);
-       else
-           fprintf(Output_file, "user_shape_%d\n", ps_img->macro_id);
-       ps_end_context();
-       return;
     }
 
-#ifdef HAVE_LIBGD
-    if (gd_img) {
-       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 (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);
         }
-       /* 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;
+        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;
        }
-       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;
        }
-
-       writePSBitmap (gd_img, bb);
-       return;
     }
-#endif
-
-    /* some other type of image */
-    agerr(AGERR, "usershape %s is not supported  in PostScript output\n", us->name);
 }
 
 codegen_t PS_CodeGen = {
index 1892b71656e50c46075336aa4869ebbed2754251..62cba4619fb0cea62ca6190f57c6820419ee0274 100644 (file)
 static int N_EPSF_files;
 static Dict_t *EPSF_contents;
 
-static void ps_image_free(Dict_t * dict, ps_image_t * p, Dtdisc_t * disc)
+static void ps_image_free(Dict_t * dict, usershape_t * p, Dtdisc_t * disc)
 {
-    free(p->contents);
+    free(p->data);
 }
 
 static Dtdisc_t ImageDictDisc = {
-    offsetof(ps_image_t, name),        /* key */
+    offsetof(usershape_t, name),/* key */
     -1,                                /* size */
     0,                         /* link offset */
     NIL(Dtmake_f),
@@ -41,7 +41,7 @@ static Dtdisc_t ImageDictDisc = {
     NIL(Dtevent_f)
 };
 
-static ps_image_t *user_init(char *str)
+static usershape_t *user_init(char *str)
 {
     char *contents;
     char line[BUFSIZ];
@@ -49,14 +49,14 @@ static ps_image_t *user_init(char *str)
     struct stat statbuf;
     int saw_bb, must_inline;
     int lx, ly, ux, uy;
-    ps_image_t *val;
+    usershape_t *us;
 
     if (!EPSF_contents)
        EPSF_contents = dtopen(&ImageDictDisc, Dtoset);
 
-    val = dtmatch(EPSF_contents, str);
-    if (val)
-       return val;
+    us = dtmatch(EPSF_contents, str);
+    if (us)
+       return us;
 
     if (!(fp = fopen(str, "r"))) {
        agerr(AGWARN, "couldn't open epsf file %s\n", str);
@@ -66,8 +66,7 @@ static ps_image_t *user_init(char *str)
     saw_bb = must_inline = FALSE;
     while (fgets(line, sizeof(line), fp)) {
        if (sscanf
-           (line, "%%%%BoundingBox: %d %d %d %d", &lx, &ly, &ux,
-            &uy) == 4) {
+           (line, "%%%%BoundingBox: %d %d %d %d", &lx, &ly, &ux, &uy) == 4) {
            saw_bb = TRUE;
        }
        if ((line[0] != '%') && strstr(line,"read")) must_inline = TRUE;
@@ -75,22 +74,22 @@ static ps_image_t *user_init(char *str)
     }
 
     if (saw_bb) {
-       val = GNEW(ps_image_t);
-       val->origin.x = lx;
-       val->origin.y = ly;
-       val->size.x = ux - lx;
-       val->size.y = uy - ly;
-       val->name = str;
-       val->macro_id = N_EPSF_files++;
+       us = GNEW(usershape_t);
+       us->x = lx;
+       us->y = ly;
+       us->w = ux - lx;
+       us->y = uy - ly;
+       us->name = str;
+       us->macro_id = N_EPSF_files++;
        fstat(fileno(fp), &statbuf);
-       contents = val->contents = N_GNEW(statbuf.st_size + 1, char);
+       contents = us->data = N_GNEW(statbuf.st_size + 1, char);
        fseek(fp, 0, SEEK_SET);
        fread(contents, statbuf.st_size, 1, fp);
        contents[statbuf.st_size] = '\0';
        fclose(fp);
-       dtinsert(EPSF_contents, val);
-       val->must_inline = must_inline;
-       return val;
+       dtinsert(EPSF_contents, us);
+       us->must_inline = must_inline;
+       return us;
     } else {
        agerr(AGWARN, "BoundingBox not found in epsf file %s\n", str);
        return NULL;
@@ -101,21 +100,21 @@ void epsf_init(node_t * n)
 {
     epsf_t *desc;
     char *str;
-    ps_image_t *img;
+    usershape_t *us;
     int dx, dy;
 
     if ((str = safefile(agget(n, "shapefile")))) {
-       img = user_init(str);
-       if (!img)
+       us = user_init(str);
+       if (!us)
            return;
-       dx = img->size.x;
-       dy = img->size.y;
+       dx = us->w;
+       dy = us->h;
        ND_width(n) = PS2INCH(dx);
        ND_height(n) = PS2INCH(dy);
        ND_shape_info(n) = desc = NEW(epsf_t);
-       desc->macro_id = img->macro_id;
-       desc->offset.x = -img->origin.x - (dx) / 2;
-       desc->offset.y = -img->origin.y - (dy) / 2;
+       desc->macro_id = us->macro_id;
+       desc->offset.x = -us->x - (dx) / 2;
+       desc->offset.y = -us->y - (dy) / 2;
     } else
        agerr(AGWARN, "shapefile not set for epsf node %s\n", n->name);
 }
@@ -132,10 +131,10 @@ void epsf_free(node_t * n)
 /* this removes EPSF DSC comments that, when nested in another
  * document, cause errors in Ghostview and other Postscript
  * processors (although legal according to the Adobe EPSF spec).                 */
-void epsf_emit_body(ps_image_t *img, FILE *of)
+void epsf_emit_body(usershape_t *us, FILE *of)
 {
        char *p;
-       p = img->contents;
+       p = us->data;
        while (*p) {
                /* skip %%EOF lines */
                if ((p[0] == '%') && (p[1] == '%')
@@ -154,9 +153,9 @@ void epsf_emit_body(ps_image_t *img, FILE *of)
        }
 }
 #else
-void epsf_emit_body(ps_image_t *img, FILE *of)
+void epsf_emit_body(usershape_t *us, FILE *of)
 {
-       if (fputs(img->contents, of) == EOF) {
+       if (fputs(us->data, of) == EOF) {
            perror("epsf_define()->fputs");
            exit(EXIT_FAILURE);
        }
@@ -165,20 +164,20 @@ void epsf_emit_body(ps_image_t *img, FILE *of)
 
 void epsf_define(FILE * of)
 {
-    ps_image_t *img;
+    usershape_t *us;
 
     if (!EPSF_contents)
        return;
-    for (img = dtfirst(EPSF_contents); img;
-        img = dtnext(EPSF_contents, img)) {
-        if (img->must_inline) continue;
-       fprintf(of, "/user_shape_%d {\n", img->macro_id);
+    for (us = dtfirst(EPSF_contents); us;
+        us = dtnext(EPSF_contents, us)) {
+        if (us->must_inline) continue;
+       fprintf(of, "/user_shape_%d {\n", us->macro_id);
 
        if (fputs("%%BeginDocument:\n", of) == EOF) {
            perror("epsf_define()->fputs");
            exit(EXIT_FAILURE);
        }
-       epsf_emit_body(img,of);
+       epsf_emit_body(us,of);
 
        if (fputs("%%EndDocument\n", of) == EOF) {
            perror("epsf_define()->fputs");
@@ -195,36 +194,30 @@ void epsf_define(FILE * of)
     }
 }
 
-point ps_image_size(graph_t * g, char *shapeimagefile)
+char *ps_string(char *ins, int latin)
 {
-    point rv;
-    ps_image_t *img;
-
-    rv.x = rv.y = -1;          /* assume error */
-    if (shapeimagefile && *shapeimagefile) {
-       img = user_init(shapeimagefile);
-       if (img) {
-           rv.x = img->size.x;
-           rv.y = img->size.y;
-       }
-    } else
-       rv.x = rv.y = 0;
-    return rv;
-}
-
-void ps_freeusershapes(void)
-{
-    if (EPSF_contents) {
-       dtclose(EPSF_contents);
-       EPSF_contents = 0;
-       N_EPSF_files = 0;
-    }
-}
-
-ps_image_t *ps_usershape_to_image(char *shapeimagefile)
-{
-    if (EPSF_contents) {
-       return dtmatch(EPSF_contents, shapeimagefile);
+    char *s;
+    char *base;
+    static agxbuf  xb;
+    int rc;
+
+    if (latin)
+        base = utf8ToLatin1 (ins);
+    else
+        base = ins;
+
+    if (xb.buf == NULL)
+        agxbinit (&xb, 0, NULL);
+
+    rc = agxbputc (&xb, LPAREN);
+    s = base;
+    while (*s) {
+        if ((*s == LPAREN) || (*s == RPAREN) || (*s == '\\'))
+            rc = agxbputc (&xb, '\\');
+        rc = agxbputc (&xb, *s++);
     }
-    return NULL;
+    agxbputc (&xb, RPAREN);
+    if (base != ins) free (base);
+    s = agxbuse(&xb);
+    return s;
 }
index 43b0e84b94d7a8c27233f02c3f23b562c8bcd375..788d8adc8435328cecce612ec884f8d191fcfa8e 100644 (file)
@@ -592,16 +592,6 @@ extern "C" {
        int flags;
     } gvlayout_features_t;
 
-    typedef struct {
-        Dtlink_t link;
-        char *name;
-        int macro_id;
-        point size;
-        point origin;
-        char *contents;
-        int must_inline;
-    } ps_image_t;
-
 #ifdef __cplusplus
 }
 #endif
index 912a668353214a659378198251afed208829cfab..c6485de696cd990bd941af9c3f4c433167b4d8a8 100644 (file)
@@ -24,12 +24,17 @@ extern "C" {
     typedef enum { FT_BMP, FT_GIF, FT_PNG, FT_JPEG, FT_PDF, FT_PS, FT_EPS } imagetype_t;
 
     typedef struct usershape_s {
+       Dtlink_t link;
        char *name;
-        FILE *f;
-        imagetype_t type;
-        unsigned int w, h, dpi;
-        void *data;                   /* data loaded by a renderer */
-        void (*datafree)(void *data); /* renderer's function for freeing data */
+       int macro_id;
+       bool must_inline;
+       FILE *f;
+       imagetype_t type;
+       char *stringtype;
+       unsigned int x, y, w, h, dpi;
+       void *data;                   /* data loaded by a renderer */
+       size_t datasize;              /* size of data (if mmap'ed) */
+       void (*datafree)(void *data); /* renderer's function for freeing data */
     } usershape_t;
 
 #ifdef __cplusplus
index 79746e20cdac32accaaee0b9bcbca3c5b84eb0af..0def439070ceb45c02a437debcff9f95c0e5709f 100644 (file)
@@ -51,20 +51,7 @@ void gvloadimage(GVJ_t * job, usershape_t *us, boxf b, bool filled, char *target
     gvloadimage_engine_t *gvli;
     char type[SMALLBUF];
 
-    switch (us->type) {
-    case FT_PNG:
-       strcpy(type, "png");
-       break;
-    case FT_JPEG:
-       strcpy(type, "jpeg");
-       break;
-    case FT_GIF:
-       strcpy(type, "gif");
-       break;
-    default:
-       strcpy(type, "");
-       break;
-    }
+    strcpy(type, us->stringtype);
     strcat(type, "2");
     strcat(type, target);
 
index 9475987af9fcbe06f08f957961d93a0baf680b5c..bc2ca8153cc8e0ea7ef1f85875e0e14ac26469a9 100644 (file)
 #include <string.h>
 
 #include "types.h"
+#include "memory.h"
 #include "graph.h"
 #include "agxbuf.h"
 #include "utils.h"
 
 static Dict_t *ImageDict;
 
-typedef struct imagerec_s {
-    Dtlink_t link;
-    usershape_t us;
-} imagerec_t;
-
 typedef struct {
     char *template;
-    int size, type;
+    int size;
+    int type;
+    char *stringtype;
 } knowntype_t;
 
 #define HDRLEN 20
@@ -49,13 +47,13 @@ typedef struct {
 #define EPS_MAGIC  "\xC5\xD0\xD3\xC6"
 
 knowntype_t knowntypes[] = {
-    { PNG_MAGIC,  sizeof(PNG_MAGIC)-1,  FT_PNG,  },
-    { PS_MAGIC,   sizeof(PS_MAGIC)-1,   FT_PS,   },
-    { BMP_MAGIC,  sizeof(BMP_MAGIC)-1,  FT_BMP,  },
-    { GIF_MAGIC,  sizeof(GIF_MAGIC)-1,  FT_GIF,  },
-    { JPEG_MAGIC, sizeof(JPEG_MAGIC)-1, FT_JPEG, },
-    { PDF_MAGIC,  sizeof(PDF_MAGIC)-1,  FT_PDF,  },
-    { EPS_MAGIC,  sizeof(EPS_MAGIC)-1,  FT_EPS,  },
+    { PNG_MAGIC,  sizeof(PNG_MAGIC)-1,  FT_PNG,  "png",  },
+    { PS_MAGIC,   sizeof(PS_MAGIC)-1,   FT_PS,   "ps",   },
+    { BMP_MAGIC,  sizeof(BMP_MAGIC)-1,  FT_BMP,  "bmp",  },
+    { GIF_MAGIC,  sizeof(GIF_MAGIC)-1,  FT_GIF,  "gif",  },
+    { JPEG_MAGIC, sizeof(JPEG_MAGIC)-1, FT_JPEG, "jpeg", },
+    { PDF_MAGIC,  sizeof(PDF_MAGIC)-1,  FT_PDF,  "pdf",  },
+    { EPS_MAGIC,  sizeof(EPS_MAGIC)-1,  FT_EPS,  "eps",  },
 };
 
 static int imagetype (usershape_t *us)
@@ -66,8 +64,10 @@ static int imagetype (usershape_t *us)
     if (fread(header, 1, HDRLEN, us->f) != HDRLEN)
        return -1;
     for (i = 0; i < sizeof(knowntypes) / sizeof(knowntype_t); i++) {
-       if (!memcmp (header, knowntypes[i].template, knowntypes[i].size))
+       if (!memcmp (header, knowntypes[i].template, knowntypes[i].size)) {
+           us->stringtype = knowntypes[i].stringtype;
            return (us->type = knowntypes[i].type);
+       }
     }
     return -1;
 }
@@ -230,55 +230,57 @@ static void ps_size (usershape_t *us)
         }
     }
     if (saw_bb) {
+       us->x = lx;
+       us->y = ly;
         us->w = ux - lx;
         us->h = uy - ly;
     }
 }
 
-static void imagerec_close (Dict_t * dict, Void_t * p, Dtdisc_t * disc)
+static void usershape_close (Dict_t * dict, Void_t * p, Dtdisc_t * disc)
 {
-    imagerec_t *val = (imagerec_t *)p;
+    usershape_t *us = (usershape_t *)p;
 
-    if (val->us.f)
-       fclose(val->us.f);
-    if (val->us.data && val->us.datafree)
-       val->us.datafree(val->us.data);
-    free (val);
+    if (us->f)
+       fclose(us->f);
+    if (us->data && us->datafree)
+       us->datafree(us);
+    free (us);
 }
 
 static Dtdisc_t ImageDictDisc = {
-    offsetof(imagerec_t, us.name), /* key */
+    offsetof(usershape_t, name), /* key */
     -1,                         /* size */
     0,                          /* link offset */
     NIL(Dtmake_f),
-    imagerec_close,
+    usershape_close,
     NIL(Dtcompar_f),
     NIL(Dthash_f),
     NIL(Dtmemory_f),
     NIL(Dtevent_f)
 };
 
-static imagerec_t *imagerec_open (char *name)
+usershape_t *gvusershape_find(char *name)
+{
+    usershape_t probe;
+
+    probe.name = name;
+    return (dtsearch(ImageDict, &probe));
+}
+
+static usershape_t *gvusershape_open (char *name)
 {
-    imagerec_t probe, *val;
     usershape_t *us;
     char *fn;
 
     if (!ImageDict)
         ImageDict = dtopen(&ImageDictDisc, Dttree);
 
-    probe.us.name = name;
-    val = dtsearch(ImageDict, &probe);
-    if (!val) {
-        val = malloc(sizeof(imagerec_t));
-        if (!val)
+    if (! (us = gvusershape_find(name))) {
+        if (! (us = zmalloc(sizeof(usershape_t))))
            return NULL;
-       us = &(val->us);
-        us->name = name;
-        us->w = us->h = 0;
-       us->data = NULL;
-       us->datafree = NULL;
 
+       us->name = name;
        if ((fn = safefile(name))) {
 #ifndef MSWIN32
            us->f = fopen(fn, "r");
@@ -309,16 +311,16 @@ static imagerec_t *imagerec_open (char *name)
                    break;
             }
         }
-        dtinsert(ImageDict, val);
+        dtinsert(ImageDict, us);
     }
 
-    return val;
+    return us;
 }
 
 point gvusershape_size(graph_t * g, char *name)
 {
     point rv;
-    imagerec_t *val;
+    usershape_t *us;
     double dpi;
 
     dpi = GD_drawing(g)->dpi;
@@ -330,14 +332,10 @@ point gvusershape_size(graph_t * g, char *name)
         rv.x = rv.y = -1;
         return rv;
     }
-    if (!strncasecmp(name, "http://", 7)) {
-        rv.x = rv.y = 0;
-        return rv;              /* punt on obvious web addresses */
-    }
 
-    if ((val = imagerec_open (name))) {
-       rv.x = val->us.w * dpi / val->us.dpi;
-       rv.y = val->us.h * dpi / val->us.dpi;
+    if ((us = gvusershape_open (name))) {
+       rv.x = us->w * dpi / us->dpi;
+       rv.y = us->h * dpi / us->dpi;
     }
     else {
         rv.x = rv.y = -1;
@@ -345,14 +343,3 @@ point gvusershape_size(graph_t * g, char *name)
 
     return rv;
 }
-
-usershape_t *gvusershape_find(char *name)
-{
-    imagerec_t probe, *val;
-
-    probe.us.name = name;
-    val = dtsearch(ImageDict, &probe);
-    if (!val)
-       return NULL;
-    return &(val->us);
-}
index b85b5246dadd294d6c59ec04cb598ef4caf87fea..7adf911ced7f520a3e010acfbe3b1c63cf2f077b 100644 (file)
 #endif
 
 #include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
 #include "gvplugin_loadimage.h"
 
-/* for ps_image_t */
-#include "types.h"
-
-/* for ND_coord_i */
-#include "graph.h"
-
 extern void svggen_fputs(GVJ_t * job, char *s);
 extern void svggen_printf(GVJ_t * job, const char *format, ...);
 
+extern void epsf_emit_body(usershape_t *us, FILE *of);
+extern shape_desc *find_user_shape(char *name);
+
 typedef enum {
     FORMAT_PNG_SVG, FORMAT_GIF_SVG, FORMAT_JPEG_SVG,
     FORMAT_PS_PS,
@@ -55,58 +56,82 @@ static void core_loadimage_svg(GVJ_t * job, usershape_t *us, boxf b, bool filled
     }
 }
 
-static void ps_freeimage(void *data)
+static void ps_freeimage(usershape_t *us)
 {
-    free (data);
+    munmap(us->data, us->datasize);
 }
 
-extern void epsf_emit_body(ps_image_t *img, FILE *of);
-extern ps_image_t *ps_usershape_to_image(char *shapeimagefile);
-
 /* usershape described by a postscript function */
 static void core_loadimage_ps(GVJ_t * job, usershape_t *us, boxf b, bool filled)
 {
-    obj_state_t *obj = job->obj;
-    ps_image_t *img = NULL;
-    point offset;
+    FILE *out = job->output_file;
+    int j;
+    pointf AF[4];
+
+    if (!us->f) {
+        if (find_user_shape(us->name)) {
+           AF[0] = b.LL;
+           AF[2] = b.UR;
+           AF[1].x = AF[0].x;
+           AF[1].y = AF[2].y;
+           AF[3].x = AF[2].x;
+           AF[3].y = AF[0].y;
+            if (filled) {
+//                ps_begin_context();
+//                ps_set_color(S[SP].fillcolor);
+                fprintf(out, "[ ");
+                for (j = 0; j < 4; j++)
+                    fprintf(out, "%g %g ", AF[j].x, AF[j].y);
+                fprintf(out, "%g %g ", AF[0].x, AF[0].y);
+                fprintf(out, "]  %d true %s\n", 4, us->name);
+//                ps_end_context();
+            }
+            fprintf(out, "[ ");
+            for (j = 0; j < 4; j++)
+                fprintf(out, "%g %g ", AF[j].x, AF[j].y);
+            fprintf(out, "%g %g ", AF[0].x, AF[0].y);
+            fprintf(out, "]  %d false %s\n", 4, us->name);
+        }
+        return;
+    }
 
     if (us->data) {
-        if (us->datafree == ps_freeimage) {
-            img = (ps_image_t *)(us->data);  /* use cached data */
-        }
-        else {
-            us->datafree(us->data);        /* free incompatible cache data */
+        if (us->datafree != (void*)ps_freeimage) {
+            us->datafree(us);        /* free incompatible cache data */
             us->data = NULL;
+            us->datafree = NULL;
+            us->datasize = 0;
         }
     }
 
-    if (!img) { /* read file into cache */
+    if (!us->data) { /* read file into cache */
+        int fd = fileno(us->f);
+       struct stat statbuf;
+
         fseek(us->f, 0, SEEK_SET);
         switch (us->type) {
             case FT_PS:
             case FT_EPS:
-                img = ps_usershape_to_image(us->name);
+               fstat(fd, &statbuf);
+               us->datasize = statbuf.st_size;
+               us->data = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
+               us->must_inline = true;
                 break;
             default:
                 break;
         }
-        if (img) {
-            us->data = (void*)img;
-            us->datafree = ps_freeimage;
-        }
+        if (us->data)
+            us->datafree = (void*)ps_freeimage;
     }
 
-    if (img) {
-        offset.x = -(img->origin.x) - (img->size.x) / 2;
-        offset.y = -(img->origin.y) - (img->size.y) / 2;
-        fprintf(job->output_file, "gsave %d %d translate newpath\n",
-            ND_coord_i(obj->n).x + offset.x,
-            ND_coord_i(obj->n).y + offset.y);
-        if (img->must_inline)
-            epsf_emit_body(img, job->output_file);
+    if (us->data) {
+        fprintf(out, "gsave %g %g translate newpath\n",
+               b.LL.x - us->x, b.LL.y - us->y);
+        if (us->must_inline)
+            epsf_emit_body(us, out);
         else
-            fprintf(job->output_file, "user_shape_%d\n", img->macro_id);
-        fprintf(job->output_file, "grestore\n");
+            fprintf(out, "user_shape_%d\n", us->macro_id);
+        fprintf(out, "grestore\n");
     }
 }
 
index 9d9d60e98b1009eb1b7803723c0f4334bc767fee..3ac746bed1242f6f5305afda89ecf0a0386441af 100644 (file)
@@ -113,18 +113,6 @@ static void psgen_begin_graph(GVJ_t * job)
                "/PUT pdfmark\n", obj->url);
 }
 
-static void psgen_end_graph(GVJ_t * job)
-{
-#if 0
-    if (EPSF_contents) {
-       dtclose(EPSF_contents);
-       EPSF_contents = 0;
-       N_EPSF_files = 0;
-    }
-    onetime = FALSE;
-#endif
-}
-
 static void psgen_begin_layer(GVJ_t * job, char *layername, int layerNum, int numLayers)
 {
     fprintf(job->output_file, "%d %d setlayer\n", layerNum, numLayers);
@@ -266,14 +254,13 @@ psgen_begin_edge(GVJ_t * job)
 static void
 ps_set_pen_style(GVJ_t *job)
 {
-#if 0
     double penwidth = job->style->penwidth * job->zoom;
     char *p, *line, **s = job->rawstyle;
 
     fprintf(stderr,"%g setlinewidth\n", penwidth);
 
     while (s && (p = line = *s++)) {
-       if (streq(line, "setlinewidth"))
+       if (strcmp(line, "setlinewidth") == 0)
            continue;
        while (*p)
            p++;
@@ -284,11 +271,10 @@ ps_set_pen_style(GVJ_t *job)
                p++;
            p++;
        }
-//     if (streq(line, "invis"))
-//         job->style->width = 0;
+       if (strcmp(line, "invis") == 0)
+           job->style->penwidth = 0;
        fprintf(stderr, "%s\n", line);
     }
-#endif
 }
 
 static void ps_set_color(GVJ_t *job, gvcolor_t *color)
@@ -448,7 +434,7 @@ static gvrender_engine_t psgen_engine = {
     psgen_begin_job,
     psgen_end_job,
     psgen_begin_graph,
-    psgen_end_graph,
+    0,                         /* psgen_end_graph */
     psgen_begin_layer,
     0,                         /* psgen_end_layer */
     psgen_begin_page,
index 54c63930f246cb59add5c7a305d676fd6a20d225..a469fd956cfd4a28744ddb7cea77ed453c6170ac 100644 (file)
@@ -40,24 +40,21 @@ typedef enum {
 } format_type;
 
 
-static void gd_freeimage(void *data)
+static void gd_freeimage(usershape_t *us)
 {
-    gdImageDestroy((gdImagePtr)data);
+    gdImageDestroy((gdImagePtr)us->data);
 }
 
 static gdImagePtr gd_loadimage(GVJ_t * job, usershape_t *us)
 {
-    gdImagePtr im = NULL;
-
     if (us->data) {
-       if (us->datafree == gd_freeimage)
-             im = (gdImagePtr)(us->data);  /* use cached data */
-       else {
-            us->datafree(us->data);        /* free incompatible cache data */
+       if (us->datafree != gd_freeimage) {
+            us->datafree(us);        /* free incompatible cache data */
             us->data = NULL;
+            us->datafree = NULL;
        }
     }
-    if (!im) { /* read file into cache */
+    if (!us->data) { /* read file into cache */
        fseek(us->f, 0, SEEK_SET);
        switch (us->type) {
 #if 0
@@ -70,48 +67,45 @@ static gdImagePtr gd_loadimage(GVJ_t * job, usershape_t *us)
 #endif
 #ifdef HAVE_GD_PNG
            case FT_PNG:
-               im = gdImageCreateFromPng(us->f);
+               us->data = (void*)gdImageCreateFromPng(us->f);
                break;
 #endif
 #ifdef HAVE_GD_GIF
            case FT_GIF:
-               im = gdImageCreateFromGif(us->f);
+               us->data = (void*)gdImageCreateFromGif(us->f);
                break;
 #endif
 #ifdef HAVE_GD_JPEG
            case FT_JPEG:
-               im = gdImageCreateFromJpeg(us->f);
+               us->data = (void*)gdImageCreateFromJpeg(us->f);
                break;
 #endif
 #if 0
 #ifdef HAVE_GD_XPM
            case FT_XPM:
-               im = gdImageCreateFromXpm(us->f);
+               us->data = (void*)gdImageCreateFromXpm(us->f);
                break;
 #endif
 #ifdef HAVE_GD_WBMP
            case FT_WBMP:
-               im = gdImageCreateFromWbmp(us->f);
+               us->data = (void*)gdImageCreateFromWbmp(us->f);
                break;
 #endif
 #endif
            default:
-               im = NULL;
+               break;
        }
-        if (im) {
-           us->data = (void*)im;
+        if (us->data)
            us->datafree = gd_freeimage;
-       }
     }
-    return im;
+    return (gdImagePtr)(us->data);
 }
 
 static void gd_loadimage_gd(GVJ_t * job, usershape_t *us, boxf b, bool filled)
 {
     gdImagePtr im3, im2 = NULL, im = (gdImagePtr) job->surface;
 
-    im2 = gd_loadimage(job, us);
-    if (im2) {
+    if ((im2 = gd_loadimage(job, us))) {
         if (job->rotation) {
             im3 = gdImageCreate(im2->sy, im2->sx); /* scratch image for rotation */
             gdImageCopyRotated(im3, im2, im3->sx / 2., im3->sy / 2.,
@@ -133,8 +127,7 @@ static void gd_loadimage_ps(GVJ_t * job, usershape_t *us, boxf b, bool filled)
     FILE *out = job->output_file;
     int X, Y, x, y, px;
 
-    im = gd_loadimage(job, us);
-    if (im) {
+    if ((im = gd_loadimage(job, us))) {
        X = im->sx;
        Y = im->sy;
 
index ed1cdf6035049cb82f0b686015a73c6fd881c607..0f104f3a9ef1f25e0d515f5104db862786a38d2a 100644 (file)
@@ -38,9 +38,9 @@ reader (void *closure, unsigned char *data, unsigned int length)
     return CAIRO_STATUS_READ_ERROR;
 }
 
-static void cairo_freeimage(void *data)
+static void cairo_freeimage(usershape_t *us)
 {
-    cairo_destroy((cairo_t*)data);
+    cairo_destroy((cairo_t*)us->data);
 }
 
 static cairo_surface_t* cairo_loadimage(GVJ_t * job, usershape_t *us)
@@ -49,7 +49,7 @@ static cairo_surface_t* cairo_loadimage(GVJ_t * job, usershape_t *us)
 
     if (us->data) {
         if (us->datafree == cairo_freeimage)
-             surface = (cairo_surface_t*)(us->data); /* use cached data */
+             surface = (cairo_surface_t*)(us); /* use cached data */
         else {
              us->datafree(us->data);        /* free incompatible cache data */
              us->data = NULL;