|
Graphviz
2.29.20120524.0446
|
00001 /* $Id$ $Revision$ */ 00002 /* vim:set shiftwidth=4 ts=8: */ 00003 00004 /************************************************************************* 00005 * Copyright (c) 2011 AT&T Intellectual Property 00006 * All rights reserved. This program and the accompanying materials 00007 * are made available under the terms of the Eclipse Public License v1.0 00008 * which accompanies this distribution, and is available at 00009 * http://www.eclipse.org/legal/epl-v10.html 00010 * 00011 * Contributors: See CVS logs. Details at http://www.graphviz.org/ 00012 *************************************************************************/ 00013 00014 #ifdef HAVE_CONFIG_H 00015 #include "config.h" 00016 #endif 00017 00018 #include <stdlib.h> 00019 #include <string.h> 00020 #include <stdarg.h> 00021 #include <ctype.h> 00022 00023 #include "gvplugin_render.h" 00024 #include "gvplugin_device.h" 00025 #include "gvio.h" 00026 #include "agxbuf.h" 00027 #include "utils.h" 00028 #include "color.h" 00029 00030 #include "const.h" 00031 00032 /* Number of points to split splines into */ 00033 #define BEZIERSUBDIVISION 6 00034 00035 #define PIC_COORDS_PER_LINE (16) /* to avoid stdio BUF overflow */ 00036 00037 typedef enum { FORMAT_PIC, } format_type; 00038 00039 static int BezierSubdivision = 10; 00040 static int onetime = TRUE; 00041 static double Fontscale; 00042 00043 /* There are a couple of ways to generate output: 00044 1. generate for whatever size is given by the bounding box 00045 - the drawing at its "natural" size might not fit on a physical page 00046 ~ dot size specification can be used to scale the drawing 00047 ~ 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) 00048 - some troff implementations may clip large graphs 00049 ~ handle by scaling to manageable size 00050 - give explicit width and height as parameters to .PS 00051 - pic scale variable is reset to 1.0 00052 - fonts are printed as size specified by caller, modified by user scaling 00053 2. scale to fit on a physical page 00054 - requires an assumption of page size (GNU pic assumes 8.5x11.0 inches) 00055 ~ any assumption is bound to be wrong more often than right 00056 - requires separate scaling of font point sizes since pic's scale variable doesn't affect text 00057 ~ possible, as above 00058 - likewise for line thickness 00059 - GNU pic does this (except for fonts) if .PS is used without explicit width or height; DWB pic does not 00060 ~ pic variants likely to cause trouble 00061 The first approach is used here. 00062 */ 00063 00064 static const char *EscComment = ".\\\" "; /* troff comment */ 00065 static const char picgen_msghdr[] = "dot pic plugin: "; 00066 00067 static void unsupported(char *s) 00068 { 00069 agerr(AGWARN, "%s%s unsupported\n", picgen_msghdr, s); 00070 } 00071 static void warn(char *s) 00072 { 00073 agerr(AGWARN, "%s%s\n", picgen_msghdr, s); 00074 } 00075 00076 /* troff font mapping */ 00077 typedef struct { 00078 char trname[3], *psname; 00079 } fontinfo; 00080 00081 static fontinfo fonttab[] = { 00082 {"AB", "AvantGarde-Demi"}, 00083 {"AI", "AvantGarde-BookOblique"}, 00084 {"AR", "AvantGarde-Book"}, 00085 {"AX", "AvantGarde-DemiOblique"}, 00086 {"B ", "Times-Bold"}, 00087 {"BI", "Times-BoldItalic"}, 00088 {"CB", "Courier-Bold"}, 00089 {"CO", "Courier"}, 00090 {"CX", "Courier-BoldOblique"}, 00091 {"H ", "Helvetica"}, 00092 {"HB", "Helvetica-Bold"}, 00093 {"HI", "Helvetica-Oblique"}, 00094 {"HX", "Helvetica-BoldOblique"}, 00095 {"Hb", "Helvetica-Narrow-Bold"}, 00096 {"Hi", "Helvetica-Narrow-Oblique"}, 00097 {"Hr", "Helvetica-Narrow"}, 00098 {"Hx", "Helvetica-Narrow-BoldOblique"}, 00099 {"I ", "Times-Italic"}, 00100 {"KB", "Bookman-Demi"}, 00101 {"KI", "Bookman-LightItalic"}, 00102 {"KR", "Bookman-Light"}, 00103 {"KX", "Bookman-DemiItalic"}, 00104 {"NB", "NewCenturySchlbk-Bold"}, 00105 {"NI", "NewCenturySchlbk-Italic"}, 00106 {"NR", "NewCenturySchlbk-Roman"}, 00107 {"NX", "NewCenturySchlbk-BoldItalic"}, 00108 {"PA", "Palatino-Roman"}, 00109 {"PB", "Palatino-Bold"}, 00110 {"PI", "Palatino-Italic"}, 00111 {"PX", "Palatino-BoldItalic"}, 00112 {"R ", "Times-Roman"}, 00113 {"S ", "Symbol"}, 00114 {"ZD", "ZapfDingbats"}, 00115 {"\000\000", (char *) 0} 00116 }; 00117 00118 static char *picfontname(char *psname) 00119 { 00120 char *rv; 00121 fontinfo *p; 00122 00123 for (p = fonttab; p->psname; p++) 00124 if (strcmp(p->psname, psname) == 0) 00125 break; 00126 if (p->psname) 00127 rv = p->trname; 00128 else { 00129 agerr(AGERR, "%s%s is not a troff font\n", picgen_msghdr, psname); 00130 /* try base font names, e.g. Helvetica-Outline-Oblique -> Helvetica-Outline -> Helvetica */ 00131 if ((rv = strrchr(psname, '-'))) { 00132 *rv = '\0'; /* psname is not specified as const ... */ 00133 rv = picfontname(psname); 00134 } else 00135 rv = "R"; 00136 } 00137 return rv; 00138 } 00139 00140 static void pic_set_color(GVJ_t *job, char *name) 00141 { 00142 gvcolor_t color; 00143 00144 colorxlate(name, &color, HSVA_DOUBLE); 00145 /* just v used to set grayscale value */ 00146 gvprintf(job, "setfillval %f\n", color.u.HSVA[2]); 00147 } 00148 00149 static void pic_set_style(GVJ_t *job, char **s) 00150 { 00151 const char *line, *p; 00152 char skip = 0; 00153 char buf[BUFSIZ]; 00154 00155 buf[0] = '\0'; 00156 gvprintf(job, "define attrs%d %%", 0); 00157 while ((p = line = *s++)) { 00158 while (*p) 00159 p++; 00160 p++; 00161 while (*p) { 00162 if (!strcmp(line, "setlinewidth")) { /* a hack to handle the user-defined (PS) style spec in proc3d.gv */ 00163 long n = atol(p); 00164 00165 sprintf(buf, 00166 "oldlinethick = linethick;linethick = %ld * scalethickness / %.0f\n", 00167 n, Fontscale); 00168 skip = 1; 00169 } else 00170 gvprintf(job, " %s", p); 00171 while (*p) 00172 p++; 00173 p++; 00174 } 00175 if (!skip) 00176 gvprintf(job, " %s", line); 00177 skip = 0; 00178 } 00179 gvprintf(job, " %%\n"); 00180 gvprintf(job, "%s", buf); 00181 } 00182 00183 static void picptarray(GVJ_t *job, pointf * A, int n, int close) 00184 { 00185 int i; 00186 point p; 00187 00188 for (i = 0; i < n; i++) { 00189 PF2P(A[i],p); 00190 gvprintf(job, " %d %d", p.x, p.y); 00191 } 00192 if (close) { 00193 PF2P(A[0],p); 00194 gvprintf(job, " %d %d", p.x, p.y); 00195 } 00196 gvputs(job, "\n"); 00197 } 00198 00199 static char *pic_string(char *s) 00200 { 00201 static char *buf = NULL; 00202 static int bufsize = 0; 00203 int pos = 0; 00204 char *p; 00205 unsigned char c; 00206 00207 if (!buf) { 00208 bufsize = 64; 00209 buf = malloc(bufsize * sizeof(char)); 00210 } 00211 00212 p = buf; 00213 while ((c = *s++)) { 00214 if (pos > (bufsize - 8)) { 00215 bufsize *= 2; 00216 buf = realloc(buf, bufsize * sizeof(char)); 00217 p = buf + pos; 00218 } 00219 if (isascii(c)) { 00220 if (c == '\\') { 00221 *p++ = '\\'; 00222 pos++; 00223 } 00224 *p++ = c; 00225 pos++; 00226 } else { 00227 *p++ = '\\'; 00228 sprintf(p, "%03o", c); 00229 p += 3; 00230 pos += 4; 00231 } 00232 } 00233 *p = '\0'; 00234 return buf; 00235 } 00236 00237 static int picColorResolve(int *new, int r, int g, int b) 00238 { 00239 #define maxColors 256 00240 static int top = 0; 00241 static short red[maxColors], green[maxColors], blue[maxColors]; 00242 int c; 00243 int ct = -1; 00244 long rd, gd, bd, dist; 00245 long mindist = 3 * 255 * 255; /* init to max poss dist */ 00246 00247 *new = 0; /* in case it is not a new color */ 00248 for (c = 0; c < top; c++) { 00249 rd = (long) (red[c] - r); 00250 gd = (long) (green[c] - g); 00251 bd = (long) (blue[c] - b); 00252 dist = rd * rd + gd * gd + bd * bd; 00253 if (dist < mindist) { 00254 if (dist == 0) 00255 return c; /* Return exact match color */ 00256 mindist = dist; 00257 ct = c; 00258 } 00259 } 00260 /* no exact match. We now know closest, but first try to allocate exact */ 00261 if (top++ == maxColors) 00262 return ct; /* Return closest available color */ 00263 red[c] = r; 00264 green[c] = g; 00265 blue[c] = b; 00266 *new = 1; /* flag new color */ 00267 return c; /* Return newly allocated color */ 00268 } 00269 00270 static void pic_line_style(obj_state_t *obj, int *line_style, double *style_val) 00271 { 00272 switch (obj->pen) { 00273 case PEN_DASHED: 00274 *line_style = 1; 00275 *style_val = 10.; 00276 break; 00277 case PEN_DOTTED: 00278 *line_style = 2; 00279 *style_val = 10.; 00280 break; 00281 case PEN_SOLID: 00282 default: 00283 *line_style = 0; 00284 *style_val = 0.; 00285 break; 00286 } 00287 } 00288 00289 static void pic_comment(GVJ_t *job, char *str) 00290 { 00291 gvprintf(job, "%s %s\n", EscComment, str); 00292 } 00293 00294 static void pic_begin_graph(GVJ_t * job) 00295 { 00296 obj_state_t *obj = job->obj; 00297 00298 gvprintf(job, "%s Creator: %s version %s (%s)\n", 00299 EscComment, job->common->info[0], job->common->info[1], job->common->info[2]); 00300 gvprintf(job, "%s Title: %s\n", EscComment, agnameof(obj->u.g)); 00301 gvprintf(job, 00302 "%s save point size and font\n.nr .S \\n(.s\n.nr DF \\n(.f\n", 00303 EscComment); 00304 } 00305 00306 static void pic_end_graph(GVJ_t * job) 00307 { 00308 gvprintf(job, 00309 "%s restore point size and font\n.ps \\n(.S\n.ft \\n(DF\n", 00310 EscComment); 00311 } 00312 00313 static void pic_begin_page(GVJ_t * job) 00314 { 00315 box pbr = job->pageBoundingBox; 00316 double height, width; 00317 00318 if (onetime && job->rotation && (job->rotation != 90)) { 00319 unsupported("rotation"); 00320 onetime = FALSE; 00321 } 00322 height = PS2INCH((double) (pbr.UR.y) - (double) (pbr.LL.y)); 00323 width = PS2INCH((double) (pbr.UR.x) - (double) (pbr.LL.x)); 00324 if (job->rotation == 90) { 00325 double temp = width; 00326 width = height; 00327 height = temp; 00328 } 00329 gvprintf(job, ".PS %.5f %.5f\n", width, height); 00330 gvprintf(job, 00331 "%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", 00332 EscComment); 00333 if (width > 0.0) { 00334 Fontscale = log10(width); 00335 Fontscale += 3.0 - (int) Fontscale; /* between 3.0 and 4.0 */ 00336 } else 00337 Fontscale = 3.0; 00338 Fontscale = pow(10.0, Fontscale); /* a power of 10 times width, between 1000 and 10000 */ 00339 gvprintf(job, ".nr SF %.0f\nscalethickness = %.0f\n", Fontscale, 00340 Fontscale); 00341 gvprintf(job, 00342 "%s don't change anything below this line in this drawing\n", 00343 EscComment); 00344 gvprintf(job, 00345 "%s non-fatal run-time pic version determination, version 2\n", 00346 EscComment); 00347 gvprintf(job, 00348 "boxrad=2.0 %s will be reset to 0.0 by gpic only\n", 00349 EscComment); 00350 gvprintf(job, "scale=1.0 %s required for comparisons\n", 00351 EscComment); 00352 gvprintf(job, 00353 "%s boxrad is now 0.0 in gpic, else it remains 2.0\n", 00354 EscComment); 00355 gvprintf(job, 00356 "%s dashwid is 0.1 in 10th Edition, 0.05 in DWB 2 and in gpic\n", 00357 EscComment); 00358 gvprintf(job, 00359 "%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", 00360 EscComment); 00361 gvprintf(job, 00362 "%s fill has no meaning in DWB 2, gpic can use fill or filled, 10th Edition uses fill only\n", 00363 EscComment); 00364 gvprintf(job, 00365 "%s DWB 2 doesn't use fill and doesn't define fillval\n", 00366 EscComment); 00367 gvprintf(job, 00368 "%s reset works in gpic and 10th edition, but isn't defined in DWB 2\n", 00369 EscComment); 00370 gvprintf(job, "%s DWB 2 compatibility definitions\n", 00371 EscComment); 00372 gvprintf(job, 00373 "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"); 00374 gvprintf(job, "reset %s set to known state\n", EscComment); 00375 gvprintf(job, "%s GNU pic vs. 10th Edition d\\(e'tente\n", 00376 EscComment); 00377 gvprintf(job, 00378 "if fillval > 0.4 then X\n\tdefine setfillval Y fillval = 1 - Y;\n\tdefine bold Y thickness 2 Y;\n"); 00379 gvprintf(job, 00380 "\t%s if you use gpic and it barfs on encountering \"solid\",\n", 00381 EscComment); 00382 gvprintf(job, 00383 "\t%s\tinstall a more recent version of gpic or switch to DWB or 10th Edition pic;\n", 00384 EscComment); 00385 gvprintf(job, 00386 "\t%s\tsorry, the groff folks changed gpic; send any complaint to them;\n", 00387 EscComment); 00388 gvprintf(job, 00389 "X else Z\n\tdefine setfillval Y fillval = Y;\n\tdefine bold Y Y;\n\tdefine filled Y fill Y;\nZ\n"); 00390 gvprintf(job, 00391 "%s arrowhead has no meaning in DWB 2, arrowhead = 7 makes filled arrowheads in gpic and in 10th Edition\n", 00392 EscComment); 00393 gvprintf(job, 00394 "%s arrowhead is undefined in DWB 2, initially 1 in gpic, 2 in 10th Edition\n", 00395 EscComment); 00396 gvprintf(job, "arrowhead = 7 %s not used by graphviz\n", 00397 EscComment); 00398 gvprintf(job, 00399 "%s GNU pic supports a boxrad variable to draw boxes with rounded corners; DWB and 10th Ed. do not\n", 00400 EscComment); 00401 gvprintf(job, "boxrad = 0 %s no rounded corners in graphviz\n", 00402 EscComment); 00403 gvprintf(job, 00404 "%s GNU pic supports a linethick variable to set line thickness; DWB and 10th Ed. do not\n", 00405 EscComment); 00406 gvprintf(job, "linethick = 0; oldlinethick = linethick\n"); 00407 gvprintf(job, 00408 "%s .PS w/o args causes GNU pic to scale drawing to fit 8.5x11 paper; DWB does not\n", 00409 EscComment); 00410 gvprintf(job, 00411 "%s maxpsht and maxpswid have no meaning in DWB 2.0, set page boundaries in gpic and in 10th Edition\n", 00412 EscComment); 00413 gvprintf(job, 00414 "%s maxpsht and maxpswid are predefined to 11.0 and 8.5 in gpic\n", 00415 EscComment); 00416 gvprintf(job, "maxpsht = %f\nmaxpswid = %f\n", height, width); 00417 gvprintf(job, "Dot: [\n"); 00418 gvprintf(job, 00419 "define attrs0 %% %%; define unfilled %% %%; define rounded %% %%; define diagonals %% %%\n"); 00420 } 00421 00422 static void pic_end_page(GVJ_t * job) 00423 { 00424 gvprintf(job, 00425 "]\n.PE\n"); 00426 } 00427 00428 static void pic_textpara(GVJ_t * job, pointf p, textpara_t * para) 00429 { 00430 static char *lastname; 00431 static int lastsize; 00432 int sz; 00433 00434 switch (para->just) { 00435 case 'l': 00436 break; 00437 case 'r': 00438 p.x -= para->width; 00439 break; 00440 default: 00441 case 'n': 00442 p.x -= para->width / 2; 00443 break; 00444 } 00445 #ifdef NOTDEF 00446 /* Why on earth would we want this? SCN 11/29/2001 */ 00447 p.y -= para->fontsize / (5.0 * POINTS_PER_INCH); 00448 #endif 00449 /* Why on earth would we do this either. But it works. SCN 2/26/2002 */ 00450 p.y += para->fontsize / (3.0 * POINTS_PER_INCH); 00451 p.x += para->width / (2.0 * POINTS_PER_INCH); 00452 00453 if (para->fontname && (!(lastname) || strcmp(lastname, para->fontname))) { 00454 gvprintf(job, ".ft %s\n", picfontname(para->fontname)); 00455 lastname = para->fontname; 00456 } 00457 if ((sz = (int)para->fontsize) < 1); 00458 sz = 1; 00459 if (sz != lastsize) { 00460 gvprintf(job, ".ps %d*\\n(SFu/%.0fu\n", sz, Fontscale); 00461 lastsize = sz; 00462 } 00463 gvprintf(job, "\"%s\" at (%.5f,%.5f);\n", 00464 pic_string(para->str), p.x, p.y); 00465 } 00466 00467 static void pic_ellipse(GVJ_t * job, pointf * A, int filled) 00468 { 00469 /* A[] contains 2 points: the center and corner. */ 00470 00471 gvprintf(job, 00472 "ellipse attrs%d %swid %.5f ht %.5f at (%.5f,%.5f);\n", 1, 00473 filled ? "fill " : "", 00474 PS2INCH(2*(A[1].x - A[0].x)), 00475 PS2INCH(2*(A[1].y - A[0].y)), 00476 PS2INCH(A[0].x), 00477 PS2INCH(A[0].y)); 00478 } 00479 00480 static void pic_bezier(GVJ_t * job, pointf * A, int n, int arrow_at_start, 00481 // start_y, end_x, end_y); 00482 int arrow_at_end, int filled) 00483 { 00484 obj_state_t *obj = job->obj; 00485 00486 int object_code = 3; /* always 3 for spline */ 00487 int sub_type; 00488 int line_style; /* solid, dotted, dashed */ 00489 int thickness = obj->penwidth; 00490 int pen_color = obj->pencolor.u.index; 00491 int fill_color = obj->fillcolor.u.index; 00492 int pen_style = 0; /* not used */ 00493 int area_fill; 00494 double style_val; 00495 int cap_style = 0; 00496 int forward_arrow = 0; 00497 int backward_arrow = 0; 00498 int npoints = n; 00499 int i; 00500 00501 pointf pf, V[4]; 00502 point p; 00503 int j, step; 00504 int count = 0; 00505 int size; 00506 00507 char *buffer; 00508 char *buf; 00509 buffer = 00510 malloc((npoints + 1) * (BEZIERSUBDIVISION + 00511 1) * 20 * sizeof(char)); 00512 buf = buffer; 00513 00514 pic_line_style(obj, &line_style, &style_val); 00515 00516 if (filled) { 00517 sub_type = 5; /* closed X-spline */ 00518 area_fill = 20; /* fully saturated color */ 00519 fill_color = job->obj->fillcolor.u.index; 00520 } 00521 else { 00522 sub_type = 4; /* opened X-spline */ 00523 area_fill = -1; 00524 fill_color = 0; 00525 } 00526 V[3].x = A[0].x; 00527 V[3].y = A[0].y; 00528 /* Write first point in line */ 00529 count++; 00530 PF2P(A[0], p); 00531 size = sprintf(buf, " %d %d", p.x, p.y); 00532 buf += size; 00533 /* write subsequent points */ 00534 for (i = 0; i + 3 < n; i += 3) { 00535 V[0] = V[3]; 00536 for (j = 1; j <= 3; j++) { 00537 V[j].x = A[i + j].x; 00538 V[j].y = A[i + j].y; 00539 } 00540 for (step = 1; step <= BEZIERSUBDIVISION; step++) { 00541 count++; 00542 pf = Bezier (V, 3, (double) step / BEZIERSUBDIVISION, NULL, NULL); 00543 PF2P(pf, p); 00544 size = sprintf(buf, " %d %d", p.x, p.y); 00545 buf += size; 00546 } 00547 } 00548 00549 // gvprintf(job, "%d %d %d %d %d %d %d %d %d %.1f %d %d %d %d\n", 00550 // object_code, 00551 // sub_type, 00552 // line_style, 00553 // thickness, 00554 // pen_color, 00555 // fill_color, 00556 // depth, 00557 // pen_style, 00558 // area_fill, 00559 // style_val, cap_style, forward_arrow, backward_arrow, count); 00560 00561 gvprintf(job, " %s\n", buffer); /* print points */ 00562 free(buffer); 00563 for (i = 0; i < count; i++) { 00564 gvprintf(job, " %d", i % (count - 1) ? 1 : 0); /* -1 on all */ 00565 } 00566 gvputs(job, "\n"); 00567 } 00568 00569 static void pic_polygon(GVJ_t * job, pointf * A, int n, int filled) 00570 { 00571 obj_state_t *obj = job->obj; 00572 00573 int object_code = 2; /* always 2 for polyline */ 00574 int sub_type = 3; /* always 3 for polygon */ 00575 int line_style; /* solid, dotted, dashed */ 00576 int thickness = obj->penwidth; 00577 int pen_color = obj->pencolor.u.index; 00578 int fill_color = obj->fillcolor.u.index; 00579 int pen_style = 0; /* not used */ 00580 int area_fill = filled ? 20 : -1; 00581 double style_val; 00582 int join_style = 0; 00583 int cap_style = 0; 00584 int radius = 0; 00585 int forward_arrow = 0; 00586 int backward_arrow = 0; 00587 int npoints = n + 1; 00588 00589 pic_line_style(obj, &line_style, &style_val); 00590 00591 // gvprintf(job, 00592 // "%d %d %d %d %d %d %d %d %d %.1f %d %d %d %d %d %d\n", 00593 // object_code, sub_type, line_style, thickness, pen_color, 00594 // fill_color, depth, pen_style, area_fill, style_val, join_style, 00595 // cap_style, radius, forward_arrow, backward_arrow, npoints); 00596 picptarray(job, A, n, 1); /* closed shape */ 00597 } 00598 00599 static void pic_polyline(GVJ_t * job, pointf * A, int n) 00600 { 00601 obj_state_t *obj = job->obj; 00602 00603 int object_code = 2; /* always 2 for polyline */ 00604 int sub_type = 1; /* always 1 for polyline */ 00605 int line_style; /* solid, dotted, dashed */ 00606 int thickness = obj->penwidth; 00607 int pen_color = obj->pencolor.u.index; 00608 int fill_color = 0; 00609 int pen_style = 0; /* not used */ 00610 int area_fill = 0; 00611 double style_val; 00612 int join_style = 0; 00613 int cap_style = 0; 00614 int radius = 0; 00615 int forward_arrow = 0; 00616 int backward_arrow = 0; 00617 int npoints = n; 00618 00619 pic_line_style(obj, &line_style, &style_val); 00620 00621 // gvprintf(job, 00622 // "%d %d %d %d %d %d %d %d %d %.1f %d %d %d %d %d %d\n", 00623 // object_code, sub_type, line_style, thickness, pen_color, 00624 // fill_color, depth, pen_style, area_fill, style_val, join_style, 00625 // cap_style, radius, forward_arrow, backward_arrow, npoints); 00626 picptarray(job, A, n, 0); /* open shape */ 00627 } 00628 00629 gvrender_engine_t pic_engine = { 00630 0, /* pic_begin_job */ 00631 0, /* pic_end_job */ 00632 pic_begin_graph, 00633 pic_end_graph, 00634 0, /* pic_begin_layer */ 00635 0, /* pic_end_layer */ 00636 pic_begin_page, 00637 pic_end_page, 00638 0, /* pic_begin_cluster */ 00639 0, /* pic_end_cluster */ 00640 0, /* pic_begin_nodes */ 00641 0, /* pic_end_nodes */ 00642 0, /* pic_begin_edges */ 00643 0, /* pic_end_edges */ 00644 0, /* pic_begin_node */ 00645 0, /* pic_end_node */ 00646 0, /* pic_begin_edge */ 00647 0, /* pic_end_edge */ 00648 0, /* pic_begin_anchor */ 00649 0, /* pic_end_anchor */ 00650 0, /* pic_begin_label */ 00651 0, /* pic_end_label */ 00652 pic_textpara, 00653 0, /* pic_resolve_color */ 00654 pic_ellipse, 00655 pic_polygon, 00656 pic_bezier, 00657 pic_polyline, 00658 pic_comment, 00659 0, /* pic_library_shape */ 00660 }; 00661 00662 00663 static gvrender_features_t render_features_pic = { 00664 0, /* flags */ 00665 4., /* default pad - graph units */ 00666 NULL, /* knowncolors */ 00667 0, /* sizeof knowncolors */ 00668 HSVA_DOUBLE, /* color_type */ 00669 }; 00670 00671 static gvdevice_features_t device_features_pic = { 00672 0, /* flags */ 00673 {0.,0.}, /* default margin - points */ 00674 {0.,0.}, /* default page width, height - points */ 00675 {72.,72.}, /* default dpi */ 00676 }; 00677 00678 gvplugin_installed_t gvrender_pic_types[] = { 00679 {FORMAT_PIC, "pic", -1, &pic_engine, &render_features_pic}, 00680 {0, NULL, 0, NULL, NULL} 00681 }; 00682 00683 gvplugin_installed_t gvdevice_pic_types[] = { 00684 {FORMAT_PIC, "pic:pic", -1, NULL, &device_features_pic}, 00685 {0, NULL, 0, NULL, NULL} 00686 };
1.7.5