// 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 #ifndef M_PI #define M_PI 3.14159265358979323846 #endif 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, const float x_percent, const float y_percent) { 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 float& r = cl.r; const float& g = cl.b; const float& b = cl.b; cairo_save(cr); cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND); // Front side of the cube: cairo_rectangle(cr, x0, y0 + (1 - y_percent) * h, w * x_percent, h * y_percent); cairo_set_source_rgb(cr, r, g, b); cairo_fill_preserve(cr); cairo_set_source_rgb(cr, 0, 0, 0); cairo_stroke(cr); // ``Upper'' visible cube side: cairo_new_path(cr); cairo_move_to(cr, x0, y0 + (1 - y_percent) * h); cairo_line_to(cr, x0 + (1 - x_percent) * w, y0); cairo_line_to(cr, x0 + w, y0); cairo_line_to(cr, x0 + w * x_percent, y0 + (1 - y_percent) * h); cairo_close_path(cr); cairo_set_source_rgb(cr, r - 0.2, g - 0.2, b - 0.2); cairo_fill_preserve(cr); cairo_set_source_rgb(cr, 0, 0, 0); cairo_stroke(cr); // ``Right'' visible cube side: cairo_new_path(cr); cairo_move_to(cr, x0 + w * x_percent, y0 + (1 - y_percent) * h); cairo_line_to(cr, x0 + w, y0); cairo_line_to(cr, x0 + w, y0 + y_percent * h); cairo_line_to(cr, x0 + w * x_percent, y0 + h); cairo_close_path(cr); cairo_set_source_rgb(cr, r - 0.4, g - 0.4, b - 0.4); cairo_fill_preserve(cr); cairo_set_source_rgb(cr, 0, 0, 0); cairo_stroke(cr); cairo_restore(cr); } 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); }