Speed up regionview creation by using pixbufs for name labels instead of Gnome::Canva...
authorNick Mainsbridge <beatroute@iprimus.com.au>
Tue, 5 May 2009 18:41:21 +0000 (18:41 +0000)
committerNick Mainsbridge <beatroute@iprimus.com.au>
Tue, 5 May 2009 18:41:21 +0000 (18:41 +0000)
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@5053 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/audio_region_view.cc
gtk2_ardour/canvas.h
gtk2_ardour/imageframe_view.cc
gtk2_ardour/region_view.cc
gtk2_ardour/time_axis_view_item.cc
gtk2_ardour/time_axis_view_item.h

index 8b6dab3cc942e4c2417aacb5f9a8469c1e9bcdde..290d8b382c809f31895f3a4f2f9e80e448178966 100644 (file)
@@ -463,10 +463,11 @@ AudioRegionView::set_height (gdouble height)
 
        manage_zero_line ();
        reset_fade_shapes ();
-       
-       if (name_text) {
-               name_text->raise_to_top();
+
+       if (name_pixbuf) {
+               name_pixbuf->raise_to_top();
        }
+
 }
 
 void
index 58bb5fcb5a662c0bf231607f15d3ca116b103585..7c001e67530637314fa35cf61681097eca0e36eb 100644 (file)
@@ -33,6 +33,7 @@ namespace Gnome {
                class Text;
                class Line;
                class Points;
+               class Pixbuf;
                class ImageFrame;
        }
 }
index d1291472a4b98b062f53db6d4529a3599f7b5991..1d6d7c9f03f5837051f0330595754952ea365138 100644 (file)
@@ -274,11 +274,11 @@ ImageFrameView::set_height (gdouble h)
        frame->raise_to_top();
        imageframe->raise_to_top();
        name_highlight->raise_to_top();
-       name_text->raise_to_top();
+       name_pixbuf->raise_to_top();
        frame_handle_start->raise_to_top();
        frame_handle_end->raise_to_top();
  
-       name_text->property_y() = h - TimeAxisViewItem::NAME_Y_OFFSET;
+       name_pixbuf->property_y() = h - TimeAxisViewItem::NAME_Y_OFFSET;
        frame->property_y2() = h;
 
        name_highlight->property_y1() = (gdouble) h - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE;
index 49b7894d11fd815c45fc1ecb3d2f9da442be6d36..2bbfa4b5f5224d2ea4a7ba5105e5dbd660d92160 100644 (file)
@@ -148,8 +148,8 @@ RegionView::init (Gdk::Color& basic_color, bool wfd)
                name_highlight->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_region_view_name_highlight_event), name_highlight, this));
        }
 
