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 <stdlib.h> |
17 | #include <string.h> |
18 | #include <stdarg.h> |
19 | #include <ctype.h> |
20 | |
21 | #include "gvplugin_render.h" |
22 | #include "gvplugin_device.h" |
23 | #include "gvio.h" |
24 | #include "agxbuf.h" |
25 | #include "utils.h" |
26 | #include "color.h" |
27 | #include "colorprocs.h" |
28 | |
29 | #include "const.h" |
30 | |
31 | /* Number of points to split splines into */ |
32 | #define BEZIERSUBDIVISION 6 |
33 | |
34 | #define PIC_COORDS_PER_LINE (16) /* to avoid stdio BUF overflow */ |
35 | |
36 | typedef enum { FORMAT_PIC, } format_type; |
37 | |
38 | static int onetime = TRUE; |
39 | static double Fontscale; |
40 | |
41 | /* There are a couple of ways to generate output: |
42 | 1. generate for whatever size is given by the bounding box |
43 | - the drawing at its "natural" size might not fit on a physical page |
44 | ~ dot size specification can be used to scale the drawing |
45 | ~ and it's not difficult for user to scale the pic output to fit (multiply 4 (3 distinct) numbers on 3 lines by a scale factor) |
46 | - some troff implementations may clip large graphs |
47 | ~ handle by scaling to manageable size |
48 | - give explicit width and height as parameters to .PS |
49 | - pic scale variable is reset to 1.0 |
50 | - fonts are printed as size specified by caller, modified by user scaling |
51 | 2. scale to fit on a physical page |
52 | - requires an assumption of page size (GNU pic assumes 8.5x11.0 inches) |
53 | ~ any assumption is bound to be wrong more often than right |
54 | - requires separate scaling of font point sizes since pic's scale variable doesn't affect text |
55 | ~ possible, as above |
56 | - likewise for line thickness |
57 | - GNU pic does this (except for fonts) if .PS is used without explicit width or height; DWB pic does not |
58 | ~ pic variants likely to cause trouble |
59 | The first approach is used here. |
60 | */ |
61 | |
62 | static const char * = ".\\\" " ; /* troff comment */ |
63 | static const char picgen_msghdr[] = "dot pic plugin: " ; |
64 | |
65 | static void unsupported(char *s) |
66 | { |
67 | agerr(AGWARN, "%s%s unsupported\n" , picgen_msghdr, s); |
68 | } |
69 | |
70 | /* troff font mapping */ |
71 | typedef struct { |
72 | char trname[3], *psname; |
73 | } fontinfo; |
74 | |
75 | static fontinfo fonttab[] = { |
76 | {"AB" , "AvantGarde-Demi" }, |
77 | {"AI" , "AvantGarde-BookOblique" }, |
78 | {"AR" , "AvantGarde-Book" }, |
79 | {"AX" , "AvantGarde-DemiOblique" }, |
80 | {"B " , "Times-Bold" }, |
81 | {"BI" , "Times-BoldItalic" }, |
82 | {"CB" , "Courier-Bold" }, |
83 | {"CO" , "Courier" }, |
84 | {"CX" , "Courier-BoldOblique" }, |
85 | {"H " , "Helvetica" }, |
86 | {"HB" , "Helvetica-Bold" }, |
87 | {"HI" , "Helvetica-Oblique" }, |
88 | {"HX" , "Helvetica-BoldOblique" }, |
89 | {"Hb" , "Helvetica-Narrow-Bold" }, |
90 | {"Hi" , "Helvetica-Narrow-Oblique" }, |
91 | {"Hr" , "Helvetica-Narrow" }, |
92 | {"Hx" , "Helvetica-Narrow-BoldOblique" }, |
93 | {"I " , "Times-Italic" }, |
94 | {"KB" , "Bookman-Demi" }, |
95 | {"KI" , "Bookman-LightItalic" }, |
96 | {"KR" , "Bookman-Light" }, |
97 | {"KX" , "Bookman-DemiItalic" }, |
98 | {"NB" , "NewCenturySchlbk-Bold" }, |
99 | {"NI" , "NewCenturySchlbk-Italic" }, |
100 | {"NR" , "NewCenturySchlbk-Roman" }, |
101 | {"NX" , "NewCenturySchlbk-BoldItalic" }, |
102 | {"PA" , "Palatino-Roman" }, |
103 | {"PB" , "Palatino-Bold" }, |
104 | {"PI" , "Palatino-Italic" }, |
105 | {"PX" , "Palatino-BoldItalic" }, |
106 | {"R " , "Times-Roman" }, |
107 | {"S " , "Symbol" }, |
108 | {"ZD" , "ZapfDingbats" }, |
109 | {"\000\000" , (char *) 0} |
110 | }; |
111 | |
112 | static char *picfontname(char *psname) |
113 | { |
114 | char *rv; |
115 | fontinfo *p; |
116 | |
117 | for (p = fonttab; p->psname; p++) |
118 | if (strcmp(p->psname, psname) == 0) |
119 | break; |
120 | if (p->psname) |
121 | rv = p->trname; |
122 | else { |
123 | agerr(AGERR, "%s%s is not a troff font\n" , picgen_msghdr, psname); |
124 | /* try base font names, e.g. Helvetica-Outline-Oblique -> Helvetica-Outline -> Helvetica */ |
125 | if ((rv = strrchr(psname, '-'))) { |
126 | *rv = '\0'; /* psname is not specified as const ... */ |
127 | rv = picfontname(psname); |
128 | } else |
129 | rv = "R" ; |
130 | } |
131 | return rv; |
132 | } |
133 | |
134 | static void picptarray(GVJ_t *job, pointf * A, int n, int close) |
135 | { |
136 | int i; |
137 | point p; |
138 | |
139 | for (i = 0; i < n; i++) { |
140 | PF2P(A[i],p); |
141 | gvprintf(job, " %d %d" , p.x, p.y); |
142 | } |
143 | if (close) { |
144 | PF2P(A[0],p); |
145 | gvprintf(job, " %d %d" , p.x, p.y); |
146 | } |
147 | gvputs(job, "\n" ); |
148 | } |
149 | |
150 | static char *pic_string(char *s) |
151 | { |
152 | static char *buf = NULL; |
153 | static int bufsize = 0; |
154 | int pos = 0; |
155 | char *p; |
156 | unsigned char c; |
157 | |
158 | if (!buf) { |
159 | bufsize = 64; |
160 | buf = malloc(bufsize * sizeof(char)); |
161 | } |
162 | |
163 | p = buf; |
164 | while ((c = *s++)) { |
165 | if (pos > (bufsize - 8)) { |
166 | bufsize *= 2; |
167 | buf = realloc(buf, bufsize * sizeof(char)); |
168 | p = buf + pos; |
169 | } |
170 | if (isascii(c)) { |
171 | if (c == '\\') { |
172 | *p++ = '\\'; |
173 | pos++; |
174 | } |
175 | *p++ = c; |
176 | pos++; |
177 | } else { |
178 | *p++ = '\\'; |
179 | sprintf(p, "%03o" , c); |
180 | p += 3; |
181 | pos += 4; |
182 | } |
183 | } |
184 | *p = '\0'; |
185 | return buf; |
186 | } |
187 | |
188 | static void pic_line_style(obj_state_t *obj, int *line_style, double *style_val) |
189 | { |
190 | switch (obj->pen) { |
191 | case PEN_DASHED: |
192 | *line_style = 1; |
193 | *style_val = 10.; |
194 | break; |
195 | case PEN_DOTTED: |
196 | *line_style = 2; |
197 | *style_val = 10.; |
198 | break; |
199 | case PEN_SOLID: |
200 | default: |
201 | *line_style = 0; |
202 | *style_val = 0.; |
203 | break; |
204 | } |
205 | } |
206 | |
207 | static void (GVJ_t *job, char *str) |
208 | { |
209 | gvprintf(job, "%s %s\n" , EscComment, str); |
210 | } |
211 | |
212 | static void pic_begin_graph(GVJ_t * job) |
213 | { |
214 | obj_state_t *obj = job->obj; |
215 | |
216 | gvprintf(job, "%s Creator: %s version %s (%s)\n" , |
217 | EscComment, job->common->info[0], job->common->info[1], job->common->info[2]); |
218 | gvprintf(job, "%s Title: %s\n" , EscComment, agnameof(obj->u.g)); |
219 | gvprintf(job, |
220 | "%s save point size and font\n.nr .S \\n(.s\n.nr DF \\n(.f\n" , |
221 | EscComment); |
222 | } |
223 | |
224 | static void pic_end_graph(GVJ_t * job) |
225 | { |
226 | gvprintf(job, |
227 | "%s restore point size and font\n.ps \\n(.S\n.ft \\n(DF\n" , |
228 | EscComment); |
229 | } |
230 | |
231 | static void pic_begin_page(GVJ_t * job) |
232 | { |
233 | box pbr = job->pageBoundingBox; |
234 | double height, width; |
235 | |
236 | if (onetime && job->rotation && (job->rotation != 90)) { |
237 | unsupported("rotation" ); |
238 | onetime = FALSE; |
239 | } |
240 | height = PS2INCH((double) (pbr.UR.y) - (double) (pbr.LL.y)); |
241 | width = PS2INCH((double) (pbr.UR.x) - (double) (pbr.LL.x)); |
242 | if (job->rotation == 90) { |
243 | double temp = width; |
244 | width = height; |
245 | height = temp; |
246 | } |
247 | gvprintf(job, ".PS %.5f %.5f\n" , width, height); |
248 | gvprintf(job, |
249 | "%s to change drawing size, multiply the width and height on the .PS line above and the number on the two lines below (rounded to the nearest integer) by a scale factor\n" , |
250 | EscComment); |
251 | if (width > 0.0) { |
252 | Fontscale = log10(width); |
253 | Fontscale += 3.0 - (int) Fontscale; /* between 3.0 and 4.0 */ |
254 | } else |
255 | Fontscale = 3.0; |
256 | Fontscale = pow(10.0, Fontscale); /* a power of 10 times width, between 1000 and 10000 */ |
257 | gvprintf(job, ".nr SF %.0f\nscalethickness = %.0f\n" , Fontscale, |
258 | Fontscale); |
259 | gvprintf(job, |
260 | "%s don't change anything below this line in this drawing\n" , |
261 | EscComment); |
262 | gvprintf(job, |
263 | "%s non-fatal run-time pic version determination, version 2\n" , |
264 | EscComment); |
265 | gvprintf(job, |
266 | "boxrad=2.0 %s will be reset to 0.0 by gpic only\n" , |
267 | EscComment); |
268 | gvprintf(job, "scale=1.0 %s required for comparisons\n" , |
269 | EscComment); |
270 | gvprintf(job, |
271 | "%s boxrad is now 0.0 in gpic, else it remains 2.0\n" , |
272 | EscComment); |
273 | gvprintf(job, |
274 | "%s dashwid is 0.1 in 10th Edition, 0.05 in DWB 2 and in gpic\n" , |
275 | EscComment); |
276 | gvprintf(job, |
277 | "%s fillval is 0.3 in 10th Edition (fill 0 means black), 0.5 in gpic (fill 0 means white), undefined in DWB 2\n" , |
278 | EscComment); |
279 | gvprintf(job, |
280 | "%s fill has no meaning in DWB 2, gpic can use fill or filled, 10th Edition uses fill only\n" , |
281 | EscComment); |
282 | gvprintf(job, |
283 | "%s DWB 2 doesn't use fill and doesn't define fillval\n" , |
284 | EscComment); |
285 | gvprintf(job, |
286 | "%s reset works in gpic and 10th edition, but isn't defined in DWB 2\n" , |
287 | EscComment); |
288 | gvprintf(job, "%s DWB 2 compatibility definitions\n" , |
289 | EscComment); |
290 | gvprintf(job, |
291 | "if boxrad > 1.0 && dashwid < 0.075 then X\n\tfillval = 1;\n\tdefine fill Y Y;\n\tdefine solid Y Y;\n\tdefine reset Y scale=1.0 Y;\nX\n" ); |
292 | gvprintf(job, "reset %s set to known state\n" , EscComment); |
293 | gvprintf(job, "%s GNU pic vs. 10th Edition d\\(e'tente\n" , |
294 | EscComment); |
295 | gvprintf(job, |
296 | "if fillval > 0.4 then X\n\tdefine setfillval Y fillval = 1 - Y;\n\tdefine bold Y thickness 2 Y;\n" ); |
297 | gvprintf(job, |
298 | "\t%s if you use gpic and it barfs on encountering \"solid\",\n" , |
299 | EscComment); |
300 | gvprintf(job, |
301 | "\t%s\tinstall a more recent version of gpic or switch to DWB or 10th Edition pic;\n" , |
302 | EscComment); |
303 | gvprintf(job, |
304 | "\t%s\tsorry, the groff folks changed gpic; send any complaint to them;\n" , |
305 | EscComment); |
306 | gvprintf(job, |
307 | "X else Z\n\tdefine setfillval Y fillval = Y;\n\tdefine bold Y Y;\n\tdefine filled Y fill Y;\nZ\n" ); |
308 | gvprintf(job, |
309 | "%s arrowhead has no meaning in DWB 2, arrowhead = 7 makes filled arrowheads in gpic and in 10th Edition\n" , |
310 | EscComment); |
311 | gvprintf(job, |
312 | "%s arrowhead is undefined in DWB 2, initially 1 in gpic, 2 in 10th Edition\n" , |
313 | EscComment); |
314 | gvprintf(job, "arrowhead = 7 %s not used by graphviz\n" , |
315 | EscComment); |
316 | gvprintf(job, |
317 | "%s GNU pic supports a boxrad variable to draw boxes with rounded corners; DWB and 10th Ed. do not\n" , |
318 | EscComment); |
319 | gvprintf(job, "boxrad = 0 %s no rounded corners in graphviz\n" , |
320 | EscComment); |
321 | gvprintf(job, |
322 | "%s GNU pic supports a linethick variable to set line thickness; DWB and 10th Ed. do not\n" , |
323 | EscComment); |
324 | gvprintf(job, "linethick = 0; oldlinethick = linethick\n" ); |
325 | gvprintf(job, |
326 | "%s .PS w/o args causes GNU pic to scale drawing to fit 8.5x11 paper; DWB does not\n" , |
327 | EscComment); |
328 | gvprintf(job, |
329 | "%s maxpsht and maxpswid have no meaning in DWB 2.0, set page boundaries in gpic and in 10th Edition\n" , |
330 | EscComment); |
331 | gvprintf(job, |
332 | "%s maxpsht and maxpswid are predefined to 11.0 and 8.5 in gpic\n" , |
333 | EscComment); |
334 | gvprintf(job, "maxpsht = %f\nmaxpswid = %f\n" , height, width); |
335 | gvprintf(job, "Dot: [\n" ); |
336 | gvprintf(job, |
337 | "define attrs0 %% %%; define unfilled %% %%; define rounded %% %%; define diagonals %% %%\n" ); |
338 | } |
339 | |
340 | static void pic_end_page(GVJ_t * job) |
341 | { |
342 | gvprintf(job, |
343 | "]\n.PE\n" ); |
344 | } |
345 | |
346 | static void pic_textspan(GVJ_t * job, pointf p, textspan_t * span) |
347 | { |
348 | static char *lastname; |
349 | static int lastsize; |
350 | int sz; |
351 | |
352 | switch (span->just) { |
353 | case 'l': |
354 | break; |
355 | case 'r': |
356 | p.x -= span->size.x; |
357 | break; |
358 | default: |
359 | case 'n': |
360 | p.x -= span->size.x / 2; |
361 | break; |
362 | } |
363 | /* Why on earth would we do this. But it works. SCN 2/26/2002 */ |
364 | p.y += span->font->size / (3.0 * POINTS_PER_INCH); |
365 | p.x += span->size.x / (2.0 * POINTS_PER_INCH); |
366 | |
367 | if (span->font->name && (!(lastname) || strcmp(lastname, span->font->name))) { |
368 | gvprintf(job, ".ft %s\n" , picfontname(span->font->name)); |
369 | lastname = span->font->name; |
370 | } |
371 | if ((sz = (int)span->font->size) < 1) |
372 | sz = 1; |
373 | if (sz != lastsize) { |
374 | gvprintf(job, ".ps %d*\\n(SFu/%.0fu\n" , sz, Fontscale); |
375 | lastsize = sz; |
376 | } |
377 | gvprintf(job, "\"%s\" at (%.5f,%.5f);\n" , |
378 | pic_string(span->str), p.x, p.y); |
379 | } |
380 | |
381 | static void pic_ellipse(GVJ_t * job, pointf * A, int filled) |
382 | { |
383 | /* A[] contains 2 points: the center and corner. */ |
384 | |
385 | gvprintf(job, |
386 | "ellipse attrs%d %swid %.5f ht %.5f at (%.5f,%.5f);\n" , 1, |
387 | filled ? "fill " : "" , |
388 | PS2INCH(2*(A[1].x - A[0].x)), |
389 | PS2INCH(2*(A[1].y - A[0].y)), |
390 | PS2INCH(A[0].x), |
391 | PS2INCH(A[0].y)); |
392 | } |
393 | |
394 | static void pic_bezier(GVJ_t * job, pointf * A, int n, int arrow_at_start, |
395 | // start_y, end_x, end_y); |
396 | int arrow_at_end, int filled) |
397 | { |
398 | obj_state_t *obj = job->obj; |
399 | |
400 | // int object_code = 3; /* always 3 for spline */ |
401 | int sub_type; |
402 | int line_style; /* solid, dotted, dashed */ |
403 | // int thickness = obj->penwidth; |
404 | // int pen_color = obj->pencolor.u.index; |
405 | int fill_color = obj->fillcolor.u.index; |
406 | // int pen_style = 0; /* not used */ |
407 | int area_fill; |
408 | double style_val; |
409 | // int cap_style = 0; |
410 | // int forward_arrow = 0; |
411 | // int backward_arrow = 0; |
412 | int npoints = n; |
413 | int i; |
414 | |
415 | pointf pf, V[4]; |
416 | point p; |
417 | int j, step; |
418 | int count = 0; |
419 | int size; |
420 | |
421 | char *buffer; |
422 | char *buf; |
423 | buffer = |
424 | malloc((npoints + 1) * (BEZIERSUBDIVISION + |
425 | 1) * 20 * sizeof(char)); |
426 | buf = buffer; |
427 | |
428 | pic_line_style(obj, &line_style, &style_val); |
429 | |
430 | if (filled) { |
431 | sub_type = 5; /* closed X-spline */ |
432 | area_fill = 20; /* fully saturated color */ |
433 | fill_color = job->obj->fillcolor.u.index; |
434 | } |
435 | else { |
436 | sub_type = 4; /* opened X-spline */ |
437 | area_fill = -1; |
438 | fill_color = 0; |
439 | } |
440 | V[3].x = A[0].x; |
441 | V[3].y = A[0].y; |
442 | /* Write first point in line */ |
443 | count++; |
444 | PF2P(A[0], p); |
445 | size = sprintf(buf, " %d %d" , p.x, p.y); |
446 | buf += size; |
447 | /* write subsequent points */ |
448 | for (i = 0; i + 3 < n; i += 3) { |
449 | V[0] = V[3]; |
450 | for (j = 1; j <= 3; j++) { |
451 | V[j].x = A[i + j].x; |
452 | V[j].y = A[i + j].y; |
453 | } |
454 | for (step = 1; step <= BEZIERSUBDIVISION; step++) { |
455 | count++; |
456 | pf = Bezier (V, 3, (double) step / BEZIERSUBDIVISION, NULL, NULL); |
457 | PF2P(pf, p); |
458 | size = sprintf(buf, " %d %d" , p.x, p.y); |
459 | buf += size; |
460 | } |
461 | } |
462 | |
463 | // gvprintf(job, "%d %d %d %d %d %d %d %d %d %.1f %d %d %d %d\n", |
464 | // object_code, |
465 | // sub_type, |
466 | // line_style, |
467 | // thickness, |
468 | // pen_color, |
469 | // fill_color, |
470 | // depth, |
471 | // pen_style, |
472 | // area_fill, |
473 | // style_val, cap_style, forward_arrow, backward_arrow, count); |
474 | |
475 | gvprintf(job, " %s\n" , buffer); /* print points */ |
476 | free(buffer); |
477 | for (i = 0; i < count; i++) { |
478 | gvprintf(job, " %d" , i % (count + 1) ? 1 : 0); /* -1 on all */ |
479 | } |
480 | gvputs(job, "\n" ); |
481 | } |
482 | |
483 | static void pic_polygon(GVJ_t * job, pointf * A, int n, int filled) |
484 | { |
485 | obj_state_t *obj = job->obj; |
486 | |
487 | // int object_code = 2; /* always 2 for polyline */ |
488 | // int sub_type = 3; /* always 3 for polygon */ |
489 | int line_style; /* solid, dotted, dashed */ |
490 | // int thickness = obj->penwidth; |
491 | // int pen_color = obj->pencolor.u.index; |
492 | // int fill_color = obj->fillcolor.u.index; |
493 | // int pen_style = 0; /* not used */ |
494 | // int area_fill = filled ? 20 : -1; |
495 | double style_val; |
496 | // int join_style = 0; |
497 | // int cap_style = 0; |
498 | // int radius = 0; |
499 | // int forward_arrow = 0; |
500 | // int backward_arrow = 0; |
501 | // int npoints = n + 1; |
502 | |
503 | pic_line_style(obj, &line_style, &style_val); |
504 | |
505 | // gvprintf(job, |
506 | // "%d %d %d %d %d %d %d %d %d %.1f %d %d %d %d %d %d\n", |
507 | // object_code, sub_type, line_style, thickness, pen_color, |
508 | // fill_color, depth, pen_style, area_fill, style_val, join_style, |
509 | // cap_style, radius, forward_arrow, backward_arrow, npoints); |
510 | picptarray(job, A, n, 1); /* closed shape */ |
511 | } |
512 | |
513 | static void pic_polyline(GVJ_t * job, pointf * A, int n) |
514 | { |
515 | obj_state_t *obj = job->obj; |
516 | |
517 | // int object_code = 2; /* always 2 for polyline */ |
518 | // int sub_type = 1; /* always 1 for polyline */ |
519 | int line_style; /* solid, dotted, dashed */ |
520 | // int thickness = obj->penwidth; |
521 | // int pen_color = obj->pencolor.u.index; |
522 | // int fill_color = 0; |
523 | // int pen_style = 0; /* not used */ |
524 | // int area_fill = 0; |
525 | double style_val; |
526 | // int join_style = 0; |
527 | // int cap_style = 0; |
528 | // int radius = 0; |
529 | // int forward_arrow = 0; |
530 | // int backward_arrow = 0; |
531 | // int npoints = n; |
532 | |
533 | pic_line_style(obj, &line_style, &style_val); |
534 | |
535 | // gvprintf(job, |
536 | // "%d %d %d %d %d %d %d %d %d %.1f %d %d %d %d %d %d\n", |
537 | // object_code, sub_type, line_style, thickness, pen_color, |
538 | // fill_color, depth, pen_style, area_fill, style_val, join_style, |
539 | // cap_style, radius, forward_arrow, backward_arrow, npoints); |
540 | picptarray(job, A, n, 0); /* open shape */ |
541 | } |
542 | |
543 | gvrender_engine_t pic_engine = { |
544 | 0, /* pic_begin_job */ |
545 | 0, /* pic_end_job */ |
546 | pic_begin_graph, |
547 | pic_end_graph, |
548 | 0, /* pic_begin_layer */ |
549 | 0, /* pic_end_layer */ |
550 | pic_begin_page, |
551 | pic_end_page, |
552 | 0, /* pic_begin_cluster */ |
553 | 0, /* pic_end_cluster */ |
554 | 0, /* pic_begin_nodes */ |
555 | 0, /* pic_end_nodes */ |
556 | 0, /* pic_begin_edges */ |
557 | 0, /* pic_end_edges */ |
558 | 0, /* pic_begin_node */ |
559 | 0, /* pic_end_node */ |
560 | 0, /* pic_begin_edge */ |
561 | 0, /* pic_end_edge */ |
562 | 0, /* pic_begin_anchor */ |
563 | 0, /* pic_end_anchor */ |
564 | 0, /* pic_begin_label */ |
565 | 0, /* pic_end_label */ |
566 | pic_textspan, |
567 | 0, /* pic_resolve_color */ |
568 | pic_ellipse, |
569 | pic_polygon, |
570 | pic_bezier, |
571 | pic_polyline, |
572 | pic_comment, |
573 | 0, /* pic_library_shape */ |
574 | }; |
575 | |
576 | |
577 | static gvrender_features_t render_features_pic = { |
578 | 0, /* flags */ |
579 | 4., /* default pad - graph units */ |
580 | NULL, /* knowncolors */ |
581 | 0, /* sizeof knowncolors */ |
582 | HSVA_DOUBLE, /* color_type */ |
583 | }; |
584 | |
585 | static gvdevice_features_t device_features_pic = { |
586 | 0, /* flags */ |
587 | {0.,0.}, /* default margin - points */ |
588 | {0.,0.}, /* default page width, height - points */ |
589 | {72.,72.}, /* default dpi */ |
590 | }; |
591 | |
592 | gvplugin_installed_t gvrender_pic_types[] = { |
593 | {FORMAT_PIC, "pic" , -1, &pic_engine, &render_features_pic}, |
594 | {0, NULL, 0, NULL, NULL} |
595 | }; |
596 | |
597 | gvplugin_installed_t gvdevice_pic_types[] = { |
598 | {FORMAT_PIC, "pic:pic" , -1, NULL, &device_features_pic}, |
599 | {0, NULL, 0, NULL, NULL} |
600 | }; |
601 | |