mirror of
https://github.com/Ardour/ardour.git
synced 2026-01-09 15:15:41 +01:00
refactor level-meter widget: 5x2 stops meter colors
This commit is contained in:
parent
447e736139
commit
571b2d70e9
3 changed files with 176 additions and 74 deletions
|
|
@ -196,10 +196,8 @@ LevelMeter::setup_meters (int len, int initial_width, int thin_width)
|
|||
if (meters[n].width != width || meters[n].length != len || color_changed) {
|
||||
delete meters[n].meter;
|
||||
meters[n].meter = new FastMeter ((uint32_t) floor (Config->get_meter_hold()), width, FastMeter::Vertical, len,
|
||||
b, m, t, c,
|
||||
b, b, m, m, t, t, c, c, c, c,
|
||||
ARDOUR_UI::config()->canvasvar_MeterBackgroundBot.get(),
|
||||
ARDOUR_UI::config()->canvasvar_MeterBackgroundMid.get(),
|
||||
ARDOUR_UI::config()->canvasvar_MeterBackgroundMid.get(),
|
||||
ARDOUR_UI::config()->canvasvar_MeterBackgroundTop.get()
|
||||
);
|
||||
meters[n].width = width;
|
||||
|
|
|
|||
|
|
@ -38,11 +38,13 @@ using namespace std;
|
|||
int FastMeter::min_pattern_metric_size = 10;
|
||||
int FastMeter::max_pattern_metric_size = 1024;
|
||||
|
||||
FastMeter::PatternMap FastMeter::v_pattern_cache;
|
||||
FastMeter::Pattern10Map FastMeter::vm_pattern_cache;
|
||||
FastMeter::PatternBgMap FastMeter::vb_pattern_cache;
|
||||
|
||||
FastMeter::FastMeter (long hold, unsigned long dimen, Orientation o, int len,
|
||||
int clr0, int clr1, int clr2, int clr3,
|
||||
int bgc0, int bgc1, int bgc2, int bgc3)
|
||||
int clr4, int clr5, int clr6, int clr7,
|
||||
int clr8, int clr9, int bgc0, int bgc1)
|
||||
{
|
||||
orientation = o;
|
||||
hold_cnt = hold;
|
||||
|
|
@ -52,15 +54,25 @@ FastMeter::FastMeter (long hold, unsigned long dimen, Orientation o, int len,
|
|||
current_level = 0;
|
||||
last_peak_rect.width = 0;
|
||||
last_peak_rect.height = 0;
|
||||
_clr0 = clr0;
|
||||
_clr1 = clr1;
|
||||
_clr2 = clr2;
|
||||
_clr3 = clr3;
|
||||
|
||||
_bgc0 = bgc0;
|
||||
_bgc1 = bgc1;
|
||||
_bgc2 = bgc2;
|
||||
_bgc3 = bgc3;
|
||||
_clr[0] = clr0;
|
||||
_clr[1] = clr1;
|
||||
_clr[2] = clr2;
|
||||
_clr[3] = clr3;
|
||||
_clr[4] = clr4;
|
||||
_clr[5] = clr5;
|
||||
_clr[6] = clr6;
|
||||
_clr[7] = clr7;
|
||||
_clr[8] = clr8;
|
||||
_clr[9] = clr9;
|
||||
|
||||
_bgc[0] = bgc0;
|
||||
_bgc[1] = bgc1;
|
||||
|
||||
_stp[0] = 55.0; // log_meter(-18);
|
||||
_stp[1] = 77.5; // log_meter(-9);
|
||||
_stp[2] = 92.5; // log_meter(-3);
|
||||
_stp[2] = 95.0; // log_meter(-2);
|
||||
|
||||
set_events (BUTTON_PRESS_MASK|BUTTON_RELEASE_MASK);
|
||||
|
||||
|
|
@ -70,8 +82,8 @@ FastMeter::FastMeter (long hold, unsigned long dimen, Orientation o, int len,
|
|||
if (!len) {
|
||||
len = 250;
|
||||
}
|
||||
fgpattern = request_vertical_meter(dimen, len, clr0, clr1, clr2, clr3);
|
||||
bgpattern = request_vertical_meter(dimen, len, _bgc0, _bgc1, _bgc2, _bgc3);
|
||||
fgpattern = request_vertical_meter(dimen, len, _clr, _stp);
|
||||
bgpattern = request_vertical_background (dimen, len, _bgc);
|
||||
pixheight = len;
|
||||
pixwidth = dimen;
|
||||
|
||||
|
|
@ -82,36 +94,17 @@ FastMeter::FastMeter (long hold, unsigned long dimen, Orientation o, int len,
|
|||
request_height= pixrect.height + 2;
|
||||
}
|
||||
|
||||
FastMeter::~FastMeter ()
|
||||
{
|
||||
}
|
||||
|
||||
Cairo::RefPtr<Cairo::Pattern>
|
||||
FastMeter::generate_meter_pattern (
|
||||
int width, int height, int clr0, int clr1, int clr2, int clr3)
|
||||
int width, int height, int *clr, float *stp)
|
||||
{
|
||||
guint8 r0,g0,b0,r1,g1,b1,r2,g2,b2,r3,g3,b3,a;
|
||||
guint8 r,g,b,a;
|
||||
int knee;
|
||||
|
||||
/*
|
||||
The knee is the hard transition point (e.g. at 0dB where the colors
|
||||
change dramatically to make clipping apparent). Thus there are two
|
||||
gradients in the pattern, the "normal range" and the "clip range", which
|
||||
are separated at the knee point.
|
||||
|
||||
clr0: color at bottom of normal range gradient
|
||||
clr1: color at top of normal range gradient
|
||||
clr2: color at bottom of clip range gradient
|
||||
clr3: color at top of clip range gradient
|
||||
*/
|
||||
|
||||
UINT_TO_RGBA (clr0, &r0, &g0, &b0, &a);
|
||||
UINT_TO_RGBA (clr1, &r1, &g1, &b1, &a);
|
||||
UINT_TO_RGBA (clr2, &r2, &g2, &b2, &a);
|
||||
UINT_TO_RGBA (clr3, &r3, &g3, &b3, &a);
|
||||
|
||||
// fake log calculation copied from log_meter.h
|
||||
// actual calculation:
|
||||
// log_meter(0.0f) =
|
||||
// def = (0.0f + 20.0f) * 2.5f + 50f
|
||||
// return def / 115.0f
|
||||
|
||||
const int knee = (int)floor((float)height * 100.0f / 115.0f);
|
||||
cairo_pattern_t* pat = cairo_pattern_create_linear (0.0, 0.0, width, height);
|
||||
|
||||
/*
|
||||
|
|
@ -119,21 +112,76 @@ FastMeter::generate_meter_pattern (
|
|||
knee-based positions by using (1.0 - y)
|
||||
*/
|
||||
|
||||
// Clip range top
|
||||
UINT_TO_RGBA (clr[9], &r, &g, &b, &a); // top/clip
|
||||
cairo_pattern_add_color_stop_rgb (pat, 0.0,
|
||||
r3/255.0, g3/255.0, b3/255.0);
|
||||
r/255.0, g/255.0, b/255.0);
|
||||
|
||||
// Clip range bottom
|
||||
cairo_pattern_add_color_stop_rgb (pat, 1.0 - (knee/(double)height),
|
||||
r2/255.0, g2/255.0, b2/255.0);
|
||||
knee = (int)floor((float)height * 100.0f / 115.0f); // -0dB
|
||||
|
||||
// Normal range top (double-stop at knee)
|
||||
UINT_TO_RGBA (clr[8], &r, &g, &b, &a);
|
||||
cairo_pattern_add_color_stop_rgb (pat, 1.0 - (knee/(double)height),
|
||||
r/255.0, g/255.0, b/255.0);
|
||||
|
||||
UINT_TO_RGBA (clr[7], &r, &g, &b, &a);
|
||||
cairo_pattern_add_color_stop_rgb (pat, 1.0 - (knee/(double)height),
|
||||
r/255.0, g/255.0, b/255.0);
|
||||
|
||||
knee = (int)floor((float)height * stp[2]/ 115.0f); // -3dB || -2dB
|
||||
|
||||
UINT_TO_RGBA (clr[6], &r, &g, &b, &a);
|
||||
cairo_pattern_add_color_stop_rgb (pat, 1.0 - (knee/(double)height),
|
||||
r/255.0, g/255.0, b/255.0);
|
||||
|
||||
UINT_TO_RGBA (clr[5], &r, &g, &b, &a);
|
||||
cairo_pattern_add_color_stop_rgb (pat, 1.0 - (knee/(double)height),
|
||||
r/255.0, g/255.0, b/255.0);
|
||||
|
||||
knee = (int)floor((float)height * stp[1] / 115.0f); // -9dB
|
||||
|
||||
UINT_TO_RGBA (clr[4], &r, &g, &b, &a);
|
||||
cairo_pattern_add_color_stop_rgb (pat, 1.0 - (knee/(double)height),
|
||||
r/255.0, g/255.0, b/255.0);
|
||||
|
||||
UINT_TO_RGBA (clr[3], &r, &g, &b, &a);
|
||||
cairo_pattern_add_color_stop_rgb (pat, 1.0 - (knee/(double)height),
|
||||
r/255.0, g/255.0, b/255.0);
|
||||
|
||||
knee = (int)floor((float)height * stp[0] / 115.0f); // -18dB
|
||||
|
||||
UINT_TO_RGBA (clr[2], &r, &g, &b, &a);
|
||||
cairo_pattern_add_color_stop_rgb (pat, 1.0 - (knee/(double)height),
|
||||
r/255.0, g/255.0, b/255.0);
|
||||
|
||||
UINT_TO_RGBA (clr[1], &r, &g, &b, &a);
|
||||
cairo_pattern_add_color_stop_rgb (pat, 1.0 - (knee/(double)height),
|
||||
r/255.0, g/255.0, b/255.0);
|
||||
|
||||
UINT_TO_RGBA (clr[0], &r, &g, &b, &a); // bottom
|
||||
cairo_pattern_add_color_stop_rgb (pat, 1.0,
|
||||
r/255.0, g/255.0, b/255.0);
|
||||
|
||||
Cairo::RefPtr<Cairo::Pattern> p (new Cairo::Pattern (pat, false));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
Cairo::RefPtr<Cairo::Pattern>
|
||||
FastMeter::generate_meter_background (
|
||||
int width, int height, int *clr)
|
||||
{
|
||||
guint8 r0,g0,b0,r1,g1,b1,a;
|
||||
|
||||
cairo_pattern_t* pat = cairo_pattern_create_linear (0.0, 0.0, width, height);
|
||||
|
||||
UINT_TO_RGBA (clr[0], &r0, &g0, &b0, &a);
|
||||
UINT_TO_RGBA (clr[1], &r1, &g1, &b1, &a);
|
||||
|
||||
cairo_pattern_add_color_stop_rgb (pat, 0.0,
|
||||
r1/255.0, g1/255.0, b1/255.0);
|
||||
|
||||
// Normal range bottom
|
||||
cairo_pattern_add_color_stop_rgb (pat, 1.0,
|
||||
r0/255.0, g0/255.0, b0/255.0); // top
|
||||
r0/255.0, g0/255.0, b0/255.0);
|
||||
|
||||
Cairo::RefPtr<Cairo::Pattern> p (new Cairo::Pattern (pat, false));
|
||||
|
||||
|
|
@ -142,30 +190,53 @@ FastMeter::generate_meter_pattern (
|
|||
|
||||
Cairo::RefPtr<Cairo::Pattern>
|
||||
FastMeter::request_vertical_meter(
|
||||
int width, int height, int clr0, int clr1, int clr2, int clr3)
|
||||
int width, int height, int *clr, float *stp)
|
||||
{
|
||||
if (height < min_pattern_metric_size)
|
||||
height = min_pattern_metric_size;
|
||||
if (height > max_pattern_metric_size)
|
||||
height = max_pattern_metric_size;
|
||||
|
||||
const PatternMapKey key (width, height, clr0, clr1, clr2, clr3);
|
||||
PatternMap::iterator i;
|
||||
if ((i = v_pattern_cache.find (key)) != v_pattern_cache.end()) {
|
||||
const Pattern10MapKey key (width, height,
|
||||
stp[0], stp[1], stp[2],
|
||||
clr[0], clr[1], clr[2], clr[3],
|
||||
clr[4], clr[5], clr[6], clr[7],
|
||||
clr[8], clr[9]);
|
||||
Pattern10Map::iterator i;
|
||||
if ((i = vm_pattern_cache.find (key)) != vm_pattern_cache.end()) {
|
||||
return i->second;
|
||||
}
|
||||
|
||||
Cairo::RefPtr<Cairo::Pattern> p = generate_meter_pattern (
|
||||
width, height, clr0, clr1, clr2, clr3);
|
||||
v_pattern_cache[key] = p;
|
||||
width, height, clr, stp);
|
||||
vm_pattern_cache[key] = p;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
FastMeter::~FastMeter ()
|
||||
Cairo::RefPtr<Cairo::Pattern>
|
||||
FastMeter::request_vertical_background(
|
||||
int width, int height, int *bgc)
|
||||
{
|
||||
if (height < min_pattern_metric_size)
|
||||
height = min_pattern_metric_size;
|
||||
if (height > max_pattern_metric_size)
|
||||
height = max_pattern_metric_size;
|
||||
|
||||
const PatternBgMapKey key (width, height, bgc[0], bgc[1]);
|
||||
PatternBgMap::iterator i;
|
||||
if ((i = vb_pattern_cache.find (key)) != vb_pattern_cache.end()) {
|
||||
return i->second;
|
||||
}
|
||||
|
||||
Cairo::RefPtr<Cairo::Pattern> p = generate_meter_background (
|
||||
width, height, bgc);
|
||||
vb_pattern_cache[key] = p;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FastMeter::set_hold_count (long val)
|
||||
{
|
||||
|
|
@ -207,10 +278,8 @@ FastMeter::on_size_allocate (Gtk::Allocation &alloc)
|
|||
}
|
||||
|
||||
if (pixheight != h) {
|
||||
fgpattern = request_vertical_meter (
|
||||
request_width, h, _clr0, _clr1, _clr2, _clr3);
|
||||
bgpattern = request_vertical_meter (
|
||||
request_width, h, _bgc0, _bgc1, _bgc2, _bgc3);
|
||||
fgpattern = request_vertical_meter (request_width, h, _clr, _stp);
|
||||
bgpattern = request_vertical_background (request_width, h, _bgc);
|
||||
pixheight = h - 2;
|
||||
pixwidth = request_width - 2;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,8 +37,12 @@ class FastMeter : public Gtk::DrawingArea {
|
|||
};
|
||||
|
||||
FastMeter (long hold_cnt, unsigned long width, Orientation, int len=0,
|
||||
int clr0=0x00ff00, int clr1=0xffff00, int clr2=0xffaa00, int clr3=0xff0000,
|
||||
int bgc0=0x111111ff, int bgc1=0x333333ff, int bgc2=0x333333ff, int bgc3=0x444444ff
|
||||
int clr0=0x008800ff, int clr1=0x008800ff,
|
||||
int clr2=0x00ff00ff, int clr3=0x00ff00ff,
|
||||
int clr4=0x80ff00ff, int clr5=0x80ff00ff,
|
||||
int clr6=0xffaa00ff, int clr7=0xffaa00ff,
|
||||
int clr8=0xff0000ff, int clr9=0xff0000ff,
|
||||
int bgc0=0x333333ff, int bgc1=0x444444ff
|
||||
);
|
||||
virtual ~FastMeter ();
|
||||
|
||||
|
|
@ -63,8 +67,10 @@ private:
|
|||
Cairo::RefPtr<Cairo::Pattern> bgpattern;
|
||||
gint pixheight;
|
||||
gint pixwidth;
|
||||
int _clr0, _clr1, _clr2, _clr3;
|
||||
int _bgc0, _bgc1, _bgc2, _bgc3;
|
||||
|
||||
float _stp[3];
|
||||
int _clr[10];
|
||||
int _bgc[2];
|
||||
|
||||
Orientation orientation;
|
||||
GdkRectangle pixrect;
|
||||
|
|
@ -82,24 +88,53 @@ private:
|
|||
void queue_vertical_redraw (const Glib::RefPtr<Gdk::Window>&, float);
|
||||
|
||||
static Cairo::RefPtr<Cairo::Pattern> generate_meter_pattern (
|
||||
int w, int h, int clr0, int clr1, int clr2, int clr3);
|
||||
int w, int h, int *clr, float *stp);
|
||||
static Cairo::RefPtr<Cairo::Pattern> request_vertical_meter (
|
||||
int w, int h, int clr0, int clr1, int clr2, int clr3);
|
||||
int w, int h, int *clr, float *stp);
|
||||
|
||||
struct PatternMapKey {
|
||||
PatternMapKey (int w, int h, int c0, int c1, int c2, int c3)
|
||||
static Cairo::RefPtr<Cairo::Pattern> generate_meter_background (
|
||||
int w, int h, int *bgc);
|
||||
static Cairo::RefPtr<Cairo::Pattern> request_vertical_background (
|
||||
int w, int h, int *bgc);
|
||||
|
||||
struct Pattern10MapKey {
|
||||
Pattern10MapKey (
|
||||
int w, int h,
|
||||
float stp0, float stp1, float stp2,
|
||||
int c0, int c1, int c2, int c3,
|
||||
int c4, int c5, int c6, int c7,
|
||||
int c8, int c9
|
||||
)
|
||||
: dim(w, h)
|
||||
, cols(c0, c1, c2, c3)
|
||||
, stp(stp0, stp1, stp2)
|
||||
, cols(c0, c1, c2, c3, c4, c5, c6, c7, c8, c9)
|
||||
{}
|
||||
inline bool operator<(const PatternMapKey& rhs) const {
|
||||
inline bool operator<(const Pattern10MapKey& rhs) const {
|
||||
return (dim < rhs.dim)
|
||||
|| (dim == rhs.dim && stp < rhs.stp)
|
||||
|| (dim == rhs.dim && stp == rhs.stp && cols < rhs.cols);
|
||||
}
|
||||
boost::tuple<int, int> dim;
|
||||
boost::tuple<float, float, float> stp;
|
||||
boost::tuple<int, int, int, int, int, int, int, int, int, int> cols;
|
||||
};
|
||||
typedef std::map<Pattern10MapKey, Cairo::RefPtr<Cairo::Pattern> > Pattern10Map;
|
||||
|
||||
struct PatternBgMapKey {
|
||||
PatternBgMapKey (int w, int h, int c0, int c1)
|
||||
: dim(w, h)
|
||||
, cols(c0, c1)
|
||||
{}
|
||||
inline bool operator<(const PatternBgMapKey& rhs) const {
|
||||
return (dim < rhs.dim) || (dim == rhs.dim && cols < rhs.cols);
|
||||
}
|
||||
boost::tuple<int, int> dim; // width, height
|
||||
boost::tuple<int, int, int, int> cols; // c0, c1, c2, c3
|
||||
boost::tuple<int, int> dim;
|
||||
boost::tuple<int, int> cols;
|
||||
};
|
||||
typedef std::map<PatternMapKey, Cairo::RefPtr<Cairo::Pattern> > PatternMap;
|
||||
typedef std::map<PatternBgMapKey, Cairo::RefPtr<Cairo::Pattern> > PatternBgMap;
|
||||
|
||||
static PatternMap v_pattern_cache;
|
||||
static Pattern10Map vm_pattern_cache;
|
||||
static PatternBgMap vb_pattern_cache;
|
||||
static int min_pattern_metric_size; // min dimension for axis that displays the meter level
|
||||
static int max_pattern_metric_size; // max dimension for axis that displays the meter level
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue