Graphviz  2.39.20141220.0545
gvusershape.c
Go to the documentation of this file.
1 /* $Id$ $Revision$ */
2 /* vim:set shiftwidth=4 ts=8: */
3 
4 /*************************************************************************
5  * Copyright (c) 2011 AT&T Intellectual Property
6  * All rights reserved. This program and the accompanying materials
7  * are made available under the terms of the Eclipse Public License v1.0
8  * which accompanies this distribution, and is available at
9  * http://www.eclipse.org/legal/epl-v10.html
10  *
11  * Contributors: See CVS logs. Details at http://www.graphviz.org/
12  *************************************************************************/
13 
14 #ifdef HAVE_CONFIG_H
15 #include "config.h"
16 #endif
17 
18 #include <stddef.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <ctype.h>
22 #include <errno.h>
23 
24 #ifdef WIN32
25 #include <windows.h>
26 #define GLOB_NOSPACE 1 /* Ran out of memory. */
27 #define GLOB_ABORTED 2 /* Read error. */
28 #define GLOB_NOMATCH 3 /* No matches found. */
29 #define GLOB_NOSORT 4
30 #define DMKEY "Software\\Microsoft" //key to look for library dir
31 #include "regex_win32.h"
32 #else
33 #include <regex.h>
34 #endif
35 
36 #include "types.h"
37 #include "logic.h"
38 #include "memory.h"
39 #include "agxbuf.h"
40 
41 #define _BLD_gvc 1
42 #include "utils.h"
43 #include "gvplugin_loadimage.h"
44 
45 extern char *Gvimagepath;
46 extern char *HTTPServerEnVar;
47 extern shape_desc *find_user_shape(const char *);
48 
49 static Dict_t *ImageDict;
50 
51 typedef struct {
52  char *template;
53  int size;
54  int type;
55  char *stringtype;
56 } knowntype_t;
57 
58 #define HDRLEN 20
59 
60 #define PNG_MAGIC "\x89PNG\x0D\x0A\x1A\x0A"
61 #define PS_MAGIC "%!PS-Adobe-"
62 #define BMP_MAGIC "BM"
63 #define GIF_MAGIC "GIF8"
64 #define JPEG_MAGIC "\xFF\xD8\xFF\xE0"
65 #define PDF_MAGIC "%PDF-"
66 #define EPS_MAGIC "\xC5\xD0\xD3\xC6"
67 #define XML_MAGIC "<?xml"
68 #define SVG_MAGIC "<svg"
69 #define RIFF_MAGIC "RIFF"
70 #define WEBP_MAGIC "WEBP"
71 //#define TIFF_MAGIC "II"
72 #define ICO_MAGIC "\x00\x00\x01\x00"
73 
74 static knowntype_t knowntypes[] = {
75  { PNG_MAGIC, sizeof(PNG_MAGIC)-1, FT_PNG, "png", },
76  { PS_MAGIC, sizeof(PS_MAGIC)-1, FT_PS, "ps", },
77  { BMP_MAGIC, sizeof(BMP_MAGIC)-1, FT_BMP, "bmp", },
78  { GIF_MAGIC, sizeof(GIF_MAGIC)-1, FT_GIF, "gif", },
79  { JPEG_MAGIC, sizeof(JPEG_MAGIC)-1, FT_JPEG, "jpeg", },
80  { PDF_MAGIC, sizeof(PDF_MAGIC)-1, FT_PDF, "pdf", },
81  { EPS_MAGIC, sizeof(EPS_MAGIC)-1, FT_EPS, "eps", },
82 /* { SVG_MAGIC, sizeof(SVG_MAGIC)-1, FT_SVG, "svg", }, - viewers expect xml preamble */
83  { XML_MAGIC, sizeof(XML_MAGIC)-1, FT_XML, "xml", },
84  { RIFF_MAGIC, sizeof(RIFF_MAGIC)-1, FT_RIFF, "riff", },
85  { ICO_MAGIC, sizeof(ICO_MAGIC)-1, FT_ICO, "ico", },
86 // { TIFF_MAGIC, sizeof(TIFF_MAGIC)-1, FT_TIFF, "tiff", },
87 };
88 
89 static int imagetype (usershape_t *us)
90 {
91  char header[HDRLEN];
92  char line[200];
93  int i;
94 
95  if (us->f && fread(header, 1, HDRLEN, us->f) == HDRLEN) {
96  for (i = 0; i < sizeof(knowntypes) / sizeof(knowntype_t); i++) {
97  if (!memcmp (header, knowntypes[i].template, knowntypes[i].size)) {
98  us->stringtype = knowntypes[i].stringtype;
99  us->type = knowntypes[i].type;
100  if (us->type == FT_XML) {
101  /* check for SVG in case of XML */
102  while (fgets(line, sizeof(line), us->f) != NULL) {
103  if (!memcmp(line, SVG_MAGIC, sizeof(SVG_MAGIC)-1)) {
104  us->stringtype = "svg";
105  return (us->type = FT_SVG);
106  }
107  }
108  }
109  else if (us->type == FT_RIFF) {
110  /* check for WEBP in case of RIFF */
111  if (!memcmp(header+8, WEBP_MAGIC, sizeof(WEBP_MAGIC)-1)) {
112  us->stringtype = "webp";
113  return (us->type = FT_WEBP);
114  }
115  }
116  return us->type;
117  }
118  }
119  }
120 
121  us->stringtype = "(lib)";
122  us->type = FT_NULL;
123 
124  return FT_NULL;
125 }
126 
127 static boolean get_int_lsb_first (FILE *f, unsigned int sz, unsigned int *val)
128 {
129  int ch, i;
130 
131  *val = 0;
132  for (i = 0; i < sz; i++) {
133  ch = fgetc(f);
134  if (feof(f))
135  return FALSE;
136  *val |= (ch << 8*i);
137  }
138  return TRUE;
139 }
140 
141 static boolean get_int_msb_first (FILE *f, unsigned int sz, unsigned int *val)
142 {
143  int ch, i;
144 
145  *val = 0;
146  for (i = 0; i < sz; i++) {
147  ch = fgetc(f);
148  if (feof(f))
149  return FALSE;
150  *val <<= 8;
151  *val |= ch;
152  }
153  return TRUE;
154 }
155 
156 static unsigned int svg_units_convert(double n, char *u)
157 {
158  if (strcmp(u, "in") == 0)
159  return ROUND(n * POINTS_PER_INCH);
160  if (strcmp(u, "px") == 0)
161  return ROUND(n * POINTS_PER_INCH / 96);
162  if (strcmp(u, "pc") == 0)
163  return ROUND(n * POINTS_PER_INCH / 6);
164  if (strcmp(u, "pt") == 0 || strcmp(u, "\"") == 0) /* ugly!! - if there are no inits then the %2s get the trailing '"' */
165  return ROUND(n);
166  if (strcmp(u, "cm") == 0)
167  return ROUND(n * POINTS_PER_CM);
168  if (strcmp(u, "mm") == 0)
169  return ROUND(n * POINTS_PER_MM);
170  return 0;
171 }
172 
173 static char* svg_attr_value_re = "([a-z][a-zA-Z]*)=\"([^\"]*)\"";
174 static regex_t re, *pre = NULL;
175 
176 static void svg_size (usershape_t *us)
177 {
178  unsigned int w = 0, h = 0;
179  double n, x0, y0, x1, y1;
180  char u[10];
181  char *attribute, *value, *re_string;
182  char line[200];
183  boolean wFlag = FALSE, hFlag = FALSE;
184 #define RE_NMATCH 4
185  regmatch_t re_pmatch[RE_NMATCH];
186 
187  /* compile on first use */
188  if (! pre) {
189  if (regcomp(&re, svg_attr_value_re, REG_EXTENDED) != 0) {
190  agerr(AGERR,"cannot compile regular expression %s", svg_attr_value_re);
191  }
192  pre = &re;
193  }
194 
195  fseek(us->f, 0, SEEK_SET);
196  while (fgets(line, sizeof(line), us->f) != NULL && (!wFlag || !hFlag)) {
197  re_string = line;
198  while (regexec(&re, re_string, RE_NMATCH, re_pmatch, 0) == 0) {
199  re_string[re_pmatch[1].rm_eo] = '\0';
200  re_string[re_pmatch[2].rm_eo] = '\0';
201  attribute = re_string + re_pmatch[1].rm_so;
202  value = re_string + re_pmatch[2].rm_so;
203  re_string += re_pmatch[0].rm_eo + 1;
204 
205  if (strcmp(attribute,"width") == 0) {
206  if (sscanf(value, "%lf%2s", &n, u) == 2) {
207  w = svg_units_convert(n, u);
208  wFlag = TRUE;
209  }
210  else if (sscanf(value, "%lf", &n) == 1) {
211  w = svg_units_convert(n, "pt");
212  wFlag = TRUE;
213  }
214  if (hFlag)
215  break;
216  }
217  else if (strcmp(attribute,"height") == 0) {
218  if (sscanf(value, "%lf%2s", &n, u) == 2) {
219  h = svg_units_convert(n, u);
220  hFlag = TRUE;
221  }
222  else if (sscanf(value, "%lf", &n) == 1) {
223  h = svg_units_convert(n, "pt");
224  hFlag = TRUE;
225  }
226  if (wFlag)
227  break;
228  }
229  else if (strcmp(attribute,"viewBox") == 0
230  && sscanf(value, "%lf %lf %lf %lf", &x0,&y0,&x1,&y1) == 4) {
231  w = x1 - x0 + 1;
232  h = y1 - y0 + 1;
233  wFlag = TRUE;
234  hFlag = TRUE;
235  break;
236  }
237  }
238  }
239  us->dpi = 0;
240  us->w = w;
241  us->h = h;
242 }
243 
244 static void png_size (usershape_t *us)
245 {
246  unsigned int w, h;
247 
248  us->dpi = 0;
249  fseek(us->f, 16, SEEK_SET);
250  if (get_int_msb_first(us->f, 4, &w) && get_int_msb_first(us->f, 4, &h)) {
251  us->w = w;
252  us->h = h;
253  }
254 }
255 
256 static void ico_size (usershape_t *us)
257 {
258  unsigned int w, h;
259 
260  us->dpi = 0;
261  fseek(us->f, 6, SEEK_SET);
262  if (get_int_msb_first(us->f, 1, &w) && get_int_msb_first(us->f, 1, &h)) {
263  us->w = w;
264  us->h = h;
265  }
266 }
267 
268 
269 // FIXME - how to get the size of a tiff image?
270 #if 0
271 static void tiff_size (usershape_t *us)
272 {
273  unsigned int w, h;
274 
275  us->dpi = 0;
276  fseek(us->f, 6, SEEK_SET);
277  if (get_int_msb_first(us->f, 1, &w) && get_int_msb_first(us->f, 1, &h)) {
278  us->w = w;
279  us->h = h;
280  }
281 }
282 #endif
283 
284 static void webp_size (usershape_t *us)
285 {
286  unsigned int w, h;
287 
288  us->dpi = 0;
289  fseek(us->f, 15, SEEK_SET);
290  if (fgetc(us->f) == 'X') { //VP8X
291  fseek(us->f, 24, SEEK_SET);
292  if (get_int_lsb_first(us->f, 4, &w) && get_int_lsb_first(us->f, 4, &h)) {
293  us->w = w;
294  us->h = h;
295  }
296  }
297  else { //VP8
298  fseek(us->f, 26, SEEK_SET);
299  if (get_int_lsb_first(us->f, 2, &w) && get_int_lsb_first(us->f, 2, &h)) {
300  us->w = w;
301  us->h = h;
302  }
303  }
304 }
305 
306 static void gif_size (usershape_t *us)
307 {
308  unsigned int w, h;
309 
310  us->dpi = 0;
311  fseek(us->f, 6, SEEK_SET);
312  if (get_int_lsb_first(us->f, 2, &w) && get_int_lsb_first(us->f, 2, &h)) {
313  us->w = w;
314  us->h = h;
315  }
316 }
317 
318 static void bmp_size (usershape_t *us) {
319  unsigned int size_x_msw, size_x_lsw, size_y_msw, size_y_lsw;
320 
321  us->dpi = 0;
322  fseek (us->f, 16, SEEK_SET);
323  if ( get_int_lsb_first (us->f, 2, &size_x_msw) &&
324  get_int_lsb_first (us->f, 2, &size_x_lsw) &&
325  get_int_lsb_first (us->f, 2, &size_y_msw) &&
326  get_int_lsb_first (us->f, 2, &size_y_lsw) ) {
327  us->w = size_x_msw << 16 | size_x_lsw;
328  us->h = size_y_msw << 16 | size_y_lsw;
329  }
330 }
331 
332 static void jpeg_size (usershape_t *us) {
333  unsigned int marker, length, size_x, size_y, junk;
334 
335  /* These are the markers that follow 0xff in the file.
336  * Other markers implicitly have a 2-byte length field that follows.
337  */
338  static unsigned char standalone_markers [] = {
339  0x01, /* Temporary */
340  0xd0, 0xd1, 0xd2, 0xd3, /* Reset */
341  0xd4, 0xd5, 0xd6,
342  0xd7,
343  0xd8, /* Start of image */
344  0xd9, /* End of image */
345  0
346  };
347 
348  us->dpi = 0;
349  while (TRUE) {
350  /* Now we must be at a 0xff or at a series of 0xff's.
351  * If that is not the case, or if we're at EOF, then there's
352  * a parsing error.
353  */
354  if (! get_int_msb_first (us->f, 1, &marker))
355  return;
356 
357  if (marker == 0xff)
358  continue;
359 
360  /* Ok.. marker now read. If it is not a stand-alone marker,
361  * then continue. If it's a Start Of Frame (0xc?), then we're there.
362  * If it's another marker with a length field, then skip ahead
363  * over that length field.
364  */
365 
366  /* A stand-alone... */
367  if (strchr ((char*)standalone_markers, marker))
368  continue;
369 
370  /* Incase of a 0xc0 marker: */
371  if (marker == 0xc0) {
372  /* Skip length and 2 lengths. */
373  if ( get_int_msb_first (us->f, 3, &junk) &&
374  get_int_msb_first (us->f, 2, &size_x) &&
375  get_int_msb_first (us->f, 2, &size_y) ) {
376 
377  /* Store length. */
378  us->h = size_x;
379  us->w = size_y;
380  }
381  return;
382  }
383 
384  /* Incase of a 0xc2 marker: */
385  if (marker == 0xc2) {
386  /* Skip length and one more byte */
387  if (! get_int_msb_first (us->f, 3, &junk))
388  return;
389 
390  /* Get length and store. */
391  if ( get_int_msb_first (us->f, 2, &size_x) &&
392  get_int_msb_first (us->f, 2, &size_y) ) {
393  us->h = size_x;
394  us->w = size_y;
395  }
396  return;
397  }
398 
399  /* Any other marker is assumed to be followed by 2 bytes length. */
400  if (! get_int_msb_first (us->f, 2, &length))
401  return;
402 
403  fseek (us->f, length - 2, SEEK_CUR);
404  }
405 }
406 
407 static void ps_size (usershape_t *us)
408 {
409  char line[BUFSIZ];
410  boolean saw_bb;
411  int lx, ly, ux, uy;
412  char* linep;
413 
414  us->dpi = 72;
415  fseek(us->f, 0, SEEK_SET);
416  saw_bb = FALSE;
417  while (fgets(line, sizeof(line), us->f)) {
418  /* PostScript accepts \r as EOL, so using fgets () and looking for a
419  * bounding box comment at the beginning doesn't work in this case.
420  * As a heuristic, we first search for a bounding box comment in line.
421  * This obviously fails if not all of the numbers make it into the
422  * current buffer. This shouldn't be a problem, as the comment is
423  * typically near the beginning, and so should be read within the first
424  * BUFSIZ bytes (even on Windows where this is 512).
425  */
426  if (!(linep = strstr (line, "%%BoundingBox:")))
427  continue;
428  if (sscanf (linep, "%%%%BoundingBox: %d %d %d %d", &lx, &ly, &ux, &uy) == 4) {
429  saw_bb = TRUE;
430  break;
431  }
432  }
433  if (saw_bb) {
434  us->x = lx;
435  us->y = ly;
436  us->w = ux - lx;
437  us->h = uy - ly;
438  }
439 }
440 
441 #define KEY "/MediaBox"
442 
443 typedef struct {
444  char* s;
445  char* buf;
446  FILE* fp;
447 } stream_t;
448 
449 static unsigned char
450 nxtc (stream_t* str)
451 {
452  if (fgets(str->buf, BUFSIZ, str->fp)) {
453  str->s = str->buf;
454  return *(str->s);
455  }
456  return '\0';
457 
458 }
459 
460 #define strc(x) (*(x->s)?*(x->s):nxtc(x))
461 #define stradv(x) (x->s++)
462 
463 static void
464 skipWS (stream_t* str)
465 {
466  unsigned char c;
467  while ((c = strc(str))) {
468  if (isspace(c)) stradv(str);
469  else return;
470  }
471 }
472 
473 static int
474 scanNum (char* tok, double* dp)
475 {
476  char* endp;
477  double d = strtod(tok, &endp);
478 
479  if (tok == endp) return 1;
480  *dp = d;
481  return 0;
482 }
483 
484 static void
485 getNum (stream_t* str, char* buf)
486 {
487  int len = 0;
488  char c;
489  skipWS(str);
490  while ((c = strc(str)) && (isdigit(c) || (c == '.'))) {
491  buf[len++] = c;
492  stradv(str);
493  if (len == BUFSIZ-1) break;
494  }
495  buf[len] = '\0';
496 
497  return;
498 }
499 
500 static int
501 boxof (stream_t* str, boxf* bp)
502 {
503  char tok[BUFSIZ];
504 
505  skipWS(str);
506  if (strc(str) != '[') return 1;
507  stradv(str);
508  getNum(str, tok);
509  if (scanNum(tok,&bp->LL.x)) return 1;
510  getNum(str, tok);
511  if (scanNum(tok,&bp->LL.y)) return 1;
512  getNum(str, tok);
513  if (scanNum(tok,&bp->UR.x)) return 1;
514  getNum(str, tok);
515  if (scanNum(tok,&bp->UR.y)) return 1;
516  return 0;
517 }
518 
519 static int
520 bboxPDF (FILE* fp, boxf* bp)
521 {
522  stream_t str;
523  char* s;
524  char buf[BUFSIZ];
525  while (fgets(buf, BUFSIZ, fp)) {
526  if ((s = strstr(buf,KEY))) {
527  str.buf = buf;
528  str.s = s+(sizeof(KEY)-1);
529  str.fp = fp;
530  return boxof(&str,bp);
531  }
532  }
533  return 1;
534 }
535 
536 static void pdf_size (usershape_t *us)
537 {
538  boxf bb;
539 
540  us->dpi = 0;
541  fseek(us->f, 0, SEEK_SET);
542  if ( ! bboxPDF (us->f, &bb)) {
543  us->x = bb.LL.x;
544  us->y = bb.LL.y;
545  us->w = bb.UR.x - bb.LL.x;
546  us->h = bb.UR.y - bb.LL.y;
547  }
548 }
549 
550 static void usershape_close (Dict_t * dict, Void_t * p, Dtdisc_t * disc)
551 {
552  usershape_t *us = (usershape_t *)p;
553 
554  if (us->f)
555  fclose(us->f);
556  if (us->data && us->datafree)
557  us->datafree(us);
558  free (us);
559 }
560 
561 static Dtdisc_t ImageDictDisc = {
562  offsetof(usershape_t, name), /* key */
563  -1, /* size */
564  0, /* link offset */
565  NIL(Dtmake_f),
566  usershape_close,
567  NIL(Dtcompar_f),
568  NIL(Dthash_f),
569  NIL(Dtmemory_f),
570  NIL(Dtevent_f)
571 };
572 
574 {
575  usershape_t *us;
576 
577  assert(name);
578  assert(name[0]);
579 
580  if (!ImageDict)
581  return NULL;
582 
583  us = dtmatch(ImageDict, name);
584  return us;
585 }
586 
587 #define MAX_USERSHAPE_FILES_OPEN 50
589 {
590  static int usershape_files_open_cnt;
591  const char *fn;
592 
593  assert(us);
594  assert(us->name);
595  assert(us->name[0]);
596 
597  if (us->f)
598  fseek(us->f, 0, SEEK_SET);
599  else {
600  if (! (fn = safefile(us->name))) {
601  agerr(AGWARN, "Filename \"%s\" is unsafe\n", us->name);
602  return FALSE;
603  }
604 #ifndef WIN32
605  us->f = fopen(fn, "r");
606 #else
607  us->f = fopen(fn, "rb");
608 #endif
609  if (us->f == NULL) {
610  agerr(AGWARN, "%s while opening %s\n", strerror(errno), fn);
611  return FALSE;
612  }
613  if (usershape_files_open_cnt >= MAX_USERSHAPE_FILES_OPEN)
614  us->nocache = TRUE;
615  else
616  usershape_files_open_cnt++;
617  }
618  assert(us->f);
619  return TRUE;
620 }
621 
623 {
624  if (us->nocache) {
625  if (us->f) {
626  fclose(us->f);
627  us->f = NULL;
628  }
629  }
630 }
631 
632 static usershape_t *gvusershape_open (char *name)
633 {
634  usershape_t *us;
635 
636  assert(name);
637 
638  if (!ImageDict)
639  ImageDict = dtopen(&ImageDictDisc, Dttree);
640 
641  if (! (us = gvusershape_find(name))) {
642  if (! (us = zmalloc(sizeof(usershape_t))))
643  return NULL;
644 
645  us->name = agstrdup (0, name);
646  if (!gvusershape_file_access(us))
647  return NULL;
648 
649  assert(us->f);
650 
651  switch(imagetype(us)) {
652  case FT_NULL:
653  if (!(us->data = (void*)find_user_shape(us->name)))
654  agerr(AGWARN, "\"%s\" was not found as a file or as a shape library member\n", us->name);
655  free(us);
656  return NULL;
657  break;
658  case FT_GIF:
659  gif_size(us);
660  break;
661  case FT_PNG:
662  png_size(us);
663  break;
664  case FT_BMP:
665  bmp_size(us);
666  break;
667  case FT_JPEG:
668  jpeg_size(us);
669  break;
670  case FT_PS:
671  ps_size(us);
672  break;
673  case FT_WEBP:
674  webp_size(us);
675  break;
676  case FT_SVG:
677  svg_size(us);
678  break;
679  case FT_PDF:
680  pdf_size(us);
681  break;
682  case FT_ICO:
683  ico_size(us);
684  break;
685 // case FT_TIFF:
686 // tiff_size(us);
687 // break;
688  case FT_EPS: /* no eps_size code available */
689  default:
690  break;
691  }
693  dtinsert(ImageDict, us);
694  return us;
695  }
697  return us;
698 }
699 
700 /* gvusershape_size_dpi:
701  * Return image size in points.
702  */
703 point
705 {
706  point rv;
707 
708  if (!us) {
709  rv.x = rv.y = -1;
710  }
711  else {
712  if (us->dpi != 0) {
713  dpi.x = dpi.y = us->dpi;
714  }
715  rv.x = us->w * POINTS_PER_INCH / dpi.x;
716  rv.y = us->h * POINTS_PER_INCH / dpi.y;
717  }
718  return rv;
719 }
720 
721 /* gvusershape_size:
722  * Loads user image from file name if not already loaded.
723  * Return image size in points.
724  */
726 {
727  point rv;
728  pointf dpi;
729  static char* oldpath;
730  usershape_t* us;
731 
732  /* no shape file, no shape size */
733  if (!name || (*name == '\0')) {
734  rv.x = rv.y = -1;
735  return rv;
736  }
737 
738  if (!HTTPServerEnVar && (oldpath != Gvimagepath)) {
739  oldpath = Gvimagepath;
740  if (ImageDict) {
741  dtclose(ImageDict);
742  ImageDict = NULL;
743  }
744  }
745 
746  if ((dpi.y = GD_drawing(g)->dpi) >= 1.0)
747  dpi.x = dpi.y;
748  else
749  dpi.x = dpi.y = (double)DEFAULT_DPI;
750 
751  us = gvusershape_open (name);
752  rv = gvusershape_size_dpi (us, dpi);
753  return rv;
754 }
void * zmalloc(size_t nbytes)
Definition: memory.c:22
#define PS_MAGIC
Definition: gvusershape.c:61
#define ICO_MAGIC
Definition: gvusershape.c:72
Definition: cgraph.h:389
point gvusershape_size(graph_t *g, char *name)
Definition: gvusershape.c:725
#define stradv(x)
Definition: gvusershape.c:461
void(* datafree)(usershape_t *us)
Definition: usershape.h:51
int regcomp(regex_t *preg, const char *pattern, int cflags)
Definition: regex_win32.c:5545
void gvusershape_file_release(usershape_t *us)
Definition: gvusershape.c:622
#define PNG_MAGIC
Definition: gvusershape.c:60
#define SVG_MAGIC
Definition: gvusershape.c:68
#define ROUND(f)
Definition: arith.h:87
char * stringtype
Definition: usershape.h:47
#define assert(x)
Definition: cghdr.h:48
void * data
Definition: usershape.h:49
Definition: geom.h:30
Definition: cdt.h:95
#define REG_EXTENDED
Definition: regex_win32.h:266
#define offsetof(typ, fld)
Definition: cghdr.h:66
int agerr(agerrlevel_t level, const char *fmt,...)
Definition: agerror.c:142
#define RE_NMATCH
regoff_t rm_eo
Definition: regex_win32.h:431
int x
Definition: geom.h:28
boolean nocache
Definition: usershape.h:44
Definition: cgraph.h:389
shape_desc * find_user_shape(const char *)
Definition: shapes.c:3765
#define WEBP_MAGIC
Definition: gvusershape.c:70
#define NIL(t)
Definition: dthdr.h:20
void free()
#define XML_MAGIC
Definition: gvusershape.c:67
int i
Definition: gvdevice.c:448
#define EPS_MAGIC
Definition: gvusershape.c:66
#define BMP_MAGIC
Definition: gvusershape.c:62
FILE * f
Definition: usershape.h:45
double y
Definition: geom.h:30
#define dtmatch(d, o)
Definition: cdt.h:310
#define RIFF_MAGIC
Definition: gvusershape.c:69
imagetype_t type
Definition: usershape.h:46
int regexec(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags)
Definition: regex_win32.c:5629
#define re
Definition: edges.h:33
Definition: grammar.c:79
#define strc(x)
Definition: gvusershape.c:460
char * agstrdup(Agraph_t *, char *)
Definition: refstr.c:97
usershape_t * gvusershape_find(char *name)
Definition: gvusershape.c:573
char * s
Definition: gvusershape.c:444
#define dtinsert(d, o)
Definition: cdt.h:311
const char * safefile(const char *filename)
Definition: utils.c:374
#define NULL
Definition: logic.h:50
point gvusershape_size_dpi(usershape_t *us, pointf dpi)
Definition: gvusershape.c:704
#define MAX_USERSHAPE_FILES_OPEN
Definition: gvusershape.c:587
Definition: geom.h:28
#define KEY
Definition: gvusershape.c:441
double x
Definition: geom.h:30
Dtmethod_t * Dttree
#define PDF_MAGIC
Definition: gvusershape.c:65
pointf LL
Definition: geom.h:37
#define JPEG_MAGIC
Definition: gvusershape.c:64
Dt_t * dtopen(Dtdisc_t *disc, Dtmethod_t *meth)
Definition: dtopen.c:12
char * stringtype
Definition: gvusershape.c:55
Definition: cdt.h:120
boolean gvusershape_file_access(usershape_t *us)
Definition: gvusershape.c:588
agxbuf * str
Definition: htmlparse.c:85
char * HTTPServerEnVar
Definition: globals.h:76
#define GIF_MAGIC
Definition: gvusershape.c:63
FILE * fp
Definition: gvusershape.c:446
char * Gvimagepath
Definition: globals.h:71
int dtclose(reg Dt_t *dt)
Definition: dtclose.c:8
#define GD_drawing(g)
Definition: types.h:336
int y
Definition: geom.h:28
const char * name
Definition: usershape.h:41
pointf UR
Definition: geom.h:37
Definition: geom.h:37
#define FALSE
Definition: cgraph.h:24
char * buf
Definition: gvusershape.c:445
#define HDRLEN
Definition: gvusershape.c:58
#define Void_t
Definition: cdt.h:12
#define TRUE
Definition: cgraph.h:27