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 #if GRAPHVIZ_VERSION >= 23600
271 skillgui_cairo_render_textpara(GVJ_t *job, pointf p, textspan_t *para)
272 #else
273 skillgui_cairo_render_textpara(GVJ_t *job, pointf p, textpara_t *para)
274 #endif
275 {
276 #ifdef USE_GVPLUGIN_TIMETRACKER
277  __tt.ping_start(__ttc_text);
278  ++__num_text;
279 #endif
281  Cairo::RefPtr<Cairo::Context> cairo = cri->get_cairo();
282  obj_state_t *obj = job->obj;
283 
284  Cairo::FontWeight weight = Cairo::FONT_WEIGHT_NORMAL;
285  Cairo::FontSlant slant = Cairo::FONT_SLANT_NORMAL;
286  char *fontweight = NULL;
287  if (obj->type == CLUSTER_OBJTYPE) {
288  fontweight = agget(obj->u.sg, (char *)"fontweight");
289  } else if (obj->type == ROOTGRAPH_OBJTYPE) {
290  fontweight = agget(obj->u.g, (char *)"fontweight");
291  } else if (obj->type == NODE_OBJTYPE) {
292  fontweight = agget(obj->u.n, (char *)"fontweight");
293  } else if (obj->type == EDGE_OBJTYPE) {
294  fontweight = agget(obj->u.e, (char *)"fontweight");
295  }
296  if (fontweight && (strcmp(fontweight, "bold") == 0)) {
297  weight = Cairo::FONT_WEIGHT_BOLD;
298  p.x -= 8;
299  }
300  char *fontslant = NULL;
301  if (obj->type == CLUSTER_OBJTYPE) {
302  fontslant = agget(obj->u.sg, (char *)"fontslant");
303  } else if (obj->type == ROOTGRAPH_OBJTYPE) {
304  fontslant = agget(obj->u.g, (char *)"fontslant");
305  } else if (obj->type == NODE_OBJTYPE) {
306  fontslant = agget(obj->u.n, (char *)"fontslant");
307  } else if (obj->type == EDGE_OBJTYPE) {
308  fontslant = agget(obj->u.e, (char *)"fontslant");
309  }
310  if (fontslant && (strcmp(fontslant, "italic") == 0)) {
311  slant = Cairo::FONT_SLANT_ITALIC;
312  }
313 
314  double offsetx = 0.0;
315  double offsety = 0.0;
316  double rotate = 0.0;
317 
318  if ((obj->type == EDGE_OBJTYPE) && obj->headlabel && (strcmp(para->str, obj->headlabel) == 0) ) {
319  char *labelrotate = agget(obj->u.e, (char *)"labelrotate");
320  if (labelrotate && (strlen(labelrotate) > 0)) {
321  rotate = fawkes::deg2rad(atof(labelrotate));
322  }
323  char *labeloffsetx = agget(obj->u.e, (char *)"labeloffsetx");
324  if (labeloffsetx && (strlen(labeloffsetx) > 0)) {
325  offsetx = atof(labeloffsetx);
326  }
327  char *labeloffsety = agget(obj->u.e, (char *)"labeloffsety");
328  if (labeloffsety && (strlen(labeloffsety) > 0)) {
329  offsety = atof(labeloffsety);
330  }
331  }
332  //__tt.ping_start(__ttc_text_1);
333 
334  Cairo::Matrix old_matrix;
335  cairo->get_matrix(old_matrix);
336 
337 #if GRAPHVIZ_VERSION >= 23600
338  cairo->select_font_face(para->font->name, slant, weight);
339  cairo->set_font_size(para->font->size);
340 #else
341  cairo->select_font_face(para->fontname, slant, weight);
342  cairo->set_font_size(para->fontsize);
343 #endif
344 
345  //cairo->set_font_options ( Cairo::FontOptions() );
346  //cairo->set_line_width(1.0);
347 
348  Cairo::TextExtents extents;
349  cairo->get_text_extents(para->str, extents);
350 
351  if (para->just == 'r') {
352  p.x -= extents.width;
353  } else if (para->just != 'l') {
354  p.x -= extents.width / 2.0;
355  }
356 
357  cairo->move_to(p.x + offsetx, -p.y + offsety);
358  cairo->rotate(rotate);
359  skillgui_cairo_set_color(cairo, &(obj->pencolor));
360  cairo->text_path( para->str );
361  cairo->fill();
362 
363  cairo->set_matrix(old_matrix);
364 
365  //__tt.ping_end(__ttc_text_5);
366 #ifdef USE_GVPLUGIN_TIMETRACKER
367  __tt.ping_end(__ttc_text);
368 #endif
369 }
370 
371 static void
372 skillgui_cairo_render_ellipse(GVJ_t *job, pointf *A, int filled)
373 {
374 #ifdef USE_GVPLUGIN_TIMETRACKER
375  __tt.ping_start(__ttc_ellipse);
376  ++__num_ellipse;
377 #endif
378  //printf("Render ellipse\n");
380  Cairo::RefPtr<Cairo::Context> cairo = cri->get_cairo();
381  obj_state_t *obj = job->obj;
382 
383  Cairo::Matrix old_matrix;
384  cairo->get_matrix(old_matrix);
385 
386  skillgui_cairo_set_penstyle(cairo, job);
387 
388  cairo->translate(A[0].x, -A[0].y);
389 
390  double rx = A[1].x - A[0].x;
391  double ry = A[1].y - A[0].y;
392  cairo->scale(1, ry / rx);
393  cairo->move_to(rx, 0);
394  cairo->arc(0, 0, rx, 0, 2 * M_PI);
395  cairo->close_path();
396 
397  cairo->set_matrix(old_matrix);
398 
399  if (filled) {
400  skillgui_cairo_set_color(cairo, &(obj->fillcolor));
401  cairo->fill_preserve();
402  }
403  skillgui_cairo_set_color(cairo, &(obj->pencolor));
404  cairo->stroke();
405 
406 #ifdef USE_GVPLUGIN_TIMETRACKER
407  __tt.ping_end(__ttc_ellipse);
408 #endif
409 }
410 
411 static void
412 skillgui_cairo_render_polygon(GVJ_t *job, pointf *A, int n, int filled)
413 {
414 #ifdef USE_GVPLUGIN_TIMETRACKER
415  __tt.ping_start(__ttc_polygon);
416  ++__num_polygon;
417 #endif
418  //printf("Polygon\n");
420  Cairo::RefPtr<Cairo::Context> cairo = cri->get_cairo();
421  obj_state_t *obj = job->obj;
422 
423  skillgui_cairo_set_penstyle(cairo, job);
424 
425  cairo->move_to(A[0].x, -A[0].y);
426  for (int i = 1; i < n; ++i) {
427  cairo->line_to(A[i].x, -A[i].y);
428  }
429  cairo->close_path();
430 
431  if (filled) {
432  skillgui_cairo_set_color(cairo, &(obj->fillcolor));
433  cairo->fill_preserve();
434  }
435 
436  // HACK to workaround graphviz bug any get the Tim style...
437  if ( obj->type == CLUSTER_OBJTYPE ) {
438  obj->pencolor.u.RGBA[0] = 0.666;
439  obj->pencolor.u.RGBA[1] = 0.666;
440  obj->pencolor.u.RGBA[2] = 1.0;
441  obj->pencolor.u.RGBA[3] = 1.0;
442  }
443  skillgui_cairo_set_color(cairo, &(obj->pencolor));
444  cairo->stroke();
445 
446 #ifdef USE_GVPLUGIN_TIMETRACKER
447  __tt.ping_end(__ttc_polygon);
448 #endif
449 }
450 
451 static void
452 skillgui_cairo_render_bezier(GVJ_t * job, pointf * A, int n, int arrow_at_start,
453  int arrow_at_end, int filled)
454 {
455 #ifdef USE_GVPLUGIN_TIMETRACKER
456  __tt.ping_start(__ttc_bezier);
457  ++__num_bezier;
458 #endif
459  //printf("Bezier\n");
461  Cairo::RefPtr<Cairo::Context> cairo = cri->get_cairo();
462  obj_state_t *obj = job->obj;
463 
464  skillgui_cairo_set_penstyle(cairo, job);
465 
466  cairo->move_to(A[0].x, -A[0].y);
467  for (int i = 1; i < n; i += 3)
468  cairo->curve_to(A[i].x, -A[i].y, A[i + 1].x, -A[i + 1].y,
469  A[i + 2].x, -A[i + 2].y);
470  if (filled) {
471  skillgui_cairo_set_color(cairo, &(obj->fillcolor));
472  cairo->fill_preserve();
473  }
474  skillgui_cairo_set_color(cairo, &(obj->pencolor));
475  cairo->stroke();
476 
477 #ifdef USE_GVPLUGIN_TIMETRACKER
478  __tt.ping_end(__ttc_bezier);
479 #endif
480 }
481 
482 static void
483 skillgui_cairo_render_polyline(GVJ_t * job, pointf * A, int n)
484 {
485 #ifdef USE_GVPLUGIN_TIMETRACKER
486  __tt.ping_start(__ttc_polyline);
487  ++__num_polyline;
488 #endif
489  //printf("Polyline\n");
491  Cairo::RefPtr<Cairo::Context> cairo = cri->get_cairo();
492  obj_state_t *obj = job->obj;
493 
494  skillgui_cairo_set_penstyle(cairo, job);
495 
496  //cairo->set_line_width(obj->penwidth * job->scale.x);
497  cairo->move_to(A[0].x, -A[0].y);
498  for (int i = 1; i < n; i++) {
499  cairo->line_to(A[i].x, -A[i].y);
500  }
501  skillgui_cairo_set_color(cairo, &(obj->pencolor));
502  cairo->stroke();
503 
504 #ifdef USE_GVPLUGIN_TIMETRACKER
505  __tt.ping_end(__ttc_polyline);
506 #endif
507 }
508 
509 
510 static 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 
543 static 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 
550 #ifdef __cplusplus
551 extern "C" {
552 #endif
553 
554 
555 static gvrender_features_t skillgui_cairo_render_features = {
556  GVRENDER_Y_GOES_DOWN |
557  GVRENDER_DOES_LABELS |
558  GVRENDER_DOES_TRANSFORM |
559  GVRENDER_NO_WHITE_BG, /* flags */
560  8, /* default pad - graph units */
561  0, /* knowncolors */
562  0, /* sizeof knowncolors */
563  RGBA_DOUBLE, /* color_type */
564 };
565 
566 
567 static gvdevice_features_t skillgui_cairo_device_features = {
568  GVDEVICE_DOES_TRUECOLOR | GVDEVICE_EVENTS, /* flags */
569  {0.,0.}, /* default margin - points */
570  {0.,0.}, /* default page width, height - points */
571  {96.,96.}, /* dpi */
572 };
573 
574 gvplugin_installed_t gvdevice_types_skillgui_cairo[] = {
575  {0, ( char *)"skillguicairo:skillguicairo", 0, &skillgui_cairo_device_engine, &skillgui_cairo_device_features},
576  {0, NULL, 0, NULL, NULL}
577 };
578 
579 gvplugin_installed_t gvrender_types_skillgui_cairo[] = {
580  {0, (char *)"skillguicairo", 10, &skillgui_cairo_render_engine, &skillgui_cairo_render_features},
581  {0, NULL, 0, NULL, NULL}
582 };
583 
584 static gvplugin_api_t apis[] = {
585  {API_device, gvdevice_types_skillgui_cairo},
586  {API_render, gvrender_types_skillgui_cairo},
587  {(api_t)0, 0},
588 };
589 
590 gvplugin_library_t gvplugin_skillgui_cairo_LTX_library = { (char *)"skillguicairo", apis };
591 
592 #ifdef __cplusplus
593 }
594 #endif
595 
596 
597 void
598 gvplugin_skillgui_cairo_setup(GVC_t *gvc, SkillGuiCairoRenderInstructor *sgcri)
599 {
600  __sgcri = sgcri;
601  gvAddLibrary(gvc, &gvplugin_skillgui_cairo_LTX_library);
602 
603 #if CAIROMM_MAJOR_VERSION > 1 || (CAIROMM_MAJOR_VERSION == 1 && CAIROMM_MINO_VERSION > 8)
604  __skillgui_cairo_render_dashed.clear();
605  __skillgui_cairo_render_dashed.push_back(6.0);
606  __skillgui_cairo_render_dotted.clear();
607  __skillgui_cairo_render_dotted.push_back(2.0);
608  __skillgui_cairo_render_dotted.push_back(6.0);
609 #else
610  __skillgui_cairo_render_dashed[0] = 6.0;
611  __skillgui_cairo_render_dotted[0] = 2.0;
612  __skillgui_cairo_render_dotted[1] = 6.0;
613 #endif
614 }
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.