00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "gvplugin_skillgui_papyrus.h"
00025
00026 #include <utils/math/angle.h>
00027 #include <utils/time/tracker.h>
00028
00029 #include <gvplugin_device.h>
00030 #include <gvplugin_render.h>
00031
00032 #include <algorithm>
00033 #include <cstdio>
00034
00035 #define NOEXPORT __attribute__ ((visibility("hidden")))
00036
00037 NOEXPORT SkillGuiGraphViewport *__sggvp = NULL;
00038
00039 NOEXPORT std::valarray<double> __skillgui_render_dashed(6., 1);
00040 NOEXPORT std::valarray<double> __skillgui_render_dotted((double[]){2., 6.}, 2);
00041
00042 #ifdef USE_GVPLUGIN_TIMETRACKER
00043 NOEXPORT fawkes::TimeTracker __tt;
00044 NOEXPORT unsigned int __ttc_page = __tt.add_class("Page");
00045 NOEXPORT unsigned int __ttc_beginpage = __tt.add_class("Begin Page");
00046 NOEXPORT unsigned int __ttc_ellipse = __tt.add_class("Ellipse");
00047 NOEXPORT unsigned int __ttc_bezier = __tt.add_class("Bezier");
00048 NOEXPORT unsigned int __ttc_polygon = __tt.add_class("Polygon");
00049 NOEXPORT unsigned int __ttc_polyline = __tt.add_class("Polyline");
00050 NOEXPORT unsigned int __ttc_text = __tt.add_class("Text");
00051 NOEXPORT unsigned int __ttc_text_1 = __tt.add_class("Text 1");
00052 NOEXPORT unsigned int __ttc_text_2 = __tt.add_class("Text 2");
00053 NOEXPORT unsigned int __ttc_text_3 = __tt.add_class("Text 3");
00054 NOEXPORT unsigned int __ttc_text_4 = __tt.add_class("Text 4");
00055 NOEXPORT unsigned int __ttc_text_5 = __tt.add_class("Text 5");
00056 NOEXPORT unsigned int __tt_count = 0;
00057 NOEXPORT unsigned int __num_ellipse = 0;
00058 NOEXPORT unsigned int __num_bezier = 0;
00059 NOEXPORT unsigned int __num_polygon = 0;
00060 NOEXPORT unsigned int __num_polyline = 0;
00061 NOEXPORT unsigned int __num_text = 0;
00062 #endif
00063
00064 static void
00065 skillgui_device_init(GVJ_t *firstjob)
00066 {
00067 Glib::RefPtr<const Gdk::Screen> s = __sggvp->get_screen();
00068 firstjob->device_dpi.x = s->get_resolution();
00069 firstjob->device_dpi.y = s->get_resolution();
00070 firstjob->device_sets_dpi = true;
00071
00072 Gtk::Allocation alloc = __sggvp->get_allocation();
00073 firstjob->width = alloc.get_width();
00074 firstjob->height = alloc.get_height();
00075
00076 firstjob->fit_mode = TRUE;
00077 }
00078
00079 static void
00080 skillgui_device_finalize(GVJ_t *firstjob)
00081 {
00082 __sggvp->set_gvjob(firstjob);
00083
00084 firstjob->context = (void *)__sggvp;
00085 firstjob->external_context = TRUE;
00086
00087
00088 (firstjob->callbacks->refresh)(firstjob);
00089 }
00090
00091
00092 static inline Papyrus::Fill::pointer
00093 skillgui_render_solidpattern(gvcolor_t *color)
00094 {
00095 Cairo::RefPtr< Cairo::SolidPattern > pattern;
00096 pattern = Cairo::SolidPattern::create_rgba(color->u.RGBA[0],
00097 color->u.RGBA[1],
00098 color->u.RGBA[2],
00099 color->u.RGBA[3]);
00100 return Papyrus::Fill::create(pattern);
00101 }
00102
00103
00104 static inline Papyrus::Stroke::pointer
00105 skillgui_render_stroke(obj_state_t *obj)
00106 {
00107 Papyrus::Stroke::pointer stroke;
00108
00109 Cairo::RefPtr< Cairo::SolidPattern > pattern;
00110 pattern = Cairo::SolidPattern::create_rgba(obj->pencolor.u.RGBA[0],
00111 obj->pencolor.u.RGBA[1],
00112 obj->pencolor.u.RGBA[2],
00113 obj->pencolor.u.RGBA[3]);
00114
00115 stroke = Papyrus::Stroke::create(pattern, obj->penwidth);
00116
00117 if (obj->pen == PEN_DASHED) {
00118 stroke->set_dash(__skillgui_render_dashed);
00119 } else if (obj->pen == PEN_DOTTED) {
00120 stroke->set_dash(__skillgui_render_dotted);
00121 }
00122
00123 return stroke;
00124 }
00125
00126 static void
00127 skillgui_render_begin_page(GVJ_t *job)
00128 {
00129 #ifdef USE_GVPLUGIN_TIMETRACKER
00130 __tt.ping_start(__ttc_page);
00131 __tt.ping_start(__ttc_beginpage);
00132 #endif
00133 SkillGuiGraphViewport *gvp = (SkillGuiGraphViewport *)job->context;
00134 gvp->clear();
00135 Gtk::Allocation alloc = __sggvp->get_allocation();
00136 float bbwidth = job->bb.UR.x - job->bb.LL.x;
00137 float bbheight = job->bb.UR.y - job->bb.LL.y;
00138 float avwidth = alloc.get_width();
00139 float avheight = alloc.get_height();
00140 float zoom_w = avwidth / bbwidth;
00141 float zoom_h = avheight / bbheight;
00142 float zoom = std::min(zoom_w, zoom_h);
00143
00144 float translate_x = 0;
00145 float translate_y = 0;
00146
00147 if (bbwidth > avwidth || bbheight > avheight) {
00148 float zwidth = bbwidth * zoom;
00149 float zheight = bbheight * zoom;
00150 translate_x += (avwidth - zwidth ) / 2.;
00151 translate_y += (avheight - zheight) / 2.;
00152 } else {
00153 zoom = 1.0;
00154 translate_x += (avwidth - bbwidth) / 2.;
00155 translate_y += (avheight - bbheight) / 2.;
00156 }
00157
00158 gvp->set_bb(bbwidth, bbheight);
00159 gvp->set_pad(job->pad.x, job->pad.y);
00160 gvp->set_scale(zoom);
00161 gvp->set_translation(translate_x, translate_y);
00162
00163 if (! gvp->scale_override()) {
00164 gvp->get_affine()->set_translate(translate_x + job->pad.x,
00165 translate_y + job->pad.y);
00166 gvp->get_affine()->set_scale(zoom);
00167 }
00168
00169
00170
00171
00172
00173
00174
00175
00176 #ifdef USE_GVPLUGIN_TIMETRACKER
00177 __num_ellipse = 0;
00178 __num_bezier = 0;
00179 __num_polygon = 0;
00180 __num_polyline = 0;
00181 __num_text = 0;
00182
00183 __tt.ping_end(__ttc_beginpage);
00184 #endif
00185 }
00186
00187 static void
00188 skillgui_render_end_page(GVJ_t * job)
00189 {
00190
00191
00192 #ifdef USE_GVPLUGIN_TIMETRACKER
00193 __tt.ping_end(__ttc_page);
00194 if ( ++__tt_count >= 10 ) {
00195 __tt_count = 0;
00196 __tt.print_to_stdout();
00197
00198 printf("Num Ellipse: %u\n"
00199 "Num Bezier: %u\n"
00200 "Num Polygon: %u\n"
00201 "Num Polyline: %u\n"
00202 "Num Text: %u\n", __num_ellipse, __num_bezier,
00203 __num_polygon, __num_polyline, __num_text);
00204 }
00205 #endif
00206 }
00207
00208 static void
00209 skillgui_render_textpara(GVJ_t *job, pointf p, textpara_t *para)
00210 {
00211 #ifdef USE_GVPLUGIN_TIMETRACKER
00212 __tt.ping_start(__ttc_text);
00213 ++__num_text;
00214 #endif
00215 SkillGuiGraphViewport *gvp = (SkillGuiGraphViewport *)job->context;
00216 obj_state_t *obj = job->obj;
00217
00218 switch (para->just) {
00219 case 'r':
00220 p.x -= para->width;
00221 break;
00222 case 'l':
00223 p.x -= 0.0;
00224 break;
00225 case 'n':
00226 default:
00227 p.x -= para->width / 2.0;
00228 break;
00229 }
00230
00231 p.y += para->height / 2.0 + para->yoffset_centerline;
00232
00233
00234
00235 Glib::RefPtr<Pango::Layout> pl = Glib::wrap((PangoLayout *)para->layout,
00236 true);
00237 Pango::FontDescription fd = pl->get_font_description();
00238 Cairo::FontSlant slant = Cairo::FONT_SLANT_NORMAL;
00239 if (fd.get_style() == Pango::STYLE_OBLIQUE ) {
00240 slant = Cairo::FONT_SLANT_OBLIQUE;
00241 } else if (fd.get_style() == Pango::STYLE_ITALIC ) {
00242 slant = Cairo::FONT_SLANT_ITALIC;
00243 }
00244 Cairo::FontWeight weight = Cairo::FONT_WEIGHT_NORMAL;
00245 if ( fd.get_weight() == Pango::WEIGHT_BOLD ) {
00246 weight = Cairo::FONT_WEIGHT_BOLD;
00247 }
00248
00249 double offsetx = 0.0;
00250 double offsety = 0.0;
00251 double rotate = 0.0;
00252
00253 if ( (obj->type == EDGE_OBJTYPE) && (strcmp(para->str, obj->headlabel) == 0) ) {
00254 char *labelrotate = agget(obj->u.e, (char *)"labelrotate");
00255 if (labelrotate && (strlen(labelrotate) > 0)) {
00256 rotate = fawkes::deg2rad(atof(labelrotate));
00257 }
00258 char *labeloffsetx = agget(obj->u.e, (char *)"labeloffsetx");
00259 if (labeloffsetx && (strlen(labeloffsetx) > 0)) {
00260 offsetx = atof(labeloffsetx) * job->scale.x;
00261 }
00262 char *labeloffsety = agget(obj->u.e, (char *)"labeloffsety");
00263 if (labeloffsety && (strlen(labeloffsety) > 0)) {
00264 offsety = atof(labeloffsety) * job->scale.y;
00265 }
00266 }
00267
00268
00269 Papyrus::Text::pointer t = Papyrus::Text::create(para->str, para->fontsize,
00270 fd.get_family(), slant, weight);
00271
00272
00273
00274 #ifdef HAVE_TIMS_PAPYRUS_PATCHES
00275 t->set_fill(skillgui_render_solidpattern(&(obj->pencolor)), false);
00276 #else
00277 t->set_fill(skillgui_render_solidpattern(&(obj->pencolor)));
00278 #endif
00279
00280
00281 t->translate(p.x + offsetx, p.y + offsety, false);
00282
00283
00284 if (rotate != 0.0) t->set_rotation(rotate, Papyrus::RADIANS, false);
00285
00286
00287 gvp->add_drawable(t);
00288
00289
00290 #ifdef USE_GVPLUGIN_TIMETRACKER
00291 __tt.ping_end(__ttc_text);
00292 #endif
00293 }
00294
00295 static void
00296 skillgui_render_ellipse(GVJ_t *job, pointf *A, int filled)
00297 {
00298 #ifdef USE_GVPLUGIN_TIMETRACKER
00299 __tt.ping_start(__ttc_ellipse);
00300 ++__num_ellipse;
00301 #endif
00302
00303 SkillGuiGraphViewport *gvp = (SkillGuiGraphViewport *)job->context;
00304 obj_state_t *obj = job->obj;
00305
00306 double rx = fabs(A[1].x - A[0].x);
00307 double ry = fabs(A[1].y - A[0].y);
00308
00309 Papyrus::Circle::pointer e = Papyrus::Circle::create(rx);
00310 e->set_stroke(skillgui_render_stroke(obj));
00311 if ( filled ) e->set_fill(skillgui_render_solidpattern(&(obj->fillcolor)));
00312 e->translate(A[0].x, A[0].y);
00313 e->set_scale_y(ry / rx);
00314
00315 gvp->add_drawable(e);
00316 #ifdef USE_GVPLUGIN_TIMETRACKER
00317 __tt.ping_end(__ttc_ellipse);
00318 #endif
00319 }
00320
00321 static void
00322 skillgui_render_polygon(GVJ_t *job, pointf *A, int n, int filled)
00323 {
00324 #ifdef USE_GVPLUGIN_TIMETRACKER
00325 __tt.ping_start(__ttc_polygon);
00326 ++__num_polygon;
00327 #endif
00328
00329 SkillGuiGraphViewport *gvp = (SkillGuiGraphViewport *)job->context;
00330 obj_state_t *obj = job->obj;
00331
00332 Papyrus::Vertices v;
00333 for (int i = 0; i < n; ++i) {
00334 v.push_back(Papyrus::Vertex(A[i].x, A[i].y));
00335 }
00336
00337 Papyrus::Polygon::pointer p = Papyrus::Polygon::create(v);
00338 p->set_stroke(skillgui_render_stroke(obj));
00339 if ( filled ) p->set_fill(skillgui_render_solidpattern(&(obj->fillcolor)));
00340 gvp->add_drawable(p);
00341 #ifdef USE_GVPLUGIN_TIMETRACKER
00342 __tt.ping_end(__ttc_polygon);
00343 #endif
00344 }
00345
00346 static void
00347 skillgui_render_bezier(GVJ_t * job, pointf * A, int n, int arrow_at_start,
00348 int arrow_at_end, int filled)
00349 {
00350 #ifdef USE_GVPLUGIN_TIMETRACKER
00351 __tt.ping_start(__ttc_bezier);
00352 ++__num_bezier;
00353 #endif
00354
00355 SkillGuiGraphViewport *gvp = (SkillGuiGraphViewport *)job->context;
00356 obj_state_t *obj = job->obj;
00357
00358 Papyrus::BezierVertices v;
00359 v.push_back(Papyrus::BezierVertex(A[0].x, A[0].y,
00360 A[0].x, A[0].y,
00361 A[1].x, A[1].y));
00362 for (int i = 1; i < n; i += 3) {
00363 if ( i < (n - 4) ) {
00364 v.push_back(Papyrus::BezierVertex(A[i+2].x, A[i+2].y,
00365 A[i+1].x, A[i+1].y,
00366 A[i+3].x, A[i+3].y));
00367 } else {
00368 v.push_back(Papyrus::BezierVertex(A[i+2].x, A[i+2].y,
00369 A[i+1].x, A[i+1].y,
00370 A[i+2].x, A[i+2].y));
00371 }
00372 }
00373
00374 Papyrus::Bezierline::pointer p = Papyrus::Bezierline::create(v);
00375 p->set_stroke(skillgui_render_stroke(obj));
00376 if ( filled ) p->set_fill(skillgui_render_solidpattern(&(obj->fillcolor)));
00377 gvp->add_drawable(p);
00378 #ifdef USE_GVPLUGIN_TIMETRACKER
00379 __tt.ping_end(__ttc_bezier);
00380 #endif
00381 }
00382
00383 static void
00384 skillgui_render_polyline(GVJ_t * job, pointf * A, int n)
00385 {
00386 #ifdef USE_GVPLUGIN_TIMETRACKER
00387 __tt.ping_start(__ttc_polyline);
00388 ++__num_polyline;
00389 #endif
00390
00391 SkillGuiGraphViewport *gvp = (SkillGuiGraphViewport *)job->context;
00392 obj_state_t *obj = job->obj;
00393
00394 Papyrus::Vertices v;
00395 for (int i = 0; i < n; ++i) {
00396 v.push_back(Papyrus::Vertex(A[i].x, A[i].y));
00397 }
00398
00399 Papyrus::Polyline::pointer p = Papyrus::Polyline::create(v);
00400 p->set_stroke(skillgui_render_stroke(obj));
00401 gvp->add_drawable(p);
00402 #ifdef USE_GVPLUGIN_TIMETRACKER
00403 __tt.ping_end(__ttc_polyline);
00404 #endif
00405 }
00406
00407
00408 static gvrender_engine_t skillgui_render_engine = {
00409 0,
00410 0,
00411 0,
00412 0,
00413 0,
00414 0,
00415 skillgui_render_begin_page,
00416 skillgui_render_end_page,
00417 0,
00418 0,
00419 0,
00420 0,
00421 0,
00422 0,
00423 0,
00424 0,
00425 0,
00426 0,
00427 0,
00428 0,
00429 0,
00430 0,
00431 skillgui_render_textpara,
00432 0,
00433 skillgui_render_ellipse,
00434 skillgui_render_polygon,
00435 skillgui_render_bezier,
00436 skillgui_render_polyline,
00437 0,
00438 0,
00439 };
00440
00441 static gvdevice_engine_t skillgui_device_engine = {
00442 skillgui_device_init,
00443 NULL,
00444 skillgui_device_finalize,
00445 };
00446
00447
00448 #ifdef __cplusplus
00449 extern "C" {
00450 #endif
00451
00452
00453 static gvrender_features_t skillgui_render_features = {
00454 GVRENDER_Y_GOES_DOWN | GVRENDER_DOES_LABELS |
00455 GVRENDER_DOES_TRANSFORM,
00456 8,
00457 0,
00458 0,
00459 RGBA_DOUBLE,
00460 };
00461
00462
00463 static gvdevice_features_t skillgui_device_features = {
00464 GVDEVICE_DOES_TRUECOLOR | GVDEVICE_EVENTS,
00465 {0.,0.},
00466 {0.,0.},
00467 {96.,96.},
00468 };
00469
00470 gvplugin_installed_t gvdevice_types_skillgui[] = {
00471 {0, ( char *)"skillgui:skillgui", 0, &skillgui_device_engine, &skillgui_device_features},
00472 {0, NULL, 0, NULL, NULL}
00473 };
00474
00475 gvplugin_installed_t gvrender_types_skillgui[] = {
00476 {0, (char *)"skillgui", 10, &skillgui_render_engine, &skillgui_render_features},
00477 {0, NULL, 0, NULL, NULL}
00478 };
00479
00480 static gvplugin_api_t apis[] = {
00481 {API_device, gvdevice_types_skillgui},
00482 {API_render, gvrender_types_skillgui},
00483 {(api_t)0, 0},
00484 };
00485
00486 gvplugin_library_t gvplugin_skillgui_LTX_library = { (char *)"skillgui", apis };
00487
00488 #ifdef __cplusplus
00489 }
00490 #endif
00491
00492
00493 void
00494 gvplugin_skillgui_setup(GVC_t *gvc, SkillGuiGraphViewport *sggvp)
00495 {
00496 __sggvp = sggvp;
00497 gvAddLibrary(gvc, &gvplugin_skillgui_LTX_library);
00498 }