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 ()
137 FastMeter::flush_pattern_cache () {
138 hb_pattern_cache.clear();
139 hm_pattern_cache.clear();
140 vb_pattern_cache.clear();
141 vm_pattern_cache.clear();
144 Cairo::RefPtr<Cairo::Pattern>
145 FastMeter::generate_meter_pattern (
146 int width, int height, int *clr, float *stp, int styleflags, bool horiz)
150 const double soft = 3.0 / (double) height;
151 const double offs = -1.0 / (double) height;
153 cairo_pattern_t* pat = cairo_pattern_create_linear (0.0, 0.0, 0.0, height);
156 Cairo coordinate space goes downwards as y value goes up, so invert
157 knee-based positions by using (1.0 - y)
160 UINT_TO_RGBA (clr[9], &r, &g, &b, &a); // top/clip
161 cairo_pattern_add_color_stop_rgb (pat, 0.0,
162 r/255.0, g/255.0, b/255.0);
164 knee = offs + stp[3] / 115.0f; // -0dB
166 UINT_TO_RGBA (clr[8], &r, &g, &b, &a);
167 cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee,
168 r/255.0, g/255.0, b/255.0);
170 UINT_TO_RGBA (clr[7], &r, &g, &b, &a);
171 cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee + soft,
172 r/255.0, g/255.0, b/255.0);
174 knee = offs + stp[2]/ 115.0f; // -3dB || -2dB
176 UINT_TO_RGBA (clr[6], &r, &g, &b, &a);
177 cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee,
178 r/255.0, g/255.0, b/255.0);
180 UINT_TO_RGBA (clr[5], &r, &g, &b, &a);
181 cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee + soft,
182 r/255.0, g/255.0, b/255.0);
184 knee = offs + stp[1] / 115.0f; // -9dB
186 UINT_TO_RGBA (clr[4], &r, &g, &b, &a);
187 cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee,
188 r/255.0, g/255.0, b/255.0);
190 UINT_TO_RGBA (clr[3], &r, &g, &b, &a);
191 cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee + soft,
192 r/255.0, g/255.0, b/255.0);
194 knee = offs + stp[0] / 115.0f; // -18dB
196 UINT_TO_RGBA (clr[2], &r, &g, &b, &a);
197 cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee,
198 r/255.0, g/255.0, b/255.0);
200 UINT_TO_RGBA (clr[1], &r, &g, &b, &a);
201 cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee + soft,
202 r/255.0, g/255.0, b/255.0);
204 UINT_TO_RGBA (clr[0], &r, &g, &b, &a); // bottom
205 cairo_pattern_add_color_stop_rgb (pat, 1.0,
206 r/255.0, g/255.0, b/255.0);
208 if ((styleflags & 1) && !no_rgba_overlay) {
209 cairo_pattern_t* shade_pattern = cairo_pattern_create_linear (0.0, 0.0, width, 0.0);
210 cairo_pattern_add_color_stop_rgba (shade_pattern, 0, 0.0, 0.0, 0.0, 0.15);
211 cairo_pattern_add_color_stop_rgba (shade_pattern, 0.4, 1.0, 1.0, 1.0, 0.05);
212 cairo_pattern_add_color_stop_rgba (shade_pattern, 1, 0.0, 0.0, 0.0, 0.25);
214 cairo_surface_t* surface;
216 surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
217 tc = cairo_create (surface);
218 cairo_set_source (tc, pat);
219 cairo_rectangle (tc, 0, 0, width, height);
221 cairo_pattern_destroy (pat);
223 cairo_set_source (tc, shade_pattern);
224 cairo_rectangle (tc, 0, 0, width, height);
226 cairo_pattern_destroy (shade_pattern);
228 if (styleflags & 2) { // LED stripes
230 cairo_set_line_width(tc, 1.0);
231 cairo_set_source_rgba(tc, .0, .0, .0, 0.4);
232 //cairo_set_operator (tc, CAIRO_OPERATOR_SOURCE);
233 for (int i = 0; float y = 0.5 + i * 2.0; ++i) {
237 cairo_move_to(tc, 0, y);
238 cairo_line_to(tc, width, y);
244 pat = cairo_pattern_create_for_surface (surface);
246 cairo_surface_destroy (surface);
250 cairo_surface_t* surface;
252 surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, height, width);
253 tc = cairo_create (surface);
256 cairo_matrix_init_rotate (&m, -M_PI/2.0);
257 cairo_matrix_translate (&m, -height, 0);
258 cairo_pattern_set_matrix (pat, &m);
259 cairo_set_source (tc, pat);
260 cairo_rectangle (tc, 0, 0, height, width);
262 cairo_pattern_destroy (pat);
263 pat = cairo_pattern_create_for_surface (surface);
265 cairo_surface_destroy (surface);
267 Cairo::RefPtr<Cairo::Pattern> p (new Cairo::Pattern (pat, false));
273 Cairo::RefPtr<Cairo::Pattern>
274 FastMeter::generate_meter_background (
275 int width, int height, int *clr, bool shade, bool horiz)
277 guint8 r0,g0,b0,r1,g1,b1,a;
279 cairo_pattern_t* pat = cairo_pattern_create_linear (0.0, 0.0, 0.0, height);
281 UINT_TO_RGBA (clr[0], &r0, &g0, &b0, &a);
282 UINT_TO_RGBA (clr[1], &r1, &g1, &b1, &a);
284 cairo_pattern_add_color_stop_rgb (pat, 0.0,
285 r1/255.0, g1/255.0, b1/255.0);
287 cairo_pattern_add_color_stop_rgb (pat, 1.0,
288 r0/255.0, g0/255.0, b0/255.0);
290 if (shade && !no_rgba_overlay) {
291 cairo_pattern_t* shade_pattern = cairo_pattern_create_linear (0.0, 0.0, width, 0.0);
292 cairo_pattern_add_color_stop_rgba (shade_pattern, 0.0, 1.0, 1.0, 1.0, 0.15);
293 cairo_pattern_add_color_stop_rgba (shade_pattern, 0.6, 0.0, 0.0, 0.0, 0.10);
294 cairo_pattern_add_color_stop_rgba (shade_pattern, 1.0, 1.0, 1.0, 1.0, 0.20);
296 cairo_surface_t* surface;
298 surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
299 tc = cairo_create (surface);
300 cairo_set_source (tc, pat);
301 cairo_rectangle (tc, 0, 0, width, height);
303 cairo_set_source (tc, shade_pattern);
304 cairo_rectangle (tc, 0, 0, width, height);
307 cairo_pattern_destroy (pat);
308 cairo_pattern_destroy (shade_pattern);
310 pat = cairo_pattern_create_for_surface (surface);
313 cairo_surface_destroy (surface);
317 cairo_surface_t* surface;
319 surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, height, width);
320 tc = cairo_create (surface);
323 cairo_matrix_init_rotate (&m, -M_PI/2.0);
324 cairo_matrix_translate (&m, -height, 0);
325 cairo_pattern_set_matrix (pat, &m);
326 cairo_set_source (tc, pat);
327 cairo_rectangle (tc, 0, 0, height, width);
329 cairo_pattern_destroy (pat);
330 pat = cairo_pattern_create_for_surface (surface);
332 cairo_surface_destroy (surface);
335 Cairo::RefPtr<Cairo::Pattern> p (new Cairo::Pattern (pat, false));
340 Cairo::RefPtr<Cairo::Pattern>
341 FastMeter::request_vertical_meter(
342 int width, int height, int *clr, float *stp, int styleflags)
344 height = max(height, min_pattern_metric_size);
345 height = min(height, max_pattern_metric_size);
347 const Pattern10MapKey key (width, height,
348 stp[0], stp[1], stp[2], stp[3],
349 clr[0], clr[1], clr[2], clr[3],
350 clr[4], clr[5], clr[6], clr[7],
351 clr[8], clr[9], styleflags);
353 Pattern10Map::iterator i;
354 if ((i = vm_pattern_cache.find (key)) != vm_pattern_cache.end()) {
357 // TODO flush pattern cache if it gets too large
359 Cairo::RefPtr<Cairo::Pattern> p = generate_meter_pattern (
360 width, height, clr, stp, styleflags, false);
361 vm_pattern_cache[key] = p;
366 Cairo::RefPtr<Cairo::Pattern>
367 FastMeter::request_vertical_background(
368 int width, int height, int *bgc, bool shade)
370 height = max(height, min_pattern_metric_size);
371 height = min(height, max_pattern_metric_size);
374 const PatternBgMapKey key (width, height, bgc[0], bgc[1], shade);
375 PatternBgMap::iterator i;
376 if ((i = vb_pattern_cache.find (key)) != vb_pattern_cache.end()) {
379 // TODO flush pattern cache if it gets too large
381 Cairo::RefPtr<Cairo::Pattern> p = generate_meter_background (
382 width, height, bgc, shade, false);
383 vb_pattern_cache[key] = p;
388 Cairo::RefPtr<Cairo::Pattern>
389 FastMeter::request_horizontal_meter(
390 int width, int height, int *clr, float *stp, int styleflags)
392 width = max(width, min_pattern_metric_size);
393 width = min(width, max_pattern_metric_size);
395 const Pattern10MapKey key (width, height,
396 stp[0], stp[1], stp[2], stp[3],
397 clr[0], clr[1], clr[2], clr[3],
398 clr[4], clr[5], clr[6], clr[7],
399 clr[8], clr[9], styleflags);
401 Pattern10Map::iterator i;
402 if ((i = hm_pattern_cache.find (key)) != hm_pattern_cache.end()) {
405 // TODO flush pattern cache if it gets too large
407 Cairo::RefPtr<Cairo::Pattern> p = generate_meter_pattern (
408 height, width, clr, stp, styleflags, true);
410 hm_pattern_cache[key] = p;
414 Cairo::RefPtr<Cairo::Pattern>
415 FastMeter::request_horizontal_background(
416 int width, int height, int *bgc, bool shade)
418 width = max(width, min_pattern_metric_size);
419 width = min(width, max_pattern_metric_size);
422 const PatternBgMapKey key (width, height, bgc[0], bgc[1], shade);
423 PatternBgMap::iterator i;
424 if ((i = hb_pattern_cache.find (key)) != hb_pattern_cache.end()) {
427 // TODO flush pattern cache if it gets too large
429 Cairo::RefPtr<Cairo::Pattern> p = generate_meter_background (
430 height, width, bgc, shade, true);
432 hb_pattern_cache[key] = p;
440 FastMeter::set_hold_count (long val)
454 FastMeter::on_size_request (GtkRequisition* req)
456 if (orientation == Vertical) {
457 vertical_size_request (req);
459 horizontal_size_request (req);
464 FastMeter::vertical_size_request (GtkRequisition* req)
466 req->height = request_height;
467 req->height = max(req->height, min_pattern_metric_size);
468 req->height = min(req->height, max_pattern_metric_size);
471 req->width = request_width;
475 FastMeter::horizontal_size_request (GtkRequisition* req)
477 req->width = request_width;
478 req->width = max(req->width, min_pattern_metric_size);
479 req->width = min(req->width, max_pattern_metric_size);
482 req->height = request_height;
486 FastMeter::on_size_allocate (Gtk::Allocation &alloc)
488 if (orientation == Vertical) {
489 vertical_size_allocate (alloc);
491 horizontal_size_allocate (alloc);
497 FastMeter::vertical_size_allocate (Gtk::Allocation &alloc)
499 if (alloc.get_width() != request_width) {
500 alloc.set_width (request_width);
503 int h = alloc.get_height();
504 h = max (h, min_pattern_metric_size + 2);
505 h = min (h, max_pattern_metric_size + 2);
507 if (h != alloc.get_height()) {
508 alloc.set_height (h);
511 if (pixheight != h) {
512 fgpattern = request_vertical_meter (request_width, h, _clr, _stp, _styleflags);
513 bgpattern = request_vertical_background (request_width, h, highlight ? _bgh : _bgc, highlight);
515 pixwidth = request_width - 2;
518 CairoWidget::on_size_allocate (alloc);
522 FastMeter::horizontal_size_allocate (Gtk::Allocation &alloc)
524 if (alloc.get_height() != request_height) {
525 alloc.set_height (request_height);
528 int w = alloc.get_width();
529 w = max (w, min_pattern_metric_size + 2);
530 w = min (w, max_pattern_metric_size + 2);
532 if (w != alloc.get_width()) {
537 fgpattern = request_horizontal_meter (w, request_height, _clr, _stp, _styleflags);
538 bgpattern = request_horizontal_background (w, request_height, highlight ? _bgh : _bgc, highlight);
540 pixheight = request_height - 2;
543 CairoWidget::on_size_allocate (alloc);
547 FastMeter::render (cairo_t* cr, cairo_rectangle_t* area)
549 if (orientation == Vertical) {
550 return vertical_expose (cr, area);
552 return horizontal_expose (cr, area);
557 FastMeter::vertical_expose (cairo_t* cr, cairo_rectangle_t* area)
560 GdkRectangle intersection;
561 GdkRectangle background;
562 GdkRectangle eventarea;
564 cairo_set_source_rgb (cr, 0, 0, 0); // black
565 rounded_rectangle (cr, 0, 0, pixwidth + 2, pixheight + 2, 2);
568 top_of_meter = (gint) floor (pixheight * current_level);
570 /* reset the height & origin of the rect that needs to show the pixbuf
573 pixrect.height = top_of_meter;
574 pixrect.y = 1 + pixheight - top_of_meter;
578 background.width = pixrect.width;
579 background.height = pixheight - top_of_meter;
581 eventarea.x = area->x;
582 eventarea.y = area->y;
583 eventarea.width = area->width;
584 eventarea.height = area->height;
586 if (gdk_rectangle_intersect (&background, &eventarea, &intersection)) {
587 cairo_set_source (cr, bgpattern->cobj());
588 cairo_rectangle (cr, intersection.x, intersection.y, intersection.width, intersection.height);
592 if (gdk_rectangle_intersect (&pixrect, &eventarea, &intersection)) {
593 // draw the part of the meter image that we need. the area we draw is bounded "in reverse" (top->bottom)
594 cairo_set_source (cr, fgpattern->cobj());
595 cairo_rectangle (cr, intersection.x, intersection.y, intersection.width, intersection.height);
602 last_peak_rect.x = 1;
603 last_peak_rect.width = pixwidth;
604 last_peak_rect.y = max(1, 1 + pixheight - (int) floor (pixheight * current_peak));
605 if (_styleflags & 2) { // LED stripes
606 last_peak_rect.y = max(0, (last_peak_rect.y & (~1)));
608 if (bright_hold || (_styleflags & 2)) {
609 last_peak_rect.height = max(0, min(3, pixheight - last_peak_rect.y - 1 ));
611 last_peak_rect.height = max(0, min(2, pixheight - last_peak_rect.y - 1 ));
614 cairo_set_source (cr, fgpattern->cobj());
615 cairo_rectangle (cr, last_peak_rect.x, last_peak_rect.y, last_peak_rect.width, last_peak_rect.height);
617 if (bright_hold && !no_rgba_overlay) {
618 cairo_fill_preserve (cr);
619 cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.3);
624 last_peak_rect.width = 0;
625 last_peak_rect.height = 0;
630 FastMeter::horizontal_expose (cairo_t* cr, cairo_rectangle_t* area)
633 GdkRectangle intersection;
634 GdkRectangle background;
635 GdkRectangle eventarea;
637 cairo_set_source_rgb (cr, 0, 0, 0); // black
638 rounded_rectangle (cr, 0, 0, pixwidth + 2, pixheight + 2, 2);
641 right_of_meter = (gint) floor (pixwidth * current_level);
643 /* reset the height & origin of the rect that needs to show the pixbuf
646 pixrect.width = right_of_meter;
648 background.x = 1 + right_of_meter;
650 background.width = pixwidth - right_of_meter;
651 background.height = pixheight;
653 eventarea.x = area->x;
654 eventarea.y = area->y;
655 eventarea.width = area->width;
656 eventarea.height = area->height;
658 if (gdk_rectangle_intersect (&background, &eventarea, &intersection)) {
659 cairo_set_source (cr, bgpattern->cobj());
660 cairo_rectangle (cr, intersection.x, intersection.y, intersection.width, intersection.height);
664 if (gdk_rectangle_intersect (&pixrect, &eventarea, &intersection)) {
665 cairo_set_source (cr, fgpattern->cobj());
666 cairo_rectangle (cr, intersection.x, intersection.y, intersection.width, intersection.height);
673 last_peak_rect.y = 1;
674 last_peak_rect.height = pixheight;
675 const int xpos = floor (pixwidth * current_peak);
676 if (bright_hold || (_styleflags & 2)) {
677 last_peak_rect.width = min(3, xpos );
679 last_peak_rect.width = min(2, xpos );
681 last_peak_rect.x = 1 + max(0, xpos - last_peak_rect.width);
683 cairo_set_source (cr, fgpattern->cobj());
684 cairo_rectangle (cr, last_peak_rect.x, last_peak_rect.y, last_peak_rect.width, last_peak_rect.height);
686 if (bright_hold && !no_rgba_overlay) {
687 cairo_fill_preserve (cr);
688 cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.3);
693 last_peak_rect.width = 0;
694 last_peak_rect.height = 0;
699 FastMeter::set (float lvl, float peak)
701 float old_level = current_level;
702 float old_peak = current_peak;
704 if (pixwidth <= 0 || pixheight <=0) return;
707 if (lvl >= current_peak) {
709 hold_state = hold_cnt;
712 if (hold_state > 0) {
713 if (--hold_state == 0) {
726 const float pixscale = (orientation == Vertical) ? pixheight : pixwidth;
727 #define PIX(X) floor(pixscale * (X))
728 if (PIX(current_level) == PIX(old_level) && PIX(current_peak) == PIX(old_peak) && (hold_state == 0 || peak != -1)) {
732 Glib::RefPtr<Gdk::Window> win;
734 if (! (win = get_window())) {
739 if (orientation == Vertical) {
740 queue_vertical_redraw (win, old_level);
742 queue_horizontal_redraw (win, old_level);
747 FastMeter::queue_vertical_redraw (const Glib::RefPtr<Gdk::Window>& win, float old_level)
751 gint new_top = (gint) floor (pixheight * current_level);
754 rect.width = pixwidth;
755 rect.height = new_top;
756 rect.y = 1 + pixheight - new_top;
758 if (current_level > old_level) {
759 /* colored/pixbuf got larger, just draw the new section */
760 /* rect.y stays where it is because of X coordinates */
761 /* height of invalidated area is between new.y (smaller) and old.y
763 X coordinates just make my brain hurt.
765 rect.height = pixrect.y - rect.y;
767 /* it got smaller, compute the difference */
768 /* rect.y becomes old.y (the smaller value) */
770 /* rect.height is the old.y (smaller) minus the new.y (larger)
772 rect.height = pixrect.height - rect.height;
775 GdkRegion* region = 0;
778 if (rect.height != 0) {
780 /* ok, first region to draw ... */
782 region = gdk_region_rectangle (&rect);
786 /* redraw the last place where the last peak hold bar was;
787 the next expose will draw the new one whether its part of
788 expose region or not.
791 if (last_peak_rect.width * last_peak_rect.height != 0) {
793 region = gdk_region_new ();
796 gdk_region_union_with_rect (region, &last_peak_rect);
799 if (hold_state && current_peak > 0) {
801 region = gdk_region_new ();
805 rect.y = max(1, 1 + pixheight - (int) floor (pixheight * current_peak));
806 if (_styleflags & 2) { // LED stripes
807 rect.y = max(0, (rect.y & (~1)));
809 if (bright_hold || (_styleflags & 2)) {
810 rect.height = max(0, min(3, pixheight - last_peak_rect.y -1 ));
812 rect.height = max(0, min(2, pixheight - last_peak_rect.y -1 ));
814 rect.width = pixwidth;
815 gdk_region_union_with_rect (region, &rect);
819 gdk_window_invalidate_region (win->gobj(), region, true);
822 gdk_region_destroy(region);
828 FastMeter::queue_horizontal_redraw (const Glib::RefPtr<Gdk::Window>& win, float old_level)
832 gint new_right = (gint) floor (pixwidth * current_level);
834 rect.height = pixheight;
837 if (current_level > old_level) {
838 rect.x = 1 + pixrect.width;
839 /* colored/pixbuf got larger, just draw the new section */
840 rect.width = new_right - pixrect.width;
842 /* it got smaller, compute the difference */
843 rect.x = 1 + new_right;
844 /* rect.height is the old.x (smaller) minus the new.x (larger) */
845 rect.width = pixrect.width - new_right;
848 GdkRegion* region = 0;
851 if (rect.height != 0) {
853 /* ok, first region to draw ... */
855 region = gdk_region_rectangle (&rect);
859 /* redraw the last place where the last peak hold bar was;
860 the next expose will draw the new one whether its part of
861 expose region or not.
864 if (last_peak_rect.width * last_peak_rect.height != 0) {
866 region = gdk_region_new ();
869 gdk_region_union_with_rect (region, &last_peak_rect);
872 if (hold_state && current_peak > 0) {
874 region = gdk_region_new ();
878 rect.height = pixheight;
879 const int xpos = floor (pixwidth * current_peak);
880 if (bright_hold || (_styleflags & 2)) {
881 rect.width = min(3, xpos);
883 rect.width = min(2, xpos);
885 rect.x = 1 + max(0, xpos - rect.width);
886 gdk_region_union_with_rect (region, &rect);
890 gdk_window_invalidate_region (win->gobj(), region, true);
893 gdk_region_destroy(region);
899 FastMeter::set_highlight (bool onoff)
901 if (highlight == onoff) {
905 if (orientation == Vertical) {
906 bgpattern = request_vertical_background (pixwidth + 2, pixheight + 2, highlight ? _bgh : _bgc, highlight);
908 bgpattern = request_horizontal_background (pixwidth + 2, pixheight + 2, highlight ? _bgh : _bgc, highlight);