Graphviz  2.41.20170921.2350
gvrender_core_vml.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 <stdarg.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <inttypes.h>
20 
21 #include "macros.h"
22 #include "const.h"
23 
24 #include "gvplugin_render.h"
25 #include "gvplugin_device.h"
26 #include "gvio.h"
27 #include "memory.h"
28 
29 typedef enum { FORMAT_VML, FORMAT_VMLZ, } format_type;
30 
31 unsigned int graphHeight,graphWidth;
32 
33 #ifndef HAVE_STRCASECMP
34 extern int strcasecmp(const char *s1, const char *s2);
35 #endif
36 
37 /* this is a direct copy fromlib/common/labels.c */
38 static int xml_isentity(char *s)
39 {
40  s++; /* already known to be '&' */
41  if (*s == '#') {
42  s++;
43  if (*s == 'x' || *s == 'X') {
44  s++;
45  while ((*s >= '0' && *s <= '9')
46  || (*s >= 'a' && *s <= 'f')
47  || (*s >= 'A' && *s <= 'F'))
48  s++;
49  } else {
50  while (*s >= '0' && *s <= '9')
51  s++;
52  }
53  } else {
54  while ((*s >= 'a' && *s <= 'z')
55  || (*s >= 'A' && *s <= 'Z'))
56  s++;
57  }
58  if (*s == ';')
59  return 1;
60  return 0;
61 }
62 
63 static void vml_bzptarray(GVJ_t * job, pointf * A, int n)
64 {
65  int i;
66  char *c;
67 
68  c = "m "; /* first point */
69  for (i = 0; i < n; i++) {
70  /* integers only in path! */
71  gvprintf(job, "%s%.0f,%.0f ", c, A[i].x, graphHeight-A[i].y);
72  if (i == 0)
73  c = "c "; /* second point */
74  else
75  c = ""; /* remaining points */
76  }
77  gvputs(job, "\"");
78 }
79 
80 static void vml_print_color(GVJ_t * job, gvcolor_t color)
81 {
82  switch (color.type) {
83  case COLOR_STRING:
84  gvputs(job, color.u.string);
85  break;
86  case RGBA_BYTE:
87  if (color.u.rgba[3] == 0) /* transparent */
88  gvputs(job, "none");
89  else
90  gvprintf(job, "#%02x%02x%02x",
91  color.u.rgba[0], color.u.rgba[1], color.u.rgba[2]);
92  break;
93  default:
94  assert(0); /* internal error */
95  }
96 }
97 
98 static void vml_grstroke(GVJ_t * job, int filled)
99 {
100  obj_state_t *obj = job->obj;
101 
102  gvputs(job, "<v:stroke color=\"");
103  vml_print_color(job, obj->pencolor);
104  if (obj->penwidth != PENWIDTH_NORMAL)
105  gvprintf(job, "\" weight=\"%.0fpt", obj->penwidth);
106  if (obj->pen == PEN_DASHED) {
107  gvputs(job, "\" dashstyle=\"dash");
108  } else if (obj->pen == PEN_DOTTED) {
109  gvputs(job, "\" dashstyle=\"dot");
110  }
111  gvputs(job, "\" />");
112 }
113 
114 
115 static void vml_grfill(GVJ_t * job, int filled)
116 {
117  obj_state_t *obj = job->obj;
118 
119  if (filled){
120  gvputs(job, " filled=\"true\" fillcolor=\"");
121  vml_print_color(job, obj->fillcolor);
122  gvputs(job, "\" ");
123  }else{
124  gvputs(job, " filled=\"false\" ");
125  }
126 }
127 
128 /* html_string is a modified version of xml_string */
129 char *html_string(char *s)
130 {
131  static char *buf = NULL;
132  static int bufsize = 0;
133  char *p, *sub, *prev = NULL;
134  int len, pos = 0;
135  int temp,cnt,remaining=0;
136  char workstr[16];
137  uint64_t charnum=0;
138  unsigned char byte;
139  unsigned char mask;
140 
141 
142  if (!buf) {
143  bufsize = 64;
144  buf = gmalloc(bufsize);
145  }
146  p = buf;
147  while (s && *s) {
148  if (pos > (bufsize - 8)) {
149  bufsize *= 2;
150  buf = grealloc(buf, bufsize);
151  p = buf + pos;
152  }
153  /* escape '&' only if not part of a legal entity sequence */
154  if (*s == '&' && !(xml_isentity(s))) {
155  sub = "&amp;";
156  len = 5;
157  }
158  /* '<' '>' are safe to substitute even if string is already UTF-8 coded
159  * since UTF-8 strings won't contain '<' or '>' */
160  else if (*s == '<') {
161  sub = "&lt;";
162  len = 4;
163  }
164  else if (*s == '>') {
165  sub = "&gt;";
166  len = 4;
167  }
168  else if (*s == '-') { /* can't be used in xml comment strings */
169  sub = "&#45;";
170  len = 5;
171  }
172  else if (*s == ' ' && prev && *prev == ' ') {
173  /* substitute 2nd and subsequent spaces with required_spaces */
174  sub = "&#160;"; /* inkscape doesn't recognise &nbsp; */
175  len = 6;
176  }
177  else if (*s == '"') {
178  sub = "&quot;";
179  len = 6;
180  }
181  else if (*s == '\'') {
182  sub = "&#39;";
183  len = 5;
184  }
185  else if ((unsigned char)*s > 127) {
186  byte=(unsigned char)*s;
187  cnt=0;
188  for (mask=127; mask < byte; mask=mask >>1){
189  cnt++;
190  byte=byte & mask;
191  }
192  if (cnt>1){
193  charnum=byte;
194  remaining=cnt-1;
195  }else{
196  charnum=charnum<<6;
197  charnum+=byte;
198  remaining--;
199  }
200  if (remaining>0){
201  s++;
202  continue;
203  }
204  /* we will build the html value right-to-left
205  * (least significant-to-most) */
206  workstr[15]=';';
207  sub=&workstr[14];
208  len=3; /* &# + ; */
209  do {
210  temp=charnum%10;
211  *(sub--)=(char)((int)'0'+ temp);
212  charnum/=10;
213  len++;
214  if (len>12){ /* 12 is arbitrary, but clearly in error */
215  fprintf(stderr, "Error during conversion to \"UTF-8\". Quiting.\n");
216  exit(1);
217  }
218  } while (charnum>0);
219  *(sub--)='#';
220  *(sub)='&';
221  }
222  else {
223  sub = s;
224  len = 1;
225  }
226  while (len--) {
227  *p++ = *sub++;
228  pos++;
229  }
230  prev = s;
231  s++;
232  }
233  *p = '\0';
234  return buf;
235 }
236 static void vml_comment(GVJ_t * job, char *str)
237 {
238  gvputs(job, " <!-- ");
239  gvputs(job, html_string(str));
240  gvputs(job, " -->\n");
241 }
242 static void vml_begin_job(GVJ_t * job)
243 {
244  gvputs(job, "<HTML>\n");
245  gvputs(job, "\n<!-- Generated by ");
246  gvputs(job, html_string(job->common->info[0]));
247  gvputs(job, " version ");
248  gvputs(job, html_string(job->common->info[1]));
249  gvputs(job, " (");
250  gvputs(job, html_string(job->common->info[2]));
251  gvputs(job, ")\n-->\n");
252 }
253 
254 static void vml_begin_graph(GVJ_t * job)
255 {
256  obj_state_t *obj = job->obj;
257  char *name;
258 
259  graphHeight =(int)(job->bb.UR.y - job->bb.LL.y);
260  graphWidth =(int)(job->bb.UR.x - job->bb.LL.x);
261 
262  gvputs(job, "<HEAD>");
263  gvputs(job, "<META http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n");
264 
265 
266  name = agnameof(obj->u.g);
267  if (name[0]) {
268  gvputs(job, "<TITLE>");
269  gvputs(job, html_string(name));
270  gvputs(job, "</TITLE>");
271  }
272  gvprintf(job, "<!-- Pages: %d -->\n", job->pagesArraySize.x * job->pagesArraySize.y);
273 
274 /* the next chunk and all the "DIV" stuff is not required,
275  * but it helps with non-IE browsers */
276  gvputs(job, " <SCRIPT LANGUAGE='Javascript'>\n");
277  gvputs(job, " function browsercheck()\n");
278  gvputs(job, " {\n");
279  gvputs(job, " var ua = window.navigator.userAgent\n");
280  gvputs(job, " var msie = ua.indexOf ( 'MSIE ' )\n");
281  gvputs(job, " var ievers;\n");
282  gvputs(job, " var item;\n");
283  gvputs(job, " var VMLyes=new Array('_VML1_','_VML2_');\n");
284  gvputs(job, " var VMLno=new Array('_notVML1_','_notVML2_');\n");
285  gvputs(job, " if ( msie > 0 ){ // If Internet Explorer, return version number\n");
286  gvputs(job, " ievers= parseInt (ua.substring (msie+5, ua.indexOf ('.', msie )))\n");
287  gvputs(job, " }\n");
288  gvputs(job, " if (ievers>=5){\n");
289  gvputs(job, " for (x in VMLyes){\n");
290  gvputs(job, " item = document.getElementById(VMLyes[x]);\n");
291  gvputs(job, " if (item) {\n");
292  gvputs(job, " item.style.visibility='visible';\n");
293  gvputs(job, " }\n");
294  gvputs(job, " }\n");
295  gvputs(job, " for (x in VMLno){\n");
296  gvputs(job, " item = document.getElementById(VMLno[x]);\n");
297  gvputs(job, " if (item) {\n");
298  gvputs(job, " item.style.visibility='hidden';\n");
299  gvputs(job, " }\n");
300  gvputs(job, " }\n");
301  gvputs(job, " }else{\n");
302  gvputs(job, " for (x in VMLyes){\n");
303  gvputs(job, " item = document.getElementById(VMLyes[x]);\n");
304  gvputs(job, " if (item) {\n");
305  gvputs(job, " item.style.visibility='hidden';\n");
306  gvputs(job, " }\n");
307  gvputs(job, " }\n");
308  gvputs(job, " for (x in VMLno){\n");
309  gvputs(job, " item = document.getElementById(VMLno[x]);\n");
310  gvputs(job, " if (item) {\n");
311  gvputs(job, " item.style.visibility='visible';\n");
312  gvputs(job, " }\n");
313  gvputs(job, " }\n");
314  gvputs(job, " }\n");
315  gvputs(job, " }\n");
316  gvputs(job, " </SCRIPT>\n");
317 
318  gvputs(job, "</HEAD>");
319  gvputs(job, "<BODY onload='browsercheck();'>\n");
320  /* add 10pt pad to the bottom of the graph */
321  gvputs(job, "<DIV id='_VML1_' style=\"position:relative; display:inline; visibility:hidden");
322  gvprintf(job, " width: %dpt; height: %dpt\">\n", graphWidth, 10+graphHeight);
323  gvputs(job, "<STYLE>\n");
324  gvputs(job, "v\\:* { behavior: url(#default#VML);display:inline-block}\n");
325  gvputs(job, "</STYLE>\n");
326  gvputs(job, "<xml:namespace ns=\"urn:schemas-microsoft-com:vml\" prefix=\"v\" />\n");
327 
328  gvputs(job, " <v:group style=\"position:relative; ");
329  gvprintf(job, " width: %dpt; height: %dpt\"", graphWidth, graphHeight);
330  gvprintf(job, " coordorigin=\"0,0\" coordsize=\"%d,%d\" >", graphWidth, graphHeight);
331 }
332 
333 static void vml_end_graph(GVJ_t * job)
334 {
335  gvputs(job, "</v:group>\n");
336  gvputs(job, "</DIV>\n");
337  /* add 10pt pad to the bottom of the graph */
338  gvputs(job, "<DIV id='_VML2_' style=\"position:relative;visibility:hidden\">\n");
339  gvputs(job, "<!-- insert any other html content here -->\n");
340  gvputs(job, "</DIV>\n");
341  gvputs(job, "<DIV id='_notVML1_' style=\"position:relative;\">\n");
342  gvputs(job, "<!-- this should only display on NON-IE browsers -->\n");
343  gvputs(job, "<H2>Sorry, this diagram will only display correctly on Internet Explorer 5 (and up) browsers.</H2>\n");
344  gvputs(job, "</DIV>\n");
345  gvputs(job, "<DIV id='_notVML2_' style=\"position:relative;\">\n");
346  gvputs(job, "<!-- insert any other NON-IE html content here -->\n");
347  gvputs(job, "</DIV>\n");
348 
349  gvputs(job, "</BODY>\n</HTML>\n");
350 }
351 
352 static void
353 vml_begin_anchor(GVJ_t * job, char *href, char *tooltip, char *target, char *id)
354 {
355  gvputs(job, "<a");
356  if (href && href[0])
357  gvprintf(job, " href=\"%s\"", html_string(href));
358  if (tooltip && tooltip[0])
359  gvprintf(job, " title=\"%s\"", html_string(tooltip));
360  if (target && target[0])
361  gvprintf(job, " target=\"%s\"", html_string(target));
362  gvputs(job, ">\n");
363 }
364 
365 static void vml_end_anchor(GVJ_t * job)
366 {
367  gvputs(job, "</a>\n");
368 }
369 
370 static void vml_textspan(GVJ_t * job, pointf p, textspan_t * span)
371 {
372  pointf p1,p2;
373  obj_state_t *obj = job->obj;
374  PostscriptAlias *pA;
375 
376  switch (span->just) {
377  case 'l':
378  p1.x=p.x;
379  break;
380  case 'r':
381  p1.x=p.x-span->size.x;
382  break;
383  default:
384  case 'n':
385  p1.x=p.x-(span->size.x/2);
386  break;
387  }
388  p2.x=p1.x+span->size.x;
389  if (span->size.y < span->font->size){
390  span->size.y = 1 + (1.1*span->font->size);
391  }
392 
393  p1.x-=8; /* vml textbox margin fudge factor */
394  p2.x+=8; /* vml textbox margin fudge factor */
395  p2.y=graphHeight-(p.y);
396  p1.y=(p2.y-span->size.y);
397  /* text "y" was too high
398  * Graphviz uses "baseline", VML seems to use bottom of descenders - so we fudge a little
399  * (heuristics - based on eyeballs) */
400  if (span->font->size <12.){ /* see graphs/directed/arrows.gv */
401  p1.y+=1.4+span->font->size/5; /* adjust by approx. descender */
402  p2.y+=1.4+span->font->size/5; /* adjust by approx. descender */
403  }else{
404  p1.y+=2+span->font->size/5; /* adjust by approx. descender */
405  p2.y+=2+span->font->size/5; /* adjust by approx. descender */
406  }
407 
408  gvprintf(job, "<v:rect style=\"position:absolute; ");
409  gvprintf(job, " left: %.2f; top: %.2f;", p1.x, p1.y);
410  gvprintf(job, " width: %.2f; height: %.2f\"", p2.x-p1.x, p2.y-p1.y);
411  gvputs(job, " stroked=\"false\" filled=\"false\">\n");
412  gvputs(job, "<v:textbox inset=\"0,0,0,0\" style=\"position:absolute; v-text-wrapping:'false';padding:'0';");
413 
414  pA = span->font->postscript_alias;
415  if (pA) {
416  gvprintf(job, "font-family: '%s';", pA->family);
417  if (pA->weight)
418  gvprintf(job, "font-weight: %s;", pA->weight);
419  if (pA->stretch)
420  gvprintf(job, "font-stretch: %s;", pA->stretch);
421  if (pA->style)
422  gvprintf(job, "font-style: %s;", pA->style);
423  }
424  else {
425  gvprintf(job, "font-family: \'%s\';", span->font->name);
426  }
427  gvprintf(job, " font-size: %.2fpt;", span->font->size);
428  switch (obj->pencolor.type) {
429  case COLOR_STRING:
430  if (strcasecmp(obj->pencolor.u.string, "black"))
431  gvprintf(job, "color:%s;", obj->pencolor.u.string);
432  break;
433  case RGBA_BYTE:
434  gvprintf(job, "color:#%02x%02x%02x;",
435  obj->pencolor.u.rgba[0], obj->pencolor.u.rgba[1], obj->pencolor.u.rgba[2]);
436  break;
437  default:
438  assert(0); /* internal error */
439  }
440  gvputs(job, "\"><center>");
441  gvputs(job, html_string(span->str));
442  gvputs(job, "</center></v:textbox>\n");
443  gvputs(job, "</v:rect>\n");
444 }
445 
446 static void vml_ellipse(GVJ_t * job, pointf * A, int filled)
447 {
448  double dx, dy, left, right, top, bottom;
449 
450  /* A[] contains 2 points: the center and corner. */
451  gvputs(job, " <v:oval style=\"position:absolute;");
452 
453  dx=A[1].x-A[0].x;
454  dy=A[1].y-A[0].y;
455 
456  top=graphHeight-(A[0].y+dy);
457  bottom=top+dy+dy;
458  left=A[0].x - dx;
459  right=A[1].x;
460  gvprintf(job, " left: %.2f; top: %.2f;",left, top);
461  gvprintf(job, " width: %.2f; height: %.2f\"", 2*dx, 2*dy);
462 
463  vml_grfill(job, filled);
464  gvputs(job, " >");
465  vml_grstroke(job, filled);
466  gvputs(job, "</v:oval>\n");
467 }
468 
469 static void
470 vml_bezier(GVJ_t * job, pointf * A, int n, int arrow_at_start,
471  int arrow_at_end, int filled)
472 {
473  gvputs(job, " <v:shape style=\"position:absolute; ");
474  gvprintf(job, " width: %d; height: %d\"", graphWidth, graphHeight);
475 
476  vml_grfill(job, filled);
477  gvputs(job, " >");
478  vml_grstroke(job, filled);
479  gvputs(job, "<v:path v=\"");
480  vml_bzptarray(job, A, n);
481  gvputs(job, "/></v:shape>\n");
482 }
483 
484 static void vml_polygon(GVJ_t * job, pointf * A, int n, int filled)
485 {
486  int i;
487  double px,py;
488 
489  gvputs(job, " <v:shape style=\"position:absolute; ");
490  gvprintf(job, " width: %d; height: %d\"", graphWidth, graphHeight);
491  vml_grfill(job, filled);
492  gvputs(job, " >");
493  vml_grstroke(job, filled);
494 
495  gvputs(job, "<v:path v=\"");
496  for (i = 0; i < n; i++)
497  {
498  px=A[i].x;
499  py= (graphHeight-A[i].y);
500  if (i==0){
501  gvputs(job, "m ");
502  }
503  /* integers only in path */
504  gvprintf(job, "%.0f %.0f ", px, py);
505  if (i==0) gvputs(job, "l ");
506  if (i==n-1) gvputs(job, "x e \"/>");
507  }
508  gvputs(job, "</v:shape>\n");
509 }
510 
511 static void vml_polyline(GVJ_t * job, pointf * A, int n)
512 {
513  int i;
514 
515  gvputs(job, " <v:shape style=\"position:absolute; ");
516  gvprintf(job, " width: %d; height: %d\" filled=\"false\">", graphWidth, graphHeight);
517  gvputs(job, "<v:path v=\"");
518  for (i = 0; i < n; i++)
519  {
520  if (i==0) gvputs(job, " m ");
521  gvprintf(job, "%.0f,%.0f ", A[i].x, graphHeight-A[i].y);
522  if (i==0) gvputs(job, " l ");
523  if (i==n-1) gvputs(job, " e "); /* no x here for polyline */
524  }
525  gvputs(job, "\"/>");
526  vml_grstroke(job, 0); /* no fill here for polyline */
527  gvputs(job, "</v:shape>\n");
528 }
529 
530 /* color names from
531  http://msdn.microsoft.com/en-us/library/bb250525(VS.85).aspx#t.color
532 */
533 /* NB. List must be LANG_C sorted */
534 static char *vml_knowncolors[] = {
535  "aqua", "black", "blue", "fuchsia",
536  "gray", "green", "lime", "maroon",
537  "navy", "olive", "purple", "red",
538  "silver", "teal", "white", "yellow"
539 };
540 
542  vml_begin_job,
543  0, /* vml_end_job */
544  vml_begin_graph,
545  vml_end_graph,
546  0, /* vml_begin_layer */
547  0, /* vml_end_layer */
548  0, /* vml_begin_page */
549  0, /* vml_end_page */
550  0, /* vml_begin_cluster */
551  0, /* vml_end_cluster */
552  0, /* vml_begin_nodes */
553  0, /* vml_end_nodes */
554  0, /* vml_begin_edges */
555  0, /* vml_end_edges */
556  0, /* vml_begin_node */
557  0, /* vml_end_node */
558  0, /* vml_begin_edge */
559  0, /* vml_end_edge */
560  vml_begin_anchor,
561  vml_end_anchor,
562  0, /* vml_begin_label */
563  0, /* vml_end_label */
564  vml_textspan,
565  0, /* vml_resolve_color */
566  vml_ellipse,
567  vml_polygon,
568  vml_bezier,
569  vml_polyline,
570  vml_comment,
571  0, /* vml_library_shape */
572 };
573 
580  | GVRENDER_DOES_TOOLTIPS, /* flags */
581  0., /* default pad - graph units */
582  vml_knowncolors, /* knowncolors */
583  sizeof(vml_knowncolors) / sizeof(char *), /* sizeof knowncolors */
584  RGBA_BYTE, /* color_type */
585 };
586 
588  GVDEVICE_DOES_TRUECOLOR, /* flags */
589  {0.,0.}, /* default margin - points */
590  {0.,0.}, /* default page width, height - points */
591  {96.,96.}, /* default dpi */
592 };
593 
596  | GVDEVICE_COMPRESSED_FORMAT, /* flags */
597  {0.,0.}, /* default margin - points */
598  {0.,0.}, /* default page width, height - points */
599  {96.,96.}, /* default dpi */
600 };
601 
603  {FORMAT_VML, "vml", 1, &vml_engine, &render_features_vml},
604  {0, NULL, 0, NULL, NULL}
605 };
606 
608  {FORMAT_VML, "vml:vml", 1, NULL, &device_features_vml},
609 #if HAVE_LIBZ
610  {FORMAT_VMLZ, "vmlz:vml", 1, NULL, &device_features_vmlz},
611 #endif
612  {0, NULL, 0, NULL, NULL}
613 };
614 
void s1(graph_t *, node_t *)
Definition: stuff.c:686
#define PENWIDTH_NORMAL
Definition: gvcjob.h:40
pointf size
Definition: textspan.h:64
union color_s::@10 u
unsigned int graphWidth
void * grealloc(void *ptr, size_t size)
Definition: memory.c:54
gvdevice_features_t device_features_vml
gvplugin_installed_t gvrender_vml_types[]
gvplugin_installed_t gvdevice_vml_types[]
char * weight
Definition: textspan.h:35
pen_type pen
Definition: gvcjob.h:206
double size
Definition: textspan.h:52
char * stretch
Definition: textspan.h:36
point pagesArraySize
Definition: gvcjob.h:313
#define assert(x)
Definition: cghdr.h:47
Definition: geom.h:28
gvrender_features_t render_features_vml
void * gmalloc(size_t nbytes)
Definition: memory.c:42
Definition: color.h:34
gvdevice_features_t device_features_vmlz
gvcolor_t pencolor
Definition: gvcjob.h:203
Definition: gvcjob.h:271
char * name
Definition: textspan.h:49
int x
Definition: geom.h:26
#define GVRENDER_DOES_TRANSFORM
Definition: gvcjob.h:97
unsigned int graphHeight
obj_state_t * obj
Definition: gvcjob.h:278
char * html_string(char *s)
gvrender_engine_t vml_engine
#define GVRENDER_Y_GOES_DOWN
Definition: gvcjob.h:96
int gvputs(GVJ_t *job, const char *s)
Definition: gvdevice.c:270
char * str
Definition: textspan.h:59
color_type_t type
Definition: color.h:44
#define GVRENDER_DOES_TARGETS
Definition: gvcjob.h:107
int
Definition: grammar.c:1264
#define GVRENDER_DOES_TOOLTIPS
Definition: gvcjob.h:106
double y
Definition: geom.h:28
CGRAPH_API char * agnameof(void *)
Definition: id.c:143
char * string
Definition: color.h:41
GVCOMMON_t * common
Definition: gvcjob.h:276
char ** info
Definition: gvcommon.h:22
PostscriptAlias * postscript_alias
Definition: textspan.h:51
Definition: grammar.c:79
boxf bb
Definition: gvcjob.h:320
graph_t * g
Definition: gvcjob.h:195
#define sub(h, i)
Definition: closest.c:75
format_type
#define GVRENDER_DOES_MAPS
Definition: gvcjob.h:100
#define NULL
Definition: logic.h:39
double x
Definition: geom.h:28
#define right(i)
Definition: closest.c:87
#define top(sp)
Definition: stack.h:35
int strcasecmp(const char *s1, const char *s2)
Definition: strcasecmp.c:21
char just
Definition: textspan.h:65
char * style
Definition: textspan.h:37
pointf LL
Definition: geom.h:35
#define GVDEVICE_COMPRESSED_FORMAT
Definition: gvcjob.h:94
union obj_state_s::@23 u
#define left
Definition: dthdr.h:16
#define GVRENDER_DOES_LABELS
Definition: gvcjob.h:99
agxbuf * str
Definition: htmlparse.c:85
gvcolor_t fillcolor
Definition: gvcjob.h:203
double penwidth
Definition: gvcjob.h:208
int y
Definition: geom.h:26
unsigned char rgba[4]
Definition: color.h:38
char * family
Definition: textspan.h:34
pointf UR
Definition: geom.h:35
#define GVDEVICE_DOES_TRUECOLOR
Definition: gvcjob.h:92
void gvprintf(GVJ_t *job, const char *format,...)
Definition: gvdevice.c:389
textfont_t * font
Definition: textspan.h:60