|
Graphviz
2.31.20130618.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 /* 00015 * graphics code generator wrapper 00016 * 00017 * This library forms the socket for run-time loadable render plugins. 00018 */ 00019 00020 #ifdef HAVE_CONFIG_H 00021 #include "config.h" 00022 #endif 00023 00024 #include <string.h> 00025 #include "memory.h" 00026 #include "const.h" 00027 #include "macros.h" 00028 #include "colorprocs.h" 00029 #include "gvplugin_render.h" 00030 #if WITH_CGRAPH 00031 #include "cgraph.h" 00032 #else 00033 #include "graph.h" 00034 #endif 00035 #include "gvcint.h" 00036 #include "geom.h" 00037 #include "geomprocs.h" 00038 #include "gvcproc.h" 00039 00040 extern int emit_once(char *str); 00041 extern shape_desc *find_user_shape(char *name); 00042 extern boolean mapbool(char *s); 00043 00044 #ifndef HAVE_STRCASECMP 00045 extern int strcasecmp(const char *s1, const char *s2); 00046 #endif 00047 00048 /* storage for temporary hacks until client API is FP */ 00049 static pointf *AF; 00050 static int sizeAF; 00051 /* end hack */ 00052 00053 int gvrender_select(GVJ_t * job, const char *str) 00054 { 00055 GVC_t *gvc = job->gvc; 00056 gvplugin_available_t *plugin; 00057 gvplugin_installed_t *typeptr; 00058 00059 gvplugin_load(gvc, API_device, str); 00060 00061 /* When job is created, it is zeroed out. 00062 * Some flags, such as OUTPUT_NOT_REQUIRED, may already be set, 00063 * so don't reset. 00064 */ 00065 /* job->flags = 0; */ 00066 plugin = gvc->api[API_device]; 00067 if (plugin) { 00068 typeptr = plugin->typeptr; 00069 job->device.engine = (gvdevice_engine_t *) (typeptr->engine); 00070 job->device.features = (gvdevice_features_t *) (typeptr->features); 00071 job->device.id = typeptr->id; 00072 job->device.type = plugin->typestr; 00073 00074 job->flags |= job->device.features->flags; 00075 } else 00076 return NO_SUPPORT; /* FIXME - should differentiate problem */ 00077 00078 /* The device plugin has a dependency on a render plugin, 00079 * so the render plugin should be available as well now */ 00080 plugin = gvc->api[API_render]; 00081 if (plugin) { 00082 typeptr = plugin->typeptr; 00083 job->render.engine = (gvrender_engine_t *) (typeptr->engine); 00084 job->render.features = (gvrender_features_t *) (typeptr->features); 00085 job->render.type = plugin->typestr; 00086 00087 job->flags |= job->render.features->flags; 00088 00089 if (job->device.engine) 00090 job->render.id = typeptr->id; 00091 else 00092 /* A null device engine indicates that the device id is also the renderer id 00093 * and that the renderer doesn't need "device" functions. 00094 * Device "features" settings are still available */ 00095 job->render.id = job->device.id; 00096 return GVRENDER_PLUGIN; 00097 } 00098 job->render.engine = NULL; 00099 return NO_SUPPORT; /* FIXME - should differentiate problem */ 00100 } 00101 00102 int gvrender_features(GVJ_t * job) 00103 { 00104 gvrender_engine_t *gvre = job->render.engine; 00105 int features = 0; 00106 00107 if (gvre) { 00108 features = job->render.features->flags; 00109 } 00110 return features; 00111 } 00112 00113 /* gvrender_begin_job: 00114 * Return 0 on success 00115 */ 00116 int gvrender_begin_job(GVJ_t * job) 00117 { 00118 gvrender_engine_t *gvre = job->render.engine; 00119 00120 if (gvdevice_initialize(job)) 00121 return 1; 00122 if (gvre) { 00123 if (gvre->begin_job) 00124 gvre->begin_job(job); 00125 } 00126 return 0; 00127 } 00128 00129 void gvrender_end_job(GVJ_t * job) 00130 { 00131 gvrender_engine_t *gvre = job->render.engine; 00132 00133 if (gvre) { 00134 if (gvre->end_job) 00135 gvre->end_job(job); 00136 } 00137 job->gvc->common.lib = NULL; /* FIXME - minimally this doesn't belong here */ 00138 gvdevice_finalize(job); 00139 } 00140 00141 /* font modifiers */ 00142 #define REGULAR 0 00143 #define BOLD 1 00144 #define ITALIC 2 00145 00146 pointf gvrender_ptf(GVJ_t * job, pointf p) 00147 { 00148 pointf rv, translation, scale; 00149 00150 translation = job->translation; 00151 scale.x = job->zoom * job->devscale.x; 00152 scale.y = job->zoom * job->devscale.y; 00153 00154 if (job->rotation) { 00155 rv.x = -(p.y + translation.y) * scale.x; 00156 rv.y = (p.x + translation.x) * scale.y; 00157 } else { 00158 rv.x = (p.x + translation.x) * scale.x; 00159 rv.y = (p.y + translation.y) * scale.y; 00160 } 00161 return rv; 00162 } 00163 00164 /* transform an array of n points */ 00165 /* *AF and *af must be preallocated */ 00166 /* *AF can be the same as *af for inplace transforms */ 00167 pointf *gvrender_ptf_A(GVJ_t * job, pointf * af, pointf * AF, int n) 00168 { 00169 int i; 00170 double t; 00171 pointf translation, scale; 00172 00173 translation = job->translation; 00174 scale.x = job->zoom * job->devscale.x; 00175 scale.y = job->zoom * job->devscale.y; 00176 00177 if (job->rotation) { 00178 for (i = 0; i < n; i++) { 00179 t = -(af[i].y + translation.y) * scale.x; 00180 AF[i].y = (af[i].x + translation.x) * scale.y; 00181 AF[i].x = t; 00182 } 00183 } else { 00184 for (i = 0; i < n; i++) { 00185 AF[i].x = (af[i].x + translation.x) * scale.x; 00186 AF[i].y = (af[i].y + translation.y) * scale.y; 00187 } 00188 } 00189 return AF; 00190 } 00191 00192 static int gvrender_comparestr(const void *s1, const void *s2) 00193 { 00194 return strcmp(*(char **) s1, *(char **) s2); 00195 } 00196 00197 static void gvrender_resolve_color(gvrender_features_t * features, 00198 char *name, gvcolor_t * color) 00199 { 00200 char *tok; 00201 int rc; 00202 00203 color->u.string = name; 00204 color->type = COLOR_STRING; 00205 tok = canontoken(name); 00206 if (!features->knowncolors 00207 || 00208 (bsearch 00209 (&tok, features->knowncolors, features->sz_knowncolors, 00210 sizeof(char *), gvrender_comparestr)) == NULL) { 00211 /* if tok was not found in known_colors */ 00212 rc = colorxlate(name, color, features->color_type); 00213 if (rc != COLOR_OK) { 00214 if (rc == COLOR_UNKNOWN) { 00215 char *missedcolor = gmalloc(strlen(name) + 16); 00216 sprintf(missedcolor, "color %s", name); 00217 if (emit_once(missedcolor)) 00218 agerr(AGWARN, "%s is not a known color.\n", name); 00219 free(missedcolor); 00220 } else { 00221 agerr(AGERR, "error in colxlate()\n"); 00222 } 00223 } 00224 } 00225 } 00226 00227 void gvrender_begin_graph(GVJ_t * job, graph_t * g) 00228 { 00229 /* GVC_t *gvc = job->gvc; */ 00230 gvrender_engine_t *gvre = job->render.engine; 00231 /* char *s; */ 00232 00233 if (gvre) { 00234 /* render specific init */ 00235 if (gvre->begin_graph) 00236 gvre->begin_graph(job); 00237 00238 #if 0 00239 /* background color */ 00240 if (((s = agget(g, "bgcolor")) != 0) && s[0]) { 00241 gvrender_resolve_color(job->render.features, s, 00242 &(gvc->bgcolor)); 00243 if (gvre->resolve_color) 00244 gvre->resolve_color(job, &(gvc->bgcolor)); 00245 } 00246 #endif 00247 00248 } 00249 } 00250 00251 void gvrender_end_graph(GVJ_t * job) 00252 { 00253 gvrender_engine_t *gvre = job->render.engine; 00254 00255 if (gvre) { 00256 if (gvre->end_graph) 00257 gvre->end_graph(job); 00258 } 00259 gvdevice_format(job); 00260 } 00261 00262 void gvrender_begin_page(GVJ_t * job) 00263 { 00264 gvrender_engine_t *gvre = job->render.engine; 00265 00266 if (gvre) { 00267 if (gvre->begin_page) 00268 gvre->begin_page(job); 00269 } 00270 } 00271 00272 void gvrender_end_page(GVJ_t * job) 00273 { 00274 gvrender_engine_t *gvre = job->render.engine; 00275 00276 if (gvre) { 00277 if (gvre->end_page) 00278 gvre->end_page(job); 00279 } 00280 } 00281 00282 void gvrender_begin_layer(GVJ_t * job) 00283 { 00284 gvrender_engine_t *gvre = job->render.engine; 00285 00286 if (gvre) { 00287 if (gvre->begin_layer) 00288 gvre->begin_layer(job, job->gvc->layerIDs[job->layerNum], 00289 job->layerNum, job->numLayers); 00290 } 00291 } 00292 00293 void gvrender_end_layer(GVJ_t * job) 00294 { 00295 gvrender_engine_t *gvre = job->render.engine; 00296 00297 if (gvre) { 00298 if (gvre->end_layer) 00299 gvre->end_layer(job); 00300 } 00301 } 00302 00303 void gvrender_begin_cluster(GVJ_t * job, graph_t * sg) 00304 { 00305 gvrender_engine_t *gvre = job->render.engine; 00306 00307 if (gvre) { 00308 if (gvre->begin_cluster) 00309 gvre->begin_cluster(job); 00310 } 00311 } 00312 00313 void gvrender_end_cluster(GVJ_t * job, graph_t * g) 00314 { 00315 gvrender_engine_t *gvre = job->render.engine; 00316 00317 if (gvre) { 00318 if (gvre->end_cluster) 00319 gvre->end_cluster(job); 00320 } 00321 } 00322 00323 void gvrender_begin_nodes(GVJ_t * job) 00324 { 00325 gvrender_engine_t *gvre = job->render.engine; 00326 00327 if (gvre) { 00328 if (gvre->begin_nodes) 00329 gvre->begin_nodes(job); 00330 } 00331 } 00332 00333 void gvrender_end_nodes(GVJ_t * job) 00334 { 00335 gvrender_engine_t *gvre = job->render.engine; 00336 00337 if (gvre) { 00338 if (gvre->end_nodes) 00339 gvre->end_nodes(job); 00340 } 00341 } 00342 00343 void gvrender_begin_edges(GVJ_t * job) 00344 { 00345 gvrender_engine_t *gvre = job->render.engine; 00346 00347 if (gvre) { 00348 if (gvre->begin_edges) 00349 gvre->begin_edges(job); 00350 } 00351 } 00352 00353 void gvrender_end_edges(GVJ_t * job) 00354 { 00355 gvrender_engine_t *gvre = job->render.engine; 00356 00357 if (gvre) { 00358 if (gvre->end_edges) 00359 gvre->end_edges(job); 00360 } 00361 } 00362 00363 void gvrender_begin_node(GVJ_t * job, node_t * n) 00364 { 00365 gvrender_engine_t *gvre = job->render.engine; 00366 00367 if (gvre) { 00368 if (gvre->begin_node) 00369 gvre->begin_node(job); 00370 } 00371 } 00372 00373 void gvrender_end_node(GVJ_t * job) 00374 { 00375 gvrender_engine_t *gvre = job->render.engine; 00376 00377 if (gvre) { 00378 if (gvre->end_node) 00379 gvre->end_node(job); 00380 } 00381 } 00382 00383 void gvrender_begin_edge(GVJ_t * job, edge_t * e) 00384 { 00385 gvrender_engine_t *gvre = job->render.engine; 00386 00387 if (gvre) { 00388 if (gvre->begin_edge) 00389 gvre->begin_edge(job); 00390 } 00391 } 00392 00393 void gvrender_end_edge(GVJ_t * job) 00394 { 00395 gvrender_engine_t *gvre = job->render.engine; 00396 00397 if (gvre) { 00398 if (gvre->end_edge) 00399 gvre->end_edge(job); 00400 } 00401 } 00402 00403 void gvrender_begin_anchor(GVJ_t * job, char *href, char *tooltip, 00404 char *target, char *id) 00405 { 00406 gvrender_engine_t *gvre = job->render.engine; 00407 00408 if (gvre) { 00409 if (gvre->begin_anchor) 00410 gvre->begin_anchor(job, href, tooltip, target, id); 00411 } 00412 } 00413 00414 void gvrender_end_anchor(GVJ_t * job) 00415 { 00416 gvrender_engine_t *gvre = job->render.engine; 00417 00418 if (gvre) { 00419 if (gvre->end_anchor) 00420 gvre->end_anchor(job); 00421 } 00422 } 00423 00424 void gvrender_begin_label(GVJ_t * job, label_type type) 00425 { 00426 gvrender_engine_t *gvre = job->render.engine; 00427 00428 if (gvre) { 00429 if (gvre->begin_label) 00430 gvre->begin_label(job, type); 00431 } 00432 } 00433 00434 void gvrender_end_label(GVJ_t * job) 00435 { 00436 gvrender_engine_t *gvre = job->render.engine; 00437 00438 if (gvre) { 00439 if (gvre->end_label) 00440 gvre->end_label(job); 00441 } 00442 } 00443 00444 void gvrender_textpara(GVJ_t * job, pointf p, textpara_t * para) 00445 { 00446 gvrender_engine_t *gvre = job->render.engine; 00447 pointf PF; 00448 00449 if (para->str && para->str[0] 00450 && (!job->obj /* because of xdgen non-conformity */ 00451 || job->obj->pen != PEN_NONE)) { 00452 if (job->flags & GVRENDER_DOES_TRANSFORM) 00453 PF = p; 00454 else 00455 PF = gvrender_ptf(job, p); 00456 if (gvre) { 00457 if (gvre->textpara) 00458 gvre->textpara(job, PF, para); 00459 } 00460 } 00461 } 00462 00463 void gvrender_set_pencolor(GVJ_t * job, char *name) 00464 { 00465 gvrender_engine_t *gvre = job->render.engine; 00466 gvcolor_t *color = &(job->obj->pencolor); 00467 char *cp = NULL; 00468 00469 if ((cp = strstr(name, ":"))) /* if its a color list, then use only first */ 00470 *cp = '\0'; 00471 if (gvre) { 00472 gvrender_resolve_color(job->render.features, name, color); 00473 if (gvre->resolve_color) 00474 gvre->resolve_color(job, color); 00475 } 00476 if (cp) /* restore color list */ 00477 *cp = ':'; 00478 } 00479 00480 void gvrender_set_fillcolor(GVJ_t * job, char *name) 00481 { 00482 gvrender_engine_t *gvre = job->render.engine; 00483 gvcolor_t *color = &(job->obj->fillcolor); 00484 char *cp = NULL; 00485 00486 if ((cp = strstr(name, ":"))) /* if its a color list, then use only first */ 00487 *cp = '\0'; 00488 if (gvre) { 00489 gvrender_resolve_color(job->render.features, name, color); 00490 if (gvre->resolve_color) 00491 gvre->resolve_color(job, color); 00492 } 00493 if (cp) 00494 *cp = ':'; 00495 } 00496 00497 void gvrender_set_gradient_vals (GVJ_t * job, char *stopcolor, int angle) 00498 { 00499 gvrender_engine_t *gvre = job->render.engine; 00500 gvcolor_t *color = &(job->obj->stopcolor); 00501 00502 if (gvre) { 00503 gvrender_resolve_color(job->render.features, stopcolor, color); 00504 if (gvre->resolve_color) 00505 gvre->resolve_color(job, color); 00506 } 00507 job->obj->gradient_angle = angle; 00508 } 00509 00510 void gvrender_set_style(GVJ_t * job, char **s) 00511 { 00512 gvrender_engine_t *gvre = job->render.engine; 00513 obj_state_t *obj = job->obj; 00514 char *line, *p; 00515 00516 obj->rawstyle = s; 00517 if (gvre) { 00518 if (s) 00519 while ((p = line = *s++)) { 00520 if (streq(line, "solid")) 00521 obj->pen = PEN_SOLID; 00522 else if (streq(line, "dashed")) 00523 obj->pen = PEN_DASHED; 00524 else if (streq(line, "dotted")) 00525 obj->pen = PEN_DOTTED; 00526 else if (streq(line, "invis") || streq(line, "invisible")) 00527 obj->pen = PEN_NONE; 00528 else if (streq(line, "bold")) 00529 obj->penwidth = PENWIDTH_BOLD; 00530 else if (streq(line, "setlinewidth")) { 00531 while (*p) 00532 p++; 00533 p++; 00534 obj->penwidth = atof(p); 00535 } else if (streq(line, "filled")) 00536 obj->fill = FILL_SOLID; 00537 else if (streq(line, "unfilled")) 00538 obj->fill = FILL_NONE; 00539 else if (streq(line, "tapered")); 00540 else { 00541 agerr(AGWARN, 00542 "gvrender_set_style: unsupported style %s - ignoring\n", 00543 line); 00544 } 00545 } 00546 } 00547 } 00548 00549 void gvrender_ellipse(GVJ_t * job, pointf * pf, int n, int filled) 00550 { 00551 gvrender_engine_t *gvre = job->render.engine; 00552 00553 if (gvre) { 00554 if (gvre->ellipse && job->obj->pen != PEN_NONE) { 00555 pointf af[2]; 00556 00557 /* center */ 00558 af[0].x = (pf[0].x + pf[1].x) / 2.; 00559 af[0].y = (pf[0].y + pf[1].y) / 2.; 00560 /* corner */ 00561 af[1] = pf[1]; 00562 00563 if (!(job->flags & GVRENDER_DOES_TRANSFORM)) 00564 gvrender_ptf_A(job, af, af, 2); 00565 gvre->ellipse(job, af, filled); 00566 } 00567 } 00568 } 00569 00570 void gvrender_polygon(GVJ_t * job, pointf * af, int n, int filled) 00571 { 00572 int noPoly = 0; 00573 gvcolor_t save_pencolor; 00574 00575 gvrender_engine_t *gvre = job->render.engine; 00576 if (gvre) { 00577 if (gvre->polygon && job->obj->pen != PEN_NONE) { 00578 if (filled & NO_POLY) { 00579 noPoly = 1; 00580 filled &= ~NO_POLY; 00581 save_pencolor = job->obj->pencolor; 00582 job->obj->pencolor = job->obj->fillcolor; 00583 } 00584 if (job->flags & GVRENDER_DOES_TRANSFORM) 00585 gvre->polygon(job, af, n, filled); 00586 else { 00587 if (sizeAF < n) { 00588 sizeAF = n + 10; 00589 AF = grealloc(AF, sizeAF * sizeof(pointf)); 00590 } 00591 gvrender_ptf_A(job, af, AF, n); 00592 gvre->polygon(job, AF, n, filled); 00593 } 00594 if (noPoly) 00595 job->obj->pencolor = save_pencolor; 00596 } 00597 } 00598 } 00599 00600 00601 void gvrender_box(GVJ_t * job, boxf B, int filled) 00602 { 00603 pointf A[4]; 00604 00605 A[0] = B.LL; 00606 A[2] = B.UR; 00607 A[1].x = A[0].x; 00608 A[1].y = A[2].y; 00609 A[3].x = A[2].x; 00610 A[3].y = A[0].y; 00611 00612 gvrender_polygon(job, A, 4, filled); 00613 } 00614 00615 void gvrender_beziercurve(GVJ_t * job, pointf * af, int n, 00616 int arrow_at_start, int arrow_at_end, 00617 boolean filled) 00618 { 00619 gvrender_engine_t *gvre = job->render.engine; 00620 00621 if (gvre) { 00622 if (gvre->beziercurve && job->obj->pen != PEN_NONE) { 00623 if (job->flags & GVRENDER_DOES_TRANSFORM) 00624 gvre->beziercurve(job, af, n, arrow_at_start, arrow_at_end, 00625 filled); 00626 else { 00627 if (sizeAF < n) { 00628 sizeAF = n + 10; 00629 AF = grealloc(AF, sizeAF * sizeof(pointf)); 00630 } 00631 gvrender_ptf_A(job, af, AF, n); 00632 gvre->beziercurve(job, AF, n, arrow_at_start, arrow_at_end, 00633 filled); 00634 } 00635 } 00636 } 00637 } 00638 00639 void gvrender_polyline(GVJ_t * job, pointf * af, int n) 00640 { 00641 gvrender_engine_t *gvre = job->render.engine; 00642 00643 if (gvre) { 00644 if (gvre->polyline && job->obj->pen != PEN_NONE) { 00645 if (job->flags & GVRENDER_DOES_TRANSFORM) 00646 gvre->polyline(job, af, n); 00647 else { 00648 if (sizeAF < n) { 00649 sizeAF = n + 10; 00650 AF = grealloc(AF, sizeAF * sizeof(pointf)); 00651 } 00652 gvrender_ptf_A(job, af, AF, n); 00653 gvre->polyline(job, AF, n); 00654 } 00655 } 00656 } 00657 } 00658 00659 void gvrender_comment(GVJ_t * job, char *str) 00660 { 00661 gvrender_engine_t *gvre = job->render.engine; 00662 00663 if (!str || !str[0]) 00664 return; 00665 00666 if (gvre) { 00667 if (gvre->comment) 00668 gvre->comment(job, str); 00669 } 00670 } 00671 00672 static imagescale_t get_imagescale(char *s) 00673 { 00674 if (*s == '\0') 00675 return IMAGESCALE_FALSE; 00676 if (!strcasecmp(s, "width")) 00677 return IMAGESCALE_WIDTH; 00678 if (!strcasecmp(s, "height")) 00679 return IMAGESCALE_HEIGHT; 00680 if (!strcasecmp(s, "both")) 00681 return IMAGESCALE_BOTH; 00682 if (mapbool(s)) 00683 return IMAGESCALE_TRUE; 00684 return IMAGESCALE_FALSE; 00685 } 00686 00687 /* gvrender_usershape: 00688 * Scale image to fill polygon bounding box according to "imagescale" 00689 */ 00690 void gvrender_usershape(GVJ_t * job, char *name, pointf * a, int n, 00691 boolean filled, char *imagescale) 00692 { 00693 gvrender_engine_t *gvre = job->render.engine; 00694 usershape_t *us; 00695 double iw, ih, pw, ph; 00696 double scalex, scaley; /* scale factors */ 00697 boxf b; /* target box */ 00698 int i; 00699 point isz; 00700 00701 if (!(us = gvusershape_find(name))) { 00702 if (find_user_shape(name)) { 00703 if (gvre && gvre->library_shape) 00704 gvre->library_shape(job, name, a, n, filled); 00705 } 00706 return; 00707 } 00708 00709 isz = gvusershape_size_dpi(us, job->dpi); 00710 if ((isz.x <= 0) && (isz.y <= 0)) 00711 return; 00712 00713 /* compute bb of polygon */ 00714 b.LL = b.UR = a[0]; 00715 for (i = 1; i < n; i++) { 00716 EXPANDBP(b, a[i]); 00717 } 00718 00719 pw = b.UR.x - b.LL.x; 00720 ph = b.UR.y - b.LL.y; 00721 ih = (double) isz.y; 00722 iw = (double) isz.x; 00723 00724 scalex = pw / iw; 00725 scaley = ph / ih; 00726 00727 switch (get_imagescale(imagescale)) { 00728 case IMAGESCALE_TRUE: 00729 /* keep aspect ratio fixed by just using the smaller scale */ 00730 if (scalex < scaley) { 00731 iw *= scalex; 00732 ih *= scalex; 00733 } else { 00734 iw *= scaley; 00735 ih *= scaley; 00736 } 00737 break; 00738 case IMAGESCALE_WIDTH: 00739 iw *= scalex; 00740 break; 00741 case IMAGESCALE_HEIGHT: 00742 ih *= scaley; 00743 break; 00744 case IMAGESCALE_BOTH: 00745 iw *= scalex; 00746 ih *= scaley; 00747 break; 00748 case IMAGESCALE_FALSE: 00749 default: 00750 break; 00751 } 00752 00753 /* if image is smaller than target area then center it */ 00754 if (iw < pw) { 00755 b.LL.x += (pw - iw) / 2.0; 00756 b.UR.x -= (pw - iw) / 2.0; 00757 } 00758 if (ih < ph) { 00759 b.LL.y += (ph - ih) / 2.0; 00760 b.UR.y -= (ph - ih) / 2.0; 00761 } 00762 00763 /* convert from graph to device coordinates */ 00764 if (!(job->flags & GVRENDER_DOES_TRANSFORM)) { 00765 b.LL = gvrender_ptf(job, b.LL); 00766 b.UR = gvrender_ptf(job, b.UR); 00767 } 00768 00769 if (b.LL.x > b.UR.x) { 00770 double d = b.LL.x; 00771 b.LL.x = b.UR.x; 00772 b.UR.x = d; 00773 } 00774 if (b.LL.y > b.UR.y) { 00775 double d = b.LL.y; 00776 b.LL.y = b.UR.y; 00777 b.UR.y = d; 00778 } 00779 if (gvre) { 00780 gvloadimage(job, us, b, filled, job->render.type); 00781 } 00782 } 00783 00784 void gvrender_set_penwidth(GVJ_t * job, double penwidth) 00785 { 00786 gvrender_engine_t *gvre = job->render.engine; 00787 00788 if (gvre) { 00789 job->obj->penwidth = penwidth; 00790 /*if (gvre->set_penwidth) gvre->set_penwidth(job, penwidth); */ 00791 } 00792 }
1.7.5