23 #include "gvplugin_skillgui_cairo.h" 25 #include <utils/math/angle.h> 26 #include <utils/time/tracker.h> 28 #include <gvplugin_device.h> 29 #include <gvplugin_render.h> 34 #define NOEXPORT __attribute__ ((visibility("hidden"))) 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;
42 NOEXPORT std::valarray<double> __skillgui_cairo_render_dashed(1);
43 NOEXPORT std::valarray<double> __skillgui_cairo_render_dotted(2);
46 #ifdef USE_GVPLUGIN_TIMETRACKER 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;
129 skillgui_cairo_device_init(GVJ_t *firstjob)
134 skillgui_cairo_device_finalize(GVJ_t *firstjob)
136 firstjob->context = (
void *)__sgcri;
137 firstjob->external_context = TRUE;
140 (firstjob->callbacks->refresh)(firstjob);
144 skillgui_cairo_set_color(Cairo::RefPtr<Cairo::Context> cairo, gvcolor_t * color)
146 cairo->set_source_rgba(color->u.RGBA[0], color->u.RGBA[1],
147 color->u.RGBA[2], color->u.RGBA[3]);
151 skillgui_cairo_set_penstyle(Cairo::RefPtr<Cairo::Context> cairo, GVJ_t *job)
153 obj_state_t *obj = job->obj;
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);
160 #if CAIROMM_MAJOR_VERSION > 1 || (CAIROMM_MAJOR_VERSION == 1 && CAIROMM_MINO_VERSION > 8) 161 std::vector<double> empty;
163 std::valarray<double> empty;
165 cairo->set_dash(empty, 0.0);
167 cairo->set_line_width(obj->penwidth);
172 skillgui_cairo_render_begin_page(GVJ_t *job)
174 #ifdef USE_GVPLUGIN_TIMETRACKER 175 __tt.ping_start(__ttc_page);
176 __tt.ping_start(__ttc_beginpage);
180 float bbwidth = job->bb.UR.x - job->bb.LL.x;
181 float bbheight = job->bb.UR.y - job->bb.LL.y;
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();
194 double avwidth, avheight;
196 float translate_x = 0;
197 float translate_y = 0;
201 float zwidth = bbwidth * zoom;
202 float zheight = bbheight * zoom;
203 translate_x += (avwidth - zwidth ) / 2.;
204 translate_y += (avheight - zheight) / 2.;
206 double translate_x, translate_y;
209 cairo->translate(translate_x, translate_y);
210 cairo->scale(zoom, zoom);
213 float zoom_w = avwidth / bbwidth;
214 float zoom_h = avheight / bbheight;
215 float zoom = std::min(zoom_w, zoom_h);
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;
224 translate_x += (avwidth - bbwidth) / 2.;
225 translate_y += (avheight - bbheight) / 2. + bbheight;
231 cairo->translate(translate_x + pad_x * zoom, translate_y - pad_y * zoom);
232 cairo->scale(zoom, zoom);
237 #ifdef USE_GVPLUGIN_TIMETRACKER 244 __tt.ping_end(__ttc_beginpage);
249 skillgui_cairo_render_end_page(GVJ_t * job)
253 #ifdef USE_GVPLUGIN_TIMETRACKER 254 __tt.ping_end(__ttc_page);
255 if ( ++__tt_count >= 10 ) {
257 __tt.print_to_stdout();
259 printf(
"Num Ellipse: %u\n" 263 "Num Text: %u\n", __num_ellipse, __num_bezier,
264 __num_polygon, __num_polyline, __num_text);
270 #if GRAPHVIZ_VERSION >= 23600 271 skillgui_cairo_render_textpara(GVJ_t *job, pointf p, textspan_t *para)
273 skillgui_cairo_render_textpara(GVJ_t *job, pointf p, textpara_t *para)
276 #ifdef USE_GVPLUGIN_TIMETRACKER 277 __tt.ping_start(__ttc_text);
281 Cairo::RefPtr<Cairo::Context> cairo = cri->
get_cairo();
282 obj_state_t *obj = job->obj;
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");
296 if (fontweight && (strcmp(fontweight,
"bold") == 0)) {
297 weight = Cairo::FONT_WEIGHT_BOLD;
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");
310 if (fontslant && (strcmp(fontslant,
"italic") == 0)) {
311 slant = Cairo::FONT_SLANT_ITALIC;
314 double offsetx = 0.0;
315 double offsety = 0.0;
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)) {
323 char *labeloffsetx = agget(obj->u.e, (
char *)
"labeloffsetx");
324 if (labeloffsetx && (strlen(labeloffsetx) > 0)) {
325 offsetx = atof(labeloffsetx);
327 char *labeloffsety = agget(obj->u.e, (
char *)
"labeloffsety");
328 if (labeloffsety && (strlen(labeloffsety) > 0)) {
329 offsety = atof(labeloffsety);
334 Cairo::Matrix old_matrix;
335 cairo->get_matrix(old_matrix);
337 #if GRAPHVIZ_VERSION >= 23600 338 cairo->select_font_face(para->font->name, slant, weight);
339 cairo->set_font_size(para->font->size);
341 cairo->select_font_face(para->fontname, slant, weight);
342 cairo->set_font_size(para->fontsize);
348 Cairo::TextExtents extents;
349 cairo->get_text_extents(para->str, extents);
351 if (para->just ==
'r') {
352 p.x -= extents.width;
353 }
else if (para->just !=
'l') {
354 p.x -= extents.width / 2.0;
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 );
363 cairo->set_matrix(old_matrix);
366 #ifdef USE_GVPLUGIN_TIMETRACKER 367 __tt.ping_end(__ttc_text);
372 skillgui_cairo_render_ellipse(GVJ_t *job, pointf *A,
int filled)
374 #ifdef USE_GVPLUGIN_TIMETRACKER 375 __tt.ping_start(__ttc_ellipse);
380 Cairo::RefPtr<Cairo::Context> cairo = cri->
get_cairo();
381 obj_state_t *obj = job->obj;
383 Cairo::Matrix old_matrix;
384 cairo->get_matrix(old_matrix);
386 skillgui_cairo_set_penstyle(cairo, job);
388 cairo->translate(A[0].x, -A[0].y);
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);
397 cairo->set_matrix(old_matrix);
400 skillgui_cairo_set_color(cairo, &(obj->fillcolor));
401 cairo->fill_preserve();
403 skillgui_cairo_set_color(cairo, &(obj->pencolor));
406 #ifdef USE_GVPLUGIN_TIMETRACKER 407 __tt.ping_end(__ttc_ellipse);
412 skillgui_cairo_render_polygon(GVJ_t *job, pointf *A,
int n,
int filled)
414 #ifdef USE_GVPLUGIN_TIMETRACKER 415 __tt.ping_start(__ttc_polygon);
420 Cairo::RefPtr<Cairo::Context> cairo = cri->
get_cairo();
421 obj_state_t *obj = job->obj;
423 skillgui_cairo_set_penstyle(cairo, job);
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);
432 skillgui_cairo_set_color(cairo, &(obj->fillcolor));
433 cairo->fill_preserve();
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;
443 skillgui_cairo_set_color(cairo, &(obj->pencolor));
446 #ifdef USE_GVPLUGIN_TIMETRACKER 447 __tt.ping_end(__ttc_polygon);
452 skillgui_cairo_render_bezier(GVJ_t * job, pointf * A,
int n,
int arrow_at_start,
453 int arrow_at_end,
int filled)
455 #ifdef USE_GVPLUGIN_TIMETRACKER 456 __tt.ping_start(__ttc_bezier);
461 Cairo::RefPtr<Cairo::Context> cairo = cri->
get_cairo();
462 obj_state_t *obj = job->obj;
464 skillgui_cairo_set_penstyle(cairo, job);
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);
471 skillgui_cairo_set_color(cairo, &(obj->fillcolor));
472 cairo->fill_preserve();
474 skillgui_cairo_set_color(cairo, &(obj->pencolor));
477 #ifdef USE_GVPLUGIN_TIMETRACKER 478 __tt.ping_end(__ttc_bezier);
483 skillgui_cairo_render_polyline(GVJ_t * job, pointf * A,
int n)
485 #ifdef USE_GVPLUGIN_TIMETRACKER 486 __tt.ping_start(__ttc_polyline);
491 Cairo::RefPtr<Cairo::Context> cairo = cri->
get_cairo();
492 obj_state_t *obj = job->obj;
494 skillgui_cairo_set_penstyle(cairo, job);
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);
501 skillgui_cairo_set_color(cairo, &(obj->pencolor));
504 #ifdef USE_GVPLUGIN_TIMETRACKER 505 __tt.ping_end(__ttc_polyline);
510 static gvrender_engine_t skillgui_cairo_render_engine = {
517 skillgui_cairo_render_begin_page,
518 skillgui_cairo_render_end_page,
533 skillgui_cairo_render_textpara,
535 skillgui_cairo_render_ellipse,
536 skillgui_cairo_render_polygon,
537 skillgui_cairo_render_bezier,
538 skillgui_cairo_render_polyline,
543 static gvdevice_engine_t skillgui_cairo_device_engine = {
544 skillgui_cairo_device_init,
546 skillgui_cairo_device_finalize,
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,
567 static gvdevice_features_t skillgui_cairo_device_features = {
568 GVDEVICE_DOES_TRUECOLOR | GVDEVICE_EVENTS,
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}
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}
584 static gvplugin_api_t apis[] = {
585 {API_device, gvdevice_types_skillgui_cairo},
586 {API_render, gvrender_types_skillgui_cairo},
590 gvplugin_library_t gvplugin_skillgui_cairo_LTX_library = { (
char *)
"skillguicairo", apis };
601 gvAddLibrary(gvc, &gvplugin_skillgui_cairo_LTX_library);
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);
610 __skillgui_cairo_render_dashed[0] = 6.0;
611 __skillgui_cairo_render_dotted[0] = 2.0;
612 __skillgui_cairo_render_dotted[1] = 6.0;
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.
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.
virtual void set_scale(double scale)=0
Set scale.