/misc/src/release/graphviz-2.18-1/src/graphviz-2.18/lib/common/psusershape.c

Go to the documentation of this file.
00001 /* $Id: psusershape.c,v 1.17 2006/09/26 15:33:37 ellson Exp $ $Revision: 1.17 $ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /**********************************************************
00005 *      This software is part of the graphviz package      *
00006 *                http://www.graphviz.org/                 *
00007 *                                                         *
00008 *            Copyright (c) 1994-2004 AT&T Corp.           *
00009 *                and is licensed under the                *
00010 *            Common Public License, Version 1.0           *
00011 *                      by AT&T Corp.                      *
00012 *                                                         *
00013 *        Information and Software Systems Research        *
00014 *              AT&T Research, Florham Park NJ             *
00015 **********************************************************/
00016 
00017 #ifndef WIN32
00018 #include <unistd.h>
00019 #endif
00020 
00021 #include <sys/stat.h>
00022 #include "render.h"
00023 
00024 static int N_EPSF_files;
00025 static Dict_t *EPSF_contents;
00026 
00027 static void ps_image_free(Dict_t * dict, usershape_t * p, Dtdisc_t * disc)
00028 {
00029     free(p->data);
00030 }
00031 
00032 static Dtdisc_t ImageDictDisc = {
00033     offsetof(usershape_t, name),/* key */
00034     -1,                         /* size */
00035     0,                          /* link offset */
00036     NIL(Dtmake_f),
00037     (Dtfree_f) ps_image_free,
00038     NIL(Dtcompar_f),
00039     NIL(Dthash_f),
00040     NIL(Dtmemory_f),
00041     NIL(Dtevent_f)
00042 };
00043 
00044 static usershape_t *user_init(char *str)
00045 {
00046     char *contents;
00047     char line[BUFSIZ];
00048     FILE *fp;
00049     struct stat statbuf;
00050     int saw_bb, must_inline, rc;
00051     int lx, ly, ux, uy;
00052     usershape_t *us;
00053 
00054     if (!EPSF_contents)
00055         EPSF_contents = dtopen(&ImageDictDisc, Dtoset);
00056 
00057     us = dtmatch(EPSF_contents, str);
00058     if (us)
00059         return us;
00060 
00061     if (!(fp = fopen(str, "r"))) {
00062         agerr(AGWARN, "couldn't open epsf file %s\n", str);
00063         return NULL;
00064     }
00065     /* try to find size */
00066     saw_bb = must_inline = FALSE;
00067     while (fgets(line, sizeof(line), fp)) {
00068         if (sscanf
00069             (line, "%%%%BoundingBox: %d %d %d %d", &lx, &ly, &ux, &uy) == 4) {
00070             saw_bb = TRUE;
00071         }
00072         if ((line[0] != '%') && strstr(line,"read")) must_inline = TRUE;
00073         if (saw_bb && must_inline) break;
00074     }
00075 
00076     if (saw_bb) {
00077         us = GNEW(usershape_t);
00078         us->x = lx;
00079         us->y = ly;
00080         us->w = ux - lx;
00081         us->y = uy - ly;
00082         us->name = str;
00083         us->macro_id = N_EPSF_files++;
00084         fstat(fileno(fp), &statbuf);
00085         contents = us->data = N_GNEW(statbuf.st_size + 1, char);
00086         fseek(fp, 0, SEEK_SET);
00087         rc = fread(contents, statbuf.st_size, 1, fp);
00088         contents[statbuf.st_size] = '\0';
00089         fclose(fp);
00090         dtinsert(EPSF_contents, us);
00091         us->must_inline = must_inline;
00092         return us;
00093     } else {
00094         agerr(AGWARN, "BoundingBox not found in epsf file %s\n", str);
00095         return NULL;
00096     }
00097 }
00098 
00099 void epsf_init(node_t * n)
00100 {
00101     epsf_t *desc;
00102     char *str;
00103     usershape_t *us;
00104     int dx, dy;
00105 
00106     if ((str = safefile(agget(n, "shapefile")))) {
00107         us = user_init(str);
00108         if (!us)
00109             return;
00110         dx = us->w;
00111         dy = us->h;
00112         ND_width(n) = PS2INCH(dx);
00113         ND_height(n) = PS2INCH(dy);
00114         ND_shape_info(n) = desc = NEW(epsf_t);
00115         desc->macro_id = us->macro_id;
00116         desc->offset.x = -us->x - (dx) / 2;
00117         desc->offset.y = -us->y - (dy) / 2;
00118     } else
00119         agerr(AGWARN, "shapefile not set for epsf node %s\n", n->name);
00120 }
00121 
00122 void epsf_free(node_t * n)
00123 {
00124 
00125     if (ND_shape_info(n))
00126         free(ND_shape_info(n));
00127 }
00128 
00129 #define FILTER_EPSF 1
00130 #ifdef FILTER_EPSF
00131 /* this removes EPSF DSC comments that, when nested in another
00132  * document, cause errors in Ghostview and other Postscript
00133  * processors (although legal according to the Adobe EPSF spec).                 */
00134 void epsf_emit_body(usershape_t *us, FILE *of)
00135 {
00136         char *p;
00137         p = us->data;
00138         while (*p) {
00139                 /* skip %%EOF lines */
00140                 if ((p[0] == '%') && (p[1] == '%')
00141                         && (!strncasecmp(&p[2], "EOF", 3)
00142                         || !strncasecmp(&p[2], "BEGIN", 5)
00143                         || !strncasecmp(&p[2], "END", 3)
00144                         || !strncasecmp(&p[2], "TRAILER", 7)
00145                 )) {
00146                         /* check for *p since last line might not end in '\n' */
00147                         while (*p && (*p++ != '\n'));
00148                         continue;
00149                 }
00150                 do {
00151                         fputc(*p, of);
00152                 } while (*p++ != '\n');
00153         }
00154 }
00155 #else
00156 void epsf_emit_body(usershape_t *us, FILE *of)
00157 {
00158         if (fputs(us->data, of) == EOF) {
00159             perror("epsf_define()->fputs");
00160             exit(EXIT_FAILURE);
00161         }
00162 }
00163 #endif
00164 
00165 void epsf_define(FILE * of)
00166 {
00167     usershape_t *us;
00168 
00169     if (!EPSF_contents)
00170         return;
00171     for (us = dtfirst(EPSF_contents); us;
00172          us = dtnext(EPSF_contents, us)) {
00173          if (us->must_inline) continue;
00174         fprintf(of, "/user_shape_%d {\n", us->macro_id);
00175 
00176         if (fputs("%%BeginDocument:\n", of) == EOF) {
00177             perror("epsf_define()->fputs");
00178             exit(EXIT_FAILURE);
00179         }
00180         epsf_emit_body(us,of);
00181 
00182         if (fputs("%%EndDocument\n", of) == EOF) {
00183             perror("epsf_define()->fputs");
00184             exit(EXIT_FAILURE);
00185         }
00186 
00187         if (fputs("} bind def\n", of) == EOF) {
00188             perror("epsf_define()->fputs");
00189             exit(EXIT_FAILURE);
00190         }
00191 #if 0
00192         fprintf(of, "} bind def\n");
00193 #endif
00194     }
00195 }
00196 
00197 enum {ASCII, LATIN1, NONLATIN};
00198 
00199 /* charsetOf:
00200  * Assuming legal utf-8 input, determine if
00201  * the character value range is ascii, latin-1 or otherwise.
00202  */
00203 static int
00204 charsetOf (char* s)
00205 {
00206     int r = ASCII;
00207     unsigned char c;
00208 
00209     while ((c = *(unsigned char*)s++)) {
00210         if (c < 0x7F) 
00211             continue;
00212         else if ((c & 0xFC) == 0xC0) {
00213             r = LATIN1;
00214             s++; /* eat second byte */
00215         }
00216         else return NONLATIN;
00217     }
00218     return r;
00219 }
00220 
00221 char *ps_string(char *ins, int latin)
00222 {
00223     char *s;
00224     char *base;
00225     static agxbuf  xb;
00226     static int warned;
00227     int rc;
00228 
00229     if (latin)
00230         base = utf8ToLatin1 (ins);
00231     else {
00232         switch (charsetOf (ins)) {
00233         case ASCII :
00234             base = ins;
00235             break;
00236         case LATIN1 :
00237             base = utf8ToLatin1 (ins);
00238             break;
00239         case NONLATIN :
00240             if (!warned) {
00241                 agerr (AGWARN, "UTF-8 input uses non-Latin1 characters which cannot be handled in PostScript output");
00242                 warned = 1;
00243             }
00244             base = ins;
00245             break;
00246         default:
00247             base = ins;
00248             break;
00249         }
00250     }
00251 
00252     if (xb.buf == NULL)
00253         agxbinit (&xb, 0, NULL);
00254 
00255     rc = agxbputc (&xb, LPAREN);
00256     s = base;
00257     while (*s) {
00258         if ((*s == LPAREN) || (*s == RPAREN) || (*s == '\\'))
00259             rc = agxbputc (&xb, '\\');
00260         rc = agxbputc (&xb, *s++);
00261     }
00262     agxbputc (&xb, RPAREN);
00263     if (base != ins) free (base);
00264     s = agxbuse(&xb);
00265     return s;
00266 }

Generated on Mon Mar 31 19:03:25 2008 for Graphviz by  doxygen 1.5.1