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,
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, pixheight, _clr, _stp, _styleflags);
114 bgpattern = request_vertical_background (pixwidth, pixheight, _bgc, false);
119 fgpattern = request_horizontal_meter(pixwidth, pixheight, _clr, _stp, _styleflags);
120 bgpattern = request_horizontal_background (pixwidth, pixheight, _bgc, false);
123 pixrect.width = pixwidth;
124 pixrect.height = pixheight;
126 request_width = pixrect.width;
127 request_height= pixrect.height;
132 FastMeter::~FastMeter ()
137 FastMeter::flush_pattern_cache ()
139 Pattern10Map::iterator i1;
140 PatternBgMap::iterator ib;
142 for (ib = hb_pattern_cache.begin(); ib != hb_pattern_cache.end(); ++ib) {
143 hb_pattern_cache.erase(ib);
146 for (i1 = hm_pattern_cache.begin(); i1 != hm_pattern_cache.end(); ++i1) {
147 hm_pattern_cache.erase(i1);
150 for (ib = vb_pattern_cache.begin(); ib != vb_pattern_cache.end(); ++ib) {
151 vb_pattern_cache.erase(ib);
154 for (i1 = vm_pattern_cache.begin(); i1 != vm_pattern_cache.end(); ++i1) {
155 vm_pattern_cache.erase(i1);
159 Cairo::RefPtr<Cairo::Pattern>
160 FastMeter::generate_meter_pattern (
161 int width, int height, int *clr, float *stp, int styleflags, bool horiz)
165 const double soft = 3.0 / (double) height;
166 const double offs = -1.0 / (double) height;
168 cairo_pattern_t* pat = cairo_pattern_create_linear (0.0, 0.0, 0.0, height);
171 Cairo coordinate space goes downwards as y value goes up, so invert
172 knee-based positions by using (1.0 - y)
175 UINT_TO_RGBA (clr[9], &r, &g, &b, &a); // top/clip
176 cairo_pattern_add_color_stop_rgb (pat, 0.0,
177 r/255.0, g/255.0, b/255.0);
179 knee = offs + stp[3] / 115.0f; // -0dB
181 UINT_TO_RGBA (clr[8], &r, &g, &b, &a);
182 cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee,
183 r/255.0, g/255.0, b/255.0);
185 UINT_TO_RGBA (clr[7], &r, &g, &b, &a);
186 cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee + soft,
187 r/255.0, g/255.0, b/255.0);
189 knee = offs + stp[2]/ 115.0f; // -3dB || -2dB
191 UINT_TO_RGBA (clr[6], &r, &g, &b, &a);
192 cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee,
193 r/255.0, g/255.0, b/255.0);
195 UINT_TO_RGBA (clr[5], &r, &g, &b, &a);
196 cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee + soft,
197 r/255.0, g/255.0, b/255.0);
199 knee = offs + stp[1] / 115.0f; // -9dB
201 UINT_TO_RGBA (clr[4], &r, &g, &b, &a);
202 cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee,
203 r/255.0, g/255.0, b/255.0);
205 UINT_TO_RGBA (clr[3], &r, &g, &b, &a);
206 cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee + soft,
207 r/255.0, g/255.0, b/255.0);
209 knee = offs + stp[0] / 115.0f; // -18dB
211 UINT_TO_RGBA (clr[2], &r, &g, &b, &a);
212 cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee,
213 r/255.0, g/255.0, b/255.0);
215 UINT_TO_RGBA (clr[1], &r, &g, &b, &a);
216 cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee + soft,
217 r/255.0, g/255.0, b/255.0);
219 UINT_TO_RGBA (clr[0], &r, &g, &b, &a); // bottom
220 cairo_pattern_add_color_stop_rgb (pat, 1.0,
221 r/255.0, g/255.0, b/255.0);
223 if ((styleflags & 1) && !no_rgba_overlay) {
224 cairo_pattern_t* shade_pattern = cairo_pattern_create_linear (0.0, 0.0, width, 0.0);
225 cairo_pattern_add_color_stop_rgba (shade_pattern, 0, 0.0, 0.0, 0.0, 0.15);
226 cairo_pattern_add_color_stop_rgba (shade_pattern, 0.4, 1.0, 1.0, 1.0, 0.05);
227 cairo_pattern_add_color_stop_rgba (shade_pattern, 1, 0.0, 0.0, 0.0, 0.25);
229 cairo_surface_t* surface;
231 surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
232 tc = cairo_create (surface);
233 cairo_set_source (tc, pat);
234 cairo_rectangle (tc, 0, 0, width, height);
236 cairo_pattern_destroy (pat);
238 cairo_set_source (tc, shade_pattern);
239 cairo_rectangle (tc, 0, 0, width, height);
241 cairo_pattern_destroy (shade_pattern);
243 if (styleflags & 2) { // LED stripes
245 cairo_set_line_width(tc, 1.0);
246 cairo_set_source_rgba(tc, .0, .0, .0, 0.4);
247 //cairo_set_operator (tc, CAIRO_OPERATOR_SOURCE);
248 for (float y=0.5; y < height; y+= 2.0) {
249 cairo_move_to(tc, 0, y);
250 cairo_line_to(tc, width, y);
256 pat = cairo_pattern_create_for_surface (surface);
258 cairo_surface_destroy (surface);
262 cairo_surface_t* surface;
264 surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, height, width);
265 tc = cairo_create (surface);
268 cairo_matrix_init_rotate (&m, -M_PI/2.0);
269 cairo_matrix_translate (&m, -height, 0);
270 cairo_pattern_set_matrix (pat, &m);
271 cairo_set_source (tc, pat);
272 cairo_rectangle (tc, 0, 0, height, width);
274 cairo_pattern_destroy (pat);
275 pat = cairo_pattern_create_for_surface (surface);
277 cairo_surface_destroy (surface);
279 Cairo::RefPtr<Cairo::Pattern> p (new Cairo::Pattern (pat, false));
285 Cairo::RefPtr<Cairo::Pattern>
286 FastMeter::generate_meter_background (
287 int width, int height, int *clr, bool shade, bool horiz)
289 guint8 r0,g0,b0,r1,g1,b1,a;
291 cairo_pattern_t* pat = cairo_pattern_create_linear (0.0, 0.0, 0.0, height);
293 UINT_TO_RGBA (clr[0], &r0, &g0, &b0, &a);
294 UINT_TO_RGBA (clr[1], &r1, &g1, &b1, &a);
296 cairo_pattern_add_color_stop_rgb (pat, 0.0,
297 r1/255.0, g1/255.0, b1/255.0);
299 cairo_pattern_add_color_stop_rgb (pat, 1.0,
300 r0/255.0, g0/255.0, b0/255.0);
302 if (shade && !no_rgba_overlay) {
303 cairo_pattern_t* shade_pattern = cairo_pattern_create_linear (0.0, 0.0, width, 0.0);
304 cairo_pattern_add_color_stop_rgba (shade_pattern, 0.0, 1.0, 1.0, 1.0, 0.15);
305 cairo_pattern_add_color_stop_rgba (shade_pattern, 0.6, 0.0, 0.0, 0.0, 0.10);
306 cairo_pattern_add_color_stop_rgba (shade_pattern, 1.0, 1.0, 1.0, 1.0, 0.20);
308 cairo_surface_t* surface;
310 surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
311 tc = cairo_create (surface);
312 cairo_set_source (tc, pat);
313 cairo_rectangle (tc, 0, 0, width, height);
315 cairo_set_source (tc, shade_pattern);
316 cairo_rectangle (tc, 0, 0, width, height);
319 cairo_pattern_destroy (pat);
320 cairo_pattern_destroy (shade_pattern);
322 pat = cairo_pattern_create_for_surface (surface);
325 cairo_surface_destroy (surface);
329 cairo_surface_t* surface;
331 surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, height, width);
332 tc = cairo_create (surface);
335 cairo_matrix_init_rotate (&m, -M_PI/2.0);
336 cairo_matrix_translate (&m, -height, 0);
337 cairo_pattern_set_matrix (pat, &m);
338 cairo_set_source (tc, pat);
339 cairo_rectangle (tc, 0, 0, height, width);
341 cairo_pattern_destroy (pat);
342 pat = cairo_pattern_create_for_surface (surface);
344 cairo_surface_destroy (surface);
347 Cairo::RefPtr<Cairo::Pattern> p (new Cairo::Pattern (pat, false));
352 Cairo::RefPtr<Cairo::Pattern>
353 FastMeter::request_vertical_meter(
354 int width, int height, int *clr, float *stp, int styleflags)
356 height = max(height, min_pattern_metric_size);
357 height = min(height, max_pattern_metric_size);
359 const Pattern10MapKey key (width, height,
360 stp[0], stp[1], stp[2], stp[3],
361 clr[0], clr[1], clr[2], clr[3],
362 clr[4], clr[5], clr[6], clr[7],
363 clr[8], clr[9], styleflags);
365 Pattern10Map::iterator i;
366 if ((i = vm_pattern_cache.find (key)) != vm_pattern_cache.end()) {
369 // TODO flush pattern cache if it gets too large
371 Cairo::RefPtr<Cairo::Pattern> p = generate_meter_pattern (
372 width, height, clr, stp, styleflags, false);
373 vm_pattern_cache[key] = p;
378 Cairo::RefPtr<Cairo::Pattern>
379 FastMeter::request_vertical_background(
380 int width, int height, int *bgc, bool /*shade */)
382 height = max(height, min_pattern_metric_size);
383 height = min(height, max_pattern_metric_size);
386 const PatternBgMapKey key (width, height, bgc[0], bgc[1], false);
387 PatternBgMap::iterator i;
388 if ((i = vb_pattern_cache.find (key)) != vb_pattern_cache.end()) {
391 // TODO flush pattern cache if it gets too large
393 Cairo::RefPtr<Cairo::Pattern> p = generate_meter_background (
394 width, height, bgc, false, false);
395 vb_pattern_cache[key] = p;
400 Cairo::RefPtr<Cairo::Pattern>
401 FastMeter::request_horizontal_meter(
402 int width, int height, int *clr, float *stp, int styleflags)
404 width = max(width, min_pattern_metric_size);
405 width = min(width, max_pattern_metric_size);
407 const Pattern10MapKey key (width, height,
408 stp[0], stp[1], stp[2], stp[3],
409 clr[0], clr[1], clr[2], clr[3],
410 clr[4], clr[5], clr[6], clr[7],
411 clr[8], clr[9], styleflags);
413 Pattern10Map::iterator i;
414 if ((i = hm_pattern_cache.find (key)) != hm_pattern_cache.end()) {
417 // TODO flush pattern cache if it gets too large
419 Cairo::RefPtr<Cairo::Pattern> p = generate_meter_pattern (
420 height, width, clr, stp, styleflags, true);
422 hm_pattern_cache[key] = p;
426 Cairo::RefPtr<Cairo::Pattern>
427 FastMeter::request_horizontal_background(
428 int width, int height, int *bgc, bool /* shade */)
430 width = max(width, min_pattern_metric_size);
431 width = min(width, max_pattern_metric_size);
434 const PatternBgMapKey key (width, height, bgc[0], bgc[1], false);
435 PatternBgMap::iterator i;
436 if ((i = hb_pattern_cache.find (key)) != hb_pattern_cache.end()) {
439 // TODO flush pattern cache if it gets too large
441 Cairo::RefPtr<Cairo::Pattern> p = generate_meter_background (
442 height, width, bgc, false, true);
444 hb_pattern_cache[key] = p;
452 FastMeter::set_hold_count (long val)
466 FastMeter::on_size_request (GtkRequisition* req)
468 if (orientation == Vertical) {
469 vertical_size_request (req);
471 horizontal_size_request (req);
476 FastMeter::vertical_size_request (GtkRequisition* req)
478 req->height = request_height;
479 req->height = max(req->height, min_pattern_metric_size);
480 req->height = min(req->height, max_pattern_metric_size);
483 req->width = request_width;
487 FastMeter::horizontal_size_request (GtkRequisition* req)
489 req->width = request_width;
490 req->width = max(req->width, min_pattern_metric_size);
491 req->width = min(req->width, max_pattern_metric_size);
494 req->height = request_height;
498 FastMeter::on_size_allocate (Gtk::Allocation &alloc)
500 if (orientation == Vertical) {
501 vertical_size_allocate (alloc);
503 horizontal_size_allocate (alloc);
509 FastMeter::vertical_size_allocate (Gtk::Allocation &alloc)
511 if (alloc.get_width() != request_width) {
512 alloc.set_width (request_width);
515 int h = alloc.get_height();
516 h = max (h, min_pattern_metric_size + 2);
517 h = min (h, max_pattern_metric_size + 2);
519 if (h != alloc.get_height()) {
520 alloc.set_height (h);
523 if (pixheight != h) {
524 fgpattern = request_vertical_meter (request_width, h, _clr, _stp, _styleflags);
525 bgpattern = request_vertical_background (request_width, h, highlight ? _bgh : _bgc, false);
527 pixwidth = request_width;
530 CairoWidget::on_size_allocate (alloc);
534 FastMeter::horizontal_size_allocate (Gtk::Allocation &alloc)
536 if (alloc.get_height() != request_height) {
537 alloc.set_height (request_height);
540 int w = alloc.get_width();
541 w = max (w, min_pattern_metric_size + 2);
542 w = min (w, max_pattern_metric_size + 2);
544 if (w != alloc.get_width()) {
549 fgpattern = request_horizontal_meter (w, request_height, _clr, _stp, _styleflags);
550 bgpattern = request_horizontal_background (w, request_height, highlight ? _bgh : _bgc, false);
552 pixheight = request_height;
555 CairoWidget::on_size_allocate (alloc);
559 FastMeter::render (cairo_t* cr, cairo_rectangle_t* area)
561 if (orientation == Vertical) {
562 return vertical_expose (cr, area);
564 return horizontal_expose (cr, area);
569 FastMeter::vertical_expose (cairo_t* cr, cairo_rectangle_t* area)
572 // GdkRectangle background;
573 // GdkRectangle eventarea;
575 //cairo_set_source_rgb (cr, 0, 0, 0); // black
576 //rounded_rectangle (cr, 0, 0, pixwidth + 2, pixheight + 2, 2);
579 top_of_meter = (gint) floor (pixheight * current_level);
581 /* reset the height & origin of the rect that needs to show the pixbuf
584 pixrect.height = top_of_meter;
585 pixrect.y = pixheight - top_of_meter;
589 // background.width = pixrect.width;
590 // background.height = pixheight - top_of_meter;
592 // eventarea.x = area->x;
593 // eventarea.y = area->y;
594 // eventarea.width = area->width;
595 // eventarea.height = area->height;
597 // Switching to CAIRO we would like to draw on the container's bkg.
598 // if (gdk_rectangle_intersect (&background, &eventarea, &intersection)) {
599 // cairo_set_source (cr, bgpattern->cobj());
600 // cairo_rectangle (cr, intersection.x, intersection.y, intersection.width, intersection.height);
604 // MEMO: Normaly MATURE OS clips so called invalidated rects itself making APP free of
605 // heavy operations which OS does with graphic HW
607 // NOTE FROM PAUL: GTK does clip already. The invalidated rect isn't the only area
608 // we want to clip to however, which is why this object/class is called FastMeter.
609 // I have left stuff commented out as I found it when I merged from Ardour in August 2014,
610 // but this commenting and the previous MEMO comment represent a misunderstanding
611 // of what this code is doing.
613 // if (gdk_rectangle_intersect (&pixrect, &eventarea, &intersection)) {
614 // draw the part of the meter image that we need. the area we draw is bounded "in reverse" (top->bottom)
615 //cairo_set_source (cr, fgpattern->cobj());
616 cairo_set_source_rgba (cr, 0.69, 0.69, 0.69, 1);
617 cairo_rectangle (cr, pixrect.x, pixrect.y, pixrect.width, pixrect.height);
624 last_peak_rect.x = 0;
625 last_peak_rect.width = pixwidth;
626 last_peak_rect.y = max(0, pixheight - (gint) floor (pixheight * current_peak));
627 if (bright_hold || (_styleflags & 2)) {
628 last_peak_rect.height = max(0, min(3, pixheight - last_peak_rect.y ));
630 last_peak_rect.height = max(0, min(2, pixheight - last_peak_rect.y ));
633 cairo_set_source (cr, fgpattern->cobj());
634 cairo_rectangle (cr, last_peak_rect.x, last_peak_rect.y, last_peak_rect.width, last_peak_rect.height);
636 if (bright_hold && !no_rgba_overlay) {
637 cairo_fill_preserve (cr);
638 cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.3);
643 last_peak_rect.width = 0;
644 last_peak_rect.height = 0;
649 FastMeter::horizontal_expose (cairo_t* cr, cairo_rectangle_t* area)
653 //cairo_set_source_rgb (cr, 0, 0, 0); // black
654 //rounded_rectangle (cr, 0, 0, pixwidth + 2, pixheight + 2, 2);
657 right_of_meter = (gint) floor (pixwidth * current_level);
659 /* reset the height & origin of the rect that needs to show the pixbuf
662 pixrect.width = right_of_meter;
667 last_peak_rect.y = 1;
668 last_peak_rect.height = pixheight;
669 const int xpos = floor (pixwidth * current_peak);
670 if (bright_hold || (_styleflags & 2)) {
671 last_peak_rect.width = min(3, xpos );
673 last_peak_rect.width = min(2, xpos );
675 last_peak_rect.x = 1 + max(0, xpos - last_peak_rect.width);
677 cairo_set_source (cr, fgpattern->cobj());
678 cairo_rectangle (cr, last_peak_rect.x, last_peak_rect.y, last_peak_rect.width, last_peak_rect.height);
680 if (bright_hold && !no_rgba_overlay) {
681 cairo_fill_preserve (cr);
682 cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.3);
687 last_peak_rect.width = 0;
688 last_peak_rect.height = 0;
693 FastMeter::set (float lvl, float peak)
695 float old_level = current_level;
696 float old_peak = current_peak;
698 if (pixwidth <= 0 || pixheight <=0) return;
701 if (lvl >= current_peak) {
703 hold_state = hold_cnt;
706 if (hold_state > 0) {
707 if (--hold_state == 0) {
720 if (current_level == old_level && current_peak == old_peak && (hold_state == 0 || peak != -1)) {
724 Glib::RefPtr<Gdk::Window> win;
726 if ((win = get_window()) == 0) {
731 if (orientation == Vertical) {
732 queue_vertical_redraw (win, old_level);
734 queue_horizontal_redraw (win, old_level);
739 FastMeter::queue_vertical_redraw (const Glib::RefPtr<Gdk::Window>& win, float old_level)
743 gint new_top = (gint) floor (pixheight * current_level);
746 rect.width = pixwidth;
747 rect.height = new_top;
748 rect.y = pixheight - new_top;
750 if (current_level > old_level) {
751 /* colored/pixbuf got larger, just draw the new section */
752 /* rect.y stays where it is because of X coordinates */
753 /* height of invalidated area is between new.y (smaller) and old.y
755 X coordinates just make my brain hurt.
757 rect.height = pixrect.y - rect.y;
759 /* it got smaller, compute the difference */
760 /* rect.y becomes old.y (the smaller value) */
762 /* rect.height is the old.y (smaller) minus the new.y (larger)
764 rect.height = pixrect.height - rect.height;
767 GdkRegion* region = 0;
770 if (rect.height != 0) {
772 /* ok, first region to draw ... */
774 region = gdk_region_rectangle (&rect);
778 /* redraw the last place where the last peak hold bar was;
779 the next expose will draw the new one whether its part of
780 expose region or not.
783 if (last_peak_rect.width * last_peak_rect.height != 0) {
785 region = gdk_region_new ();
788 gdk_region_union_with_rect (region, &last_peak_rect);
791 if (hold_state && current_peak > 0) {
793 region = gdk_region_new ();
797 rect.y = max(1, 1 + pixheight - (gint) floor (pixheight * current_peak));
798 if (bright_hold || (_styleflags & 2)) {
799 rect.height = max(0, min(3, pixheight - last_peak_rect.y -1 ));
801 rect.height = max(0, min(2, pixheight - last_peak_rect.y -1 ));
803 rect.width = pixwidth;
804 gdk_region_union_with_rect (region, &rect);
808 gdk_window_invalidate_region (win->gobj(), region, true);
811 gdk_region_destroy(region);
817 FastMeter::queue_horizontal_redraw (const Glib::RefPtr<Gdk::Window>& win, float old_level)
821 gint new_right = (gint) floor (pixwidth * current_level);
823 rect.height = pixheight;
826 if (current_level > old_level) {
827 rect.x = 1 + pixrect.width;
828 /* colored/pixbuf got larger, just draw the new section */
829 rect.width = new_right - pixrect.width;
831 /* it got smaller, compute the difference */
832 rect.x = 1 + new_right;
833 /* rect.height is the old.x (smaller) minus the new.x (larger) */
834 rect.width = pixrect.width - new_right;
837 GdkRegion* region = 0;
840 if (rect.height != 0) {
842 /* ok, first region to draw ... */
844 region = gdk_region_rectangle (&rect);
848 /* redraw the last place where the last peak hold bar was;
849 the next expose will draw the new one whether its part of
850 expose region or not.
853 if (last_peak_rect.width * last_peak_rect.height != 0) {
855 region = gdk_region_new ();
858 gdk_region_union_with_rect (region, &last_peak_rect);
861 if (hold_state && current_peak > 0) {
863 region = gdk_region_new ();
867 rect.height = pixheight;
868 const int xpos = floor (pixwidth * current_peak);
869 if (bright_hold || (_styleflags & 2)) {
870 rect.width = min(3, xpos);
872 rect.width = min(2, xpos);
874 rect.x = 1 + max(0, xpos - rect.width);
875 gdk_region_union_with_rect (region, &rect);
879 gdk_window_invalidate_region (win->gobj(), region, true);
882 gdk_region_destroy(region);
888 FastMeter::set_highlight (bool onoff)
890 if (highlight == onoff) {
894 if (orientation == Vertical) {
895 bgpattern = request_vertical_background (pixwidth + 2, pixheight + 2, highlight ? _bgh : _bgc, false);
897 bgpattern = request_horizontal_background (pixwidth + 2, pixheight + 2, highlight ? _bgh : _bgc, false);