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