/* * GTK plotting routines source file * * Copyright (c) 1999 Mark Taylor * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /* $Id: gpkplotting.c,v 1.12 2011/05/07 16:05:17 rbrito Exp $ */ #ifdef HAVE_CONFIG_H # include #endif #include "gpkplotting.h" #ifdef STDC_HEADERS # include #else # ifndef HAVE_STRCHR # define strchr index # define strrchr rindex # endif char *strchr(), *strrchr(); # ifndef HAVE_MEMCPY # define memcpy(d, s, n) bcopy ((s), (d), (n)) # define memmove(d, s, n) bcopy ((s), (d), (n)) # endif #endif #ifdef WITH_DMALLOC #include #endif static gint num_plotwindows = 0; static gint max_plotwindows = 10; static GdkPixmap *pixmaps[10]; static GtkWidget *pixmapboxes[10]; /* compute a gdkcolor */ void setcolor(GtkWidget * widget, GdkColor * color, gint red, gint green, gint blue) { /* colors in GdkColor are taken from 0 to 65535, not 0 to 255. */ color->red = red * (65535 / 255); color->green = green * (65535 / 255); color->blue = blue * (65535 / 255); color->pixel = (gulong) (color->red * 65536 + color->green * 256 + color->blue); /* find closest in colormap, if needed */ gdk_color_alloc(gtk_widget_get_colormap(widget), color); } void gpk_redraw(GdkPixmap * pixmap, GtkWidget * pixmapbox) { /* redraw the entire pixmap */ gdk_draw_pixmap(pixmapbox->window, pixmapbox->style->fg_gc[GTK_WIDGET_STATE(pixmapbox)], pixmap, 0, 0, 0, 0, pixmapbox->allocation.width, pixmapbox->allocation.height); } static GdkPixmap ** findpixmap(GtkWidget * widget) { int i; for (i = 0; i < num_plotwindows && widget != pixmapboxes[i]; i++); if (i >= num_plotwindows) { g_print("findpixmap(): bad argument widget \n"); return NULL; } return &pixmaps[i]; } void gpk_graph_draw(GtkWidget * widget, /* plot on this widged */ int n, /* number of data points */ gdouble * xcord, gdouble * ycord, /* data */ gdouble xmn, gdouble ymn, /* coordinates of corners */ gdouble xmx, gdouble ymx, int clear, /* clear old plot first */ char *title, /* add a title (only if clear=1) */ GdkColor * color) { GdkPixmap **ppixmap; GdkPoint *points; int i; gint16 width, height; GdkFont *fixed_font; GdkGC *gc; gc = gdk_gc_new(widget->window); gdk_gc_set_foreground(gc, color); if ((ppixmap = findpixmap(widget))) { width = widget->allocation.width; height = widget->allocation.height; if (clear) { /* white background */ gdk_draw_rectangle(*ppixmap, widget->style->white_gc, TRUE, 0, 0, width, height); /* title */ #ifdef _WIN32 fixed_font = gdk_font_load("-misc-fixed-large-r-*-*-*-100-*-*-*-*-*-*"); #else fixed_font = gdk_font_load("-misc-fixed-medium-r-*-*-*-100-*-*-*-*-iso8859-1"); #endif gdk_draw_text(*ppixmap, fixed_font, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], 0, 10, title, strlen(title)); } points = g_malloc(n * sizeof(GdkPoint)); for (i = 0; i < n; i++) { points[i].x = .5 + ((xcord[i] - xmn) * (width - 1) / (xmx - xmn)); points[i].y = .5 + ((ycord[i] - ymx) * (height - 1) / (ymn - ymx)); } gdk_draw_lines(*ppixmap, gc, points, n); g_free(points); gpk_redraw(*ppixmap, widget); } gdk_gc_destroy(gc); } void gpk_rectangle_draw(GtkWidget * widget, /* plot on this widged */ gdouble * xcord, gdouble * ycord, /* corners */ gdouble xmn, gdouble ymn, /* coordinates of corners */ gdouble xmx, gdouble ymx, GdkColor * color) { GdkPixmap **ppixmap; GdkPoint points[2]; int i; gint16 width, height; GdkGC *gc; gc = gdk_gc_new(widget->window); gdk_gc_set_foreground(gc, color); if ((ppixmap = findpixmap(widget))) { width = widget->allocation.width; height = widget->allocation.height; for (i = 0; i < 2; i++) { points[i].x = .5 + ((xcord[i] - xmn) * (width - 1) / (xmx - xmn)); points[i].y = .5 + ((ycord[i] - ymx) * (height - 1) / (ymn - ymx)); } width = points[1].x - points[0].x + 1; height = points[1].y - points[0].y + 1; gdk_draw_rectangle(*ppixmap, gc, TRUE, points[0].x, points[0].y, width, height); gpk_redraw(*ppixmap, widget); } gdk_gc_destroy(gc); } void gpk_bargraph_draw(GtkWidget * widget, /* plot on this widged */ int n, /* number of data points */ gdouble * xcord, gdouble * ycord, /* data */ gdouble xmn, gdouble ymn, /* coordinates of corners */ gdouble xmx, gdouble ymx, int clear, /* clear old plot first */ char *title, /* add a title (only if clear=1) */ int barwidth, /* bar width. 0=compute based on window size */ GdkColor * color) { GdkPixmap **ppixmap; GdkPoint points[2]; int i; gint16 width, height, x, y, barheight; GdkFont *fixed_font; GdkGC *gc; int titleSplit; gc = gdk_gc_new(widget->window); gdk_gc_set_foreground(gc, color); if ((ppixmap = findpixmap(widget))) { width = widget->allocation.width; height = widget->allocation.height; if (clear) { /* white background */ gdk_draw_rectangle(*ppixmap, widget->style->white_gc, TRUE, 0, 0, width, height); /* title */ #ifdef _WIN32 fixed_font = gdk_font_load("-misc-fixed-large-r-*-*-*-100-*-*-*-*-*-*"); #else fixed_font = gdk_font_load("-misc-fixed-medium-r-*-*-*-100-*-*-*-*-iso8859-1"); #endif titleSplit = strcspn(title, "\n"); if (titleSplit && (titleSplit != strlen(title))) { gdk_draw_text(*ppixmap, fixed_font, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], 0, 10, title, titleSplit); gdk_draw_text(*ppixmap, fixed_font, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], 0, 22, title + titleSplit + 1, (strlen(title) - titleSplit) - 1); } else { gdk_draw_text(*ppixmap, fixed_font, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], 0, 10, title, strlen(title)); } } for (i = 0; i < n; i++) { points[1].x = .5 + ((xcord[i] - xmn) * (width - 1) / (xmx - xmn)); points[1].y = .5 + ((ycord[i] - ymx) * (height - 1) / (ymn - ymx)); points[0].x = points[1].x; points[0].y = height - 1; x = .5 + ((xcord[i] - xmn) * (width - 1) / (xmx - xmn)); y = .5 + ((ycord[i] - ymx) * (height - 1) / (ymn - ymx)); if (!barwidth) barwidth = (width / (n + 1)) - 1; barwidth = barwidth > 5 ? 5 : barwidth; barwidth = barwidth < 1 ? 1 : barwidth; barheight = height - 1 - y; /* gdk_draw_lines(*ppixmap,gc,points,2); */ gdk_draw_rectangle(*ppixmap, gc, TRUE, x, y, barwidth, barheight); } gpk_redraw(*ppixmap, widget); } gdk_gc_destroy(gc); } /* Create a new backing pixmap of the appropriate size */ static gint configure_event(GtkWidget * widget, GdkEventConfigure * event, gpointer data) { GdkPixmap **ppixmap; if ((ppixmap = findpixmap(widget))) { if (*ppixmap) gdk_pixmap_unref(*ppixmap); *ppixmap = gdk_pixmap_new(widget->window, widget->allocation.width, widget->allocation.height, -1); gdk_draw_rectangle(*ppixmap, widget->style->white_gc, TRUE, 0, 0, widget->allocation.width, widget->allocation.height); } return TRUE; } /* Redraw the screen from the backing pixmap */ static gint expose_event(GtkWidget * widget, GdkEventExpose * event, gpointer data) { GdkPixmap **ppixmap; if ((ppixmap = findpixmap(widget))) { gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], *ppixmap, event->area.x, event->area.y, event->area.x, event->area.y, event->area.width, event->area.height); } return FALSE; } GtkWidget * gpk_plot_new(int width, int height) { GtkWidget *pixmapbox; pixmapbox = gtk_drawing_area_new(); gtk_drawing_area_size(GTK_DRAWING_AREA(pixmapbox), width, height); gtk_signal_connect(GTK_OBJECT(pixmapbox), "expose_event", (GtkSignalFunc) expose_event, NULL); gtk_signal_connect(GTK_OBJECT(pixmapbox), "configure_event", (GtkSignalFunc) configure_event, NULL); gtk_widget_set_events(pixmapbox, GDK_EXPOSURE_MASK); if (num_plotwindows < max_plotwindows) { pixmapboxes[num_plotwindows] = pixmapbox; pixmaps[num_plotwindows] = NULL; num_plotwindows++; } else { g_print("gtk_plotarea_new(): exceeded maximum of 10 plotarea windows\n"); } return pixmapbox; }