From 25e5a7319bc3a55765fd13a41905b51dad868121 Mon Sep 17 00:00:00 2001 From: tchernobog Date: Fri, 28 Jul 2006 15:24:56 +0000 Subject: [PATCH] - Add CairoElements - Start code for double buffering in custom widgets, using an off-screen pixmap. Problem: we don't know the height from the beginning git-svn-id: svn://svn.gna.org/svn/sgpemv2/trunk@798 3ecf2c5c-341e-0410-92b4-d18e462d057c --- Makefile.am | 2 + plugins/pyloader/src/python_policy.cc | 4 +- src/backend/scheduler.cc | 2 +- src/cairo_elements.cc | 184 ++++++++++++++++++++++++++ src/cairo_elements.hh | 78 +++++++++++ src/schedulables_widget.cc | 60 ++++----- 6 files changed, 296 insertions(+), 34 deletions(-) create mode 100644 src/cairo_elements.cc create mode 100644 src/cairo_elements.hh diff --git a/Makefile.am b/Makefile.am index f33ef6e..62acb4c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -271,6 +271,7 @@ sgpemv2_LDADD = \ # Please keep this in sorted order: sgpemv2_SOURCES = \ + src/cairo_elements.cc \ src/graphical_terminal_io.cc \ src/gui_builder.cc \ src/main.cc \ @@ -282,6 +283,7 @@ sgpemv2_SOURCES = \ src/text_simulation.cc noinst_HEADERS += \ + src/cairo_elements.hh \ src/graphical_simulation.hh \ src/graphical_terminal_io.hh \ src/gui_builder.hh \ diff --git a/plugins/pyloader/src/python_policy.cc b/plugins/pyloader/src/python_policy.cc index 358e75d..b1eebb6 100644 --- a/plugins/pyloader/src/python_policy.cc +++ b/plugins/pyloader/src/python_policy.cc @@ -173,10 +173,8 @@ PythonPolicy::wait_unlock() const throw(UserInterruptException) { Py_UNBLOCK_THREADS; usleep(WAIT_FOR); // hack'a'ton! magggggiccc nummmbeeerrrrrs!! - cout << "got here..." << endl; Py_BLOCK_THREADS; - cout << "wow I also got here!" << endl; - + PyObject* retval = PyObject_CallMethod(_adapter, "mutex_test_lock", NULL); assert(retval); still_locked = PyObject_IsTrue(retval); diff --git a/src/backend/scheduler.cc b/src/backend/scheduler.cc index 2d34a40..7bb8a84 100644 --- a/src/backend/scheduler.cc +++ b/src/backend/scheduler.cc @@ -212,7 +212,7 @@ Scheduler::step_forward(History& history, Policy& cpu_policy) throw(UserInterrup // should be done here as the first thing, instead than // directly after selecting them if(current.get_total_cpu_time() - current.get_elapsed_time() > 0) - running_thread->decrease_remaining_time(); + current.decrease_remaining_time(); // 2. mark threads that used all their allotted time as terminated if(current.get_total_cpu_time() - current.get_elapsed_time() == 0) diff --git a/src/cairo_elements.cc b/src/cairo_elements.cc new file mode 100644 index 0000000..37612d8 --- /dev/null +++ b/src/cairo_elements.cc @@ -0,0 +1,184 @@ +// src/cairo_elements.cc - Copyright 2005, 2006, University +// of Padova, dept. of Pure and Applied +// Mathematics +// +// This file is part of SGPEMv2. +// +// This is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// SGPEMv2 is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with SGPEMv2; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +#include "cairo_elements.hh" + +#include + +using namespace sgpem; + + +CairoElements::CairoElements(cairo_t* const ctx) + : _ctx(ctx) +{ +} + + +void +CairoElements::draw_3dsphere(const Point& center, float radius, const Color& cl) +{ + cairo_t*& cr = _ctx; + const float& x = center.x; + const float& y = center.y; + const float& r = cl.r; + const float& g = cl.g; + const float& b = cl.b; + + // Draw initial sphere perimeter + cairo_save(cr); + cairo_new_path(cr); + cairo_arc(cr, x, y, radius, 0, 2*M_PI); + cairo_pattern_t* grad = cairo_pattern_create_radial(x, y, radius, x, y, radius - .15); + cairo_pattern_add_color_stop_rgba(grad, 0, r - .2, g - .2, b - .2, 1); + cairo_pattern_add_color_stop_rgba(grad, 1, r, g, b, 1); + cairo_set_source(cr, grad); + cairo_fill_preserve(cr); + cairo_pattern_destroy(grad); + cairo_set_source_rgba(cr, 0, 0, 0, 1); + cairo_set_line_width(cr, radius * .01); + cairo_stroke(cr); + cairo_restore(cr); + + // Internal gradient + cairo_save(cr); + grad = cairo_pattern_create_linear(x, y, x, y + radius); + cairo_pattern_add_color_stop_rgba(grad, 1, r - .4, g - .4, b - .4, 1); + cairo_pattern_add_color_stop_rgba(grad, 0, r, g, b, .7); + cairo_set_source(cr, grad); + cairo_translate(cr, x*.2, (y + radius*8/9) * 1/3); + cairo_scale(cr, .8, 2./3); + cairo_arc(cr, x, y, radius, 0, 2*M_PI); + cairo_fill(cr); + cairo_pattern_destroy(grad); + cairo_restore(cr); + + // Internal glow + cairo_save(cr); + grad = cairo_pattern_create_linear(x, y - radius, x, y); + cairo_pattern_add_color_stop_rgba(grad, 0, 1, 1, 1, .9); + cairo_pattern_add_color_stop_rgba(grad, 1, 1, 1, 1, .2); + cairo_set_source(cr, grad); + cairo_translate(cr, x * .2, (y - radius*8/9) * 1/3); + cairo_scale(cr, .8, 2./3); + cairo_arc(cr, x, y, radius, 0, 2*M_PI); + cairo_fill(cr); + cairo_pattern_destroy(grad); + cairo_restore(cr); +} + +void +CairoElements::draw_3dcube(const Rectangle& area, const Color& cl) +{ + cairo_t*& cr = _ctx; + const float& x0 = area.x0; + const float& y0 = area.y0; + const float& w = area.w; + const float& h = area.h; + + + // FIXME : not implemented +} + + +void +CairoElements::draw_container(const Rectangle& area) +{ + cairo_t*& cr = _ctx; + const float& x0 = area.x0; + const float& y0 = area.y0; + const float& w = area.w; + const float& h = area.h; + + const double corner_radius = 0.05; + + cairo_save(cr); + cairo_new_path(cr); + cairo_move_to(cr, x0 + corner_radius, y0); + + // NW -> NE + cairo_line_to(cr, x0+w - corner_radius, y0); + cairo_curve_to(cr, x0+w, y0, x0+w, y0, x0+w, y0 + corner_radius); + // NE -> SE + cairo_line_to(cr, x0+w, y0+h - corner_radius); + cairo_curve_to(cr, x0+w, y0+h, x0+w, y0+h, x0+w - corner_radius, y0+h); + // SE -> SW + cairo_line_to(cr, x0 + corner_radius, y0+h); + cairo_curve_to(cr, x0, y0+h, x0, y0+h, x0, y0+h - corner_radius); + // SW -> NW + cairo_line_to(cr, x0, y0 + corner_radius); + cairo_curve_to(cr, x0, y0, x0, y0, x0 + corner_radius, y0); + cairo_close_path(cr); + + cairo_set_source_rgb(cr, 1, 1, 0.9); + cairo_fill_preserve(cr); + cairo_set_line_width(cr, .005); + cairo_set_source_rgb(cr, 0, 0, 0); + cairo_stroke(cr); + cairo_restore(cr); +} + + +void +CairoElements::draw_expandable(const Rectangle& area, bool expanded) +{ + cairo_t*& cr = _ctx; + const float& x0 = area.x0; + const float& y0 = area.y0; + const float& w = area.w; + const float& h = area.h; + + cairo_save(cr); + + cairo_set_line_width(cr, .005); + cairo_set_source_rgb(cr, 1, 1, 1); + + cairo_new_path(cr); + cairo_rectangle(cr, x0, y0, w, h); + cairo_set_source_rgb(cr, 1, 1, 1); + cairo_fill_preserve(cr); + cairo_set_source_rgb(cr, 0, 0, 0); + cairo_stroke(cr); + + cairo_move_to(cr, x0 + w/10, y0 + h/2); + cairo_line_to(cr, x0 + w*9/10, y0 + h/2); + cairo_stroke(cr); + + if(!expanded) + { + cairo_move_to(cr, x0 + w/2, y0 + h/10); + cairo_line_to(cr, x0 + w/2, y0 + h*9/10); + cairo_stroke(cr); + } + + cairo_restore(cr); +} + + +Rectangle draw_thread_status(const Point& top_left_crn, + const Thread& thread_info) +{ +} + + +Rectangle draw_process_status(const Point& top_left_crn, + const Process& process_info) +{ +} + diff --git a/src/cairo_elements.hh b/src/cairo_elements.hh new file mode 100644 index 0000000..8f69faf --- /dev/null +++ b/src/cairo_elements.hh @@ -0,0 +1,78 @@ +// src/cairo_elements.hh - Copyright 2005, 2006, University +// of Padova, dept. of Pure and Applied +// Mathematics +// +// This file is part of SGPEMv2. +// +// This is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// SGPEMv2 is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with SGPEMv2; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +#ifndef CAIRO_ELEMENTS_HH +#define CAIRO_ELEMENTS_HH 1 + +#include "config.h" + +#include "backend/thread.hh" +#include "backend/process.hh" + +#include + +namespace sgpem +{ + + struct Point + { + float x; + float y; + }; + + struct Rectangle + { + float x0; + float y0; + float w; + float h; + }; + + struct Color + { + float r; + float g; + float b; + }; + + + class CairoElements + { + public: + CairoElements(cairo_t* const ctx); + + void draw_3dsphere(const Point& center, float radius, const Color& cl); + void draw_3dcube(const Rectangle& area, const Color& cl); + void draw_container(const Rectangle& area); + void draw_expandable(const Rectangle& area, bool expanded = false); + + Rectangle draw_thread_status(const Point& top_left_crn, + const Thread& thread_info); + Rectangle draw_process_status(const Point& top_left_crn, + const Process& process_info); + + private: + cairo_t* _ctx; + }; + +} //~ namespace sgpem + + +#endif //~ CAIRO_ELEMENTS_HH diff --git a/src/schedulables_widget.cc b/src/schedulables_widget.cc index 636939c..72438a8 100644 --- a/src/schedulables_widget.cc +++ b/src/schedulables_widget.cc @@ -18,6 +18,7 @@ // along with SGPEMv2; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#include "cairo_elements.hh" #include "schedulables_widget.hh" #include @@ -26,23 +27,39 @@ using namespace sgpem; SchedulablesWidget::SchedulablesWidget() - : _ctx(NULL) + : Gtk::DrawingArea(), _ctx(NULL) { // Add other events we want to manage (as mouse clicks) // when needed - add_events(Gdk::EXPOSURE_MASK); + add_events(Gdk::EXPOSURE_MASK); } SchedulablesWidget::~SchedulablesWidget() { + if(_ctx != NULL) + cairo_destroy(_ctx); } void SchedulablesWidget::update(const History& history) { - // FIXME : write me + // FIXME : write me using double buffering + // GdkPixmap* buffer = gdk_pixmap_new(...); + // _ctx = gdk_cairo_create(buffer); + + // do the drawing... + + + // NOTE: just to try + CairoElements ce(_ctx); + Color red = { 1, 0, 0 }; + Point center = { 25, 25 }; + + ce.draw_3dsphere(center, 25, red); + + // manually force an expose_event? } @@ -60,7 +77,6 @@ bool SchedulablesWidget::on_expose_event(GdkEventExpose* event) { // Use double buffering or we're CPU-dead - Glib::RefPtr window = get_window(); GdkWindow* gdkWindow = window->gobj(); GdkDrawable* gdkDrawable; @@ -71,50 +87,34 @@ SchedulablesWidget::on_expose_event(GdkEventExpose* event) // we should use something like create_similar to instantiate a // compatible surface and then copy the buffer to fg // So the following two lines WILL HAVE TO CHANGE. - cairo_t*& cr = _ctx; - cr = gdk_cairo_create(gdkDrawable); + if(_ctx == NULL) + _ctx = gdk_cairo_create(gdkDrawable); + cairo_t* cr = gdk_cairo_create(gdkDrawable); + const Gtk::Allocation& allocation = get_allocation(); int width = allocation.get_width(); int height = allocation.get_height(); - // Already clip, so that paint hasn't to care about it: + // Clip to redraw only the smallest possible area if(event) { cairo_rectangle(cr, event->area.x, event->area.y, event->area.width, event->area.height); cairo_clip(cr); } - - // NOTE: just to try: - + // should be calculated dinamically: set_size_request(200,400); + // Copy from buffer to video + // if(_ctx != NULL) + // gdk_draw_drawable(buffer, GC??, gdkDrawable, ...clip-region...); + // Height should be calculated dynamically? cairo_scale(cr, width, width); - cairo_set_line_width(cr, 0.02); - cairo_set_source_rgba(cr, 0, 0, 0, 1); - - // Draw initial sphere perimeter - float r = 1.f, g = 0.f, b = 0.f; - double x = .5, y = .5, radius = .5; - cairo_save(cr); - cairo_new_path(cr); - cairo_arc(cr, x, y, radius, 0, 2*M_PI); - cairo_pattern_t* grad = cairo_pattern_create_radial(x, y, radius, x, y, radius - .15); - cairo_pattern_add_color_stop_rgba(grad, 0, r - .2, g - .2, b - .2, 1); - cairo_pattern_add_color_stop_rgba(grad, 1, r, g, b, 1); - cairo_set_source(cr, grad); - cairo_fill_preserve(cr); - cairo_pattern_destroy(grad); - cairo_set_source_rgba(cr, 0, 0, 0, 1); - cairo_set_line_width(cr, radius * .01); - cairo_stroke(cr); - cairo_restore(cr); cairo_destroy(cr); - return true; }