📄 chart.c
字号:
/* GKrellM| Copyright (C) 1999-2006 Bill Wilson|| Author: Bill Wilson billw@gkrellm.net| Latest versions might be found at: http://gkrellm.net|| This program is free software which I release under the GNU General Public| License. You may redistribute and/or modify this program under the terms| of that license as published by the Free Software Foundation; either| version 2 of the License, or (at your option) any later version.|| This program 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. Version 2 is in the| COPYRIGHT file in the top level directory of this distribution.| | To get a copy of the GNU General Puplic License, write to the Free Software| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/#include "gkrellm.h"#include "gkrellm-private.h"#include <math.h>static void set_grid_resolution_spin_button(GkrellmChart *, gint); /* For grid images of height 2 pixels, make room at bottom of chartdata | window so both pixel lines will show. */#define GRID_HEIGHT_Y_OFFSET_ADJUST(cp) \ (( gdk_pixbuf_get_height((cp)->bg_grid_piximage->pixbuf) < 2) ? 0 : 1) /* Map internal y values with origin at lower left to X screen coordinates | which have origin at upper left. */#define Y_SCREEN_MAP(cp,y) ((cp)->h - (y) - 1)#define MIN_CHARTHEIGHT 5#define MAX_CHARTHEIGHT 200static GList *chart_list;// #define DEBUG1// #define DEBUG2// #define DEBUG3/* ----------------------------------------------------------------------- */static gintcomputed_index(GkrellmChart *cp, gint i) { gint x; x = (cp->position + i + 1) % cp->w; return x; }GList *gkrellm_get_chart_list() { return chart_list; }gintgkrellm_get_chart_scalemax(GkrellmChart *cp) { if (!cp) return 0; return cp->scale_max; }gintgkrellm_get_current_chartdata(GkrellmChartdata *cd) { if (!cd) return 0; return cd->data[cd->chart->position]; }gintgkrellm_get_chartdata_data(GkrellmChartdata *cd, gint index) { gint x; if (!cd) return 0; x = computed_index(cd->chart, index); return cd->data[x]; }voidgkrellm_clear_chart(GkrellmChart *cp) { if (!cp) return; gdk_draw_drawable(cp->pixmap, _GK.draw1_GC, cp->bg_src_pixmap, 0, 0, 0, 0, cp->w, cp->h); gdk_draw_drawable(cp->bg_pixmap, _GK.draw1_GC, cp->bg_src_pixmap, 0, 0, 0, 0, cp->w, cp->h); if (cp->drawing_area->window) gdk_draw_drawable(cp->drawing_area->window, _GK.draw1_GC, cp->pixmap, 0, 0, 0, 0, cp->w, cp->h); }voidgkrellm_clear_chart_pixmap(GkrellmChart *cp) { if (!cp) return; gdk_draw_drawable(cp->pixmap, _GK.draw1_GC, cp->bg_src_pixmap, 0, 0, 0, 0, cp->w, cp->h); gdk_draw_drawable(cp->bg_pixmap, _GK.draw1_GC, cp->bg_src_pixmap, 0, 0, 0, 0, cp->w, cp->h); }voidgkrellm_clean_bg_src_pixmap(GkrellmChart *cp) { if (!cp) return; if (!gkrellm_winop_draw_rootpixmap_onto_transparent_chart(cp)) gdk_draw_drawable(cp->bg_src_pixmap, _GK.draw1_GC, cp->bg_clean_pixmap, 0, 0, 0, 0, cp->w, cp->h); cp->bg_sequence_id += 1; }voidgkrellm_draw_chart_grid_line(GkrellmChart *cp, GdkPixmap *pixmap, gint y) { gint h; if (!cp) return; gdk_drawable_get_size(cp->bg_grid_pixmap, NULL, &h); gdk_draw_drawable(pixmap, _GK.draw1_GC, cp->bg_grid_pixmap, 0, 0, cp->x, y, cp->w, h); }voidgkrellm_draw_chart_to_screen(GkrellmChart *cp) { /* Draw the expose pixmap onto the screen. */ if (cp && cp->drawing_area->window) gdk_draw_drawable(cp->drawing_area->window, _GK.draw1_GC, cp->pixmap, 0, 0, 0, 0, cp->w, cp->h); }static voiddefault_draw_chart_function(GkrellmChart *cp) { if (!cp) return; gkrellm_draw_chartdata(cp); gkrellm_draw_chart_to_screen(cp); }voidgkrellm_set_draw_chart_function(GkrellmChart *cp, void (*func)(), gpointer data) { if (!cp) return; cp->draw_chart = func; cp->draw_chart_data = data; }voidgkrellm_scale_chartdata(GkrellmChartdata *cd, gint multiplier, gint divisor) { gint i; if (!cd || !cd->data || divisor < 1) return; for (i = 0; i < cd->chart->w; ++i) cd->data[i] = cd->data[i] * multiplier / divisor; cd->previous = cd->previous * multiplier / divisor; }voidgkrellm_offset_chartdata(GkrellmChartdata *cd, gint offset) { gint i; if (!cd || !cd->data) return; for (i = 0; i < cd->chart->w; ++i) cd->data[i] = cd->data[i] + offset; cd->previous = cd->previous + offset; }voidgkrellm_reset_chart(GkrellmChart *cp) { GList *list; GkrellmChartdata *cd; gint i; cp->scale_max = 0; cp->maxval = 0; cp->redraw_all = TRUE; cp->position = cp->w - 1; cp->primed = FALSE; for (list = cp->cd_list; list; list = list->next) { cd = (GkrellmChartdata *) list->data; cd->maxval = 0; cd->previous = 0; if (cd->data) for (i = 0; i < cp->w; ++i) cd->data[i] = 0; } }voidgkrellm_reset_and_draw_chart(GkrellmChart *cp) { if (!cp) return; gkrellm_reset_chart(cp); if (cp->draw_chart) (*(cp->draw_chart))(cp->draw_chart_data); }voidgkrellm_monotonic_chartdata(GkrellmChartdata *cd, gboolean value) { if (cd) cd->monotonic = value; }voidgkrellm_set_chartdata_draw_style(GkrellmChartdata *cd, gint dstyle) { if (cd) cd->draw_style = dstyle; }voidgkrellm_set_chartdata_draw_style_default(GkrellmChartdata *cd, gint dstyle) { if (cd && cd->chart->config && !cd->chart->config->config_loaded) cd->draw_style = dstyle; }voidgkrellm_set_chartdata_flags(GkrellmChartdata *cd, gint flags) { if (cd) cd->flags = flags; }static gintchartdata_ycoord(GkrellmChart *cp, GkrellmChartdata *cd, gint yd) { glong y; guint64 Y; if (cp->scale_max <= 0) cp->scale_max = 1; if (yd > 2000000000 / MAX_CHARTHEIGHT) { Y = (guint64) yd * (guint64) cd->h; y = Y / cp->scale_max; } else y = ((glong) yd * cd->h / cp->scale_max); if (y < 0) y = 0; if (y >= cd->h) y = cd->h - 1; if (cd->inverted) y = cd->h - y - 1; y += cd->y; return Y_SCREEN_MAP(cp, y); }static voiddraw_layer_grid_lines(GkrellmChart *cp) { GList *list; GkrellmChartdata *cd; gint y, y0, h, grid_res, lines; gint active_split, current_split; gboolean do_next_split, done_once_per_split, tmp; gdk_draw_drawable(cp->bg_pixmap, _GK.draw1_GC, cp->bg_src_pixmap, 0, 0, 0, 0, cp->w, cp->h); do_next_split = TRUE; for (active_split = 0; do_next_split; ++active_split) { do_next_split = FALSE; done_once_per_split = FALSE; current_split = 0; for (list = cp->cd_list; list; list = list->next) { cd = (GkrellmChartdata *) list->data; if (cd->hide) continue; current_split += cd->split_chart; if (active_split != current_split) { if (current_split > active_split) do_next_split = TRUE; continue; } gdk_draw_drawable(cd->layer.pixmap, _GK.draw1_GC, *(cd->layer.src_pixmap), 0, 0, 0, 0, cp->w, cp->h); grid_res = cp->config->grid_resolution; lines = cp->scale_max / grid_res; if (lines && cd->h / lines > 2) /* No grids if h is too small */ { for (y = 0; y <= cp->scale_max; y += grid_res) { if ( _GK.bg_grid_mode == GRID_MODE_RESTRAINED && ((y == 0 && cp->y == 0) || y == cp->scale_max) ) continue; tmp = cd->inverted; /* Draw grid lines in one direction*/ cd->inverted = FALSE; /* else, may not line up by 1 pixel*/ y0 = chartdata_ycoord(cp, cd, y); cd->inverted = tmp; gdk_drawable_get_size(cd->layer.grid_pixmap, NULL, &h); gdk_draw_drawable(cd->layer.pixmap, _GK.draw1_GC, cd->layer.grid_pixmap, 0, 0, cp->x, y0, cp->w, h); if (!done_once_per_split) { gdk_drawable_get_size(cp->bg_grid_pixmap, NULL, &h); gdk_draw_drawable(cp->bg_pixmap, _GK.draw1_GC, cp->bg_grid_pixmap, 0, 0, cp->x, y0, cp->w, h); } } } if (current_split > 0 && !done_once_per_split) { y = cd->y - 1; /* Get separator y value */ y -= GRID_HEIGHT_Y_OFFSET_ADJUST(cp); if (y >= 0) { gdk_draw_drawable(cp->bg_pixmap, _GK.draw1_GC, _GK.bg_separator_pixmap, 0, 0, cp->x, Y_SCREEN_MAP(cp, y), cp->w, _GK.bg_separator_height); } } done_once_per_split = TRUE; } } } /* Return TRUE as long as there is a next split with impulse data needing | to be drawn. */static gbooleandraw_chartdata_impulses(GkrellmChart *cp, GList *cd_list, gint i0, gint active_split) { GList *list; GkrellmChartdata *cd; gint n, x, y, y0, y1, yN, yI; gint current_split; gboolean need_next_split = FALSE; if (!cd_list) return FALSE; for (n = i0; n < cp->w; ++n) { x = computed_index(cp, n); y0 = y1 = -1; yN = yI = 0; current_split = 0; for (list = cp->cd_list; list; list= list->next) { cd = (GkrellmChartdata *) list->data; if (cd->hide) continue; current_split += cd->split_chart; if ( cd->draw_style != CHARTDATA_IMPULSE || current_split != active_split ) { if ( current_split > active_split && cd->draw_style == CHARTDATA_IMPULSE ) need_next_split = TRUE; continue; } if (cd->inverted) { if (y1 < 0) y1 = chartdata_ycoord(cp, cd, 0); yI += cd->data[x]; y = chartdata_ycoord(cp, cd, yI); if (cd->data[x] > 0) gdk_draw_line(cd->data_bitmap, _GK.bit1_GC, n, y1, n, y); y1 = y; } else { if (y0 < 0) y0 = chartdata_ycoord(cp, cd, 0); yN += cd->data[x]; y = chartdata_ycoord(cp, cd, yN); if (cd->data[x] > 0) gdk_draw_line(cd->data_bitmap, _GK.bit1_GC, n, y0, n, y); y0 = y; } } } /* Push the grided pixmaps through the data bitmaps onto the expose pixmap */ current_split = 0; for (list = cp->cd_list; list; list = list->next) { cd = (GkrellmChartdata *) list->data; if (cd->hide) continue; current_split += cd->split_chart; if (cd->draw_style == CHARTDATA_LINE || current_split != active_split) continue; if (cd->maxval > 0) { y0 = chartdata_ycoord(cp, cd, 0); y1 = chartdata_ycoord(cp, cd, cd->maxval); gdk_gc_set_clip_mask(_GK.draw1_GC, cd->data_bitmap); if (cd->inverted) gdk_draw_drawable(cp->pixmap, _GK.draw1_GC, cd->layer.pixmap, 0, y0, 0, y0, cp->w, y1 - y0 + 1); else gdk_draw_drawable(cp->pixmap, _GK.draw1_GC, cd->layer.pixmap, 0, y1, 0, y1, cp->w, y0 - y1 + 1); } } return need_next_split; }static gintfix_y(gint yn, gint yp, gint ypp) { gint y; if (yp > ypp && yn < yp) { y = (yp + yn) / 2; if (y < ypp) y = ypp; } else if (yp < ypp && yn > yp) { y = (yp + yn) / 2; if (y > ypp) y = ypp; } else y = yp; return y; }static voiddraw_chartdata_lines(GkrellmChart *cp, GkrellmChartdata *cd, gint i0) { gint n, x, xp, y, y0, y1; y0 = chartdata_ycoord(cp, cd, 0); for (n = i0; n < cp->w; ++n) { x = computed_index(cp, n); y1 = chartdata_ycoord(cp, cd, cd->data[x]); if (n == 0) cd->y_p = y1; else if (!cd->y_p_valid && i0 == cp->w - 1) { if ((xp = x - 1) < 0) xp = cp->w - 1; cd->y_p = cd->y_pp = chartdata_ycoord(cp, cd, cd->data[xp]); } y = fix_y(y1, cd->y_p, cd->y_pp); cd->y_pp = y; cd->y_p = y1; cd->y_p_valid = FALSE; /* Need a store_chartdata to make it valid */ if (cd->data[x] > 0 || (cd->inverted ? (y > y0) : (y < y0))) { if (y == y1) gdk_draw_point(cd->data_bitmap, _GK.bit1_GC, cp->x + n, y1); else gdk_draw_line(cd->data_bitmap, _GK.bit1_GC, cp->x + n, y, cp->x + n, y1); } } /* Push the grided pixmap through the data bitmap onto the expose pixmap */ if (cd->maxval > 0) { y0 = chartdata_ycoord(cp, cd, 0); y1 = chartdata_ycoord(cp, cd, cd->maxval); gdk_gc_set_clip_mask(_GK.draw1_GC, cd->data_bitmap); if (cd->inverted) gdk_draw_drawable(cp->pixmap, _GK.draw1_GC, cd->layer.pixmap, 0, y0, 0, y0, cp->w, y1 - y0 + 1); else gdk_draw_drawable(cp->pixmap, _GK.draw1_GC, cd->layer.pixmap, 0, y1, 0, y1, cp->w, y0 - y1 + 1); } } /* See the README for description of auto grid resolution behavior. */static voidset_auto_grid_resolution(GkrellmChart *cp, gint maxval) { GkrellmChartconfig *cf = cp->config; gint grids, grid_res, maxval_base; if (maxval <= cp->maxval_auto_base) maxval = cp->maxval_auto_base; else { if (maxval > cp->maxval_peak) cp->maxval_peak = maxval;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -