#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; */
static void ps_end_graph(void)
{
- ps_freeusershapes();
onetime = FALSE;
}
}
}
-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;
#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");
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:
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;
}
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 = {
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),
NIL(Dtevent_f)
};
-static ps_image_t *user_init(char *str)
+static usershape_t *user_init(char *str)
{
char *contents;
char line[BUFSIZ];
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);
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;
}
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;
{
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);
}
/* 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] == '%')
}
}
#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);
}
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");
}
}
-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;
}
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
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
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);
#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
#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)
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;
}
}
}
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");
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;
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;
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);
-}
#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,
}
}
-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");
}
}
"/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);
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++;
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)
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,
} 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
#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.,
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;
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)
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;