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