00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include "config.h"
00025 #endif
00026
00027 #include <string.h>
00028 #include "memory.h"
00029 #include "const.h"
00030 #include "macros.h"
00031 #include "colorprocs.h"
00032 #include "gvplugin_render.h"
00033 #include "graph.h"
00034 #include "gvcint.h"
00035 #include "geom.h"
00036 #include "geomprocs.h"
00037 #include "gvcproc.h"
00038
00039 extern int emit_once(char *str);
00040 extern shape_desc *find_user_shape(char *name);
00041 extern boolean mapbool(char *s);
00042
00043
00044 static pointf *AF;
00045 static int sizeAF;
00046 #ifdef WITH_CODEGENS
00047 static point *A;
00048 static int sizeA;
00049 #endif
00050
00051
00052 int gvrender_select(GVJ_t * job, char *str)
00053 {
00054 GVC_t *gvc = job->gvc;
00055 gvplugin_available_t *plugin;
00056 gvplugin_installed_t *typeptr;
00057 #ifdef WITH_CODEGENS
00058 codegen_info_t *cg_info;
00059 #endif
00060
00061 gvplugin_load(gvc, API_device, str);
00062
00063 job->flags = 0;
00064 plugin = gvc->api[API_device];
00065 if (plugin) {
00066 #ifdef WITH_CODEGENS
00067 if (strcmp(plugin->packagename, "cg") == 0) {
00068 cg_info = (codegen_info_t *) (plugin->typeptr);
00069 job->codegen = cg_info->cg;
00070 job->render.engine = NULL;
00071 return cg_info->id;
00072 }
00073 #endif
00074 typeptr = plugin->typeptr;
00075 job->device.engine = (gvdevice_engine_t *) (typeptr->engine);
00076 job->device.features = (gvdevice_features_t *) (typeptr->features);
00077 job->device.id = typeptr->id;
00078 job->device.type = plugin->typestr;
00079
00080 job->flags |= job->device.features->flags;
00081 }
00082 else
00083 return NO_SUPPORT;
00084
00085
00086
00087 plugin = gvc->api[API_render];
00088 if (plugin) {
00089 typeptr = plugin->typeptr;
00090 job->render.engine = (gvrender_engine_t *) (typeptr->engine);
00091 job->render.features = (gvrender_features_t *) (typeptr->features);
00092 job->render.type = plugin->typestr;
00093
00094 job->flags |= job->render.features->flags;
00095
00096 if (job->device.engine)
00097 job->render.id = typeptr->id;
00098 else
00099
00100
00101
00102 job->render.id = job->device.id;
00103 return GVRENDER_PLUGIN;
00104 }
00105 job->render.engine = NULL;
00106 return NO_SUPPORT;
00107 }
00108
00109 int gvrender_features(GVJ_t * job)
00110 {
00111 gvrender_engine_t *gvre = job->render.engine;
00112 int features = 0;
00113
00114 if (gvre) {
00115 features = job->render.features->flags;
00116 }
00117 #ifdef WITH_CODEGENS
00118 else {
00119 codegen_t *cg = job->codegen;
00120
00121 if (cg) {
00122 if (cg->bezier_has_arrows)
00123 features |= GVRENDER_DOES_ARROWS;
00124 if (cg->begin_layer)
00125 features |= GVDEVICE_DOES_LAYERS;
00126 }
00127 }
00128 #endif
00129 return features;
00130 }
00131
00132 void gvrender_begin_job(GVJ_t * job)
00133 {
00134 GVC_t *gvc = job->gvc;
00135 gvrender_engine_t *gvre = job->render.engine;
00136
00137 gvdevice_initialize(job);
00138 if (gvre) {
00139 if (gvre->begin_job)
00140 gvre->begin_job(job);
00141 }
00142 #ifdef WITH_CODEGENS
00143 else {
00144 codegen_t *cg = job->codegen;
00145
00146 if (cg && cg->begin_job)
00147 cg->begin_job(job->output_file, gvc->g,
00148 gvc->common.lib,
00149 gvc->common.user,
00150 gvc->common.info,
00151 job->pagesArraySize);
00152 }
00153 #endif
00154 }
00155
00156 void gvrender_end_job(GVJ_t * job)
00157 {
00158 gvrender_engine_t *gvre = job->render.engine;
00159
00160 if (gvre) {
00161 if (gvre->end_job)
00162 gvre->end_job(job);
00163 }
00164 #ifdef WITH_CODEGENS
00165 else {
00166 codegen_t *cg = job->codegen;
00167
00168 if (cg && cg->end_job)
00169 cg->end_job();
00170 }
00171 #endif
00172 job->gvc->common.lib = NULL;
00173 gvdevice_finalize(job);
00174 }
00175
00176
00177 #define REGULAR 0
00178 #define BOLD 1
00179 #define ITALIC 2
00180
00181 pointf gvrender_ptf(GVJ_t *job, pointf p)
00182 {
00183 pointf rv, translation, scale;
00184
00185 translation = job->translation;
00186 scale.x = job->zoom * job->devscale.x;
00187 scale.y = job->zoom * job->devscale.y;
00188
00189 if (job->rotation) {
00190 rv.x = -(p.y + translation.y) * scale.x;
00191 rv.y = (p.x + translation.x) * scale.y;
00192 } else {
00193 rv.x = (p.x + translation.x) * scale.x;
00194 rv.y = (p.y + translation.y) * scale.y;
00195 }
00196 return rv;
00197 }
00198
00199
00200
00201
00202 pointf* gvrender_ptf_A(GVJ_t *job, pointf *af, pointf *AF, int n)
00203 {
00204 int i;
00205 double t;
00206 pointf translation, scale;
00207
00208 translation = job->translation;
00209 scale.x = job->zoom * job->devscale.x;
00210 scale.y = job->zoom * job->devscale.y;
00211
00212 if (job->rotation) {
00213 for (i = 0; i < n; i++) {
00214 t = -(af[i].y + translation.y) * scale.x;
00215 AF[i].y = (af[i].x + translation.x) * scale.y;
00216 AF[i].x = t;
00217 }
00218 }
00219 else {
00220 for (i = 0; i < n; i++) {
00221 AF[i].x = (af[i].x + translation.x) * scale.x;
00222 AF[i].y = (af[i].y + translation.y) * scale.y;
00223 }
00224 }
00225 return AF;
00226 }
00227
00228 static int gvrender_comparestr(const void *s1, const void *s2)
00229 {
00230 return strcmp(*(char **) s1, *(char **) s2);
00231 }
00232
00233 static void gvrender_resolve_color(gvrender_features_t * features,
00234 char *name, gvcolor_t * color)
00235 {
00236 char *tok;
00237 int rc;
00238
00239 color->u.string = name;
00240 color->type = COLOR_STRING;
00241 tok = canontoken(name);
00242 if (!features->knowncolors || (bsearch(&tok, features->knowncolors, features->sz_knowncolors,
00243 sizeof(char *), gvrender_comparestr)) == NULL) {
00244
00245 rc = colorxlate(name, color, features->color_type);
00246 if (rc != COLOR_OK) {
00247 if (rc == COLOR_UNKNOWN) {
00248 char *missedcolor = gmalloc(strlen(name) + 16);
00249 sprintf(missedcolor, "color %s", name);
00250 if (emit_once(missedcolor))
00251 agerr(AGWARN, "%s is not a known color.\n", name);
00252 free(missedcolor);
00253 }
00254 else {
00255 agerr(AGERR, "error in colxlate()\n");
00256 }
00257 }
00258 }
00259 }
00260
00261 void gvrender_begin_graph(GVJ_t * job, graph_t * g)
00262 {
00263 GVC_t *gvc = job->gvc;
00264 gvrender_engine_t *gvre = job->render.engine;
00265 char *s;
00266
00267 if (gvre) {
00268
00269 if (gvre->begin_graph)
00270 gvre->begin_graph(job);
00271
00272
00273 if (((s = agget(g, "bgcolor")) != 0) && s[0]) {
00274 gvrender_resolve_color(job->render.features, s, &(gvc->bgcolor));
00275 if (gvre->resolve_color)
00276 gvre->resolve_color(job, &(gvc->bgcolor));
00277 }
00278
00279 }
00280 #ifdef WITH_CODEGENS
00281 else {
00282 codegen_t *cg = job->codegen;
00283 box canvasBox;
00284
00285 BF2B(job->canvasBox, canvasBox);
00286
00287 if (cg && cg->begin_graph)
00288 cg->begin_graph(gvc, g, canvasBox, gvc->pb);
00289 }
00290 #endif
00291 }
00292
00293 void gvrender_end_graph(GVJ_t * job)
00294 {
00295 gvrender_engine_t *gvre = job->render.engine;
00296
00297 if (gvre) {
00298 if (gvre->end_graph)
00299 gvre->end_graph(job);
00300 }
00301 #ifdef WITH_CODEGENS
00302 else {
00303 codegen_t *cg = job->codegen;
00304
00305 if (cg && cg->end_graph)
00306 cg->end_graph();
00307 }
00308 #endif
00309 gvdevice_format(job);
00310 }
00311
00312 void gvrender_begin_page(GVJ_t * job)
00313 {
00314 gvrender_engine_t *gvre = job->render.engine;
00315
00316 if (gvre) {
00317 if (gvre->begin_page)
00318 gvre->begin_page(job);
00319 }
00320 #ifdef WITH_CODEGENS
00321 else {
00322 codegen_t *cg = job->codegen;
00323 point offset;
00324
00325 PF2P(job->pageOffset, offset);
00326 if (cg && cg->begin_page)
00327 cg->begin_page(job->gvc->g, job->pagesArrayElem,
00328 job->zoom, job->rotation, offset);
00329 }
00330 #endif
00331 }
00332
00333 void gvrender_end_page(GVJ_t * job)
00334 {
00335 gvrender_engine_t *gvre = job->render.engine;
00336
00337 if (gvre) {
00338 if (gvre->end_page)
00339 gvre->end_page(job);
00340 }
00341 #ifdef WITH_CODEGENS
00342 else {
00343 codegen_t *cg = job->codegen;
00344
00345 if (cg && cg->end_page)
00346 cg->end_page();
00347 }
00348 #endif
00349 }
00350
00351 void gvrender_begin_layer(GVJ_t * job)
00352 {
00353 gvrender_engine_t *gvre = job->render.engine;
00354
00355 if (gvre) {
00356 if (gvre->begin_layer)
00357 gvre->begin_layer(job, job->gvc->layerIDs[job->layerNum], job->layerNum, job->numLayers);
00358 }
00359 #ifdef WITH_CODEGENS
00360 else {
00361 codegen_t *cg = job->codegen;
00362
00363 if (cg && cg->begin_layer)
00364 cg->begin_layer(job->gvc->layerIDs[job->layerNum], job->layerNum, job->numLayers);
00365 }
00366 #endif
00367 }
00368
00369 void gvrender_end_layer(GVJ_t * job)
00370 {
00371 gvrender_engine_t *gvre = job->render.engine;
00372
00373 if (gvre) {
00374 if (gvre->end_layer)
00375 gvre->end_layer(job);
00376 }
00377 #ifdef WITH_CODEGENS
00378 else {
00379 codegen_t *cg = job->codegen;
00380
00381 if (cg && cg->end_layer)
00382 cg->end_layer();
00383 }
00384 #endif
00385 }
00386
00387 void gvrender_begin_cluster(GVJ_t * job, graph_t * sg)
00388 {
00389 gvrender_engine_t *gvre = job->render.engine;
00390
00391 if (gvre) {
00392 if (gvre->begin_cluster)
00393 gvre->begin_cluster(job);
00394 }
00395 #ifdef WITH_CODEGENS
00396 else {
00397 codegen_t *cg = job->codegen;
00398
00399 if (cg && cg->begin_cluster)
00400 cg->begin_cluster(sg);
00401 }
00402 #endif
00403 }
00404
00405 void gvrender_end_cluster(GVJ_t * job, graph_t *g)
00406 {
00407 gvrender_engine_t *gvre = job->render.engine;
00408
00409 if (gvre) {
00410 if (gvre->end_cluster)
00411 gvre->end_cluster(job);
00412 }
00413 #ifdef WITH_CODEGENS
00414 else {
00415 codegen_t *cg = job->codegen;
00416
00417 if (cg && cg->end_cluster)
00418 cg->end_cluster();
00419 }
00420 #endif
00421 }
00422
00423 void gvrender_begin_nodes(GVJ_t * job)
00424 {
00425 gvrender_engine_t *gvre = job->render.engine;
00426
00427 if (gvre) {
00428 if (gvre->begin_nodes)
00429 gvre->begin_nodes(job);
00430 }
00431 #ifdef WITH_CODEGENS
00432 else {
00433 codegen_t *cg = job->codegen;
00434
00435 if (cg && cg->begin_nodes)
00436 cg->begin_nodes();
00437 }
00438 #endif
00439 }
00440
00441 void gvrender_end_nodes(GVJ_t * job)
00442 {
00443 gvrender_engine_t *gvre = job->render.engine;
00444
00445 if (gvre) {
00446 if (gvre->end_nodes)
00447 gvre->end_nodes(job);
00448 }
00449 #ifdef WITH_CODEGENS
00450 else {
00451 codegen_t *cg = job->codegen;
00452
00453 if (cg && cg->end_nodes)
00454 cg->end_nodes();
00455 }
00456 #endif
00457 }
00458
00459 void gvrender_begin_edges(GVJ_t * job)
00460 {
00461 gvrender_engine_t *gvre = job->render.engine;
00462
00463 if (gvre) {
00464 if (gvre->begin_edges)
00465 gvre->begin_edges(job);
00466 }
00467 #ifdef WITH_CODEGENS
00468 else {
00469 codegen_t *cg = job->codegen;
00470
00471 if (cg && cg->begin_edges)
00472 cg->begin_edges();
00473 }
00474 #endif
00475 }
00476
00477 void gvrender_end_edges(GVJ_t * job)
00478 {
00479 gvrender_engine_t *gvre = job->render.engine;
00480
00481 if (gvre) {
00482 if (gvre->end_edges)
00483 gvre->end_edges(job);
00484 }
00485 #ifdef WITH_CODEGENS
00486 else {
00487 codegen_t *cg = job->codegen;
00488
00489 if (cg && cg->end_edges)
00490 cg->end_edges();
00491 }
00492 #endif
00493 }
00494
00495 void gvrender_begin_node(GVJ_t * job, node_t * n)
00496 {
00497 gvrender_engine_t *gvre = job->render.engine;
00498
00499 if (gvre) {
00500 if (gvre->begin_node)
00501 gvre->begin_node(job);
00502 }
00503 #ifdef WITH_CODEGENS
00504 else {
00505 codegen_t *cg = job->codegen;
00506
00507 if (cg && cg->begin_node)
00508 cg->begin_node(n);
00509 }
00510 #endif
00511 }
00512
00513 void gvrender_end_node(GVJ_t * job)
00514 {
00515 gvrender_engine_t *gvre = job->render.engine;
00516
00517 if (gvre) {
00518 if (gvre->end_node)
00519 gvre->end_node(job);
00520 }
00521 #ifdef WITH_CODEGENS
00522 else {
00523 codegen_t *cg = job->codegen;
00524
00525 if (cg && cg->end_node)
00526 cg->end_node();
00527 }
00528 #endif
00529 }
00530
00531 void gvrender_begin_edge(GVJ_t * job, edge_t * e)
00532 {
00533 gvrender_engine_t *gvre = job->render.engine;
00534
00535 if (gvre) {
00536 if (gvre->begin_edge)
00537 gvre->begin_edge(job);
00538 }
00539 #ifdef WITH_CODEGENS
00540 else {
00541 codegen_t *cg = job->codegen;
00542
00543 if (cg && cg->begin_edge)
00544 cg->begin_edge(e);
00545 }
00546 #endif
00547 }
00548
00549 void gvrender_end_edge(GVJ_t * job)
00550 {
00551 gvrender_engine_t *gvre = job->render.engine;
00552
00553 if (gvre) {
00554 if (gvre->end_edge)
00555 gvre->end_edge(job);
00556 }
00557 #ifdef WITH_CODEGENS
00558 else {
00559 codegen_t *cg = job->codegen;
00560
00561 if (cg && cg->end_edge)
00562 cg->end_edge();
00563 }
00564 #endif
00565 }
00566
00567 void gvrender_begin_context(GVJ_t * job)
00568 {
00569 #ifdef WITH_CODEGENS
00570 gvrender_engine_t *gvre = job->render.engine;
00571 codegen_t *cg = job->codegen;
00572
00573 if (!gvre && cg && cg->begin_context)
00574 cg->begin_context();
00575 #endif
00576 }
00577
00578 void gvrender_end_context(GVJ_t * job)
00579 {
00580 #ifdef WITH_CODEGENS
00581 gvrender_engine_t *gvre = job->render.engine;
00582 codegen_t *cg = job->codegen;
00583
00584 if (!gvre && cg && cg->end_context)
00585 cg->end_context();
00586 #endif
00587 }
00588
00589 void gvrender_begin_anchor(GVJ_t * job, char *href, char *tooltip, char *target)
00590 {
00591 gvrender_engine_t *gvre = job->render.engine;
00592
00593 if (gvre) {
00594 if (gvre->begin_anchor)
00595 gvre->begin_anchor(job, href, tooltip, target);
00596 }
00597 #ifdef WITH_CODEGENS
00598 else {
00599 codegen_t *cg = job->codegen;
00600
00601 if (cg && cg->begin_anchor)
00602 cg->begin_anchor(href, tooltip, target);
00603 }
00604 #endif
00605 }
00606
00607 void gvrender_end_anchor(GVJ_t * job)
00608 {
00609 gvrender_engine_t *gvre = job->render.engine;
00610
00611 if (gvre) {
00612 if (gvre->end_anchor)
00613 gvre->end_anchor(job);
00614 }
00615 #ifdef WITH_CODEGENS
00616 else {
00617 codegen_t *cg = job->codegen;
00618
00619 if (cg && cg->end_anchor)
00620 cg->end_anchor();
00621 }
00622 #endif
00623 }
00624
00625 void gvrender_set_font(GVJ_t * job, char *fontname, double fontsize)
00626 {
00627 gvrender_engine_t *gvre = job->render.engine;
00628
00629 #ifdef WITH_CODEGENS
00630 if (!gvre) {
00631 codegen_t *cg = job->codegen;
00632
00633 if (cg && cg->set_font)
00634 cg->set_font(fontname, fontsize);
00635 }
00636 #endif
00637 }
00638
00639 void gvrender_textpara(GVJ_t * job, pointf p, textpara_t * para)
00640 {
00641 gvrender_engine_t *gvre = job->render.engine;
00642 pointf PF;
00643
00644 if (para->str && para->str[0]
00645 && ( ! job->obj
00646 || job->obj->pen != PEN_NONE)) {
00647 if (job->flags & GVRENDER_DOES_TRANSFORM)
00648 PF = p;
00649 else
00650 PF = gvrender_ptf(job, p);
00651 if (gvre) {
00652 if (gvre->textpara)
00653 gvre->textpara(job, PF, para);
00654 }
00655 #ifdef WITH_CODEGENS
00656 else {
00657 codegen_t *cg = job->codegen;
00658 point P;
00659
00660 PF2P(p, P);
00661 if (cg && cg->textpara)
00662 cg->textpara(P, para);
00663 }
00664 #endif
00665 }
00666 }
00667
00668 void gvrender_set_pencolor(GVJ_t * job, char *name)
00669 {
00670 gvrender_engine_t *gvre = job->render.engine;
00671 gvcolor_t *color = &(job->obj->pencolor);
00672
00673 if (gvre) {
00674 gvrender_resolve_color(job->render.features, name, color);
00675 if (gvre->resolve_color)
00676 gvre->resolve_color(job, color);
00677 }
00678 #ifdef WITH_CODEGENS
00679 else {
00680 codegen_t *cg = job->codegen;
00681
00682 if (cg && cg->set_pencolor)
00683 cg->set_pencolor(name);
00684 }
00685 #endif
00686 }
00687
00688 void gvrender_set_fillcolor(GVJ_t * job, char *name)
00689 {
00690 gvrender_engine_t *gvre = job->render.engine;
00691 gvcolor_t *color = &(job->obj->fillcolor);
00692
00693 if (gvre) {
00694 gvrender_resolve_color(job->render.features, name, color);
00695 if (gvre->resolve_color)
00696 gvre->resolve_color(job, color);
00697 }
00698 #ifdef WITH_CODEGENS
00699 else {
00700 codegen_t *cg = job->codegen;
00701
00702 if (cg && cg->set_fillcolor)
00703 cg->set_fillcolor(name);
00704 }
00705 #endif
00706 }
00707
00708 void gvrender_set_style(GVJ_t * job, char **s)
00709 {
00710 gvrender_engine_t *gvre = job->render.engine;
00711 obj_state_t *obj = job->obj;
00712 char *line, *p;
00713
00714 obj->rawstyle = s;
00715 if (gvre) {
00716 if (s) while ((p = line = *s++)) {
00717 if (streq(line, "solid"))
00718 obj->pen = PEN_SOLID;
00719 else if (streq(line, "dashed"))
00720 obj->pen = PEN_DASHED;
00721 else if (streq(line, "dotted"))
00722 obj->pen = PEN_DOTTED;
00723 else if (streq(line, "invis") || streq(line, "invisible"))
00724 obj->pen = PEN_NONE;
00725 else if (streq(line, "bold"))
00726 obj->penwidth = PENWIDTH_BOLD;
00727 else if (streq(line, "setlinewidth")) {
00728 while (*p)
00729 p++;
00730 p++;
00731 obj->penwidth = atof(p);
00732 } else if (streq(line, "filled"))
00733 obj->fill = FILL_SOLID;
00734 else if (streq(line, "unfilled"))
00735 obj->fill = FILL_NONE;
00736 else {
00737 agerr(AGWARN,
00738 "gvrender_set_style: unsupported style %s - ignoring\n",
00739 line);
00740 }
00741 }
00742 }
00743 #ifdef WITH_CODEGENS
00744 else {
00745 codegen_t *cg = job->codegen;
00746
00747 if (cg && cg->set_style)
00748 cg->set_style(s);
00749 }
00750 #endif
00751 }
00752
00753 void gvrender_ellipse(GVJ_t * job, pointf * pf, int n, boolean filled)
00754 {
00755 gvrender_engine_t *gvre = job->render.engine;
00756
00757 if (gvre) {
00758 if (gvre->ellipse && job->obj->pen != PEN_NONE) {
00759 pointf af[2];
00760
00761
00762 af[0].x = (pf[0].x + pf[1].x)/2.;
00763 af[0].y = (pf[0].y + pf[1].y)/2.;
00764
00765 af[1] = pf[1];
00766
00767 if (! (job->flags & GVRENDER_DOES_TRANSFORM))
00768 gvrender_ptf_A(job, af, af, 2);
00769 gvre->ellipse(job, af, filled);
00770 }
00771 }
00772 #ifdef WITH_CODEGENS
00773 else {
00774 codegen_t *cg = job->codegen;
00775
00776 if (cg && cg->ellipse) {
00777 pointf af[2];
00778 point p, r;
00779
00780
00781 af[0].x = (pf[0].x + pf[1].x)/2.;
00782 af[0].y = (pf[0].y + pf[1].y)/2.;
00783
00784 af[1].x = pf[1].x - af[0].x;
00785 af[1].y = pf[1].y - af[0].y;
00786
00787 PF2P(af[0], p);
00788 PF2P(af[1], r);
00789 cg->ellipse(p, r.x, r.y, filled);
00790 }
00791 }
00792 #endif
00793 }
00794
00795 void gvrender_polygon(GVJ_t * job, pointf * af, int n, boolean filled)
00796 {
00797 gvrender_engine_t *gvre = job->render.engine;
00798
00799 if (gvre) {
00800 if (gvre->polygon && job->obj->pen != PEN_NONE) {
00801 if (job->flags & GVRENDER_DOES_TRANSFORM)
00802 gvre->polygon(job, af, n, filled);
00803 else {
00804 if (sizeAF < n) {
00805 sizeAF = n+10;
00806 AF = grealloc(AF, sizeAF * sizeof(pointf));
00807 }
00808 gvrender_ptf_A(job, af, AF, n);
00809 gvre->polygon(job, AF, n, filled);
00810 }
00811 }
00812 }
00813 #ifdef WITH_CODEGENS
00814 else {
00815 codegen_t *cg = job->codegen;
00816 int i;
00817
00818 if (sizeA < n) {
00819 sizeA = n+10;
00820 A = grealloc(A, sizeA * sizeof(point));
00821 }
00822 for (i = 0; i < n; i++)
00823 PF2P(af[i], A[i]);
00824 if (cg && cg->polygon)
00825 cg->polygon(A, n, filled);
00826 }
00827 #endif
00828 }
00829
00830 void gvrender_box(GVJ_t * job, boxf B, boolean filled)
00831 {
00832 pointf A[4];
00833
00834 A[0] = B.LL;
00835 A[2] = B.UR;
00836 A[1].x = A[0].x;
00837 A[1].y = A[2].y;
00838 A[3].x = A[2].x;
00839 A[3].y = A[0].y;
00840
00841 gvrender_polygon(job, A, 4, filled);
00842 }
00843
00844 void gvrender_beziercurve(GVJ_t * job, pointf * af, int n,
00845 int arrow_at_start, int arrow_at_end, boolean filled)
00846 {
00847 gvrender_engine_t *gvre = job->render.engine;
00848
00849 if (gvre) {
00850 if (gvre->beziercurve && job->obj->pen != PEN_NONE) {
00851 if (job->flags & GVRENDER_DOES_TRANSFORM)
00852 gvre->beziercurve(job, af, n, arrow_at_start, arrow_at_end,filled);
00853 else {
00854 if (sizeAF < n) {
00855 sizeAF = n+10;
00856 AF = grealloc(AF, sizeAF * sizeof(pointf));
00857 }
00858 gvrender_ptf_A(job, af, AF, n);
00859 gvre->beziercurve(job, AF, n, arrow_at_start, arrow_at_end,filled);
00860 }
00861 }
00862 }
00863 #ifdef WITH_CODEGENS
00864 else {
00865 codegen_t *cg = job->codegen;
00866 int i;
00867 if (sizeA < n) {
00868 sizeA = n+10;
00869 A = grealloc(A, sizeA * sizeof(point));
00870 }
00871 for (i = 0; i < n; i++) {
00872 PF2P(af[i], A[i]);
00873 }
00874 if (cg && cg->beziercurve)
00875 cg->beziercurve(A, n, arrow_at_start, arrow_at_end, filled);
00876 }
00877 #endif
00878 }
00879
00880 void gvrender_polyline(GVJ_t * job, pointf * af, int n)
00881 {
00882 gvrender_engine_t *gvre = job->render.engine;
00883
00884 if (gvre) {
00885 if (gvre->polyline && job->obj->pen != PEN_NONE) {
00886 if (job->flags & GVRENDER_DOES_TRANSFORM)
00887 gvre->polyline(job, af, n);
00888 else {
00889 if (sizeAF < n) {
00890 sizeAF = n+10;
00891 AF = grealloc(AF, sizeAF * sizeof(pointf));
00892 }
00893 gvrender_ptf_A(job, af, AF, n);
00894 gvre->polyline(job, AF, n);
00895 }
00896 }
00897 }
00898 #ifdef WITH_CODEGENS
00899 else {
00900 codegen_t *cg = job->codegen;
00901 int i;
00902
00903 if (sizeA < n) {
00904 sizeA = n+10;
00905 A = grealloc(A, sizeA * sizeof(point));
00906 }
00907 for (i = 0; i < n; i++)
00908 PF2P(af[i], A[i]);
00909 if (cg && cg->polyline)
00910 cg->polyline(A, n);
00911 }
00912 #endif
00913 }
00914
00915 void gvrender_comment(GVJ_t * job, char *str)
00916 {
00917 gvrender_engine_t *gvre = job->render.engine;
00918
00919 if (!str || !str[0])
00920 return;
00921
00922 if (gvre) {
00923 if (gvre->comment)
00924 gvre->comment(job, str);
00925 }
00926 #ifdef WITH_CODEGENS
00927 else {
00928 codegen_t *cg = job->codegen;
00929
00930 if (cg && cg->comment)
00931 cg->comment(str);
00932 }
00933 #endif
00934 }
00935
00936 static imagescale_t get_imagescale(char *s)
00937 {
00938 if (*s == '\0') return IMAGESCALE_FALSE;
00939 if (!strcasecmp(s, "width")) return IMAGESCALE_WIDTH;
00940 if (!strcasecmp(s, "height")) return IMAGESCALE_HEIGHT;
00941 if (!strcasecmp(s, "both")) return IMAGESCALE_BOTH;
00942 if (mapbool(s)) return IMAGESCALE_TRUE;
00943 return IMAGESCALE_FALSE;
00944 }
00945
00946
00947
00948
00949 void gvrender_usershape(GVJ_t * job, char *name, pointf * a, int n,
00950 boolean filled, char *imagescale)
00951 {
00952 gvrender_engine_t *gvre = job->render.engine;
00953 usershape_t *us;
00954 double iw, ih, pw, ph;
00955 double scalex, scaley;
00956 boxf b;
00957 int i;
00958 point isz;
00959
00960 if (! (us = gvusershape_find(name))) {
00961 if (find_user_shape(name)) {
00962 if (gvre && gvre->library_shape)
00963 gvre->library_shape(job, name, a, n, filled);
00964 }
00965 return;
00966 }
00967
00968 isz = gvusershape_size_dpi (us, job->dpi);
00969 if ((isz.x <= 0) && (isz.y <= 0)) return;
00970
00971
00972 b.LL = b.UR = a[0];
00973 for (i = 1; i < n; i++) {
00974 EXPANDBP(b, a[i]);
00975 }
00976
00977 pw = b.UR.x - b.LL.x;
00978 ph = b.UR.y - b.LL.y;
00979 ih = (double)isz.y;
00980 iw = (double)isz.x;
00981
00982 scalex = pw / iw;
00983 scaley = ph / ih;
00984
00985 switch (get_imagescale(imagescale)) {
00986 case IMAGESCALE_TRUE:
00987
00988 if (scalex < scaley) {
00989 iw *= scalex;
00990 ih *= scalex;
00991 } else {
00992 iw *= scaley;
00993 ih *= scaley;
00994 }
00995 break;
00996 case IMAGESCALE_WIDTH:
00997 iw *= scalex;
00998 break;
00999 case IMAGESCALE_HEIGHT:
01000 ih *= scaley;
01001 break;
01002 case IMAGESCALE_BOTH:
01003 iw *= scalex;
01004 ih *= scaley;
01005 break;
01006 case IMAGESCALE_FALSE:
01007 default:
01008 break;
01009 }
01010
01011
01012 if (iw < pw) {
01013 b.LL.x += (pw - iw) / 2.0;
01014 b.UR.x -= (pw - iw) / 2.0;
01015 }
01016 if (ih < ph) {
01017 b.LL.y += (ph - ih) / 2.0;
01018 b.UR.y -= (ph - ih) / 2.0;
01019 }
01020
01021
01022 if (!(job->flags & GVRENDER_DOES_TRANSFORM)) {
01023 b.LL = gvrender_ptf(job, b.LL);
01024 b.UR = gvrender_ptf(job, b.UR);
01025 }
01026
01027 if (b.LL.x > b.UR.x) {
01028 double d = b.LL.x;
01029 b.LL.x = b.UR.x;
01030 b.UR.x = d;
01031 }
01032 if (b.LL.y > b.UR.y) {
01033 double d = b.LL.y;
01034 b.LL.y = b.UR.y;
01035 b.UR.y = d;
01036 }
01037 if (gvre) {
01038 gvloadimage(job, us, b, filled, job->render.type);
01039 }
01040 #ifdef WITH_CODEGENS
01041 else {
01042 codegen_t *cg = job->codegen;
01043
01044 if (sizeA < n) {
01045 sizeA = n+10;
01046 A = grealloc(A, sizeA * sizeof(point));
01047 }
01048 for (i = 0; i < n; i++)
01049 PF2P(a[i], A[i]);
01050 if (cg && cg->usershape)
01051 cg->usershape(us, b, A, n, filled);
01052 }
01053 #endif
01054 }
01055
01056 void gvrender_set_penwidth(GVJ_t * job, double penwidth)
01057 {
01058 gvrender_engine_t *gvre = job->render.engine;
01059
01060 if (gvre) {
01061 job->obj->penwidth = penwidth;
01062
01063 }
01064 #ifdef WITH_CODEGENS
01065 else {
01066 codegen_t *cg = job->codegen;
01067
01068 if (cg && cg->set_penwidth)
01069 cg->set_penwidth(penwidth);
01070 }
01071 #endif
01072 }