📄 krell.c
字号:
tx = (GkrellmText *) list->data; if (x) *x = tx->x_off; if (y) *y = tx->y_off + d->y_ink; }voidgkrellm_decal_scroll_text_align_center(GkrellmDecal *d, gboolean center) { gint prev_center; if (!d) return; prev_center = d->flags & DF_SCROLL_TEXT_CENTER; if ((center && prev_center) || (!center && !prev_center)) return; if (center) d->flags |= DF_SCROLL_TEXT_CENTER; else d->flags &= ~DF_SCROLL_TEXT_CENTER; d->modified = TRUE; }voidgkrellm_decal_scroll_text_horizontal_loop(GkrellmDecal *d, gboolean loop) { gint prev_loop; if (!d) return; prev_loop = d->flags & DF_SCROLL_TEXT_H_LOOP; if ((loop && prev_loop) || (!loop && !prev_loop)) return; if (loop) d->flags |= DF_SCROLL_TEXT_H_LOOP; else d->flags &= ~DF_SCROLL_TEXT_H_LOOP; d->modified = TRUE; }voidgkrellm_decal_scroll_text_vertical_loop(GkrellmDecal *d, gboolean loop) { gint prev_loop; if (!d) return; prev_loop = d->flags & DF_SCROLL_TEXT_V_LOOP; if ((loop && prev_loop) || (!loop && !prev_loop)) return; if (loop) d->flags |= DF_SCROLL_TEXT_V_LOOP; else d->flags &= ~DF_SCROLL_TEXT_V_LOOP; d->modified = TRUE; }voidgkrellm_decal_scroll_text_get_size(GkrellmDecal *d, gint *w, gint *h) { if (!d) return; if (w) *w = d->scroll_width; if (h) *h = d->scroll_height + ((d->flags & DF_SCROLL_TEXT_V_LOOP) ? d->y_ink : 0); }static PangoLayout *decal_scroll_text_layout(GkrellmDecal *d, gchar *text, gint *yink) { PangoLayout *layout; PangoRectangle ink, logical; GkrellmTextstyle *ts; gint y_ink; ts = &d->text_style; layout = gtk_widget_create_pango_layout(gkrellm_get_top_window(), NULL); pango_layout_set_spacing(layout, 0); if (d->flags & DF_SCROLL_TEXT_CENTER) pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER); pango_layout_set_font_description(layout, ts->font); if (d->flags & DF_TEXT_USE_MARKUP) pango_layout_set_markup(layout, text, strlen(text)); else pango_layout_set_text(layout, text, strlen(text)); pango_layout_get_pixel_extents(layout, &ink, &logical); d->scroll_width = logical.width + ts->effect; /* incl trailing spaces */ d->scroll_height = ink.height + ts->effect; y_ink = ink.y - logical.y; /* y_ink change can happen if markup up text sizes differently from sizing | at decal creation. Adjust the decal y_ink so text doesn't get bumped | upward which clips top of text string. This means the decal height | should probably also be changed because now descenders might get | clipped when switching back out of scrolling. | But this is much less noticeable... later. */ if (d->y_ink > y_ink) d->y_ink = y_ink; if (yink) *yink = y_ink; return layout; } /* If mixing draw_decal_text and scroll_text calls, must reset decal regions | in bg_text_layer_pixmap to bg_pixmap at first switch to scroll_text calls. */static voidreset_text_layer_pixmap_decal_region(GkrellmPanel *p, GkrellmDecal *d) { if (d->flags & DF_MOVED) { gdk_draw_drawable(p->bg_text_layer_pixmap, _GK.draw1_GC, p->bg_pixmap, d->x_old, d->y_old, d->x_old, d->y_old, d->w, d->h); d->flags &= ~DF_MOVED; } else gdk_draw_drawable(p->bg_text_layer_pixmap, _GK.draw1_GC, p->bg_pixmap, d->x, d->y, d->x, d->y, d->w, d->h); } /* Draw Pango rendered text onto a pixmap which can be scrolled across | a decal's extents. So when scrolling, a slow Pango redraw at each scroll | step can be avoided if the text string has not changed. | There are a couple of limitations because it's impossible to generate a | stencil bitmask of Pango rendered text (Pango doesn't allow writting to | depth 1 and it looks at the background pixmap colors as it renders): | 1) A scroll text decal is not transparent and will hide any objects | underneath it, so when this condition is detected, scroll drawing | is diverted to Pango at each step gkrellm_draw_decal_text(). | 2) The scroll text must be rendered onto a background which for many | themes won't exactly blend with the panel background as the scroll | pixmap is scrolled. It should be at worst only slightly noticeable | for most themes, but might be a problem for themes with high gradient | panel backgrounds. */static voidgkrellm_decal_scroll_text_set_internal(GkrellmPanel *p, GkrellmDecal *d, gchar *text) { GtkWidget *top_win = gkrellm_get_top_window(); PangoLayout *layout; GdkPixbuf *pixbuf; GList *list; GkrellmDecal *dcheck; GkrellmBorder *b; GkrellmTextstyle *ts; gint dx, y_ink; gboolean new_text, no_scroll_caching, first_scroll; if (!p || !text || !d || d->state == DS_INVISIBLE) return; first_scroll = (d->scroll_text == NULL); new_text = gkrellm_dup_string(&d->scroll_text, text); no_scroll_caching = (p->transparency || p->scroll_text_cache_off); for (list = p->decal_list; list; list = list->next) { dcheck = (GkrellmDecal *) list->data; /* Scroll text underneath is OK */ if (dcheck == d && !no_scroll_caching) break; /* But scroll text overlapping and on top of any other decal requires | scroll text to be pushed. */ if ( no_scroll_caching || ( d->x + d->w > dcheck->x && d->x < dcheck->x + dcheck->w && d->y + d->h > dcheck->y && d->y < dcheck->y + dcheck->h ) ) { if (first_scroll && d->text_list) reset_text_layer_pixmap_decal_region(p, d); d->flags |= (DF_TEXT_OVERLAPS | DF_SCROLL_TEXT_DIVERTED); if (new_text) { layout = decal_scroll_text_layout(d, text, NULL); g_object_unref(G_OBJECT(layout)); } gkrellm_draw_decal_internal(p, d, text, -1); return; } } if (d->text_list) /* Erase any previous gkrellm_draw_decal_text() */ { reset_text_layer_pixmap_decal_region(p, d); decal_text_list_free(&d->text_list); d->value = -1; } d->modified = TRUE; if (!new_text && !(d->flags & DF_SCROLL_TEXT_DIVERTED)) return; layout = decal_scroll_text_layout(d, text, &y_ink); gkrellm_free_pixmap(&d->pixmap); d->pixmap = gdk_pixmap_new(top_win->window, d->scroll_width, d->scroll_height, -1); if (!d->pixmap) /* too wide maybe? */ { d->flags |= (DF_TEXT_OVERLAPS | DF_SCROLL_TEXT_DIVERTED); g_object_unref(G_OBJECT(layout)); gkrellm_draw_decal_text(p, d, text, -1); return; } d->flags &= ~(DF_TEXT_OVERLAPS | DF_SCROLL_TEXT_DIVERTED); dx = d->w - d->scroll_width; if (dx >= 0) pixbuf = gdk_pixbuf_get_from_drawable(NULL, p->bg_pixmap, NULL, d->x + ((d->flags & DF_SCROLL_TEXT_CENTER) ? dx / 2 : 0), d->y, 0, 0, d->scroll_width, d->h); else { gint xfudge, yfudge; /* Many themes have sloppy margins XXX */ xfudge = d->w > 20 ? d->w / 6 : 0; /* and gradient compensate a bit */ yfudge = d->h > 5 ? d->h / 5 : 0; pixbuf = gdk_pixbuf_get_from_drawable(NULL, p->bg_pixmap, NULL, d->x + xfudge, d->y + yfudge, 0, 0, d->w - 2 * xfudge, d->h - 2 * yfudge); } if (pixbuf) { gkrellm_paste_pixbuf(pixbuf, d->pixmap, 0, 0, d->scroll_width, d->scroll_height); g_object_unref(G_OBJECT(pixbuf)); } else { b = &p->bg_piximage->border; gkrellm_paste_pixbuf(p->bg_piximage->pixbuf, d->pixmap, b->left, b->top, d->scroll_width + b->left + b->right, d->scroll_height + b->top + b->bottom); /* XXX */ } ts = &d->text_style; if (ts->effect) { gdk_gc_set_foreground(_GK.text_GC, &ts->shadow_color); gdk_draw_layout_with_colors(d->pixmap, _GK.text_GC, 1, -y_ink + 1, layout, &ts->shadow_color, NULL); } gdk_gc_set_foreground(_GK.text_GC, &ts->color); gdk_draw_layout(d->pixmap, _GK.text_GC, 0, -y_ink, layout); g_object_unref(G_OBJECT(layout)); }voidgkrellm_decal_scroll_text_set_markup(GkrellmPanel *p, GkrellmDecal *d, gchar *text) { d->flags |= DF_TEXT_USE_MARKUP; gkrellm_decal_scroll_text_set_internal(p, d, text); }voidgkrellm_decal_scroll_text_set_text(GkrellmPanel *p, GkrellmDecal *d, gchar *text) { d->flags &= ~DF_TEXT_USE_MARKUP; gkrellm_decal_scroll_text_set_internal(p, d, text); }voidgkrellm_move_krell_yoff(GkrellmPanel *p, GkrellmKrell *k, gint y) { if (!k) return; if (!k->modified) k->old_draw = k->draw; k->y0 = k->draw.y_dst = y; k->modified = TRUE; }static void_destroy_krell(GkrellmKrell *k) { if (!k) return; gkrellm_free_bitmap(&k->stencil); gkrellm_free_pixmap(&k->pixmap); gkrellm_free_bitmap(&k->mask); g_free(k); }voidgkrellm_destroy_krell(GkrellmKrell *k) { if (!k) return; gkrellm_remove_krell((GkrellmPanel *) k->panel, k); _destroy_krell(k); }voidgkrellm_remove_krell(GkrellmPanel *p, GkrellmKrell *k) { GkrellmDrawrec *dr; if (!k || !k->panel || !p || !g_list_find(p->krell_list, k)) return; p->krell_list = g_list_remove(p->krell_list, k); k->panel = NULL; dr = &k->draw; if (p->pixmap && p->bg_pixmap) { gdk_draw_drawable(p->pixmap, _GK.draw1_GC, p->bg_pixmap, dr->x_dst, dr->y_dst, dr->x_dst, dr->y_dst, dr->w, dr->h); if (p->drawing_area && p->drawing_area->window) gdk_draw_drawable(p->drawing_area->window, _GK.draw1_GC, p->bg_pixmap, dr->x_dst, dr->y_dst, dr->x_dst, dr->y_dst, dr->w, dr->h); gkrellm_draw_panel_layers_force(p); } }voidgkrellm_insert_krell(GkrellmPanel *p, GkrellmKrell *k, gboolean append) { if (!k || k->panel || !p || g_list_find(p->krell_list, k)) return; if (append) p->krell_list = g_list_append(p->krell_list, k); else p->krell_list = g_list_prepend(p->krell_list, k); k->panel = (GkrellmPanel *) p; gkrellm_draw_panel_layers_force(p); }voidgkrellm_insert_krell_nth(GkrellmPanel *p, GkrellmKrell *k, gint n) { if (!p || !k || g_list_find(p->krell_list, k)) return; p->krell_list = g_list_insert(p->krell_list, k, n); k->panel = (GkrellmPanel *) p; gkrellm_draw_panel_layers_force(p); }voidgkrellm_destroy_krell_list(GkrellmPanel *p) { GList *list; if (!p) return; for (list = p->krell_list; list; list = list->next) _destroy_krell((GkrellmKrell *) list->data); if (p->krell_list) g_list_free(p->krell_list); p->krell_list = NULL; }voidgkrellm_set_krell_margins(GkrellmPanel *p, GkrellmKrell *k, gint left, gint right) { if (!k) return; if (left > _GK.chart_width - 3) left = _GK.chart_width - 3; k->x0 = left; k->w_scale = _GK.chart_width - k->x0 - right - 1; if (k->w_scale < 2) k->w_scale = 2; if (p && p->pixmap && p->bg_pixmap) { /* Move the krell proportionally between the new limits */ k->x_position = -1; if (k->monotonic) k->previous -= k->value; gkrellm_update_krell(p, k, k->value); gkrellm_draw_panel_layers_force(p); } }voidgkrellm_set_krell_full_scale(GkrellmKrell *k, gint full_scale, gint expand) { if (!k) return; k->full_scale_expand = (expand <= 0 ) ? 1 : expand; k->full_scale = full_scale * k->full_scale_expand; } GkrellmKrell *gkrellm_create_krell(GkrellmPanel *p, GkrellmPiximage *im, GkrellmStyle *style) { GtkWidget *top_win = gkrellm_get_top_window(); GkrellmKrell *k; gint w, h, h_render, w_render; k = (GkrellmKrell *) g_new0(GkrellmKrell, 1); if (p) p->krell_list = g_list_append(p->krell_list, k); k->panel = (gpointer) p; k->bar_mode = k->flags = 0; if (im == NULL || style == NULL) { printf(_("create_krell: NULL image or style\n")); exit(0); } /* Set left krell margin */ k->x0 = style->krell_left_margin; if (k->x0 > _GK.chart_width - 3) k->x0 = _GK.chart_width - 3; /* Set right krell margin via w_scale (-1 adjust to keep x_hot visible */ k->w_scale = _GK.chart_width - k->x0 - style->krell_right_margin - 1; if (k->w_scale < 2) k->w_scale = 2; /* krell_yoff values: >= 0, put krell at krell_yoff in the panel. | == -1 put krell inside of margins at top margin. | == -2 put krell at bottom of panel | == -3 put krell inside of margins at bottom margin. | For anything else, caller must gkrellm_krell_move_yoff() after create. | Inside of top margin handled here, but panel configure must handle | bottom of panel adjustments. */ k->y0 = style->krell_yoff; if (k->y0 > 0 && !style->krell_yoff_not_scalable ) k->y0 = k->y0 * _GK.theme_scale / 100; if (k->y0 == -1 || k->y0 == -3) k->flags |= KRELL_FLAG_BOTTOM_MARGIN; if (k->y0 == -1) gkrellm_get_top_bottom_margins(style, &k->y0, NULL); w = gdk_pixbuf_get_width(im->pixbuf); h = gdk_pixbuf_get_height(im->pixbuf); if (style->krell_x_hot < 0) style->krell_x_hot = w / 2; w_render = w * _GK.theme_scale / 100; k->x_hot = style->krell_x_hot * _GK.theme_scale / 100; switch (style->krell_expand) { case KRELL_EXPAND_NONE: break; case KRELL_EXPAND_BAR_MODE: w_render = _GK.chart_width; k->bar_mode = KRELL_EXPAND_BAR_MODE; break; case KRELL_EXPAND_BAR_MODE_SCALED: w_render = k->w_scale + 1; /* undo -1 from w_scale calc */ k->bar_mode = KRELL_EXPAND_BAR_MODE_SCALED; break; case KRELL_EXPAND_LEFT: if (style->krell_x_hot > 0 && style->krell_x_hot < w) { w_render = _GK.chart_width * w / style->krell_x_hot; k->x_hot = _GK.chart_width - 1; } break; case KRELL_EXPAND_LEFT_SCALED: if (style->krell_x_hot > 0 && style->krell_x_hot < w) { w_render = (k->w_scale + 1) * w / style->krell_x_hot; k->x_hot = k->w_scale; } break; case KRELL_EXPAND_RIGHT: if (w > style->krell_x_hot) { w_render = _GK.chart_width * w / (w - style->krell_x_hot); k->x_hot = style->krell_x_hot * w_render / w; } break; case KRELL_EXPAND_RIGHT_SCALED: if (w > style->krell_x_hot) { w_render = (k->w_scale + 1) * w / (w - style->krell_x_hot); k->x_hot = style->krell_x_hot * w_render / w; } break; } k->depth = style->krell_depth; if (k->depth < 1) k->depth = 1; k->h_frame = h / k->depth * _GK.theme_scale / 100; if (k->h_frame < 1) k->h_frame = 1; h_render = k->h_frame * k->depth; gkrellm_scale_piximage_to_pixmap(im, &k->pixmap, &k->mask, w_render, h_render); k->h = h_render;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -