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