Back to index

easystroke  0.5.5.1
composite.cc
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008-2009, Thomas Jaeger <ThJaeger@gmail.com>
00003  *
00004  * Permission to use, copy, modify, and/or distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
00009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00011  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
00013  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
00014  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 #include "prefdb.h"
00017 #include "composite.h"
00018 #include <gdkmm.h>
00019 #include <glibmm/i18n.h>
00020 
00021 double red, green, blue, alpha, width;
00022 std::list<Trace::Point> points;
00023 
00024 Popup::Popup(int x1, int y1, int x2, int y2) : Gtk::Window(Gtk::WINDOW_POPUP), rect(x1, y1, x2-x1, y2-y1) {
00025        if (!is_composited())
00026               throw std::runtime_error(_("'composite' not available"));
00027 
00028        Glib::RefPtr<Gdk::Colormap> colormap = get_screen()->get_rgba_colormap();
00029        if (colormap)
00030               set_colormap(colormap);
00031        signal_expose_event().connect(sigc::mem_fun(*this, &Popup::on_expose));
00032        realize();
00033        move(x1, y1);
00034        resize(x2-x1, y2-y1);
00035        get_window()->input_shape_combine_region(Gdk::Region(), 0, 0);
00036        // tell compiz to leave this window the hell alone
00037        get_window()->set_type_hint(Gdk::WINDOW_TYPE_HINT_DESKTOP);
00038 }
00039 
00040 void Popup::invalidate(int x1, int y1, int x2, int y2) {
00041        if (is_mapped()) {
00042               Gdk::Rectangle inv(x1 - rect.get_x(), y1 - rect.get_y(), x2-x1, y2-y1);
00043               get_window()->invalidate_rect(inv, false);
00044        } else
00045               show();
00046 }
00047 
00048 Composite::Composite() {
00049 #define N 128
00050        int w = gdk_screen_width();
00051        int h = gdk_screen_height();
00052        num_x = (gdk_screen_width()  - 1)/N + 1;
00053        num_y = (gdk_screen_height() - 1)/N + 1;
00054        pieces = new Popup**[num_x];
00055        for (int i = 0; i < num_x; i++) {
00056               pieces[i] = new Popup*[num_y];
00057               for (int j = 0; j < num_y; j++)
00058                      pieces[i][j] = new Popup(i*N,j*N,MIN((i+1)*N,w),MIN((j+1)*N,h));
00059 
00060        }
00061 }
00062 
00063 void Composite::draw(Point p, Point q) {
00064        if (!points.size()) {
00065               points.push_back(p);
00066        }
00067        points.push_back(q);
00068        int x1 = (int)(p.x < q.x ? p.x : q.x);
00069        int x2 = (int)(p.x < q.x ? q.x : p.x);
00070        int y1 = (int)(p.y < q.y ? p.y : q.y);
00071        int y2 = (int)(p.y < q.y ? q.y : p.y);
00072        int bw = (int)(width/2.0) + 2;
00073        x1 -= bw; y1 -= bw;
00074        x2 += bw; y2 += bw;
00075        if (x1 < 0)
00076               x1 = 0;
00077        if (y1 < 0)
00078               y1 = 0;
00079        for (int i = x1/N; i<num_x && i<=x2/N; i++)
00080               for (int j = y1/N; j<num_y && j<=y2/N; j++)
00081                      pieces[i][j]->invalidate(x1, y1, x2, y2);
00082 }
00083 
00084 void Composite::start_() {
00085        RGBA rgba = prefs.color.get();
00086        red = rgba.color.get_red_p();
00087        green = rgba.color.get_green_p();
00088        blue = rgba.color.get_blue_p();
00089        alpha = ((double)rgba.alpha)/65535.0;
00090        width = prefs.trace_width.get();
00091 }
00092 
00093 void Popup::draw_line(Cairo::RefPtr<Cairo::Context> ctx) {
00094        if (!points.size())
00095               return;
00096        std::list<Trace::Point>::iterator i = points.begin();
00097        ctx->move_to (i->x, i->y);
00098        for (; i != points.end(); i++)
00099               ctx->line_to (i->x, i->y);
00100        ctx->set_source_rgba((red+0.5)/2.0, (green+0.5)/2.0, (blue+0.5)/2.0, alpha/2.0);
00101        ctx->set_line_width(width+1.0);
00102        ctx->set_line_cap(Cairo::LINE_CAP_ROUND);
00103        ctx->set_line_join(Cairo::LINE_JOIN_ROUND);
00104        ctx->stroke_preserve();
00105 
00106        ctx->set_source_rgba(red, green, blue, alpha);
00107        ctx->set_line_width(width*0.7);
00108        ctx->stroke();
00109 
00110 }
00111 
00112 bool Popup::on_expose(GdkEventExpose* event) {
00113        Cairo::RefPtr<Cairo::Context> ctx = get_window()->create_cairo_context();
00114        ctx->set_operator(Cairo::OPERATOR_SOURCE);
00115 
00116        Gdk::Region region(event->region, true);
00117        Gdk::Cairo::add_region_to_path(ctx, region);
00118        ctx->clip();
00119 
00120        Gdk::Cairo::add_region_to_path(ctx, region);
00121        ctx->set_source_rgba(0.0, 0.0, 0.0, 0.0);
00122        ctx->fill();
00123 
00124        ctx->translate(-rect.get_x(), -rect.get_y());
00125        draw_line(ctx);
00126 
00127        return false;
00128 }
00129 
00130 void Composite::end_() {
00131        points.clear();
00132        for (int i = 0; i < num_x; i++)
00133               for (int j = 0; j < num_y; j++)
00134                      pieces[i][j]->hide();
00135 }
00136 
00137 Composite::~Composite() {
00138        for (int i = 0; i < num_x; i++) {
00139               for (int j = 0; j < num_y; j++)
00140                      delete pieces[i][j];
00141               delete[] pieces[i];
00142        }
00143        delete[] pieces;
00144 }