/misc/src/release/graphviz-2.18-1/src/graphviz-2.18/lib/gvc/gvrender.c

Go to the documentation of this file.
00001 /* $Id: gvrender.c,v 1.142 2007/12/04 21:22:17 erg Exp $ $Revision: 1.142 $ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /**********************************************************
00005 *      This software is part of the graphviz package      *
00006 *                http://www.graphviz.org/                 *
00007 *                                                         *
00008 *            Copyright (c) 1994-2004 AT&T Corp.           *
00009 *                and is licensed under the                *
00010 *            Common Public License, Version 1.0           *
00011 *                      by AT&T Corp.                      *
00012 *                                                         *
00013 *        Information and Software Systems Research        *
00014 *              AT&T Research, Florham Park NJ             *
00015 **********************************************************/
00016 
00017 /*
00018  *  graphics code generator wrapper
00019  *
00020  *  This library forms the socket for run-time loadable render plugins.
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 /* storage for temporary hacks until client API is FP */
00044 static pointf *AF;
00045 static int sizeAF;
00046 #ifdef WITH_CODEGENS
00047 static point *A;
00048 static int sizeA;
00049 #endif
00050 /* end hack */
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;  /* FIXME - should differentiate problem */
00084     
00085     /* The device plugin has a dependency on a render plugin,
00086      * so the render plugin should be available as well now */
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             /* A null device engine indicates that the device id is also the renderer id
00100              * and that the renderer doesn't need "device" functions.
00101              * Device "features" settings are still available */
00102             job->render.id = job->device.id;
00103         return GVRENDER_PLUGIN;
00104     }
00105     job->render.engine = NULL;
00106     return NO_SUPPORT;  /* FIXME - should differentiate problem */
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;    /* FIXME - minimally this doesn't belong here */
00173     gvdevice_finalize(job);
00174 }
00175 
00176 /* font modifiers */
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 /* transform an array of n points */
00200 /*  *AF and *af must be preallocated */
00201 /*  *AF can be the same as *af for inplace transforms */
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         /* if tok was not found in known_colors */
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         /* render specific init */
00269         if (gvre->begin_graph)
00270             gvre->begin_graph(job);
00271 
00272         /* background color */
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  /* because of xdgen non-conformity */
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             /* center */
00762             af[0].x = (pf[0].x + pf[1].x)/2.;
00763             af[0].y = (pf[0].y + pf[1].y)/2.;
00764             /* corner */
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             /* center */
00781             af[0].x = (pf[0].x + pf[1].x)/2.;
00782             af[0].y = (pf[0].y + pf[1].y)/2.;
00783             /* radius */
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 /* gvrender_usershape:
00947  * Scale image to fill polygon bounding box according to "imagescale"
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;  /* scale factors */
00956     boxf b;                 /* target box */
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     /* compute bb of polygon */
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         /* keep aspect ratio fixed by just using the smaller scale */
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     /* if image is smaller than target area then center it */
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     /* convert from graph to device coordinates */
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         /*if (gvre->set_penwidth) gvre->set_penwidth(job, penwidth);*/
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 }

Generated on Mon Mar 31 19:03:27 2008 for Graphviz by  doxygen 1.5.1