📄 krell.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"static GkrellmBorder zero_border;static GkrellmMargin zero_margin; /* Smooth the krell response with an exponential moving average. | Eponential MA is quicker responding than pure moving average. | a = 2 / (period + 1) | ema = ema + a * (reading - ema) | Don't need floating point precision here, so do the int math in an | order to minimize roundoff error and scale by 256 for some precision. */static gintexp_MA(GkrellmKrell *k) { gint ema, p, reading, round_up; /* First, help the krell settle to zero and full scale. This gives | on/off fast response while the ema is smoothing in between. */ if (k->reading == 0 && k->last_reading == 0) return 0; if (k->reading >= k->full_scale && k->last_reading >= k->full_scale) return k->full_scale; if (k->last_reading == 0) /* Fast liftoff as well */ return k->reading; ema = k->ema << 8; p = k->period + 1; /* Don't scale this! */ reading = (k->reading) << 8; ema = ema + 2 * reading / p - 2 * ema / p; round_up = ((ema & 0xff) > 127) ? 1 : 0; return (ema >> 8) + round_up; } /* If the Krell has moved, redraw its layer on its stencil. */voidgkrellm_update_krell(GkrellmPanel *p, GkrellmKrell *k, gulong value) { gint xnew, x_src, y_src, x_dst, w1, w2, w_overlap, d, frame; if (!p || !k || k->full_scale == 0) return; k->value = value; if (value < k->previous) /* unsigned long overflow? */ { k->previous = value; return; } if (!k->monotonic) k->previous = 0; k->reading = (gint) (value - k->previous) * k->full_scale_expand; if (k->reading > k->full_scale) k->reading = k->full_scale; k->ema = (k->period > 1) ? exp_MA(k) : k->reading; if (k->monotonic) k->previous = value; k->last_reading = k->reading; xnew = k->x0 + k->ema * k->w_scale / k->full_scale; if (xnew == k->x0 && k->reading) { xnew = k->x0 + 1; /* Show something for all activity */ k->ema = 1; } if (xnew == k->x_position) return; k->x_position = xnew; /* If the krell has depth, pick the frame to display as function of | ema. Depth == 2 means display frame 0 at xnew == 0, and frame 1 | everywhere else. Depth > 2 means same thing for frame 0, | diplay frame depth - 1 at xnew == full_scale, and display other | frames in between at xnew proportional to ema/full_scale. */ d = k->depth; if (k->ema == 0 || xnew == k->x0) /* Krell can settle before ema*/ frame = 0; else if (k->ema >= k->full_scale) frame = d - 1; else { if (d == 1) frame = 0; else if (d == 2) frame = 1; else frame = 1 + ((d - 2) * k->ema / k->full_scale); } y_src = k->h_frame * frame; if (k->bar_mode) { x_src = (k->bar_mode == KRELL_EXPAND_BAR_MODE_SCALED) ? 0 : k->x0; x_dst = k->x0; w_overlap = xnew - k->x0; } else { x_src = k->x_hot - (xnew - k->x0); if (x_src < 0) x_src = 0; x_dst = xnew - k->x_hot; if (x_dst < k->x0) x_dst = k->x0; w1 = k->w - x_src; w2 = (k->x0 + k->w_scale + 1) - x_dst; w_overlap = (w2 > w1) ? w1 : w2; } /* Clear the krell stencil bitmap and draw the mask. */ gdk_draw_rectangle(k->stencil, _GK.bit0_GC, TRUE, 0,0, k->w, k->h_frame); if (k->mask) gdk_draw_drawable(k->stencil, _GK.bit1_GC, k->mask, x_src, y_src, x_dst, 0, w_overlap, k->h_frame); else gdk_draw_rectangle(k->stencil, _GK.bit1_GC, TRUE, x_dst, 0, w_overlap, k->h_frame); if (!k->modified) /* Preserve original old draw if there has been */ k->old_draw = k->draw; /* no intervening draw_panel_layers() */ k->draw.x_src = x_src; k->draw.y_src = y_src; k->draw.x_dst = x_dst; k->draw.y_dst = k->y0; k->draw.w = w_overlap; k->draw.h = k->h_frame; k->modified = TRUE; }voidgkrellm_decal_get_size(GkrellmDecal *d, gint *w, gint *h) { if (!d) return; if (w) *w = d->w; if (h) *h = d->h; }voidgkrellm_draw_decal_on_chart(GkrellmChart *cp, GkrellmDecal *d, gint xd, gint yd) { PangoLayout *layout; PangoRectangle ink; GList *list; GdkRectangle rect, *r; GkrellmTextstyle *ts; GkrellmText *tx; gint x, y, max; if (!cp || !d || d->state != DS_VISIBLE) return; d->x = xd; d->y = yd; if (d->text_list) { r = &d->ink; if (d->modified || d->chart_sequence_id != cp->bg_sequence_id) { gdk_draw_drawable(cp->bg_text_pixmap, _GK.draw1_GC, cp->bg_pixmap, d->x, d->y, d->x, d->y, d->w, d->h); layout = gtk_widget_create_pango_layout( gkrellm_get_top_window(), NULL); memset(r, 0, sizeof(GdkRectangle)); rect.x = d->x; rect.y = d->y; rect.width = d->w; rect.height = d->h; gdk_gc_set_clip_rectangle(_GK.text_GC, &rect); for (list = d->text_list; list; list = list->next) { tx = (GkrellmText *) list->data; ts = &tx->text_style; pango_layout_set_font_description(layout, ts->font); if (d->flags & DF_TEXT_USE_MARKUP) pango_layout_set_markup(layout, tx->text,strlen(tx->text)); else pango_layout_set_text(layout, tx->text, strlen(tx->text)); x = d->x + tx->x_off; y = d->y + tx->y_off; if (ts->effect) { gdk_gc_set_foreground(_GK.text_GC, &ts->shadow_color); gdk_draw_layout_with_colors(cp->bg_text_pixmap, _GK.text_GC, x + 1, y + 1, layout, &ts->shadow_color, NULL); } gdk_gc_set_foreground(_GK.text_GC, &ts->color); gdk_draw_layout(cp->bg_text_pixmap, _GK.text_GC, x, y, layout); pango_layout_get_pixel_extents(layout, &ink, NULL); if (r->x == 0 || ink.x + x < r->x) /* Shadow ??? */ r->x = ink.x + x; if (r->y == 0 || ink.y + y < r->y) r->y = ink.y + y; max = ink.x + x + ink.width; if (r->x + r->width < max) r->width = max - r->x; max = ink.y + y + ink.height; if (r->y + r->height < max) r->height = max - r->y; } gdk_gc_set_clip_rectangle(_GK.text_GC, NULL); g_object_unref(layout); d->chart_sequence_id = cp->bg_sequence_id; d->modified = FALSE; } gdk_draw_drawable(cp->pixmap, _GK.draw1_GC, cp->bg_text_pixmap, r->x, r->y, r->x, r->y, r->width, r->height); } else { gdk_gc_set_clip_mask(_GK.text_GC, d->stencil); gdk_gc_set_clip_origin(_GK.text_GC, xd, yd); gdk_draw_drawable(cp->pixmap, _GK.text_GC, d->pixmap, 0, d->y_src, xd, yd, d->w, d->h); gdk_gc_set_clip_mask(_GK.text_GC, NULL); gdk_gc_set_clip_origin(_GK.text_GC, 0, 0); } }voidgkrellm_draw_decal_pixmap(GkrellmPanel *p, GkrellmDecal *d, gint index) { gint y_src; if (!d) return; if (d->value != index) { /* Write the new decal mask onto the panel stencil */ y_src = index * d->h; d->y_src = y_src; if (d->mask) /* Can be NULL if no transparency */ gdk_draw_drawable(d->stencil, _GK.bit1_GC, d->mask, 0, y_src, 0, 0, d->w, d->h); else /* Fill decal extent with white */ gdk_draw_rectangle(d->stencil, _GK.bit1_GC, TRUE, 0, 0, d->w, d->h); d->modified = TRUE; } d->value = index; }static voiddecal_text_list_free(GList **text_list) { GList *list; if (!text_list || !*text_list) return; for (list = *text_list; list; list = list->next) g_free(((GkrellmText *) list->data)->text); gkrellm_free_glist_and_data(text_list); } /* Draw to first GkrellmText in text_list and truncate text_list to make | gkrellm_draw_decal_text() compatible with plugin code written before | the text_list implementation. For backwards compatibility, d->x_off | shadows the first tx->x_off. | Combining gkrellm_draw_decal_text() and gkrellm_decal_text_insert() | functions on the same decal may lead to unexpected results. */static voidgkrellm_draw_decal_internal(GkrellmPanel *p, GkrellmDecal *d, gchar *s, gint value) { GkrellmText *tx; GList *list; if (!s || !d || d->state == DS_INVISIBLE) return; if (!d->text_list) d->text_list = g_list_append(d->text_list, g_new0(GkrellmText, 1)); list = d->text_list; tx = (GkrellmText *) list->data; if ( gkrellm_dup_string(&tx->text, s) || tx->x_off_prev != d->x_off || tx->text_style.font != d->text_style.font || tx->text_style.color.pixel != d->text_style.color.pixel ) d->modified = TRUE; tx->x_off = d->x_off; tx->x_off_prev = d->x_off; tx->y_off = d->y_off - d->y_ink; tx->text_style = d->text_style; if (list->next) decal_text_list_free(&list->next); d->value = value; }voidgkrellm_draw_decal_text(GkrellmPanel *p, GkrellmDecal *d, gchar *s, gint value) { d->flags &= ~DF_TEXT_USE_MARKUP; /* In case mixing scroll_text and draw_decal_text calls */ d->flags &= ~DF_SCROLL_TEXT_DIVERTED; if (d->scroll_text) { g_free(d->scroll_text); d->scroll_text = NULL; } gkrellm_draw_decal_internal(p, d, s, value); }voidgkrellm_draw_decal_markup(GkrellmPanel *p, GkrellmDecal *d, gchar *s) { d->flags |= DF_TEXT_USE_MARKUP; /* In case mixing scroll_text and draw_decal_text calls */ d->flags &= ~DF_SCROLL_TEXT_DIVERTED; if (d->scroll_text) { g_free(d->scroll_text); d->scroll_text = NULL; } gkrellm_draw_decal_internal(p, d, s, 0); }voidgkrellm_decal_text_get_offset(GkrellmDecal *d, gint *x, gint *y) { if (!d) return; if (x) *x = d->x_off; if (y) *y = d->y_off; } /* Setting offset of text decal means setting offset of first GkrellmText | in text_list. For backwards compatibility with plugin code that | directly accesses d->x_off, shadow d->x_off to first tx->x_off. */voidgkrellm_decal_text_set_offset(GkrellmDecal *d, gint x, gint y) { GList *list; GkrellmText *tx; if (!d || (d->x_off == x && d->y_off == y)) return; d->x_off = x; d->y_off = y; if ((list = d->text_list) != NULL) { tx = (GkrellmText *) list->data; tx->x_off = x; tx->x_off_prev = x; tx->y_off = y - d->y_ink;; } d->modified = TRUE; }voidgkrellm_decal_text_clear(GkrellmDecal *d) { GList *list; GkrellmText *tx; if (!d || ((list = d->text_list) == NULL)) return; tx = (GkrellmText *) list->data; if (list->next) decal_text_list_free(&list->next); gkrellm_dup_string(&tx->text, ""); tx->text_style = d->text_style; if (d->scroll_text) g_free(d->scroll_text); d->scroll_text = NULL; d->modified = TRUE; } /* Insert text into a decal's text_list at a given offset. Using text | insert functions makes d->x_off and d->y_off meaningless since offsets | are in each GkrellmText's tx->x_off and tx->y_off. */voidgkrellm_decal_text_insert(GkrellmDecal *d, gchar *s, GkrellmTextstyle *ts, gint x_off, gint y_off) { GkrellmText *tx = NULL; if (!s || !d || d->state == DS_INVISIBLE) return; d->flags &= ~DF_TEXT_USE_MARKUP; if (!ts) ts = &d->text_style; if ( d->text_list && !*((GkrellmText *) d->text_list->data)->text ) tx = (GkrellmText *) d->text_list->data; if (!tx) { tx = g_new0(GkrellmText, 1); d->text_list = g_list_append(d->text_list, tx); } gkrellm_dup_string(&tx->text, s); tx->x_off = x_off; tx->x_off_prev = x_off; tx->y_off = y_off - d->y_ink; tx->text_style = *ts; d->modified = TRUE; }voidgkrellm_decal_text_markup_insert(GkrellmDecal *d, gchar *s, GkrellmTextstyle *ts, gint x_off, gint y_off) { GkrellmText *tx = NULL; if (!s || !d || d->state == DS_INVISIBLE) return; d->flags |= DF_TEXT_USE_MARKUP; if (!ts) ts = &d->text_style; if ( d->text_list && !*((GkrellmText *) d->text_list->data)->text ) tx = (GkrellmText *) d->text_list->data; if (!tx) { tx = g_new0(GkrellmText, 1); d->text_list = g_list_append(d->text_list, tx); } gkrellm_dup_string(&tx->text, s); tx->x_off = x_off; tx->x_off_prev = x_off; tx->y_off = y_off - d->y_ink; tx->text_style = *ts; d->modified = TRUE; }voidgkrellm_decal_text_nth_inserted_set_offset(GkrellmDecal *d, gint n, gint x, gint y) { GList *list; GkrellmText *tx; if (!d || (list = g_list_nth(d->text_list, n)) == NULL) return; tx = (GkrellmText *) list->data; if (tx->x_off != x || tx->y_off != y) { tx->x_off = x; tx->x_off_prev = x; tx->y_off = y - d->y_ink;; d->modified = TRUE; } }voidgkrellm_decal_text_nth_inserted_get_offset(GkrellmDecal *d, gint n, gint *x, gint *y) { GList *list; GkrellmText *tx; if (!d || (list = g_list_nth(d->text_list, n)) == NULL) return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -