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 skillgui_cairo_render_textpara(GVJ_t *job, pointf p, textpara_t *para)
272 #ifdef USE_GVPLUGIN_TIMETRACKER
273 __tt.ping_start(__ttc_text);
277 Cairo::RefPtr<Cairo::Context> cairo = cri->
get_cairo();
278 obj_state_t *obj = job->obj;
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");
292 if (fontweight && (strcmp(fontweight,
"bold") == 0)) {
293 weight = Cairo::FONT_WEIGHT_BOLD;
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");
306 if (fontslant && (strcmp(fontslant,
"italic") == 0)) {
307 slant = Cairo::FONT_SLANT_ITALIC;
310 double offsetx = 0.0;
311 double offsety = 0.0;
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)) {
319 char *labeloffsetx = agget(obj->u.e, (
char *)
"labeloffsetx");
320 if (labeloffsetx && (strlen(labeloffsetx) > 0)) {
321 offsetx = atof(labeloffsetx);
323 char *labeloffsety = agget(obj->u.e, (
char *)
"labeloffsety");
324 if (labeloffsety && (strlen(labeloffsety) > 0)) {
325 offsety = atof(labeloffsety);
330 Cairo::Matrix old_matrix;
331 cairo->get_matrix(old_matrix);
333 cairo->select_font_face(para->fontname, slant, weight);
334 cairo->set_font_size(para->fontsize);
338 Cairo::TextExtents extents;
339 cairo->get_text_extents(para->str, extents);
341 if (para->just ==
'r') {
342 p.x -= extents.width;
343 }
else if (para->just !=
'l') {
344 p.x -= extents.width / 2.0;
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 );
353 cairo->set_matrix(old_matrix);
356 #ifdef USE_GVPLUGIN_TIMETRACKER
357 __tt.ping_end(__ttc_text);
362 skillgui_cairo_render_ellipse(GVJ_t *job, pointf *A,
int filled)
364 #ifdef USE_GVPLUGIN_TIMETRACKER
365 __tt.ping_start(__ttc_ellipse);
370 Cairo::RefPtr<Cairo::Context> cairo = cri->
get_cairo();
371 obj_state_t *obj = job->obj;
373 Cairo::Matrix old_matrix;
374 cairo->get_matrix(old_matrix);
376 skillgui_cairo_set_penstyle(cairo, job);
378 cairo->translate(A[0].x, -A[0].y);
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);
387 cairo->set_matrix(old_matrix);
390 skillgui_cairo_set_color(cairo, &(obj->fillcolor));
391 cairo->fill_preserve();
393 skillgui_cairo_set_color(cairo, &(obj->pencolor));
396 #ifdef USE_GVPLUGIN_TIMETRACKER
397 __tt.ping_end(__ttc_ellipse);
402 skillgui_cairo_render_polygon(GVJ_t *job, pointf *A,
int n,
int filled)
404 #ifdef USE_GVPLUGIN_TIMETRACKER
405 __tt.ping_start(__ttc_polygon);
410 Cairo::RefPtr<Cairo::Context> cairo = cri->
get_cairo();
411 obj_state_t *obj = job->obj;
413 skillgui_cairo_set_penstyle(cairo, job);
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);
422 skillgui_cairo_set_color(cairo, &(obj->fillcolor));
423 cairo->fill_preserve();
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;
433 skillgui_cairo_set_color(cairo, &(obj->pencolor));
436 #ifdef USE_GVPLUGIN_TIMETRACKER
437 __tt.ping_end(__ttc_polygon);
442 skillgui_cairo_render_bezier(GVJ_t * job, pointf * A,
int n,
int arrow_at_start,
443 int arrow_at_end,
int filled)
445 #ifdef USE_GVPLUGIN_TIMETRACKER
446 __tt.ping_start(__ttc_bezier);
451 Cairo::RefPtr<Cairo::Context> cairo = cri->
get_cairo();
452 obj_state_t *obj = job->obj;
454 skillgui_cairo_set_penstyle(cairo, job);
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);
461 skillgui_cairo_set_color(cairo, &(obj->fillcolor));
462 cairo->fill_preserve();
464 skillgui_cairo_set_color(cairo, &(obj->pencolor));
467 #ifdef USE_GVPLUGIN_TIMETRACKER
468 __tt.ping_end(__ttc_bezier);
473 skillgui_cairo_render_polyline(GVJ_t * job, pointf * A,
int n)
475 #ifdef USE_GVPLUGIN_TIMETRACKER
476 __tt.ping_start(__ttc_polyline);
481 Cairo::RefPtr<Cairo::Context> cairo = cri->
get_cairo();
482 obj_state_t *obj = job->obj;
484 skillgui_cairo_set_penstyle(cairo, job);
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);
491 skillgui_cairo_set_color(cairo, &(obj->pencolor));
494 #ifdef USE_GVPLUGIN_TIMETRACKER
495 __tt.ping_end(__ttc_polyline);
500 static gvrender_engine_t skillgui_cairo_render_engine = {
507 skillgui_cairo_render_begin_page,
508 skillgui_cairo_render_end_page,
523 skillgui_cairo_render_textpara,
525 skillgui_cairo_render_ellipse,
526 skillgui_cairo_render_polygon,
527 skillgui_cairo_render_bezier,
528 skillgui_cairo_render_polyline,
533 static gvdevice_engine_t skillgui_cairo_device_engine = {
534 skillgui_cairo_device_init,
536 skillgui_cairo_device_finalize,
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,
557 static gvdevice_features_t skillgui_cairo_device_features = {
558 GVDEVICE_DOES_TRUECOLOR | GVDEVICE_EVENTS,
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}
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}
574 static gvplugin_api_t apis[] = {
575 {API_device, gvdevice_types_skillgui_cairo},
576 {API_render, gvrender_types_skillgui_cairo},
580 gvplugin_library_t gvplugin_skillgui_cairo_LTX_library = { (
char *)
"skillguicairo", apis };
591 gvAddLibrary(gvc, &gvplugin_skillgui_cairo_LTX_library);
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);
600 __skillgui_cairo_render_dashed[0] = 6.0;
601 __skillgui_cairo_render_dotted[0] = 2.0;
602 __skillgui_cairo_render_dotted[1] = 6.0;