00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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),
00034 -1,
00035 0,
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
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
00132
00133
00134 void epsf_emit_body(usershape_t *us, FILE *of)
00135 {
00136 char *p;
00137 p = us->data;
00138 while (*p) {
00139
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
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
00200
00201
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++;
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 }