$search
00001 00002 /*************************************************************************** 00003 * gvplugin_skillgui_cairo.cpp - Graphviz plugin for Skill GUI using cairo 00004 * 00005 * Created: Fri Dec 19 12:01:39 2008 00006 * Copyright 2008-2010 Tim Niemueller [www.niemueller.de] 00007 * 2010 Carnegie Mellon University 00008 * 2010 Intel Labs Pittsburgh 00009 ****************************************************************************/ 00010 00011 /* This program is free software; you can redistribute it and/or modify 00012 * it under the terms of the GNU General Public License as published by 00013 * the Free Software Foundation; either version 2 of the License, or 00014 * (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Library General Public License for more details. 00020 * 00021 * Read the full text in the LICENSE.GPL file in the doc directory. 00022 */ 00023 00024 #include "gvplugin_skillgui_cairo.h" 00025 00026 #ifdef USE_ROS 00027 # include "angle.h" 00028 #else 00029 # include <utils/math/angle.h> 00030 # include <utils/time/tracker.h> 00031 #endif 00032 00033 #include <gvplugin_device.h> 00034 #include <gvplugin_render.h> 00035 00036 #include <algorithm> 00037 #include <cstdio> 00038 00039 #define NOEXPORT __attribute__ ((visibility("hidden"))) 00040 00041 NOEXPORT SkillGuiCairoRenderInstructor *__sgcri = NULL; 00042 00043 #if CAIROMM_MAJOR_VERSION > 1 || (CAIROMM_MAJOR_VERSION == 1 && CAIROMM_MINO_VERSION > 8) 00044 NOEXPORT std::vector<double> __skillgui_cairo_render_dashed; 00045 NOEXPORT std::vector<double> __skillgui_cairo_render_dotted; 00046 #else 00047 NOEXPORT std::valarray<double> __skillgui_cairo_render_dashed(1); 00048 NOEXPORT std::valarray<double> __skillgui_cairo_render_dotted(2); 00049 #endif 00050 NOEXPORT const char *__fontname = NULL; 00051 00052 #ifdef USE_GVPLUGIN_TIMETRACKER 00053 NOEXPORT fawkes::TimeTracker __tt; 00054 NOEXPORT unsigned int __ttc_page = __tt.add_class("Page"); 00055 NOEXPORT unsigned int __ttc_beginpage = __tt.add_class("Begin Page"); 00056 NOEXPORT unsigned int __ttc_ellipse = __tt.add_class("Ellipse"); 00057 NOEXPORT unsigned int __ttc_bezier = __tt.add_class("Bezier"); 00058 NOEXPORT unsigned int __ttc_polygon = __tt.add_class("Polygon"); 00059 NOEXPORT unsigned int __ttc_polyline = __tt.add_class("Polyline"); 00060 NOEXPORT unsigned int __ttc_text = __tt.add_class("Text"); 00061 NOEXPORT unsigned int __ttc_text_1 = __tt.add_class("Text 1"); 00062 NOEXPORT unsigned int __ttc_text_2 = __tt.add_class("Text 2"); 00063 NOEXPORT unsigned int __ttc_text_3 = __tt.add_class("Text 3"); 00064 NOEXPORT unsigned int __ttc_text_4 = __tt.add_class("Text 4"); 00065 NOEXPORT unsigned int __ttc_text_5 = __tt.add_class("Text 5"); 00066 NOEXPORT unsigned int __tt_count = 0; 00067 NOEXPORT unsigned int __num_ellipse = 0; 00068 NOEXPORT unsigned int __num_bezier = 0; 00069 NOEXPORT unsigned int __num_polygon = 0; 00070 NOEXPORT unsigned int __num_polyline = 0; 00071 NOEXPORT unsigned int __num_text = 0; 00072 #endif 00073 00074 00133 static void 00134 skillgui_cairo_device_init(GVJ_t *firstjob) 00135 { 00136 } 00137 00138 static void 00139 skillgui_cairo_device_finalize(GVJ_t *firstjob) 00140 { 00141 firstjob->context = (void *)__sgcri; 00142 firstjob->external_context = TRUE; 00143 00144 // Render! 00145 (firstjob->callbacks->refresh)(firstjob); 00146 } 00147 00148 static inline void 00149 skillgui_cairo_set_color(Cairo::RefPtr<Cairo::Context> cairo, gvcolor_t * color) 00150 { 00151 cairo->set_source_rgba(color->u.RGBA[0], color->u.RGBA[1], 00152 color->u.RGBA[2], color->u.RGBA[3]); 00153 } 00154 00155 static inline void 00156 skillgui_cairo_set_penstyle(Cairo::RefPtr<Cairo::Context> cairo, GVJ_t *job) 00157 { 00158 obj_state_t *obj = job->obj; 00159 00160 if (obj->pen == PEN_DASHED) { 00161 cairo->set_dash(__skillgui_cairo_render_dashed, 0.0); 00162 } else if (obj->pen == PEN_DOTTED) { 00163 cairo->set_dash(__skillgui_cairo_render_dotted, 0.0); 00164 } else { 00165 #if CAIROMM_MAJOR_VERSION > 1 || (CAIROMM_MAJOR_VERSION == 1 && CAIROMM_MINO_VERSION > 8) 00166 std::vector<double> empty; 00167 #else 00168 std::valarray<double> empty; 00169 #endif 00170 cairo->set_dash(empty, 0.0); 00171 } 00172 cairo->set_line_width(obj->penwidth); 00173 } 00174 00175 00176 static void 00177 skillgui_cairo_render_begin_page(GVJ_t *job) 00178 { 00179 #ifdef USE_GVPLUGIN_TIMETRACKER 00180 __tt.ping_start(__ttc_page); 00181 __tt.ping_start(__ttc_beginpage); 00182 #endif 00183 SkillGuiCairoRenderInstructor *cri = (SkillGuiCairoRenderInstructor *)job->context; 00184 00185 obj_state_t *obj = job->obj; 00186 if (obj && obj->type == ROOTGRAPH_OBJTYPE) { 00187 __fontname = agget(obj->u.g, (char *)"fontname"); 00188 } 00189 00190 float bbwidth = job->bb.UR.x - job->bb.LL.x; 00191 float bbheight = job->bb.UR.y - job->bb.LL.y; 00192 00193 cri->set_bb(bbwidth, bbheight); 00194 cri->set_pad(job->pad.x, job->pad.y); 00195 Cairo::RefPtr<Cairo::Context> cairo = cri->get_cairo(); 00196 00197 double pad_x, pad_y; 00198 cri->get_pad(pad_x, pad_y); 00199 00200 // For internal calculations we need to care about the padding 00201 //bbwidth += 2 * pad_x; 00202 //bbheight += 2 * pad_y; 00203 00204 double avwidth, avheight; 00205 cri->get_dimensions(avwidth, avheight); 00206 float translate_x = 0; 00207 float translate_y = 0; 00208 00209 if ( cri->scale_override() ) { 00210 float zoom = cri->get_scale(); 00211 float zwidth = bbwidth * zoom; 00212 float zheight = bbheight * zoom; 00213 translate_x += (avwidth - zwidth ) / 2.; 00214 translate_y += (avheight - zheight) / 2.; 00215 00216 double translate_x, translate_y; 00217 cri->get_translation(translate_x, translate_y); 00218 00219 cairo->translate(translate_x, translate_y); 00220 cairo->scale(zoom, zoom); 00221 00222 } else { 00223 float zoom_w = avwidth / bbwidth; 00224 float zoom_h = avheight / bbheight; 00225 float zoom = std::min(zoom_w, zoom_h); 00226 00227 if (bbwidth > avwidth || bbheight > avheight) { 00228 float zwidth = bbwidth * zoom; 00229 float zheight = bbheight * zoom; 00230 translate_x += (avwidth - zwidth ) / 2.; 00231 translate_y += (avheight - zheight) / 2. + zheight; 00232 } else { 00233 zoom = 1.0; 00234 translate_x += (avwidth - bbwidth) / 2.; 00235 translate_y += (avheight - bbheight) / 2. + bbheight; 00236 } 00237 00238 cri->set_scale(zoom); 00239 cri->set_translation(translate_x, translate_y); 00240 00241 cairo->translate(translate_x + pad_x * zoom, translate_y - pad_y * zoom); 00242 cairo->scale(zoom, zoom); 00243 } 00244 00245 00246 00247 #ifdef USE_GVPLUGIN_TIMETRACKER 00248 __num_ellipse = 0; 00249 __num_bezier = 0; 00250 __num_polygon = 0; 00251 __num_polyline = 0; 00252 __num_text = 0; 00253 00254 __tt.ping_end(__ttc_beginpage); 00255 #endif 00256 } 00257 00258 static void 00259 skillgui_cairo_render_end_page(GVJ_t * job) 00260 { 00261 //SkillGuiCairoRenderInstructor *cri = (SkillGuiCairoRenderInstructor *)job->context; 00262 //cri->queue_draw(); 00263 #ifdef USE_GVPLUGIN_TIMETRACKER 00264 __tt.ping_end(__ttc_page); 00265 if ( ++__tt_count >= 10 ) { 00266 __tt_count = 0; 00267 __tt.print_to_stdout(); 00268 00269 printf("Num Ellipse: %u\n" 00270 "Num Bezier: %u\n" 00271 "Num Polygon: %u\n" 00272 "Num Polyline: %u\n" 00273 "Num Text: %u\n", __num_ellipse, __num_bezier, 00274 __num_polygon, __num_polyline, __num_text); 00275 } 00276 #endif 00277 } 00278 00279 static void 00280 skillgui_cairo_render_textpara(GVJ_t *job, pointf p, textpara_t *para) 00281 { 00282 #ifdef USE_GVPLUGIN_TIMETRACKER 00283 __tt.ping_start(__ttc_text); 00284 ++__num_text; 00285 #endif 00286 SkillGuiCairoRenderInstructor *cri = (SkillGuiCairoRenderInstructor *)job->context; 00287 Cairo::RefPtr<Cairo::Context> cairo = cri->get_cairo(); 00288 obj_state_t *obj = job->obj; 00289 00290 Cairo::FontWeight weight = Cairo::FONT_WEIGHT_NORMAL; 00291 Cairo::FontSlant slant = Cairo::FONT_SLANT_NORMAL; 00292 char *fontweight = NULL; 00293 char *fontslant = NULL; 00294 if (obj->type == CLUSTER_OBJTYPE) { 00295 fontweight = agget(obj->u.sg, (char *)"fontweight"); 00296 fontslant = agget(obj->u.sg, (char *)"fontslant"); 00297 } else if (obj->type == ROOTGRAPH_OBJTYPE) { 00298 fontweight = agget(obj->u.g, (char *)"fontweight"); 00299 fontslant = agget(obj->u.g, (char *)"fontslant"); 00300 } else if (obj->type == NODE_OBJTYPE) { 00301 fontweight = agget(obj->u.n, (char *)"fontweight"); 00302 fontslant = agget(obj->u.n, (char *)"fontslant"); 00303 } else if (obj->type == EDGE_OBJTYPE) { 00304 fontweight = agget(obj->u.e, (char *)"fontweight"); 00305 fontslant = agget(obj->u.e, (char *)"fontslant"); 00306 } 00307 if (fontweight && (strcmp(fontweight, "bold") == 0)) { 00308 weight = Cairo::FONT_WEIGHT_BOLD; 00309 p.x -= 8; 00310 } 00311 if (fontslant && (strcmp(fontslant, "italic") == 0)) { 00312 slant = Cairo::FONT_SLANT_ITALIC; 00313 } 00314 00315 double offsetx = 0.0; 00316 double offsety = 0.0; 00317 double rotate = 0.0; 00318 00319 if ( (obj->type == EDGE_OBJTYPE) && (strcmp(para->str, obj->headlabel) == 0) ) { 00320 char *labelrotate = agget(obj->u.e, (char *)"labelrotate"); 00321 if (labelrotate && (strlen(labelrotate) > 0)) { 00322 rotate = fawkes::deg2rad(atof(labelrotate)); 00323 } 00324 char *labeloffsetx = agget(obj->u.e, (char *)"labeloffsetx"); 00325 if (labeloffsetx && (strlen(labeloffsetx) > 0)) { 00326 offsetx = atof(labeloffsetx); 00327 } 00328 char *labeloffsety = agget(obj->u.e, (char *)"labeloffsety"); 00329 if (labeloffsety && (strlen(labeloffsety) > 0)) { 00330 offsety = atof(labeloffsety); 00331 } 00332 } 00333 //__tt.ping_start(__ttc_text_1); 00334 00335 Cairo::Matrix old_matrix; 00336 cairo->get_matrix(old_matrix); 00337 00338 if (__fontname) { 00339 cairo->select_font_face(__fontname, slant, weight); 00340 } else { 00341 cairo->select_font_face(para->fontname, slant, weight); 00342 } 00343 cairo->set_font_size(para->fontsize); 00344 //cairo->set_font_options ( Cairo::FontOptions() ); 00345 //cairo->set_line_width(1.0); 00346 00347 Cairo::TextExtents extents; 00348 cairo->get_text_extents(para->str, extents); 00349 00350 if (para->just == 'r') { 00351 p.x -= extents.width; 00352 } else if (para->just != 'l') { 00353 p.x -= extents.width / 2.0; 00354 } 00355 00356 cairo->move_to(p.x + offsetx, -p.y + offsety); 00357 cairo->rotate(rotate); 00358 skillgui_cairo_set_color(cairo, &(obj->pencolor)); 00359 cairo->text_path( para->str ); 00360 cairo->fill(); 00361 00362 cairo->set_matrix(old_matrix); 00363 00364 //__tt.ping_end(__ttc_text_5); 00365 #ifdef USE_GVPLUGIN_TIMETRACKER 00366 __tt.ping_end(__ttc_text); 00367 #endif 00368 } 00369 00370 static void 00371 skillgui_cairo_render_ellipse(GVJ_t *job, pointf *A, int filled) 00372 { 00373 #ifdef USE_GVPLUGIN_TIMETRACKER 00374 __tt.ping_start(__ttc_ellipse); 00375 ++__num_ellipse; 00376 #endif 00377 //printf("Render ellipse\n"); 00378 SkillGuiCairoRenderInstructor *cri = (SkillGuiCairoRenderInstructor *)job->context; 00379 Cairo::RefPtr<Cairo::Context> cairo = cri->get_cairo(); 00380 obj_state_t *obj = job->obj; 00381 00382 Cairo::Matrix old_matrix; 00383 cairo->get_matrix(old_matrix); 00384 00385 skillgui_cairo_set_penstyle(cairo, job); 00386 00387 cairo->translate(A[0].x, -A[0].y); 00388 00389 double rx = A[1].x - A[0].x; 00390 double ry = A[1].y - A[0].y; 00391 cairo->scale(1, ry / rx); 00392 cairo->move_to(rx, 0); 00393 cairo->arc(0, 0, rx, 0, 2 * M_PI); 00394 cairo->close_path(); 00395 00396 cairo->set_matrix(old_matrix); 00397 00398 if (filled) { 00399 skillgui_cairo_set_color(cairo, &(obj->fillcolor)); 00400 cairo->fill_preserve(); 00401 } 00402 skillgui_cairo_set_color(cairo, &(obj->pencolor)); 00403 cairo->stroke(); 00404 00405 #ifdef USE_GVPLUGIN_TIMETRACKER 00406 __tt.ping_end(__ttc_ellipse); 00407 #endif 00408 } 00409 00410 static void 00411 skillgui_cairo_render_polygon(GVJ_t *job, pointf *A, int n, int filled) 00412 { 00413 #ifdef USE_GVPLUGIN_TIMETRACKER 00414 __tt.ping_start(__ttc_polygon); 00415 ++__num_polygon; 00416 #endif 00417 //printf("Polygon\n"); 00418 SkillGuiCairoRenderInstructor *cri = (SkillGuiCairoRenderInstructor *)job->context; 00419 Cairo::RefPtr<Cairo::Context> cairo = cri->get_cairo(); 00420 obj_state_t *obj = job->obj; 00421 00422 skillgui_cairo_set_penstyle(cairo, job); 00423 00424 cairo->move_to(A[0].x, -A[0].y); 00425 for (int i = 1; i < n; ++i) { 00426 cairo->line_to(A[i].x, -A[i].y); 00427 } 00428 cairo->close_path(); 00429 00430 if (filled) { 00431 skillgui_cairo_set_color(cairo, &(obj->fillcolor)); 00432 cairo->fill_preserve(); 00433 } 00434 00435 // HACK to workaround graphviz bug any get the Tim style... 00436 if ( obj->type == CLUSTER_OBJTYPE ) { 00437 obj->pencolor.u.RGBA[0] = 0.666; 00438 obj->pencolor.u.RGBA[1] = 0.666; 00439 obj->pencolor.u.RGBA[2] = 1.0; 00440 obj->pencolor.u.RGBA[3] = 1.0; 00441 } 00442 skillgui_cairo_set_color(cairo, &(obj->pencolor)); 00443 cairo->stroke(); 00444 00445 #ifdef USE_GVPLUGIN_TIMETRACKER 00446 __tt.ping_end(__ttc_polygon); 00447 #endif 00448 } 00449 00450 static void 00451 skillgui_cairo_render_bezier(GVJ_t * job, pointf * A, int n, int arrow_at_start, 00452 int arrow_at_end, int filled) 00453 { 00454 #ifdef USE_GVPLUGIN_TIMETRACKER 00455 __tt.ping_start(__ttc_bezier); 00456 ++__num_bezier; 00457 #endif 00458 //printf("Bezier\n"); 00459 SkillGuiCairoRenderInstructor *cri = (SkillGuiCairoRenderInstructor *)job->context; 00460 Cairo::RefPtr<Cairo::Context> cairo = cri->get_cairo(); 00461 obj_state_t *obj = job->obj; 00462 00463 skillgui_cairo_set_penstyle(cairo, job); 00464 00465 cairo->move_to(A[0].x, -A[0].y); 00466 for (int i = 1; i < n; i += 3) 00467 cairo->curve_to(A[i].x, -A[i].y, A[i + 1].x, -A[i + 1].y, 00468 A[i + 2].x, -A[i + 2].y); 00469 if (filled) { 00470 skillgui_cairo_set_color(cairo, &(obj->fillcolor)); 00471 cairo->fill_preserve(); 00472 } 00473 skillgui_cairo_set_color(cairo, &(obj->pencolor)); 00474 cairo->stroke(); 00475 00476 #ifdef USE_GVPLUGIN_TIMETRACKER 00477 __tt.ping_end(__ttc_bezier); 00478 #endif 00479 } 00480 00481 static void 00482 skillgui_cairo_render_polyline(GVJ_t * job, pointf * A, int n) 00483 { 00484 #ifdef USE_GVPLUGIN_TIMETRACKER 00485 __tt.ping_start(__ttc_polyline); 00486 ++__num_polyline; 00487 #endif 00488 //printf("Polyline\n"); 00489 SkillGuiCairoRenderInstructor *cri = (SkillGuiCairoRenderInstructor *)job->context; 00490 Cairo::RefPtr<Cairo::Context> cairo = cri->get_cairo(); 00491 obj_state_t *obj = job->obj; 00492 00493 skillgui_cairo_set_penstyle(cairo, job); 00494 00495 //cairo->set_line_width(obj->penwidth * job->scale.x); 00496 cairo->move_to(A[0].x, -A[0].y); 00497 for (int i = 1; i < n; i++) { 00498 cairo->line_to(A[i].x, -A[i].y); 00499 } 00500 skillgui_cairo_set_color(cairo, &(obj->pencolor)); 00501 cairo->stroke(); 00502 00503 #ifdef USE_GVPLUGIN_TIMETRACKER 00504 __tt.ping_end(__ttc_polyline); 00505 #endif 00506 } 00507 00508 00509 static gvrender_engine_t skillgui_cairo_render_engine = { 00510 0, /* skillgui_cairo_render_begin_job */ 00511 0, /* skillgui_cairo_render_end_job */ 00512 0, /* skillgui_cairo_render_begin_graph */ 00513 0, /* skillgui_cairo_render_end_graph */ 00514 0, /* skillgui_cairo_render_begin_layer */ 00515 0, /* skillgui_cairo_render_end_layer */ 00516 skillgui_cairo_render_begin_page, 00517 skillgui_cairo_render_end_page, 00518 0, /* skillgui_cairo_render_begin_cluster */ 00519 0, /* skillgui_cairo_render_end_cluster */ 00520 0, /* skillgui_cairo_render_begin_nodes */ 00521 0, /* skillgui_cairo_render_end_nodes */ 00522 0, /* skillgui_cairo_render_begin_edges */ 00523 0, /* skillgui_cairo_render_end_edges */ 00524 0, /* skillgui_cairo_render_begin_node */ 00525 0, /* skillgui_cairo_render_end_node */ 00526 0, /* skillgui_cairo_render_begin_edge */ 00527 0, /* skillgui_cairo_render_end_edge */ 00528 0, /* skillgui_cairo_render_begin_anchor */ 00529 0, /* skillgui_cairo_render_end_anchor */ 00530 0, /* skillgui_cairo_begin_label */ 00531 0, /* skillgui_cairo_end_label */ 00532 skillgui_cairo_render_textpara, 00533 0, /* skillgui_cairo_render_resolve_color */ 00534 skillgui_cairo_render_ellipse, 00535 skillgui_cairo_render_polygon, 00536 skillgui_cairo_render_bezier, 00537 skillgui_cairo_render_polyline, 00538 0, /* skillgui_cairo_render_comment */ 00539 0, /* skillgui_cairo_render_library_shape */ 00540 }; 00541 00542 static gvdevice_engine_t skillgui_cairo_device_engine = { 00543 skillgui_cairo_device_init, 00544 NULL, /* skillgui_cairo_device_format */ 00545 skillgui_cairo_device_finalize, 00546 }; 00547 00548 00549 #ifdef __cplusplus 00550 extern "C" { 00551 #endif 00552 00553 00554 static gvrender_features_t skillgui_cairo_render_features = { 00555 GVRENDER_Y_GOES_DOWN | 00556 GVRENDER_DOES_LABELS | 00557 GVRENDER_DOES_TRANSFORM | 00558 GVRENDER_NO_WHITE_BG, /* flags */ 00559 8, /* default pad - graph units */ 00560 0, /* knowncolors */ 00561 0, /* sizeof knowncolors */ 00562 RGBA_DOUBLE, /* color_type */ 00563 }; 00564 00565 00566 static gvdevice_features_t skillgui_cairo_device_features = { 00567 GVDEVICE_DOES_TRUECOLOR | GVDEVICE_EVENTS, /* flags */ 00568 {0.,0.}, /* default margin - points */ 00569 {0.,0.}, /* default page width, height - points */ 00570 {96.,96.}, /* dpi */ 00571 }; 00572 00573 gvplugin_installed_t gvdevice_types_skillgui_cairo[] = { 00574 {0, ( char *)"skillguicairo:skillguicairo", 0, &skillgui_cairo_device_engine, &skillgui_cairo_device_features}, 00575 {0, NULL, 0, NULL, NULL} 00576 }; 00577 00578 gvplugin_installed_t gvrender_types_skillgui_cairo[] = { 00579 {0, (char *)"skillguicairo", 10, &skillgui_cairo_render_engine, &skillgui_cairo_render_features}, 00580 {0, NULL, 0, NULL, NULL} 00581 }; 00582 00583 static gvplugin_api_t apis[] = { 00584 {API_device, gvdevice_types_skillgui_cairo}, 00585 {API_render, gvrender_types_skillgui_cairo}, 00586 {(api_t)0, 0}, 00587 }; 00588 00589 gvplugin_library_t gvplugin_skillgui_cairo_LTX_library = { (char *)"skillguicairo", apis }; 00590 00591 #ifdef __cplusplus 00592 } 00593 #endif 00594 00595 00596 void 00597 gvplugin_skillgui_cairo_setup(GVC_t *gvc, SkillGuiCairoRenderInstructor *sgcri) 00598 { 00599 __sgcri = sgcri; 00600 gvAddLibrary(gvc, &gvplugin_skillgui_cairo_LTX_library); 00601 00602 #if CAIROMM_MAJOR_VERSION > 1 || (CAIROMM_MAJOR_VERSION == 1 && CAIROMM_MINO_VERSION > 8) 00603 __skillgui_cairo_render_dashed.clear(); 00604 __skillgui_cairo_render_dashed.push_back(6.0); 00605 __skillgui_cairo_render_dotted.clear(); 00606 __skillgui_cairo_render_dotted.push_back(2.0); 00607 __skillgui_cairo_render_dotted.push_back(6.0); 00608 #else 00609 __skillgui_cairo_render_dashed[0] = 6.0; 00610 __skillgui_cairo_render_dotted[0] = 2.0; 00611 __skillgui_cairo_render_dotted[1] = 6.0; 00612 #endif 00613 }