-       if (name_text) {
-               name_text->set_data ("regionview", this);
+       if (name_pixbuf) {
+               name_pixbuf->set_data ("regionview", this);
        }
 
        reset_width_dependent_items ((double) _region->length() / samples_per_unit);
index 0a33b4c205f2a41808eb213d7519ba8d4f26c6e6..75d3cbd595ac56d0e874c53803575df83a4f5e31 100644 (file)
@@ -53,6 +53,37 @@ double TimeAxisViewItem::NAME_Y_OFFSET;
 double TimeAxisViewItem::NAME_HIGHLIGHT_SIZE;
 double TimeAxisViewItem::NAME_HIGHLIGHT_THRESH;
 
+inline guint8
+convert_color_channel (guint8 src,
+                      guint8 alpha)
+{
+       return alpha ? ((guint (src) << 8) - src) / alpha : 0;
+}
+
+void
+convert_bgra_to_rgba (guint8 const* src,
+                     guint8*       dst,
+                     int           width,
+                     int           height)
+{
+       guint8 const* src_pixel = src;
+       guint8*       dst_pixel = dst;
+       
+       for (int y = 0; y < height; y++)
+               for (int x = 0; x < width; x++)
+               {
+                       dst_pixel[0] = convert_color_channel (src_pixel[2],
+                                                             src_pixel[3]);
+                       dst_pixel[1] = convert_color_channel (src_pixel[1],
+                                                             src_pixel[3]);
+                       dst_pixel[2] = convert_color_channel (src_pixel[0],
+                                                             src_pixel[3]);
+                       dst_pixel[3] = src_pixel[3];
+                       
+                       dst_pixel += 4;
+                       src_pixel += 4;
+               }
+}
 
 //---------------------------------------------------------------------------------------//
 // Constructor / Desctructor
@@ -78,7 +109,7 @@ TimeAxisViewItem::TimeAxisViewItem(const string & it_name, ArdourCanvas::Group&
                /* first constructed item sets up font info */
 
                NAME_FONT = get_font_for_style (N_("TimeAxisViewItemName"));
-               
+
                Gtk::Window win;
                Gtk::Label foo;
                win.add (foo);
@@ -122,13 +153,10 @@ TimeAxisViewItem::TimeAxisViewItem (const TimeAxisViewItem& other)
        init (other.item_name, other.samples_per_unit, c, other.frame_position, other.item_duration, other.visibility);
 }
 
-
 void
 TimeAxisViewItem::init (const string& it_name, double spu, Gdk::Color& base_color, nframes_t start, nframes_t duration, Visibility vis)
 {
        item_name = it_name ;
-       name_text_width = ::pixel_width (it_name, *NAME_FONT);
-       last_name_text_width = 0;
        samples_per_unit = spu ;
        should_show_selection = true;
        frame_position = start ;
@@ -226,21 +254,11 @@ TimeAxisViewItem::init (const string& it_name, double spu, Gdk::Color& base_colo
        }
 
        if (visibility & ShowNameText) {
-               name_text = new ArdourCanvas::Text (*group);
-               name_text->property_x() = (double) TimeAxisViewItem::NAME_X_OFFSET;
-               /* trackview.current_height() is the bottom of the trackview. subtract 1 to get back to the bottom of the highlight,
-                  then NAME_Y_OFFSET to position the text in the vertical center of the highlight
-               */
-               name_text->property_y() = (double) trackview.current_height() - 1.0 - TimeAxisViewItem::NAME_Y_OFFSET;
-               name_text->property_font_desc() = *NAME_FONT;
-               name_text->property_anchor() = Gtk::ANCHOR_NW;
-
-               name_text->set_data ("timeaxisviewitem", this);
-               
-       } else {
-               name_text = 0;
+               name_pixbuf = new ArdourCanvas::Pixbuf(*group);
+               name_pixbuf->property_x() = NAME_X_OFFSET;
+               name_pixbuf->property_y() = trackview.current_height() - 1.0 - NAME_Y_OFFSET;
+       
        }
-
        set_color (base_color) ;
        
        set_duration (item_duration, this) ;
@@ -487,7 +505,6 @@ TimeAxisViewItem::set_item_name(std::string new_name, void* src)
        if (new_name != item_name) {
                std::string temp_name = item_name ;
                item_name = new_name ;
-               name_text_width = ::pixel_width (new_name, *NAME_FONT);
                NameChanged (item_name, temp_name, src) ; /* EMIT_SIGNAL */
        }
 }
@@ -555,11 +572,44 @@ TimeAxisViewItem::get_time_axis_view()
 void
 TimeAxisViewItem::set_name_text(const ustring& new_name)
 {
-       if (name_text) {
-               name_text->property_text() = new_name;
-               name_text_width = pixel_width (new_name, *NAME_FONT);
-               name_text_size_cache.clear ();
+       uint32_t pb_width, it_width;
+       double font_size;
+
+       font_size = NAME_FONT->get_size() / Pango::SCALE;
+       it_width = trackview.editor.frame_to_pixel(item_duration);
+       pb_width = new_name.length() * font_size;
+
+       if (pb_width > it_width - NAME_X_OFFSET) {
+               pb_width = it_width - NAME_X_OFFSET;
+       }
+
+       if (pb_width <= 0 || it_width < NAME_X_OFFSET) {
+               name_pixbuf->hide();
+               return;
+       } else {
+               name_pixbuf->show();
        }
+
+       Glib::RefPtr<Gdk::Pixbuf> buf = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, pb_width, NAME_HIGHLIGHT_SIZE);
+
+       cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, pb_width, NAME_HIGHLIGHT_SIZE );
+       cairo_t *cr = cairo_create (surface);
+       cairo_text_extents_t te;
+       cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
+       cairo_select_font_face (cr, NAME_FONT->get_family().c_str(),
+                               CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
+       cairo_set_font_size (cr, font_size);
+       cairo_text_extents (cr, new_name.c_str(), &te);
+       
+       cairo_move_to (cr, 0.5,
+                      0.5 - te.height / 2 - te.y_bearing + NAME_HIGHLIGHT_SIZE / 2);
+       cairo_show_text (cr, new_name.c_str());
+       
+       unsigned char* src = cairo_image_surface_get_data (surface);
+       convert_bgra_to_rgba(src, buf->get_pixels(), pb_width, NAME_HIGHLIGHT_SIZE);
+       
+       cairo_destroy(cr);
+       name_pixbuf->property_pixbuf() = buf;
 }
 
 /**
@@ -573,14 +623,12 @@ TimeAxisViewItem::set_height (double height)
        if (name_highlight) {
                if (height < NAME_HIGHLIGHT_THRESH) {
                        name_highlight->hide();
-                       if (name_text) {
-                               name_text->hide();
-                       }
+                       name_pixbuf->hide();
+                       
                } else {
                        name_highlight->show();
-                       if (name_text) {
-                               name_text->show();
-                       }
+                       name_pixbuf->show();
+                       
                }
 
                if (height > NAME_HIGHLIGHT_SIZE) {
@@ -593,14 +641,7 @@ TimeAxisViewItem::set_height (double height)
                }
        }
 
-       if (name_text) {
-               name_text->property_y() = height+1 - NAME_Y_OFFSET;
-               if (height < NAME_HIGHLIGHT_THRESH) {
-                       name_text->property_fill_color_rgba() =  fill_color;
-               } else {
-                       name_text->property_fill_color_rgba() = label_color;
-               }
-       }
+       name_pixbuf->property_y() = height+1 - NAME_Y_OFFSET;
 
        if (frame) {
                frame->property_y2() = height+1;
@@ -649,10 +690,10 @@ TimeAxisViewItem::get_name_highlight()
 /**
  * 
  */
-ArdourCanvas::Text*
-TimeAxisViewItem::get_name_text()
+ArdourCanvas::Pixbuf*
+TimeAxisViewItem::get_name_pixbuf()
 {
-       return (name_text) ;
+       return (name_pixbuf) ;
 }
 
 /**
@@ -756,20 +797,6 @@ void
 TimeAxisViewItem::set_colors()
 {
        set_frame_color() ;
-       if (name_text) {
-               double height = NAME_HIGHLIGHT_THRESH;
-
-               if (frame) {
-                       height = frame->property_y2();
-               }
-
-               if (height < NAME_HIGHLIGHT_THRESH) {
-                       name_text->property_fill_color_rgba() =  fill_color;
-               }
-               else {
-                       name_text->property_fill_color_rgba() = label_color;
-               }
-       }
 
        if (name_highlight) {
                name_highlight->property_fill_color_rgba() = fill_color;
@@ -845,9 +872,7 @@ TimeAxisViewItem::reset_width_dependent_items (double pixel_width)
 
                if (name_highlight) {
                        name_highlight->hide();
-                       if (name_text) {
-                               name_text->hide();
-                       }
+                       name_pixbuf->hide();
                }
 
                if (frame) {
@@ -868,13 +893,10 @@ TimeAxisViewItem::reset_width_dependent_items (double pixel_width)
 
                        if (height < NAME_HIGHLIGHT_THRESH) {
                                name_highlight->hide();
-                               if (name_text) {
-                                       name_text->hide();
-                               }
+                               name_pixbuf->hide();
                        } else {
                                name_highlight->show();
-                               if (name_text && !get_item_name().empty()) {
-                                       name_text->show();
+                               if (!get_item_name().empty()) {
                                        reset_name_width (pixel_width);
                                }
                        }
@@ -909,90 +931,7 @@ TimeAxisViewItem::reset_width_dependent_items (double pixel_width)
 void
 TimeAxisViewItem::reset_name_width (double pixel_width)
 {
-       if (name_text == 0) {
-               return;
-       }
-
-       int limit = (int) floor (pixel_width - NAME_X_OFFSET);
-       bool shrinking = (last_name_text_width > pixel_width);
-       int actual_width;
-       ustring ustr;
-       ustring::size_type n;
-
-       if ((last_name_text_width &&                                       // we did this once
-            shrinking &&                                                  // we're getting smaller
-            (name_text_width <= limit) &&                                 // fits the new size
-            (name_text_width <= last_name_text_width - NAME_X_OFFSET))) { // fit into the old size too
-               last_name_text_width = pixel_width;
-               return;
-       }
-
-       /* now check the cache of existing truncations */
-
-       Gtk::Label foo;
-       Glib::RefPtr<Pango::Layout> layout = foo.create_pango_layout ("");
-
-       for (n = item_name.length(); n > 0; --n) {
-               
-               map<ustring::size_type,int>::iterator i;
-
-               if ((i = name_text_size_cache.find (n)) != name_text_size_cache.end()) {
-
-                       /* we know the length of this substring already */
-                       
-                       if ((actual_width = (*i).second) < limit) {
-
-                               /* it fits, use it */
-                               
-                               ustr = item_name.substr (0, n);
-                               break;
-                       }
-                                               
-               } else {
-                       
-                       /* we don't know the length of this substring already, so compute
-                          it and put it into the cache.
-                        */
-
-                       layout->set_text (item_name.substr (0, n));
-                       
-                       int width, height;
-                       Gtkmm2ext::get_ink_pixel_size (layout, width, height);
-                       
-                       name_text_size_cache[n] = width;
-
-                       if ((actual_width = width) < limit) {
-                               ustr = item_name.substr (0, n);
-                               break;
-                       }
-               }
-       }
-
-       if (n == 0) {
-               name_text->property_text() = "";
-               last_name_text_width = pixel_width;
-               return;
-       } 
-
-       /* don't use name for event handling if it leaves no room
-          for trimming to work.
-       */
-       
-       if (pixel_width - actual_width < (NAME_X_OFFSET * 2.0)) {
-               if (name_connected) {
-                       name_connected = false;
-               }
-       } else {
-               if (!name_connected) {
-                       name_connected = true;
-               }
-       }
-       
-       name_text->property_text() = ustr;
-       name_text_width = actual_width;
-       name_text->show();
-       last_name_text_width = pixel_width;
-
+       set_name_text (item_name);
 }
 
 
