Fawkes API Fawkes Development Version
gvplugin_skillgui_cairo.cpp
1
2/***************************************************************************
3 * gvplugin_skillgui_cairo.cpp - Graphviz plugin for Skill GUI using cairo
4 *
5 * Created: Fri Dec 19 12:01:39 2008
6 * Copyright 2008-2009 Tim Niemueller [www.niemueller.de]
7 *
8 ****************************************************************************/
9
10/* This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Library General Public License for more details.
19 *
20 * Read the full text in the LICENSE.GPL file in the doc directory.
21 */
22
23#include "gvplugin_skillgui_cairo.h"
24
25#include <utils/math/angle.h>
26#include <utils/time/tracker.h>
27
28#include <algorithm>
29#include <cstdio>
30#include <gvplugin_device.h>
31#include <gvplugin_render.h>
32
33#define NOEXPORT __attribute__((visibility("hidden")))
34
35NOEXPORT SkillGuiCairoRenderInstructor *sgcri_ = NULL;
36
37#if CAIROMM_MAJOR_VERSION > 1 || (CAIROMM_MAJOR_VERSION == 1 && CAIROMM_MINO_VERSION > 8)
38NOEXPORT std::vector<double> skillgui_cairo_render_dashed_;
39NOEXPORT std::vector<double> skillgui_cairo_render_dotted_;
40#else
41NOEXPORT std::valarray<double> skillgui_cairo_render_dashed_(1);
42NOEXPORT std::valarray<double> skillgui_cairo_render_dotted_(2);
43#endif
44
45#ifdef USE_GVPLUGIN_TIMETRACKER
46NOEXPORT fawkes::TimeTracker tt_;
47NOEXPORT unsigned int ttc_page_ = tt_.add_class("Page");
48NOEXPORT unsigned int ttc_beginpage_ = tt_.add_class("Begin Page");
49NOEXPORT unsigned int ttc_ellipse_ = tt_.add_class("Ellipse");
50NOEXPORT unsigned int ttc_bezier_ = tt_.add_class("Bezier");
51NOEXPORT unsigned int ttc_polygon_ = tt_.add_class("Polygon");
52NOEXPORT unsigned int ttc_polyline_ = tt_.add_class("Polyline");
53NOEXPORT unsigned int ttc_text_ = tt_.add_class("Text");
54NOEXPORT unsigned int ttc_text_1_ = tt_.add_class("Text 1");
55NOEXPORT unsigned int ttc_text_2_ = tt_.add_class("Text 2");
56NOEXPORT unsigned int ttc_text_3_ = tt_.add_class("Text 3");
57NOEXPORT unsigned int ttc_text_4_ = tt_.add_class("Text 4");
58NOEXPORT unsigned int ttc_text_5_ = tt_.add_class("Text 5");
59NOEXPORT unsigned int tt_count_ = 0;
60NOEXPORT unsigned int num_ellipse_ = 0;
61NOEXPORT unsigned int num_bezier_ = 0;
62NOEXPORT unsigned int num_polygon_ = 0;
63NOEXPORT unsigned int num_polyline_ = 0;
64NOEXPORT unsigned int num_text_ = 0;
65#endif
66
67/** @class SkillGuiCairoRenderInstructor
68 * Graphviz Cairo render plugin instructor.
69 * @author Tim Niemueller
70 *
71 * @fn Cairo::RefPtr<Cairo::Context> SkillGuiCairoRenderInstructor::get_cairo()
72 * Get Cairo context.
73 * @return cairo context to use for drawing
74 *
75 * @fn bool SkillGuiCairoRenderInstructor::scale_override()
76 * Check if scale override is enabled.
77 * @return true if the instructor determines the scaling, false to have the
78 * plugin do this.
79 *
80 * @fn void SkillGuiCairoRenderInstructor::get_dimensions(double &width, double &height)
81 * Get available space dimensions.
82 * @param width upon return contains the available width
83 * @param height upon return contains the available height
84 *
85 * @fn double SkillGuiCairoRenderInstructor::get_scale()
86 * Get scale factor.
87 * If scale_override() returns true, shall return the requested scale value.
88 * @return scale factor
89 *
90 * @fn void SkillGuiCairoRenderInstructor::set_scale(double scale)
91 * Set scale.
92 * Set the scale value that the plugin determined.
93 * @param scale scale determined by plugin
94 *
95 * @fn void SkillGuiCairoRenderInstructor::get_translation(double &tx, double &ty)
96 * Get translation values.
97 * If scale_override() returns true, shall return the requested translation values.
98 * @param tx upon return contains translation in x
99 * @param ty upon return contains translation in y
100 *
101 * @fn void SkillGuiCairoRenderInstructor::set_translation(double tx, double ty)
102 * Set translation.
103 * Set the translation values the plugin determined.
104 * @param tx translation in x
105 * @param ty translation in y
106 *
107 * @fn void SkillGuiCairoRenderInstructor::set_bb(double bbw, double bbh)
108 * Set the bounding box.
109 * Set by the plugin before calling any other function.
110 * @param bbw bounding box width
111 * @param bbh bounding box height
112 *
113 * @fn void SkillGuiCairoRenderInstructor::set_pad(double pad_x, double pad_y)
114 * Set padding.
115 * Set by the plugin immediately after set_bb() is called.
116 * @param pad_x padding in x
117 * @param pad_y padding in y
118 *
119 * @fn void SkillGuiCairoRenderInstructor::get_pad(double &pad_x, double &pad_y)
120 * Get padding.
121 * If scale_override() returns true, shall return the requested padding values.
122 * @param pad_x upon return contains padding in x
123 * @param pad_y upon return contains padding in y
124 */
125
126static void
127skillgui_cairo_device_init(GVJ_t *firstjob)
128{
129}
130
131static void
132skillgui_cairo_device_finalize(GVJ_t *firstjob)
133{
134 firstjob->context = (void *)sgcri_;
135 firstjob->external_context = TRUE;
136
137 // Render!
138 (firstjob->callbacks->refresh)(firstjob);
139}
140
141static inline void
142skillgui_cairo_set_color(Cairo::RefPtr<Cairo::Context> cairo, gvcolor_t *color)
143{
144 cairo->set_source_rgba(color->u.RGBA[0], color->u.RGBA[1], color->u.RGBA[2], color->u.RGBA[3]);
145}
146
147static inline void
148skillgui_cairo_set_penstyle(Cairo::RefPtr<Cairo::Context> cairo, GVJ_t *job)
149{
150 obj_state_t *obj = job->obj;
151
152 if (obj->pen == PEN_DASHED) {
153 cairo->set_dash(skillgui_cairo_render_dashed_, 0.0);
154 } else if (obj->pen == PEN_DOTTED) {
155 cairo->set_dash(skillgui_cairo_render_dotted_, 0.0);
156 } else {
157#if CAIROMM_MAJOR_VERSION > 1 || (CAIROMM_MAJOR_VERSION == 1 && CAIROMM_MINO_VERSION > 8)
158 std::vector<double> empty;
159#else
160 std::valarray<double> empty;
161#endif
162 cairo->set_dash(empty, 0.0);
163 }
164 cairo->set_line_width(obj->penwidth);
165}
166
167static void
168skillgui_cairo_render_begin_page(GVJ_t *job)
169{
170#ifdef USE_GVPLUGIN_TIMETRACKER
171 tt_.ping_start(ttc_page_);
172 tt_.ping_start(ttc_beginpage_);
173#endif
174 SkillGuiCairoRenderInstructor *cri = static_cast<SkillGuiCairoRenderInstructor *>(job->context);
175
176 float bbwidth = job->bb.UR.x - job->bb.LL.x;
177 float bbheight = job->bb.UR.y - job->bb.LL.y;
178
179 cri->set_bb(bbwidth, bbheight);
180 cri->set_pad(job->pad.x, job->pad.y);
181 Cairo::RefPtr<Cairo::Context> cairo = cri->get_cairo();
182
183 double pad_x, pad_y;
184 cri->get_pad(pad_x, pad_y);
185
186 // For internal calculations we need to care about the padding
187 //bbwidth += 2 * pad_x;
188 //bbheight += 2 * pad_y;
189
190 double avwidth, avheight;
191 cri->get_dimensions(avwidth, avheight);
192 float translate_x = 0;
193 float translate_y = 0;
194
195 if (cri->scale_override()) {
196 float zoom = cri->get_scale();
197 float zwidth = bbwidth * zoom;
198 float zheight = bbheight * zoom;
199 translate_x += (avwidth - zwidth) / 2.;
200 translate_y += (avheight - zheight) / 2.;
201
202 double translate_x, translate_y;
203 cri->get_translation(translate_x, translate_y);
204
205 cairo->translate(translate_x, translate_y);
206 cairo->scale(zoom, zoom);
207
208 } else {
209 float zoom_w = avwidth / bbwidth;
210 float zoom_h = avheight / bbheight;
211 float zoom = std::min(zoom_w, zoom_h);
212
213 if (bbwidth > avwidth || bbheight > avheight) {
214 float zwidth = bbwidth * zoom;
215 float zheight = bbheight * zoom;
216 translate_x += (avwidth - zwidth) / 2.;
217 translate_y += (avheight - zheight) / 2. + zheight;
218 } else {
219 zoom = 1.0;
220 translate_x += (avwidth - bbwidth) / 2.;
221 translate_y += (avheight - bbheight) / 2. + bbheight;
222 }
223
224 cri->set_scale(zoom);
225 cri->set_translation(translate_x, translate_y);
226
227 cairo->translate(translate_x + pad_x * zoom, translate_y - pad_y * zoom);
228 cairo->scale(zoom, zoom);
229 }
230
231#ifdef USE_GVPLUGIN_TIMETRACKER
232 num_ellipse_ = 0;
233 num_bezier_ = 0;
234 num_polygon_ = 0;
235 num_polyline_ = 0;
236 num_text_ = 0;
237
238 tt_.ping_end(ttc_beginpage_);
239#endif
240}
241
242static void
243skillgui_cairo_render_end_page(GVJ_t *job)
244{
245 //SkillGuiCairoRenderInstructor *cri = (SkillGuiCairoRenderInstructor *)job->context;
246 //cri->queue_draw();
247#ifdef USE_GVPLUGIN_TIMETRACKER
248 tt_.ping_end(ttc_page_);
249 if (++tt_count_ >= 10) {
250 tt_count_ = 0;
251 tt_.print_to_stdout();
252
253 printf("Num Ellipse: %u\n"
254 "Num Bezier: %u\n"
255 "Num Polygon: %u\n"
256 "Num Polyline: %u\n"
257 "Num Text: %u\n",
258 num_ellipse_,
259 num_bezier_,
260 num_polygon_,
261 num_polyline_,
262 num_text_);
263 }
264#endif
265}
266
267static void
268#if GRAPHVIZ_VERSION >= 23600
269skillgui_cairo_render_textpara(GVJ_t *job, pointf p, textspan_t *para)
270#else
271skillgui_cairo_render_textpara(GVJ_t *job, pointf p, textpara_t *para)
272#endif
273{
274#ifdef USE_GVPLUGIN_TIMETRACKER
275 tt_.ping_start(ttc_text_);
276 ++num_text_;
277#endif
279 Cairo::RefPtr<Cairo::Context> cairo = cri->get_cairo();
280 obj_state_t * obj = job->obj;
281
282 Cairo::FontWeight weight = Cairo::FONT_WEIGHT_NORMAL;
283 Cairo::FontSlant slant = Cairo::FONT_SLANT_NORMAL;
284 char * fontweight = NULL;
285 if (obj->type == CLUSTER_OBJTYPE) {
286 fontweight = agget(obj->u.sg, (char *)"fontweight");
287 } else if (obj->type == ROOTGRAPH_OBJTYPE) {
288 fontweight = agget(obj->u.g, (char *)"fontweight");
289 } else if (obj->type == NODE_OBJTYPE) {
290 fontweight = agget(obj->u.n, (char *)"fontweight");
291 } else if (obj->type == EDGE_OBJTYPE) {
292 fontweight = agget(obj->u.e, (char *)"fontweight");
293 }
294 if (fontweight && (strcmp(fontweight, "bold") == 0)) {
295 weight = Cairo::FONT_WEIGHT_BOLD;
296 p.x -= 8;
297 }
298 char *fontslant = NULL;
299 if (obj->type == CLUSTER_OBJTYPE) {
300 fontslant = agget(obj->u.sg, (char *)"fontslant");
301 } else if (obj->type == ROOTGRAPH_OBJTYPE) {
302 fontslant = agget(obj->u.g, (char *)"fontslant");
303 } else if (obj->type == NODE_OBJTYPE) {
304 fontslant = agget(obj->u.n, (char *)"fontslant");
305 } else if (obj->type == EDGE_OBJTYPE) {
306 fontslant = agget(obj->u.e, (char *)"fontslant");
307 }
308 if (fontslant && (strcmp(fontslant, "italic") == 0)) {
309 slant = Cairo::FONT_SLANT_ITALIC;
310 }
311
312 double offsetx = 0.0;
313 double offsety = 0.0;
314 double rotate = 0.0;
315
316 if ((obj->type == EDGE_OBJTYPE) && obj->headlabel && (strcmp(para->str, obj->headlabel) == 0)) {
317 char *labelrotate = agget(obj->u.e, (char *)"labelrotate");
318 if (labelrotate && (strlen(labelrotate) > 0)) {
319 rotate = fawkes::deg2rad(atof(labelrotate));
320 }
321 char *labeloffsetx = agget(obj->u.e, (char *)"labeloffsetx");
322 if (labeloffsetx && (strlen(labeloffsetx) > 0)) {
323 offsetx = atof(labeloffsetx);
324 }
325 char *labeloffsety = agget(obj->u.e, (char *)"labeloffsety");
326 if (labeloffsety && (strlen(labeloffsety) > 0)) {
327 offsety = atof(labeloffsety);
328 }
329 }
330 //tt_.ping_start(ttc_text_1_);
331
332 Cairo::Matrix old_matrix;
333 cairo->get_matrix(old_matrix);
334
335#if GRAPHVIZ_VERSION >= 23600
336 cairo->select_font_face(para->font->name, slant, weight);
337 cairo->set_font_size(para->font->size);
338#else
339 cairo->select_font_face(para->fontname, slant, weight);
340 cairo->set_font_size(para->fontsize);
341#endif
342
343 //cairo->set_font_options ( Cairo::FontOptions() );
344 //cairo->set_line_width(1.0);
345
346 Cairo::TextExtents extents;
347 cairo->get_text_extents(para->str, extents);
348
349 if (para->just == 'r') {
350 p.x -= extents.width;
351 } else if (para->just != 'l') {
352 p.x -= extents.width / 2.0;
353 }
354
355 cairo->move_to(p.x + offsetx, -p.y + offsety);
356 cairo->rotate(rotate);
357 skillgui_cairo_set_color(cairo, &(obj->pencolor));
358 cairo->text_path(para->str);
359 cairo->fill();
360
361 cairo->set_matrix(old_matrix);
362
363 //tt_.ping_end(ttc_text_5_);
364#ifdef USE_GVPLUGIN_TIMETRACKER
365 tt_.ping_end(ttc_text_);
366#endif
367}
368
369static void
370skillgui_cairo_render_ellipse(GVJ_t *job, pointf *A, int filled)
371{
372#ifdef USE_GVPLUGIN_TIMETRACKER
373 tt_.ping_start(ttc_ellipse_);
374 ++num_ellipse_;
375#endif
376 //printf("Render ellipse\n");
378 Cairo::RefPtr<Cairo::Context> cairo = cri->get_cairo();
379 obj_state_t * obj = job->obj;
380
381 Cairo::Matrix old_matrix;
382 cairo->get_matrix(old_matrix);
383
384 skillgui_cairo_set_penstyle(cairo, job);
385
386 cairo->translate(A[0].x, -A[0].y);
387
388 double rx = A[1].x - A[0].x;
389 double ry = A[1].y - A[0].y;
390 cairo->scale(1, ry / rx);
391 cairo->move_to(rx, 0);
392 cairo->arc(0, 0, rx, 0, 2 * M_PI);
393 cairo->close_path();
394
395 cairo->set_matrix(old_matrix);
396
397 if (filled) {
398 skillgui_cairo_set_color(cairo, &(obj->fillcolor));
399 cairo->fill_preserve();
400 }
401 skillgui_cairo_set_color(cairo, &(obj->pencolor));
402 cairo->stroke();
403
404#ifdef USE_GVPLUGIN_TIMETRACKER
405 tt_.ping_end(ttc_ellipse_);
406#endif
407}
408
409static void
410skillgui_cairo_render_polygon(GVJ_t *job, pointf *A, int n, int filled)
411{
412#ifdef USE_GVPLUGIN_TIMETRACKER
413 tt_.ping_start(ttc_polygon_);
414 ++num_polygon_;
415#endif
416 //printf("Polygon\n");
418 Cairo::RefPtr<Cairo::Context> cairo = cri->get_cairo();
419 obj_state_t * obj = job->obj;
420
421 skillgui_cairo_set_penstyle(cairo, job);
422
423 cairo->move_to(A[0].x, -A[0].y);
424 for (int i = 1; i < n; ++i) {
425 cairo->line_to(A[i].x, -A[i].y);
426 }
427 cairo->close_path();
428
429 if (filled) {
430 skillgui_cairo_set_color(cairo, &(obj->fillcolor));
431 cairo->fill_preserve();
432 }
433
434 // HACK to workaround graphviz bug any get the Tim style...
435 if (obj->type == CLUSTER_OBJTYPE) {
436 obj->pencolor.u.RGBA[0] = 0.666;
437 obj->pencolor.u.RGBA[1] = 0.666;
438 obj->pencolor.u.RGBA[2] = 1.0;
439 obj->pencolor.u.RGBA[3] = 1.0;
440 }
441 skillgui_cairo_set_color(cairo, &(obj->pencolor));
442 cairo->stroke();
443
444#ifdef USE_GVPLUGIN_TIMETRACKER
445 tt_.ping_end(ttc_polygon_);
446#endif
447}
448
449static void
450skillgui_cairo_render_bezier(GVJ_t * job,
451 pointf *A,
452 int n,
453 int arrow_at_start,
454 int arrow_at_end,
455 int filled)
456{
457#ifdef USE_GVPLUGIN_TIMETRACKER
458 tt_.ping_start(ttc_bezier_);
459 ++num_bezier_;
460#endif
461 //printf("Bezier\n");
463 Cairo::RefPtr<Cairo::Context> cairo = cri->get_cairo();
464 obj_state_t * obj = job->obj;
465
466 skillgui_cairo_set_penstyle(cairo, job);
467
468 cairo->move_to(A[0].x, -A[0].y);
469 for (int i = 1; i < n; i += 3)
470 cairo->curve_to(A[i].x, -A[i].y, A[i + 1].x, -A[i + 1].y, A[i + 2].x, -A[i + 2].y);
471 if (filled) {
472 skillgui_cairo_set_color(cairo, &(obj->fillcolor));
473 cairo->fill_preserve();
474 }
475 skillgui_cairo_set_color(cairo, &(obj->pencolor));
476 cairo->stroke();
477
478#ifdef USE_GVPLUGIN_TIMETRACKER
479 tt_.ping_end(ttc_bezier_);
480#endif
481}
482
483static void
484skillgui_cairo_render_polyline(GVJ_t *job, pointf *A, int n)
485{
486#ifdef USE_GVPLUGIN_TIMETRACKER
487 tt_.ping_start(ttc_polyline_);
488 ++num_polyline_;
489#endif
490 //printf("Polyline\n");
491 SkillGuiCairoRenderInstructor *cri = static_cast<SkillGuiCairoRenderInstructor *>(job->context);
492 Cairo::RefPtr<Cairo::Context> cairo = cri->get_cairo();
493 obj_state_t * obj = job->obj;
494
495 skillgui_cairo_set_penstyle(cairo, job);
496
497 //cairo->set_line_width(obj->penwidth * job->scale.x);
498 cairo->move_to(A[0].x, -A[0].y);
499 for (int i = 1; i < n; i++) {
500 cairo->line_to(A[i].x, -A[i].y);
501 }
502 skillgui_cairo_set_color(cairo, &(obj->pencolor));
503 cairo->stroke();
504
505#ifdef USE_GVPLUGIN_TIMETRACKER
506 tt_.ping_end(ttc_polyline_);
507#endif
508}
509
510static gvrender_engine_t skillgui_cairo_render_engine = {
511 0, /* skillgui_cairo_render_begin_job */
512 0, /* skillgui_cairo_render_end_job */
513 0, /* skillgui_cairo_render_begin_graph */
514 0, /* skillgui_cairo_render_end_graph */
515 0, /* skillgui_cairo_render_begin_layer */
516 0, /* skillgui_cairo_render_end_layer */
517 skillgui_cairo_render_begin_page,
518 skillgui_cairo_render_end_page,
519 0, /* skillgui_cairo_render_begin_cluster */
520 0, /* skillgui_cairo_render_end_cluster */
521 0, /* skillgui_cairo_render_begin_nodes */
522 0, /* skillgui_cairo_render_end_nodes */
523 0, /* skillgui_cairo_render_begin_edges */
524 0, /* skillgui_cairo_render_end_edges */
525 0, /* skillgui_cairo_render_begin_node */
526 0, /* skillgui_cairo_render_end_node */
527 0, /* skillgui_cairo_render_begin_edge */
528 0, /* skillgui_cairo_render_end_edge */
529 0, /* skillgui_cairo_render_begin_anchor */
530 0, /* skillgui_cairo_render_end_anchor */
531 0, /* skillgui_cairo_begin_label */
532 0, /* skillgui_cairo_end_label */
533 skillgui_cairo_render_textpara,
534 0, /* skillgui_cairo_render_resolve_color */
535 skillgui_cairo_render_ellipse,
536 skillgui_cairo_render_polygon,
537 skillgui_cairo_render_bezier,
538 skillgui_cairo_render_polyline,
539 0, /* skillgui_cairo_render_comment */
540 0, /* skillgui_cairo_render_library_shape */
541};
542
543static gvdevice_engine_t skillgui_cairo_device_engine = {
544 skillgui_cairo_device_init,
545 NULL, /* skillgui_cairo_device_format */
546 skillgui_cairo_device_finalize,
547};
548
549#ifdef __cplusplus
550extern "C" {
551#endif
552
553static gvrender_features_t skillgui_cairo_render_features = {
554 GVRENDER_Y_GOES_DOWN | GVRENDER_DOES_LABELS | GVRENDER_DOES_TRANSFORM
555 | GVRENDER_NO_WHITE_BG, /* flags */
556 8, /* default pad - graph units */
557 0, /* knowncolors */
558 0, /* sizeof knowncolors */
559 RGBA_DOUBLE, /* color_type */
560};
561
562static gvdevice_features_t skillgui_cairo_device_features = {
563 GVDEVICE_DOES_TRUECOLOR | GVDEVICE_EVENTS, /* flags */
564 {0., 0.}, /* default margin - points */
565 {0., 0.}, /* default page width, height - points */
566 {96., 96.}, /* dpi */
567};
568
569gvplugin_installed_t gvdevice_types_skillgui_cairo[] = {{0,
570 (char *)"skillguicairo:skillguicairo",
571 0,
572 &skillgui_cairo_device_engine,
573 &skillgui_cairo_device_features},
574 {0, NULL, 0, NULL, NULL}};
575
576gvplugin_installed_t gvrender_types_skillgui_cairo[] = {
577 {0, (char *)"skillguicairo", 10, &skillgui_cairo_render_engine, &skillgui_cairo_render_features},
578 {0, NULL, 0, NULL, NULL}};
579
580static gvplugin_api_t apis[] = {
581 {API_device, gvdevice_types_skillgui_cairo},
582 {API_render, gvrender_types_skillgui_cairo},
583 {(api_t)0, 0},
584};
585
586gvplugin_library_t gvplugin_skillgui_cairo_LTX_library = {(char *)"skillguicairo", apis};
587
588#ifdef __cplusplus
589}
590#endif
591
592void
593gvplugin_skillgui_cairo_setup(GVC_t *gvc, SkillGuiCairoRenderInstructor *sgcri)
594{
595 sgcri_ = sgcri;
596 gvAddLibrary(gvc, &gvplugin_skillgui_cairo_LTX_library);
597
598#if CAIROMM_MAJOR_VERSION > 1 || (CAIROMM_MAJOR_VERSION == 1 && CAIROMM_MINO_VERSION > 8)
599 skillgui_cairo_render_dashed_.clear();
600 skillgui_cairo_render_dashed_.push_back(6.0);
601 skillgui_cairo_render_dotted_.clear();
602 skillgui_cairo_render_dotted_.push_back(2.0);
603 skillgui_cairo_render_dotted_.push_back(6.0);
604#else
605 skillgui_cairo_render_dashed_[0] = 6.0;
606 skillgui_cairo_render_dotted_[0] = 2.0;
607 skillgui_cairo_render_dotted_[1] = 6.0;
608#endif
609}
Graphviz Cairo render plugin instructor.
virtual void get_pad(double &pad_x, double &pad_y)=0
Get padding.
virtual void get_dimensions(double &width, double &height)=0
Get available space dimensions.
virtual void set_scale(double scale)=0
Set scale.
virtual void get_translation(double &tx, double &ty)=0
Get translation values.
virtual void set_translation(double tx, double ty)=0
Set translation.
virtual double get_scale()=0
Get scale factor.
virtual Cairo::RefPtr< Cairo::Context > get_cairo()=0
Get Cairo context.
virtual void set_pad(double pad_x, double pad_y)=0
Set padding.
virtual bool scale_override()=0
Check if scale override is enabled.
virtual void set_bb(double bbw, double bbh)=0
Set the bounding box.
Time tracking utility.
Definition: tracker.h:37
float deg2rad(float deg)
Convert an angle given in degrees to radians.
Definition: angle.h:36