+void
+PixFader::flush_pattern_cache () {
+ for (list<FaderImage*>::iterator f = _patterns.begin(); f != _patterns.end(); ++f) {
+ cairo_pattern_destroy ((*f)->pattern);
+ }
+ _patterns.clear();
+}
+
+
+cairo_pattern_t*
+PixFader::find_pattern (double afr, double afg, double afb,
+ double abr, double abg, double abb,
+ int w, int h)
+{
+ for (list<FaderImage*>::iterator f = _patterns.begin(); f != _patterns.end(); ++f) {
+ if ((*f)->matches (afr, afg, afb, abr, abg, abb, w, h)) {
+ return (*f)->pattern;
+ }
+ }
+ return 0;
+}
+
+void
+PixFader::create_patterns ()
+{
+ Gdk::Color c = get_style()->get_fg (get_state());
+ float fr, fg, fb;
+ float br, bg, bb;
+
+ fr = c.get_red_p ();
+ fg = c.get_green_p ();
+ fb = c.get_blue_p ();
+
+ c = get_style()->get_bg (get_state());
+
+ br = c.get_red_p ();
+ bg = c.get_green_p ();
+ bb = c.get_blue_p ();
+
+ cairo_surface_t* surface;
+ cairo_t* tc = 0;
+
+ if (get_width() <= 1 || get_height() <= 1) {
+ return;
+ }
+
+ if ((_pattern = find_pattern (fr, fg, fb, br, bg, bb, get_width(), get_height())) != 0) {
+ /* found it - use it */
+ return;
+ }
+
+ if (_orien == VERT) {
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, get_width(), get_height() * 2.0);
+ tc = cairo_create (surface);
+
+ /* paint background + border */
+
+ cairo_pattern_t* shade_pattern = cairo_pattern_create_linear (0.0, 0.0, get_width(), 0);
+ cairo_pattern_add_color_stop_rgba (shade_pattern, 0, br*0.4,bg*0.4,bb*0.4, 1.0);
+ cairo_pattern_add_color_stop_rgba (shade_pattern, 0.25, br*0.6,bg*0.6,bb*0.6, 1.0);
+ cairo_pattern_add_color_stop_rgba (shade_pattern, 1, br*0.8,bg*0.8,bb*0.8, 1.0);
+ cairo_set_source (tc, shade_pattern);
+ cairo_rectangle (tc, 0, 0, get_width(), get_height() * 2.0);
+ cairo_fill (tc);
+
+ cairo_pattern_destroy (shade_pattern);
+
+ /* paint lower shade */
+
+ shade_pattern = cairo_pattern_create_linear (0.0, 0.0, get_width() - 2 - CORNER_OFFSET , 0);
+ cairo_pattern_add_color_stop_rgba (shade_pattern, 0, fr*0.8,fg*0.8,fb*0.8, 1.0);
+ cairo_pattern_add_color_stop_rgba (shade_pattern, 1, fr*0.6,fg*0.6,fb*0.6, 1.0);
+ cairo_set_source (tc, shade_pattern);
+ Gtkmm2ext::rounded_top_half_rectangle (tc, CORNER_OFFSET, get_height() + CORNER_OFFSET,
+ get_width() - CORNER_SIZE, get_height(), CORNER_RADIUS);
+ cairo_fill (tc);
+
+ cairo_pattern_destroy (shade_pattern);
+
+ _pattern = cairo_pattern_create_for_surface (surface);
+
+ } else {
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, get_width() * 2.0, get_height());
+ tc = cairo_create (surface);
+
+ /* paint right shade (background section)*/
+
+ cairo_pattern_t* shade_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, get_height());
+ cairo_pattern_add_color_stop_rgba (shade_pattern, 0, br*0.4,bg*0.4,bb*0.4, 1.0);
+ cairo_pattern_add_color_stop_rgba (shade_pattern, 0.25, br*0.6,bg*0.6,bb*0.6, 1.0);
+ cairo_pattern_add_color_stop_rgba (shade_pattern, 1, br*0.8,bg*0.8,bb*0.8, 1.0);
+ cairo_set_source (tc, shade_pattern);
+ cairo_rectangle (tc, 0, 0, get_width() * 2.0, get_height());
+ cairo_fill (tc);
+
+ /* paint left shade (active section/foreground) */
+
+ shade_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, get_height());
+ cairo_pattern_add_color_stop_rgba (shade_pattern, 0, fr*0.8,fg*0.8,fb*0.8, 1.0);
+ cairo_pattern_add_color_stop_rgba (shade_pattern, 1, fr*0.6,fg*0.6,fb*0.6, 1.0);
+ cairo_set_source (tc, shade_pattern);
+ Gtkmm2ext::rounded_right_half_rectangle (tc, CORNER_OFFSET, CORNER_OFFSET,
+ get_width() - CORNER_OFFSET, get_height() - CORNER_SIZE, CORNER_RADIUS);
+ cairo_fill (tc);
+ cairo_pattern_destroy (shade_pattern);
+
+ _pattern = cairo_pattern_create_for_surface (surface);
+ }
+
+ /* cache it for others to use */
+
+ _patterns.push_back (new FaderImage (_pattern, fr, fg, fb, br, bg, bb, get_width(), get_height()));
+
+ cairo_destroy (tc);
+ cairo_surface_destroy (surface);
+}
+
+void
+PixFader::render (cairo_t *cr, cairo_rectangle_t* area)