gpkplotting.c

Go to the documentation of this file.
00001 /*
00002  *      GTK plotting routines source file
00003  *
00004  *      Copyright (c) 1999 Mark Taylor
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Library General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the
00018  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019  * Boston, MA 02111-1307, USA.
00020  */
00021 
00022 /* $Id: gpkplotting.c,v 1.11 2007/07/24 17:46:08 bouvigne Exp $ */
00023 
00024 #ifdef HAVE_CONFIG_H
00025 # include <config.h>
00026 #endif
00027 
00028 #include "gpkplotting.h"
00029 
00030 #ifdef STDC_HEADERS
00031 # include <string.h>
00032 #else
00033 # ifndef HAVE_STRCHR
00034 #  define strchr index
00035 #  define strrchr rindex
00036 # endif
00037 char   *strchr(), *strrchr();
00038 # ifndef HAVE_MEMCPY
00039 #  define memcpy(d, s, n) bcopy ((s), (d), (n))
00040 #  define memmove(d, s, n) bcopy ((s), (d), (n))
00041 # endif
00042 #endif
00043 
00044 #ifdef WITH_DMALLOC
00045 #include <dmalloc.h>
00046 #endif
00047 
00048 static gint num_plotwindows = 0;
00049 static gint max_plotwindows = 10;
00050 static GdkPixmap *pixmaps[10];
00051 static GtkWidget *pixmapboxes[10];
00052 
00053 
00054 
00055 
00056 /* compute a gdkcolor */
00057 void
00058 setcolor(GtkWidget * widget, GdkColor * color, gint red, gint green, gint blue)
00059 {
00060 
00061     /* colors in GdkColor are taken from 0 to 65535, not 0 to 255.    */
00062     color->red = red * (65535 / 255);
00063     color->green = green * (65535 / 255);
00064     color->blue = blue * (65535 / 255);
00065     color->pixel = (gulong) (color->red * 65536 + color->green * 256 + color->blue);
00066     /* find closest in colormap, if needed */
00067     gdk_color_alloc(gtk_widget_get_colormap(widget), color);
00068 }
00069 
00070 
00071 void
00072 gpk_redraw(GdkPixmap * pixmap, GtkWidget * pixmapbox)
00073 {
00074     /* redraw the entire pixmap */
00075     gdk_draw_pixmap(pixmapbox->window,
00076                     pixmapbox->style->fg_gc[GTK_WIDGET_STATE(pixmapbox)],
00077                     pixmap, 0, 0, 0, 0, pixmapbox->allocation.width, pixmapbox->allocation.height);
00078 }
00079 
00080 
00081 static GdkPixmap **
00082 findpixmap(GtkWidget * widget)
00083 {
00084     int     i;
00085     for (i = 0; i < num_plotwindows && widget != pixmapboxes[i]; i++);
00086     if (i >= num_plotwindows) {
00087         g_print("findpixmap(): bad argument widget \n");
00088         return NULL;
00089     }
00090     return &pixmaps[i];
00091 }
00092 
00093 void
00094 gpk_graph_draw(GtkWidget * widget, /* plot on this widged */
00095                int n,        /* number of data points */
00096                gdouble * xcord, gdouble * ycord, /* data */
00097                gdouble xmn, gdouble ymn, /* coordinates of corners */
00098                gdouble xmx, gdouble ymx, int clear, /* clear old plot first */
00099                char *title,  /* add a title (only if clear=1) */
00100                GdkColor * color)
00101 {
00102     GdkPixmap **ppixmap;
00103     GdkPoint *points;
00104     int     i;
00105     gint16  width, height;
00106     GdkFont *fixed_font;
00107     GdkGC  *gc;
00108 
00109     gc = gdk_gc_new(widget->window);
00110     gdk_gc_set_foreground(gc, color);
00111 
00112 
00113 
00114     if ((ppixmap = findpixmap(widget))) {
00115         width = widget->allocation.width;
00116         height = widget->allocation.height;
00117 
00118 
00119         if (clear) {
00120             /* white background */
00121             gdk_draw_rectangle(*ppixmap, widget->style->white_gc, TRUE, 0, 0, width, height);
00122             /* title */
00123 #ifdef _WIN32
00124             fixed_font = gdk_font_load("-misc-fixed-large-r-*-*-*-100-*-*-*-*-*-*");
00125 #else
00126             fixed_font = gdk_font_load("-misc-fixed-medium-r-*-*-*-100-*-*-*-*-iso8859-1");
00127 #endif
00128 
00129             gdk_draw_text(*ppixmap, fixed_font,
00130                           widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
00131                           0, 10, title, strlen(title));
00132         }
00133 
00134 
00135         points = g_malloc(n * sizeof(GdkPoint));
00136         for (i = 0; i < n; i++) {
00137             points[i].x = .5 + ((xcord[i] - xmn) * (width - 1) / (xmx - xmn));
00138             points[i].y = .5 + ((ycord[i] - ymx) * (height - 1) / (ymn - ymx));
00139         }
00140         gdk_draw_lines(*ppixmap, gc, points, n);
00141         g_free(points);
00142         gpk_redraw(*ppixmap, widget);
00143     }
00144     gdk_gc_destroy(gc);
00145 }
00146 
00147 
00148 
00149 void
00150 gpk_rectangle_draw(GtkWidget * widget, /* plot on this widged */
00151                    gdouble * xcord, gdouble * ycord, /* corners */
00152                    gdouble xmn, gdouble ymn, /* coordinates of corners */
00153                    gdouble xmx, gdouble ymx, GdkColor * color)
00154 {
00155     GdkPixmap **ppixmap;
00156     GdkPoint points[2];
00157     int     i;
00158     gint16  width, height;
00159     GdkGC  *gc;
00160 
00161 
00162     gc = gdk_gc_new(widget->window);
00163     gdk_gc_set_foreground(gc, color);
00164 
00165 
00166     if ((ppixmap = findpixmap(widget))) {
00167         width = widget->allocation.width;
00168         height = widget->allocation.height;
00169 
00170 
00171         for (i = 0; i < 2; i++) {
00172             points[i].x = .5 + ((xcord[i] - xmn) * (width - 1) / (xmx - xmn));
00173             points[i].y = .5 + ((ycord[i] - ymx) * (height - 1) / (ymn - ymx));
00174         }
00175         width = points[1].x - points[0].x + 1;
00176         height = points[1].y - points[0].y + 1;
00177         gdk_draw_rectangle(*ppixmap, gc, TRUE, points[0].x, points[0].y, width, height);
00178         gpk_redraw(*ppixmap, widget);
00179     }
00180     gdk_gc_destroy(gc);
00181 }
00182 
00183 
00184 
00185 void
00186 gpk_bargraph_draw(GtkWidget * widget, /* plot on this widged */
00187                   int n,     /* number of data points */
00188                   gdouble * xcord, gdouble * ycord, /* data */
00189                   gdouble xmn, gdouble ymn, /* coordinates of corners */
00190                   gdouble xmx, gdouble ymx, int clear, /* clear old plot first */
00191                   char *title, /* add a title (only if clear=1) */
00192                   int barwidth, /* bar width. 0=compute based on window size */
00193                   GdkColor * color)
00194 {
00195     GdkPixmap **ppixmap;
00196     GdkPoint points[2];
00197     int     i;
00198     gint16  width, height, x, y, barheight;
00199     GdkFont *fixed_font;
00200     GdkGC  *gc;
00201     int     titleSplit;
00202 
00203 
00204     gc = gdk_gc_new(widget->window);
00205     gdk_gc_set_foreground(gc, color);
00206 
00207 
00208     if ((ppixmap = findpixmap(widget))) {
00209         width = widget->allocation.width;
00210         height = widget->allocation.height;
00211 
00212 
00213         if (clear) {
00214             /* white background */
00215             gdk_draw_rectangle(*ppixmap, widget->style->white_gc, TRUE, 0, 0, width, height);
00216             /* title */
00217 #ifdef _WIN32
00218             fixed_font = gdk_font_load("-misc-fixed-large-r-*-*-*-100-*-*-*-*-*-*");
00219 #else
00220             fixed_font = gdk_font_load("-misc-fixed-medium-r-*-*-*-100-*-*-*-*-iso8859-1");
00221 #endif
00222 
00223             titleSplit = strcspn(title, "\n");
00224 
00225             if (titleSplit && (titleSplit != strlen(title))) {
00226                 gdk_draw_text(*ppixmap, fixed_font,
00227                               widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
00228                               0, 10, title, titleSplit);
00229 
00230                 gdk_draw_text(*ppixmap, fixed_font,
00231                               widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
00232                               0, 22, title + titleSplit + 1, (strlen(title) - titleSplit) - 1);
00233 
00234 
00235             }
00236             else {
00237                 gdk_draw_text(*ppixmap, fixed_font,
00238                               widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
00239                               0, 10, title, strlen(title));
00240             }
00241         }
00242 
00243 
00244         for (i = 0; i < n; i++) {
00245             points[1].x = .5 + ((xcord[i] - xmn) * (width - 1) / (xmx - xmn));
00246             points[1].y = .5 + ((ycord[i] - ymx) * (height - 1) / (ymn - ymx));
00247             points[0].x = points[1].x;
00248             points[0].y = height - 1;
00249 
00250             x = .5 + ((xcord[i] - xmn) * (width - 1) / (xmx - xmn));
00251             y = .5 + ((ycord[i] - ymx) * (height - 1) / (ymn - ymx));
00252             if (!barwidth)
00253                 barwidth = (width / (n + 1)) - 1;
00254             barwidth = barwidth > 5 ? 5 : barwidth;
00255             barwidth = barwidth < 1 ? 1 : barwidth;
00256             barheight = height - 1 - y;
00257             /* gdk_draw_lines(*ppixmap,gc,points,2); */
00258             gdk_draw_rectangle(*ppixmap, gc, TRUE, x, y, barwidth, barheight);
00259 
00260         }
00261         gpk_redraw(*ppixmap, widget);
00262     }
00263     gdk_gc_destroy(gc);
00264 }
00265 
00266 
00267 
00268 
00269 
00270 /* Create a new backing pixmap of the appropriate size */
00271 static  gint
00272 configure_event(GtkWidget * widget, GdkEventConfigure * event, gpointer data)
00273 {
00274     GdkPixmap **ppixmap;
00275     if ((ppixmap = findpixmap(widget))) {
00276         if (*ppixmap)
00277             gdk_pixmap_unref(*ppixmap);
00278         *ppixmap = gdk_pixmap_new(widget->window,
00279                                   widget->allocation.width, widget->allocation.height, -1);
00280         gdk_draw_rectangle(*ppixmap,
00281                            widget->style->white_gc,
00282                            TRUE, 0, 0, widget->allocation.width, widget->allocation.height);
00283     }
00284     return TRUE;
00285 }
00286 
00287 
00288 
00289 /* Redraw the screen from the backing pixmap */
00290 static  gint
00291 expose_event(GtkWidget * widget, GdkEventExpose * event, gpointer data)
00292 {
00293     GdkPixmap **ppixmap;
00294     if ((ppixmap = findpixmap(widget))) {
00295         gdk_draw_pixmap(widget->window,
00296                         widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
00297                         *ppixmap,
00298                         event->area.x, event->area.y,
00299                         event->area.x, event->area.y, event->area.width, event->area.height);
00300     }
00301 
00302     return FALSE;
00303 }
00304 
00305 
00306 
00307 
00308 
00309 GtkWidget *
00310 gpk_plot_new(int width, int height)
00311 {
00312     GtkWidget *pixmapbox;
00313 
00314     pixmapbox = gtk_drawing_area_new();
00315     gtk_drawing_area_size(GTK_DRAWING_AREA(pixmapbox), width, height);
00316     gtk_signal_connect(GTK_OBJECT(pixmapbox), "expose_event", (GtkSignalFunc) expose_event, NULL);
00317     gtk_signal_connect(GTK_OBJECT(pixmapbox), "configure_event",
00318                        (GtkSignalFunc) configure_event, NULL);
00319     gtk_widget_set_events(pixmapbox, GDK_EXPOSURE_MASK);
00320 
00321     if (num_plotwindows < max_plotwindows) {
00322         pixmapboxes[num_plotwindows] = pixmapbox;
00323         pixmaps[num_plotwindows] = NULL;
00324         num_plotwindows++;
00325     }
00326     else {
00327         g_print("gtk_plotarea_new(): exceeded maximum of 10 plotarea windows\n");
00328     }
00329 
00330     return pixmapbox;
00331 }

Generated on Sun Dec 2 11:34:17 2007 for LAME by  doxygen 1.5.2