#include <stdlib.h>
+#include <glibmm.h>
+#include <gdkmm.h>
#include <gdkmm/rectangle.h>
#include <gtkmm2ext/fastmeter.h>
#include <gtkmm2ext/utils.h>
#define UINT_TO_RGB(u,r,g,b) { (*(r)) = ((u)>>16)&0xff; (*(g)) = ((u)>>8)&0xff; (*(b)) = (u)&0xff; }
#define UINT_TO_RGBA(u,r,g,b,a) { UINT_TO_RGB(((u)>>8),r,g,b); (*(a)) = (u)&0xff; }
+
using namespace Gtk;
-using namespace Gdk;
using namespace Glib;
using namespace Gtkmm2ext;
using namespace std;
float stp2, float stp3,
int styleflags
)
+ : pixheight(0)
+ , pixwidth(0)
+ , _styleflags(styleflags)
+ , orientation(o)
+ , hold_cnt(hold)
+ , hold_state(0)
+ , bright_hold(false)
+ , current_level(0)
+ , current_peak(0)
+ , highlight(false)
{
- orientation = o;
- hold_cnt = hold;
- hold_state = 0;
- bright_hold = false;
- current_peak = 0;
- current_level = 0;
last_peak_rect.width = 0;
last_peak_rect.height = 0;
+ last_peak_rect.x = 0;
+ last_peak_rect.y = 0;
- highlight = false;
no_rgba_overlay = ! Glib::getenv("NO_METER_SHADE").empty();
_clr[0] = clr0;
_stp[2] = stp2;
_stp[3] = stp3;
- _styleflags = styleflags;
-
- set_events (BUTTON_PRESS_MASK|BUTTON_RELEASE_MASK);
+ set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
pixrect.x = 1;
pixrect.y = 1;
request_width = pixrect.width + 2;
request_height= pixrect.height + 2;
- queue_draw ();
+ clear ();
}
FastMeter::~FastMeter ()
{
}
+void
+FastMeter::flush_pattern_cache () {
+ hb_pattern_cache.clear();
+ hm_pattern_cache.clear();
+ vb_pattern_cache.clear();
+ vm_pattern_cache.clear();
+}
+
Cairo::RefPtr<Cairo::Pattern>
FastMeter::generate_meter_pattern (
int width, int height, int *clr, float *stp, int styleflags, bool horiz)
cairo_set_line_width(tc, 1.0);
cairo_set_source_rgba(tc, .0, .0, .0, 0.4);
//cairo_set_operator (tc, CAIRO_OPERATOR_SOURCE);
- for (float y=0.5; y < height; y+= 2.0) {
+ for (int i = 0; float y = 0.5 + i * 2.0; ++i) {
+ if (y >= height) {
+ break;
+ }
cairo_move_to(tc, 0, y);
cairo_line_to(tc, width, y);
cairo_stroke (tc);
pixwidth = request_width - 2;
}
- DrawingArea::on_size_allocate (alloc);
+ CairoWidget::on_size_allocate (alloc);
}
void
pixheight = request_height - 2;
}
- DrawingArea::on_size_allocate (alloc);
+ CairoWidget::on_size_allocate (alloc);
}
-bool
-FastMeter::on_expose_event (GdkEventExpose* ev)
+void
+FastMeter::render (cairo_t* cr, cairo_rectangle_t* area)
{
if (orientation == Vertical) {
- return vertical_expose (ev);
+ return vertical_expose (cr, area);
} else {
- return horizontal_expose (ev);
+ return horizontal_expose (cr, area);
}
}
-bool
-FastMeter::vertical_expose (GdkEventExpose* ev)
+void
+FastMeter::vertical_expose (cairo_t* cr, cairo_rectangle_t* area)
{
- Glib::RefPtr<Gdk::Window> win = get_window ();
gint top_of_meter;
GdkRectangle intersection;
GdkRectangle background;
-
- cairo_t* cr = gdk_cairo_create (get_window ()->gobj());
-
- cairo_rectangle (cr, ev->area.x, ev->area.y, ev->area.width, ev->area.height);
- cairo_clip (cr);
+ GdkRectangle eventarea;
cairo_set_source_rgb (cr, 0, 0, 0); // black
rounded_rectangle (cr, 0, 0, pixwidth + 2, pixheight + 2, 2);
background.width = pixrect.width;
background.height = pixheight - top_of_meter;
- if (gdk_rectangle_intersect (&background, &ev->area, &intersection)) {
+ eventarea.x = area->x;
+ eventarea.y = area->y;
+ eventarea.width = area->width;
+ eventarea.height = area->height;
+
+ if (gdk_rectangle_intersect (&background, &eventarea, &intersection)) {
cairo_set_source (cr, bgpattern->cobj());
cairo_rectangle (cr, intersection.x, intersection.y, intersection.width, intersection.height);
cairo_fill (cr);
}
- if (gdk_rectangle_intersect (&pixrect, &ev->area, &intersection)) {
+ if (gdk_rectangle_intersect (&pixrect, &eventarea, &intersection)) {
// draw the part of the meter image that we need. the area we draw is bounded "in reverse" (top->bottom)
cairo_set_source (cr, fgpattern->cobj());
cairo_rectangle (cr, intersection.x, intersection.y, intersection.width, intersection.height);
if (hold_state) {
last_peak_rect.x = 1;
last_peak_rect.width = pixwidth;
- last_peak_rect.y = max(1, 1 + pixheight - (gint) floor (pixheight * current_peak));
+ last_peak_rect.y = max(1, 1 + pixheight - (int) floor (pixheight * current_peak));
+ if (_styleflags & 2) { // LED stripes
+ last_peak_rect.y = max(0, (last_peak_rect.y & (~1)));
+ }
if (bright_hold || (_styleflags & 2)) {
- last_peak_rect.height = max(0, min(3, pixheight - last_peak_rect.y -1 ));
+ last_peak_rect.height = max(0, min(3, pixheight - last_peak_rect.y - 1 ));
} else {
- last_peak_rect.height = max(0, min(2, pixheight - last_peak_rect.y -1 ));
+ last_peak_rect.height = max(0, min(2, pixheight - last_peak_rect.y - 1 ));
}
cairo_set_source (cr, fgpattern->cobj());
last_peak_rect.width = 0;
last_peak_rect.height = 0;
}
-
- cairo_destroy (cr);
-
- return TRUE;
}
-bool
-FastMeter::horizontal_expose (GdkEventExpose* ev)
+void
+FastMeter::horizontal_expose (cairo_t* cr, cairo_rectangle_t* area)
{
- Glib::RefPtr<Gdk::Window> win = get_window ();
gint right_of_meter;
GdkRectangle intersection;
GdkRectangle background;
-
- cairo_t* cr = gdk_cairo_create (get_window ()->gobj());
-
- cairo_rectangle (cr, ev->area.x, ev->area.y, ev->area.width, ev->area.height);
- cairo_clip (cr);
+ GdkRectangle eventarea;
cairo_set_source_rgb (cr, 0, 0, 0); // black
rounded_rectangle (cr, 0, 0, pixwidth + 2, pixheight + 2, 2);
background.width = pixwidth - right_of_meter;
background.height = pixheight;
- if (gdk_rectangle_intersect (&background, &ev->area, &intersection)) {
+ eventarea.x = area->x;
+ eventarea.y = area->y;
+ eventarea.width = area->width;
+ eventarea.height = area->height;
+
+ if (gdk_rectangle_intersect (&background, &eventarea, &intersection)) {
cairo_set_source (cr, bgpattern->cobj());
cairo_rectangle (cr, intersection.x, intersection.y, intersection.width, intersection.height);
cairo_fill (cr);
}
- if (gdk_rectangle_intersect (&pixrect, &ev->area, &intersection)) {
+ if (gdk_rectangle_intersect (&pixrect, &eventarea, &intersection)) {
cairo_set_source (cr, fgpattern->cobj());
cairo_rectangle (cr, intersection.x, intersection.y, intersection.width, intersection.height);
cairo_fill (cr);
last_peak_rect.y = 1;
last_peak_rect.height = pixheight;
const int xpos = floor (pixwidth * current_peak);
- if (bright_hold) {
- last_peak_rect.width = min(4, xpos );
+ if (bright_hold || (_styleflags & 2)) {
+ last_peak_rect.width = min(3, xpos );
} else {
last_peak_rect.width = min(2, xpos );
}
last_peak_rect.width = 0;
last_peak_rect.height = 0;
}
-
- cairo_destroy (cr);
-
- return TRUE;
}
void
float old_level = current_level;
float old_peak = current_peak;
+ if (pixwidth <= 0 || pixheight <=0) return;
+
if (peak == -1) {
if (lvl >= current_peak) {
current_peak = lvl;
current_level = lvl;
- if (current_level == old_level && current_peak == old_peak && (hold_state == 0 || peak != -1)) {
+ const float pixscale = (orientation == Vertical) ? pixheight : pixwidth;
+#define PIX(X) floor(pixscale * (X))
+ if (PIX(current_level) == PIX(old_level) && PIX(current_peak) == PIX(old_peak) && (hold_state == 0 || peak != -1)) {
return;
}
Glib::RefPtr<Gdk::Window> win;
- if ((win = get_window()) == 0) {
+ if (! (win = get_window())) {
queue_draw ();
return;
}
queue = true;
}
rect.x = 1;
- rect.y = max(1, 1 + pixheight - (gint) floor (pixheight * current_peak));
- if (bright_hold) {
- rect.height = max(0, min(4, pixheight - last_peak_rect.y -1 ));
+ rect.y = max(1, 1 + pixheight - (int) floor (pixheight * current_peak));
+ if (_styleflags & 2) { // LED stripes
+ rect.y = max(0, (rect.y & (~1)));
+ }
+ if (bright_hold || (_styleflags & 2)) {
+ rect.height = max(0, min(3, pixheight - last_peak_rect.y -1 ));
} else {
rect.height = max(0, min(2, pixheight - last_peak_rect.y -1 ));
}
rect.y = 1;
rect.height = pixheight;
const int xpos = floor (pixwidth * current_peak);
- if (bright_hold) {
- rect.width = min(4, xpos);
+ if (bright_hold || (_styleflags & 2)) {
+ rect.width = min(3, xpos);
} else {
rect.width = min(2, xpos);
}