24 #include "gvplugin_skillgui_papyrus.h" 26 #include <utils/math/angle.h> 27 #include <utils/time/tracker.h> 31 #include <gvplugin_device.h> 32 #include <gvplugin_render.h> 34 #define NOEXPORT __attribute__((visibility("hidden"))) 38 NOEXPORT std::valarray<double> skillgui_render_dashed_(6., 1);
39 NOEXPORT std::valarray<double> skillgui_render_dotted_((
double[]){2., 6.}, 2);
41 #ifdef USE_GVPLUGIN_TIMETRACKER 43 NOEXPORT
unsigned int ttc_page_ = tt_.add_class(
"Page");
44 NOEXPORT
unsigned int ttc_beginpage_ = tt_.add_class(
"Begin Page");
45 NOEXPORT
unsigned int ttc_ellipse_ = tt_.add_class(
"Ellipse");
46 NOEXPORT
unsigned int ttc_bezier_ = tt_.add_class(
"Bezier");
47 NOEXPORT
unsigned int ttc_polygon_ = tt_.add_class(
"Polygon");
48 NOEXPORT
unsigned int ttc_polyline_ = tt_.add_class(
"Polyline");
49 NOEXPORT
unsigned int ttc_text_ = tt_.add_class(
"Text");
50 NOEXPORT
unsigned int ttc_text_1_ = tt_.add_class(
"Text 1");
51 NOEXPORT
unsigned int ttc_text_2_ = tt_.add_class(
"Text 2");
52 NOEXPORT
unsigned int ttc_text_3_ = tt_.add_class(
"Text 3");
53 NOEXPORT
unsigned int ttc_text_4_ = tt_.add_class(
"Text 4");
54 NOEXPORT
unsigned int ttc_text_5_ = tt_.add_class(
"Text 5");
55 NOEXPORT
unsigned int tt_count_ = 0;
56 NOEXPORT
unsigned int num_ellipse_ = 0;
57 NOEXPORT
unsigned int num_bezier_ = 0;
58 NOEXPORT
unsigned int num_polygon_ = 0;
59 NOEXPORT
unsigned int num_polyline_ = 0;
60 NOEXPORT
unsigned int num_text_ = 0;
64 skillgui_device_init(GVJ_t *firstjob)
66 Glib::RefPtr<const Gdk::Screen> s = sggvp_->get_screen();
67 firstjob->device_dpi.x = s->get_resolution();
68 firstjob->device_dpi.y = s->get_resolution();
69 firstjob->device_sets_dpi =
true;
71 Gtk::Allocation alloc = sggvp_->get_allocation();
72 firstjob->width = alloc.get_width();
73 firstjob->height = alloc.get_height();
75 firstjob->fit_mode = TRUE;
79 skillgui_device_finalize(GVJ_t *firstjob)
83 firstjob->context = (
void *)sggvp_;
84 firstjob->external_context = TRUE;
87 (firstjob->callbacks->refresh)(firstjob);
90 static inline Papyrus::Fill::pointer
91 skillgui_render_solidpattern(gvcolor_t *color)
93 Cairo::RefPtr<Cairo::SolidPattern> pattern;
94 pattern = Cairo::SolidPattern::create_rgba(color->u.RGBA[0],
98 return Papyrus::Fill::create(pattern);
101 static inline Papyrus::Stroke::pointer
102 skillgui_render_stroke(obj_state_t *obj)
104 Papyrus::Stroke::pointer stroke;
106 Cairo::RefPtr<Cairo::SolidPattern> pattern;
107 pattern = Cairo::SolidPattern::create_rgba(obj->pencolor.u.RGBA[0],
108 obj->pencolor.u.RGBA[1],
109 obj->pencolor.u.RGBA[2],
110 obj->pencolor.u.RGBA[3]);
112 stroke = Papyrus::Stroke::create(pattern, obj->penwidth);
114 if (obj->pen == PEN_DASHED) {
115 stroke->set_dash(skillgui_render_dashed_);
116 }
else if (obj->pen == PEN_DOTTED) {
117 stroke->set_dash(skillgui_render_dotted_);
124 skillgui_render_begin_page(GVJ_t *job)
126 #ifdef USE_GVPLUGIN_TIMETRACKER 127 tt_.ping_start(ttc_page_);
128 tt_.ping_start(ttc_beginpage_);
132 Gtk::Allocation alloc = sggvp_->get_allocation();
133 float bbwidth = job->bb.UR.x - job->bb.LL.x;
134 float bbheight = job->bb.UR.y - job->bb.LL.y;
135 float avwidth = alloc.get_width();
136 float avheight = alloc.get_height();
137 float zoom_w = avwidth / bbwidth;
138 float zoom_h = avheight / bbheight;
139 float zoom = std::min(zoom_w, zoom_h);
141 float translate_x = 0;
142 float translate_y = 0;
144 if (bbwidth > avwidth || bbheight > avheight) {
145 float zwidth = bbwidth * zoom;
146 float zheight = bbheight * zoom;
147 translate_x += (avwidth - zwidth) / 2.;
148 translate_y += (avheight - zheight) / 2.;
151 translate_x += (avwidth - bbwidth) / 2.;
152 translate_y += (avheight - bbheight) / 2.;
155 gvp->
set_bb(bbwidth, bbheight);
156 gvp->
set_pad(job->pad.x, job->pad.y);
161 gvp->
get_affine()->set_translate(translate_x + job->pad.x, translate_y + job->pad.y);
172 #ifdef USE_GVPLUGIN_TIMETRACKER 179 tt_.ping_end(ttc_beginpage_);
184 skillgui_render_end_page(GVJ_t *job)
188 #ifdef USE_GVPLUGIN_TIMETRACKER 189 tt_.ping_end(ttc_page_);
190 if (++tt_count_ >= 10) {
192 tt_.print_to_stdout();
194 printf(
"Num Ellipse: %u\n" 209 skillgui_render_textpara(GVJ_t *job, pointf p, textpara_t *para)
211 #ifdef USE_GVPLUGIN_TIMETRACKER 212 tt_.ping_start(ttc_text_);
216 obj_state_t * obj = job->obj;
218 switch (para->just) {
219 case 'r': p.x -= para->width;
break;
220 case 'l': p.x -= 0.0;
break;
222 default: p.x -= para->width / 2.0;
break;
225 p.y += para->height / 2.0 + para->yoffset_centerline;
229 Glib::RefPtr<Pango::Layout> pl = Glib::wrap((PangoLayout *)para->layout,
231 Pango::FontDescription fd = pl->get_font_description();
232 Cairo::FontSlant slant = Cairo::FONT_SLANT_NORMAL;
233 if (fd.get_style() == Pango::STYLE_OBLIQUE) {
234 slant = Cairo::FONT_SLANT_OBLIQUE;
235 }
else if (fd.get_style() == Pango::STYLE_ITALIC) {
236 slant = Cairo::FONT_SLANT_ITALIC;
238 Cairo::FontWeight weight = Cairo::FONT_WEIGHT_NORMAL;
239 if (fd.get_weight() == Pango::WEIGHT_BOLD) {
240 weight = Cairo::FONT_WEIGHT_BOLD;
243 double offsetx = 0.0;
244 double offsety = 0.0;
247 if ((obj->type == EDGE_OBJTYPE) && (strcmp(para->str, obj->headlabel) == 0)) {
248 char *labelrotate = agget(obj->u.e, (
char *)
"labelrotate");
249 if (labelrotate && (strlen(labelrotate) > 0)) {
252 char *labeloffsetx = agget(obj->u.e, (
char *)
"labeloffsetx");
253 if (labeloffsetx && (strlen(labeloffsetx) > 0)) {
254 offsetx = atof(labeloffsetx) * job->scale.x;
256 char *labeloffsety = agget(obj->u.e, (
char *)
"labeloffsety");
257 if (labeloffsety && (strlen(labeloffsety) > 0)) {
258 offsety = atof(labeloffsety) * job->scale.y;
263 Papyrus::Text::pointer t =
264 Papyrus::Text::create(para->str, para->fontsize, fd.get_family(), slant, weight);
268 #ifdef HAVE_TIMS_PAPYRUS_PATCHES 269 t->set_fill(skillgui_render_solidpattern(&(obj->pencolor)),
false);
271 t->set_fill(skillgui_render_solidpattern(&(obj->pencolor)));
275 t->translate(p.x + offsetx, p.y + offsety,
false);
279 t->set_rotation(rotate, Papyrus::RADIANS,
false);
285 #ifdef USE_GVPLUGIN_TIMETRACKER 286 tt_.ping_end(ttc_text_);
291 skillgui_render_ellipse(GVJ_t *job, pointf *A,
int filled)
293 #ifdef USE_GVPLUGIN_TIMETRACKER 294 tt_.ping_start(ttc_ellipse_);
299 obj_state_t * obj = job->obj;
301 double rx = fabs(A[1].x - A[0].x);
302 double ry = fabs(A[1].y - A[0].y);
304 Papyrus::Circle::pointer e = Papyrus::Circle::create(rx);
305 e->set_stroke(skillgui_render_stroke(obj));
307 e->set_fill(skillgui_render_solidpattern(&(obj->fillcolor)));
308 e->translate(A[0].x, A[0].y);
309 e->set_scale_y(ry / rx);
312 #ifdef USE_GVPLUGIN_TIMETRACKER 313 tt_.ping_end(ttc_ellipse_);
318 skillgui_render_polygon(GVJ_t *job, pointf *A,
int n,
int filled)
320 #ifdef USE_GVPLUGIN_TIMETRACKER 321 tt_.ping_start(ttc_polygon_);
326 obj_state_t * obj = job->obj;
329 for (
int i = 0; i < n; ++i) {
330 v.push_back(Papyrus::Vertex(A[i].x, A[i].y));
333 Papyrus::Polygon::pointer p = Papyrus::Polygon::create(v);
334 p->set_stroke(skillgui_render_stroke(obj));
336 p->set_fill(skillgui_render_solidpattern(&(obj->fillcolor)));
338 #ifdef USE_GVPLUGIN_TIMETRACKER 339 tt_.ping_end(ttc_polygon_);
344 skillgui_render_bezier(GVJ_t * job,
351 #ifdef USE_GVPLUGIN_TIMETRACKER 352 tt_.ping_start(ttc_bezier_);
357 obj_state_t * obj = job->obj;
359 Papyrus::BezierVertices v;
360 v.push_back(Papyrus::BezierVertex(A[0].x, A[0].y, A[0].x, A[0].y, A[1].x, A[1].y));
361 for (
int i = 1; i < n; i += 3) {
363 v.push_back(Papyrus::BezierVertex(
364 A[i + 2].x, A[i + 2].y, A[i + 1].x, A[i + 1].y, A[i + 3].x, A[i + 3].y));
366 v.push_back(Papyrus::BezierVertex(
367 A[i + 2].x, A[i + 2].y, A[i + 1].x, A[i + 1].y, A[i + 2].x, A[i + 2].y));
371 Papyrus::Bezierline::pointer p = Papyrus::Bezierline::create(v);
372 p->set_stroke(skillgui_render_stroke(obj));
374 p->set_fill(skillgui_render_solidpattern(&(obj->fillcolor)));
376 #ifdef USE_GVPLUGIN_TIMETRACKER 377 tt_.ping_end(ttc_bezier_);
382 skillgui_render_polyline(GVJ_t *job, pointf *A,
int n)
384 #ifdef USE_GVPLUGIN_TIMETRACKER 385 tt_.ping_start(ttc_polyline_);
390 obj_state_t * obj = job->obj;
393 for (
int i = 0; i < n; ++i) {
394 v.push_back(Papyrus::Vertex(A[i].x, A[i].y));
397 Papyrus::Polyline::pointer p = Papyrus::Polyline::create(v);
398 p->set_stroke(skillgui_render_stroke(obj));
400 #ifdef USE_GVPLUGIN_TIMETRACKER 401 tt_.ping_end(ttc_polyline_);
405 static gvrender_engine_t skillgui_render_engine = {
412 skillgui_render_begin_page,
413 skillgui_render_end_page,
428 skillgui_render_textpara,
430 skillgui_render_ellipse,
431 skillgui_render_polygon,
432 skillgui_render_bezier,
433 skillgui_render_polyline,
438 static gvdevice_engine_t skillgui_device_engine = {
439 skillgui_device_init,
441 skillgui_device_finalize,
448 static gvrender_features_t skillgui_render_features = {
449 GVRENDER_Y_GOES_DOWN | GVRENDER_DOES_LABELS
450 | GVRENDER_DOES_TRANSFORM,
457 static gvdevice_features_t skillgui_device_features = {
458 GVDEVICE_DOES_TRUECOLOR | GVDEVICE_EVENTS,
464 gvplugin_installed_t gvdevice_types_skillgui[] = {
465 {0, (
char *)
"skillgui:skillgui", 0, &skillgui_device_engine, &skillgui_device_features},
466 {0, NULL, 0, NULL, NULL}};
468 gvplugin_installed_t gvrender_types_skillgui[] = {
469 {0, (
char *)
"skillgui", 10, &skillgui_render_engine, &skillgui_render_features},
470 {0, NULL, 0, NULL, NULL}};
472 static gvplugin_api_t apis[] = {
473 {API_device, gvdevice_types_skillgui},
474 {API_render, gvrender_types_skillgui},
478 gvplugin_library_t gvplugin_skillgui_LTX_library = {(
char *)
"skillgui", apis};
488 gvAddLibrary(gvc, &gvplugin_skillgui_LTX_library);
void set_pad(double pad_x, double pad_y)
Set padding.
void set_scale(double scale)
Set scale.
bool scale_override()
Check if scale override is enabled.
void add_drawable(Papyrus::Drawable::pointer d)
Add a drawable.
void set_bb(double bbw, double bbh)
Set bounding box.
virtual void clear()
Clear all drawables.
void set_gvjob(GVJ_t *job)
Set current Graphviz job.
Papyrus::AffineController::pointer get_affine()
Get scaler.
void set_translation(double tx, double ty)
Set translation.
float deg2rad(float deg)
Convert an angle given in degrees to radians.
Skill FSM Graph Viewport.