index c01287c99630f823ef64e0e7dbf223df2136dfe5..41fc88d17faca5fb76846042582cebaf2aef9880 100644 (file)
@@ -23,7 +23,7 @@
 #include <jack/jack.h>
 #include <string>
 
-#include <libgnomecanvasmm/text.h>
+#include <libgnomecanvasmm/pixbuf.h>
 
 #include "selectable.h"
 #include "simplerect.h"
@@ -231,7 +231,7 @@ class TimeAxisViewItem : public Selectable
     /**
      * 
      */
-    ArdourCanvas::Text* get_name_text();
+    ArdourCanvas::Pixbuf* get_name_pixbuf();
 
 
     /**
@@ -454,18 +454,13 @@ class TimeAxisViewItem : public Selectable
     ArdourCanvas::Group*      group;
     ArdourCanvas::SimpleRect* vestigial_frame;
     ArdourCanvas::SimpleRect* frame;
-    ArdourCanvas::Text*       name_text;
+    ArdourCanvas::Pixbuf*     name_pixbuf;
     ArdourCanvas::SimpleRect* name_highlight;
     ArdourCanvas::SimpleRect* frame_handle_start;
     ArdourCanvas::SimpleRect* frame_handle_end;
 
-    int name_text_width;
-    double last_name_text_width;
-
-    std::map<Glib::ustring::size_type,int> name_text_size_cache;
-    
     Visibility visibility;
-       bool _recregion;
+    bool _recregion;
 
 
 }; /* class TimeAxisViewItem */