2 Copyright (C) 2003-2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 #include <gdkmm/rectangle.h>
31 #include <gtkmm2ext/fastmeter.h>
32 #include <gtkmm2ext/utils.h>
34 #define UINT_TO_RGB(u,r,g,b) { (*(r)) = ((u)>>16)&0xff; (*(g)) = ((u)>>8)&0xff; (*(b)) = (u)&0xff; }
35 #define UINT_TO_RGBA(u,r,g,b,a) { UINT_TO_RGB(((u)>>8),r,g,b); (*(a)) = (u)&0xff; }
39 using namespace Gtkmm2ext;
42 int FastMeter::min_pattern_metric_size = 16;
43 int FastMeter::max_pattern_metric_size = 1024;
44 bool FastMeter::no_rgba_overlay = false;
46 FastMeter::Pattern10Map FastMeter::vm_pattern_cache;
47 FastMeter::PatternBgMap FastMeter::vb_pattern_cache;
49 FastMeter::Pattern10Map FastMeter::hm_pattern_cache;
50 FastMeter::PatternBgMap FastMeter::hb_pattern_cache;
52 FastMeter::FastMeter (long hold, unsigned long dimen, Orientation o, int len,
53 int clr0, int clr1, int clr2, int clr3,
54 int clr4, int clr5, int clr6, int clr7,
58 float stp0, float stp1,
59 float stp2, float stp3,
64 , _styleflags(styleflags)
73 last_peak_rect.width = 0;
74 last_peak_rect.height = 0;
78 no_rgba_overlay = ! Glib::getenv("NO_METER_SHADE").empty();
102 set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
110 if (orientation == Vertical) {
113 fgpattern = request_vertical_meter(pixwidth + 2, pixheight + 2, _clr, _stp, _styleflags);
114 bgpattern = request_vertical_background (pixwidth + 2, pixheight + 2, _bgc, false);
119 fgpattern = request_horizontal_meter(pixwidth + 2, pixheight + 2, _clr, _stp, _styleflags);
120 bgpattern = request_horizontal_background (pixwidth + 2, pixheight + 2, _bgc, false);
123 pixrect.width = pixwidth;
124 pixrect.height = pixheight;
126 request_width = pixrect.width + 2;
127 request_height= pixrect.height + 2;
132 FastMeter::~FastMeter ()
136 Cairo::RefPtr<Cairo::Pattern>
137 FastMeter::generate_meter_pattern (
138 int width, int height, int *clr, float *stp, int styleflags, bool horiz)
142 const double soft = 3.0 / (double) height;
143 const double offs = -1.0 / (double) height;
145 cairo_pattern_t* pat = cairo_pattern_create_linear (0.0, 0.0, 0.0, height);
148 Cairo coordinate space goes downwards as y value goes up, so invert
149 knee-based positions by using (1.0 - y)
152 UINT_TO_RGBA (clr[9], &r, &g, &b, &a); // top/clip
153 cairo_pattern_add_color_stop_rgb (pat, 0.0,
154 r/255.0, g/255.0, b/255.0);
156 knee = offs + stp[3] / 115.0f; // -0dB
158 UINT_TO_RGBA (clr[8], &r, &g, &b, &a);
159 cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee,
160 r/255.0, g/255.0, b/255.0);
162 UINT_TO_RGBA (clr[7], &r, &g, &b, &a);
163 cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee + soft,
164 r/255.0, g/255.0, b/255.0);
166 knee = offs + stp[2]/ 115.0f; // -3dB || -2dB
168 UINT_TO_RGBA (clr[6], &r, &g, &b, &a);
169 cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee,
170 r/255.0, g/255.0, b/255.0);
172 UINT_TO_RGBA (clr[5], &r, &g, &b, &a);
173 cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee + soft,
174 r/255.0, g/255.0, b/255.0);
176 knee = offs + stp[1] / 115.0f; // -9dB
178 UINT_TO_RGBA (clr[4], &r, &g, &b, &a);
179 cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee,
180 r/255.0, g/255.0, b/255.0);
182 UINT_TO_RGBA (clr[3], &r, &g, &b, &a);
183 cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee + soft,
184 r/255.0, g/255.0, b/255.0);
186 knee = offs + stp[0] / 115.0f; // -18dB
188 UINT_TO_RGBA (clr[2], &r, &g, &b, &a);
189 cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee,
190 r/255.0, g/255.0, b/255.0);
192 UINT_TO_RGBA (clr[1], &r, &g, &b, &a);
193 cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee + soft,
194 r/255.0, g/255.0, b/255.0);
196 UINT_TO_RGBA (clr[0], &r, &g, &b, &a); // bottom
197 cairo_pattern_add_color_stop_rgb (pat, 1.0,
198 r/255.0, g/255.0, b/255.0);
200 if ((styleflags & 1) && !no_rgba_overlay) {
201 cairo_pattern_t* shade_pattern = cairo_pattern_create_linear (0.0, 0.0, width, 0.0);
202 cairo_pattern_add_color_stop_rgba (shade_pattern, 0, 0.0, 0.0, 0.0, 0.15);
203 cairo_pattern_add_color_stop_rgba (shade_pattern, 0.4, 1.0, 1.0, 1.0, 0.05);
204 cairo_pattern_add_color_stop_rgba (shade_pattern, 1, 0.0, 0.0, 0.0, 0.25);
206 cairo_surface_t* surface;
208 surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
209 tc = cairo_create (surface);
210 cairo_set_source (tc, pat);
211 cairo_rectangle (tc, 0, 0, width, height);
213 cairo_pattern_destroy (pat);
215 cairo_set_source (tc, shade_pattern);
216 cairo_rectangle (tc, 0, 0, width, height);
218 cairo_pattern_destroy (shade_pattern);
220 if (styleflags & 2) { // LED stripes
222 cairo_set_line_width(tc, 1.0);
223 cairo_set_source_rgba(tc, .0, .0, .0, 0.4);
224 //cairo_set_operator (tc, CAIRO_OPERATOR_SOURCE);
225 for (float y=0.5; y < height; y+= 2.0) {
226 cairo_move_to(tc, 0, y);
227 cairo_line_to(tc, width, y);
233 pat = cairo_pattern_create_for_surface (surface);
235 cairo_surface_destroy (surface);
239 cairo_surface_t* surface;
241 surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, height, width);
242 tc = cairo_create (surface);
245 cairo_matrix_init_rotate (&m, -M_PI/2.0);
246 cairo_matrix_translate (&m, -height, 0);
247 cairo_pattern_set_matrix (pat, &m);
248 cairo_set_source (tc, pat);
249 cairo_rectangle (tc, 0, 0, height, width);
251 cairo_pattern_destroy (pat);
252 pat = cairo_pattern_create_for_surface (surface);
254 cairo_surface_destroy (surface);
256 Cairo::RefPtr<Cairo::Pattern> p (new Cairo::Pattern (pat, false));
262 Cairo::RefPtr<Cairo::Pattern>
263 FastMeter::generate_meter_background (
264 int width, int height, int *clr, bool shade, bool horiz)
266 guint8 r0,g0,b0,r1,g1,b1,a;
268 cairo_pattern_t* pat = cairo_pattern_create_linear (0.0, 0.0, 0.0, height);
270 UINT_TO_RGBA (clr[0], &r0, &g0, &b0, &a);
271 UINT_TO_RGBA (clr[1], &r1, &g1, &b1, &a);
273 cairo_pattern_add_color_stop_rgb (pat, 0.0,
274 r1/255.0, g1/255.0, b1/255.0);
276 cairo_pattern_add_color_stop_rgb (pat, 1.0,
277 r0/255.0, g0/255.0, b0/255.0);
279 if (shade && !no_rgba_overlay) {
280 cairo_pattern_t* shade_pattern = cairo_pattern_create_linear (0.0, 0.0, width, 0.0);
281 cairo_pattern_add_color_stop_rgba (shade_pattern, 0.0, 1.0, 1.0, 1.0, 0.15);
282 cairo_pattern_add_color_stop_rgba (shade_pattern, 0.6, 0.0, 0.0, 0.0, 0.10);
283 cairo_pattern_add_color_stop_rgba (shade_pattern, 1.0, 1.0, 1.0, 1.0, 0.20);
285 cairo_surface_t* surface;
287 surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
288 tc = cairo_create (surface);
289 cairo_set_source (tc, pat);
290 cairo_rectangle (tc, 0, 0, width, height);
292 cairo_set_source (tc, shade_pattern);
293 cairo_rectangle (tc, 0, 0, width, height);
296 cairo_pattern_destroy (pat);
297 cairo_pattern_destroy (shade_pattern);
299 pat = cairo_pattern_create_for_surface (surface);
302 cairo_surface_destroy (surface);
306 cairo_surface_t* surface;
308 surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, height, width);
309 tc = cairo_create (surface);
312 cairo_matrix_init_rotate (&m, -M_PI/2.0);
313 cairo_matrix_translate (&m, -height, 0);
314 cairo_pattern_set_matrix (pat, &m);
315 cairo_set_source (tc, pat);
316 cairo_rectangle (tc, 0, 0, height, width);
318 cairo_pattern_destroy (pat);
319 pat = cairo_pattern_create_for_surface (surface);
321 cairo_surface_destroy (surface);
324 Cairo::RefPtr<Cairo::Pattern> p (new Cairo::Pattern (pat, false));
329 Cairo::RefPtr<Cairo::Pattern>
330 FastMeter::request_vertical_meter(
331 int width, int height, int *clr, float *stp, int styleflags)
333 height = max(height, min_pattern_metric_size);
334 height = min(height, max_pattern_metric_size);
336 const Pattern10MapKey key (width, height,
337 stp[0], stp[1], stp[2], stp[3],
338 clr[0], clr[1], clr[2], clr[3],
339 clr[4], clr[5], clr[6], clr[7],
340 clr[8], clr[9], styleflags);
342 Pattern10Map::iterator i;
343 if ((i = vm_pattern_cache.find (key)) != vm_pattern_cache.end()) {
346 // TODO flush pattern cache if it gets too large
348 Cairo::RefPtr<Cairo::Pattern> p = generate_meter_pattern (
349 width, height, clr, stp, styleflags, false);
350 vm_pattern_cache[key] = p;
355 Cairo::RefPtr<Cairo::Pattern>
356 FastMeter::request_vertical_background(
357 int width, int height, int *bgc, bool shade)
359 height = max(height, min_pattern_metric_size);
360 height = min(height, max_pattern_metric_size);
363 const PatternBgMapKey key (width, height, bgc[0], bgc[1], shade);
364 PatternBgMap::iterator i;
365 if ((i = vb_pattern_cache.find (key)) != vb_pattern_cache.end()) {
368 // TODO flush pattern cache if it gets too large
370 Cairo::RefPtr<Cairo::Pattern> p = generate_meter_background (
371 width, height, bgc, shade, false);
372 vb_pattern_cache[key] = p;
377 Cairo::RefPtr<Cairo::Pattern>
378 FastMeter::request_horizontal_meter(
379 int width, int height, int *clr, float *stp, int styleflags)
381 width = max(width, min_pattern_metric_size);
382 width = min(width, max_pattern_metric_size);
384 const Pattern10MapKey key (width, height,
385 stp[0], stp[1], stp[2], stp[3],
386 clr[0], clr[1], clr[2], clr[3],
387 clr[4], clr[5], clr[6], clr[7],
388 clr[8], clr[9], styleflags);
390 Pattern10Map::iterator i;
391 if ((i = hm_pattern_cache.find (key)) != hm_pattern_cache.end()) {
394 // TODO flush pattern cache if it gets too large
396 Cairo::RefPtr<Cairo::Pattern> p = generate_meter_pattern (
397 height, width, clr, stp, styleflags, true);
399 hm_pattern_cache[key] = p;
403 Cairo::RefPtr<Cairo::Pattern>
404 FastMeter::request_horizontal_background(
405 int width, int height, int *bgc, bool shade)
407 width = max(width, min_pattern_metric_size);
408 width = min(width, max_pattern_metric_size);
411 const PatternBgMapKey key (width, height, bgc[0], bgc[1], shade);
412 PatternBgMap::iterator i;
413 if ((i = hb_pattern_cache.find (key)) != hb_pattern_cache.end()) {
416 // TODO flush pattern cache if it gets too large
418 Cairo::RefPtr<Cairo::Pattern> p = generate_meter_background (
419 height, width, bgc, shade, true);
421 hb_pattern_cache[key] = p;
429 FastMeter::set_hold_count (long val)
443 FastMeter::on_size_request (GtkRequisition* req)
445 if (orientation == Vertical) {
446 vertical_size_request (req);
448 horizontal_size_request (req);
453 FastMeter::vertical_size_request (GtkRequisition* req)
455 req->height = request_height;
456 req->height = max(req->height, min_pattern_metric_size);
457 req->height = min(req->height, max_pattern_metric_size);
460 req->width = request_width;
464 FastMeter::horizontal_size_request (GtkRequisition* req)
466 req->width = request_width;
467 req->width = max(req->width, min_pattern_metric_size);
468 req->width = min(req->width, max_pattern_metric_size);
471 req->height = request_height;
475 FastMeter::on_size_allocate (Gtk::Allocation &alloc)
477 if (orientation == Vertical) {
478 vertical_size_allocate (alloc);
480 horizontal_size_allocate (alloc);
486 FastMeter::vertical_size_allocate (Gtk::Allocation &alloc)
488 if (alloc.get_width() != request_width) {
489 alloc.set_width (request_width);
492 int h = alloc.get_height();
493 h = max (h, min_pattern_metric_size + 2);
494 h = min (h, max_pattern_metric_size + 2);
496 if (h != alloc.get_height()) {
497 alloc.set_height (h);
500 if (pixheight != h) {
501 fgpattern = request_vertical_meter (request_width, h, _clr, _stp, _styleflags);
502 bgpattern = request_vertical_background (request_width, h, highlight ? _bgh : _bgc, highlight);
504 pixwidth = request_width - 2;
507 CairoWidget::on_size_allocate (alloc);
511 FastMeter::horizontal_size_allocate (Gtk::Allocation &alloc)
513 if (alloc.get_height() != request_height) {
514 alloc.set_height (request_height);
517 int w = alloc.get_width();
518 w = max (w, min_pattern_metric_size + 2);
519 w = min (w, max_pattern_metric_size + 2);
521 if (w != alloc.get_width()) {
526 fgpattern = request_horizontal_meter (w, request_height, _clr, _stp, _styleflags);
527 bgpattern = request_horizontal_background (w, request_height, highlight ? _bgh : _bgc, highlight);
529 pixheight = request_height - 2;
532 CairoWidget::on_size_allocate (alloc);
536 FastMeter::render (cairo_t* cr, cairo_rectangle_t* area)
538 if (orientation == Vertical) {
539 return vertical_expose (cr, area);
541 return horizontal_expose (cr, area);
546 FastMeter::vertical_expose (cairo_t* cr, cairo_rectangle_t* area)
549 GdkRectangle intersection;
550 GdkRectangle background;
551 GdkRectangle eventarea;
553 cairo_set_source_rgb (cr, 0, 0, 0); // black
554 rounded_rectangle (cr, 0, 0, pixwidth + 2, pixheight + 2, 2);
557 top_of_meter = (gint) floor (pixheight * current_level);
559 /* reset the height & origin of the rect that needs to show the pixbuf
562 pixrect.height = top_of_meter;
563 pixrect.y = 1 + pixheight - top_of_meter;
567 background.width = pixrect.width;
568 background.height = pixheight - top_of_meter;
570 eventarea.x = area->x;
571 eventarea.y = area->y;
572 eventarea.width = area->width;
573 eventarea.height = area->height;
575 if (gdk_rectangle_intersect (&background, &eventarea, &intersection)) {
576 cairo_set_source (cr, bgpattern->cobj());
577 cairo_rectangle (cr, intersection.x, intersection.y, intersection.width, intersection.height);
581 if (gdk_rectangle_intersect (&pixrect, &eventarea, &intersection)) {
582 // draw the part of the meter image that we need. the area we draw is bounded "in reverse" (top->bottom)
583 cairo_set_source (cr, fgpattern->cobj());
584 cairo_rectangle (cr, intersection.x, intersection.y, intersection.width, intersection.height);
591 last_peak_rect.x = 1;
592 last_peak_rect.width = pixwidth;
593 last_peak_rect.y = max(1, 1 + pixheight - (int) floor (pixheight * current_peak));
594 if (_styleflags & 2) { // LED stripes
595 last_peak_rect.y = max(0, (last_peak_rect.y & (~1)));
597 if (bright_hold || (_styleflags & 2)) {
598 last_peak_rect.height = max(0, min(3, pixheight - last_peak_rect.y - 1 ));
600 last_peak_rect.height = max(0, min(2, pixheight - last_peak_rect.y - 1 ));
603 cairo_set_source (cr, fgpattern->cobj());
604 cairo_rectangle (cr, last_peak_rect.x, last_peak_rect.y, last_peak_rect.width, last_peak_rect.height);
606 if (bright_hold && !no_rgba_overlay) {
607 cairo_fill_preserve (cr);
608 cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.3);
613 last_peak_rect.width = 0;
614 last_peak_rect.height = 0;
619 FastMeter::horizontal_expose (cairo_t* cr, cairo_rectangle_t* area)
622 GdkRectangle intersection;
623 GdkRectangle background;
624 GdkRectangle eventarea;
626 cairo_set_source_rgb (cr, 0, 0, 0); // black
627 rounded_rectangle (cr, 0, 0, pixwidth + 2, pixheight + 2, 2);
630 right_of_meter = (gint) floor (pixwidth * current_level);
632 /* reset the height & origin of the rect that needs to show the pixbuf
635 pixrect.width = right_of_meter;
637 background.x = 1 + right_of_meter;
639 background.width = pixwidth - right_of_meter;
640 background.height = pixheight;
642 eventarea.x = area->x;
643 eventarea.y = area->y;
644 eventarea.width = area->width;
645 eventarea.height = area->height;
647 if (gdk_rectangle_intersect (&background, &eventarea, &intersection)) {
648 cairo_set_source (cr, bgpattern->cobj());
649 cairo_rectangle (cr, intersection.x, intersection.y, intersection.width, intersection.height);
653 if (gdk_rectangle_intersect (&pixrect, &eventarea, &intersection)) {
654 cairo_set_source (cr, fgpattern->cobj());
655 cairo_rectangle (cr, intersection.x, intersection.y, intersection.width, intersection.height);
662 last_peak_rect.y = 1;
663 last_peak_rect.height = pixheight;
664 const int xpos = floor (pixwidth * current_peak);
665 if (bright_hold || (_styleflags & 2)) {
666 last_peak_rect.width = min(3, xpos );
668 last_peak_rect.width = min(2, xpos );
670 last_peak_rect.x = 1 + max(0, xpos - last_peak_rect.width);
672 cairo_set_source (cr, fgpattern->cobj());
673 cairo_rectangle (cr, last_peak_rect.x, last_peak_rect.y, last_peak_rect.width, last_peak_rect.height);
675 if (bright_hold && !no_rgba_overlay) {
676 cairo_fill_preserve (cr);
677 cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.3);
682 last_peak_rect.width = 0;
683 last_peak_rect.height = 0;
688 FastMeter::set (float lvl, float peak)
690 float old_level = current_level;
691 float old_peak = current_peak;
693 if (pixwidth <= 0 || pixheight <=0) return;
696 if (lvl >= current_peak) {
698 hold_state = hold_cnt;
701 if (hold_state > 0) {
702 if (--hold_state == 0) {
715 if (current_level == old_level && current_peak == old_peak && (hold_state == 0 || peak != -1)) {
719 Glib::RefPtr<Gdk::Window> win;
721 if ((win = get_window()) == 0) {
726 if (orientation == Vertical) {
727 queue_vertical_redraw (win, old_level);
729 queue_horizontal_redraw (win, old_level);
734 FastMeter::queue_vertical_redraw (const Glib::RefPtr<Gdk::Window>& win, float old_level)
738 gint new_top = (gint) floor (pixheight * current_level);
741 rect.width = pixwidth;
742 rect.height = new_top;
743 rect.y = 1 + pixheight - new_top;
745 if (current_level > old_level) {
746 /* colored/pixbuf got larger, just draw the new section */
747 /* rect.y stays where it is because of X coordinates */
748 /* height of invalidated area is between new.y (smaller) and old.y
750 X coordinates just make my brain hurt.
752 rect.height = pixrect.y - rect.y;
754 /* it got smaller, compute the difference */
755 /* rect.y becomes old.y (the smaller value) */
757 /* rect.height is the old.y (smaller) minus the new.y (larger)
759 rect.height = pixrect.height - rect.height;
762 GdkRegion* region = 0;
765 if (rect.height != 0) {
767 /* ok, first region to draw ... */
769 region = gdk_region_rectangle (&rect);
773 /* redraw the last place where the last peak hold bar was;
774 the next expose will draw the new one whether its part of
775 expose region or not.
778 if (last_peak_rect.width * last_peak_rect.height != 0) {
780 region = gdk_region_new ();
783 gdk_region_union_with_rect (region, &last_peak_rect);
786 if (hold_state && current_peak > 0) {
788 region = gdk_region_new ();
792 rect.y = max(1, 1 + pixheight - (int) floor (pixheight * current_peak));
793 if (_styleflags & 2) { // LED stripes
794 rect.y = max(0, (rect.y & (~1)));
796 if (bright_hold || (_styleflags & 2)) {
797 rect.height = max(0, min(3, pixheight - last_peak_rect.y -1 ));
799 rect.height = max(0, min(2, pixheight - last_peak_rect.y -1 ));
801 rect.width = pixwidth;
802 gdk_region_union_with_rect (region, &rect);
806 gdk_window_invalidate_region (win->gobj(), region, true);
809 gdk_region_destroy(region);
815 FastMeter::queue_horizontal_redraw (const Glib::RefPtr<Gdk::Window>& win, float old_level)
819 gint new_right = (gint) floor (pixwidth * current_level);
821 rect.height = pixheight;
824 if (current_level > old_level) {
825 rect.x = 1 + pixrect.width;
826 /* colored/pixbuf got larger, just draw the new section */
827 rect.width = new_right - pixrect.width;
829 /* it got smaller, compute the difference */
830 rect.x = 1 + new_right;
831 /* rect.height is the old.x (smaller) minus the new.x (larger) */
832 rect.width = pixrect.width - new_right;
835 GdkRegion* region = 0;
838 if (rect.height != 0) {
840 /* ok, first region to draw ... */
842 region = gdk_region_rectangle (&rect);
846 /* redraw the last place where the last peak hold bar was;
847 the next expose will draw the new one whether its part of
848 expose region or not.
851 if (last_peak_rect.width * last_peak_rect.height != 0) {
853 region = gdk_region_new ();
856 gdk_region_union_with_rect (region, &last_peak_rect);
859 if (hold_state && current_peak > 0) {
861 region = gdk_region_new ();
865 rect.height = pixheight;
866 const int xpos = floor (pixwidth * current_peak);
867 if (bright_hold || (_styleflags & 2)) {
868 rect.width = min(3, xpos);
870 rect.width = min(2, xpos);
872 rect.x = 1 + max(0, xpos - rect.width);
873 gdk_region_union_with_rect (region, &rect);
877 gdk_window_invalidate_region (win->gobj(), region, true);
880 gdk_region_destroy(region);
886 FastMeter::set_highlight (bool onoff)
888 if (highlight == onoff) {
892 if (orientation == Vertical) {
893 bgpattern = request_vertical_background (pixwidth + 2, pixheight + 2, highlight ? _bgh : _bgc, highlight);
895 bgpattern = request_horizontal_background (pixwidth + 2, pixheight + 2, highlight ? _bgh : _bgc, highlight);