refresh frame fix, dblclk proxy viewer fix, vicon refresh fix for awdw resize, fix...
[goodguy/history.git] / cinelerra-5.1 / guicast / bctheme.C
index 06cbff8d139a65aca6453dda08d1a3211d6f0387..c206f258af27131ab8e8dd0a3e1d12a3812444ef 100644 (file)
 
 BC_Theme::BC_Theme()
 {
-       data_ptr = 0;
-       contents_ptr = 0;
-       last_image = 0;
-       last_pointer = 0;
+       last_image_data = 0;
+       last_image_set = 0;
+       image_sets_start = -1;
 }
 
 BC_Theme::~BC_Theme()
 {
        image_sets.remove_all_objects();
+       images.remove_all_objects();
 }
 
 void BC_Theme::dump()
 {
-       printf("BC_Theme::dump 1 image_sets=%d contents=%d\n",
-               image_sets.total,
-               contents.total);
-       for(int i = 0; i < contents.total; i++)
-               printf("    %s %p\n", contents.values[i], pointers.values[i]);
+       printf("BC_Theme::dump 1 images=%d\n", images.size());
+       for( int i=0; i<images.size(); ++i ) {
+               BC_ImageData *image_data = images[i];
+               printf("%4d. %s %p\n", i, image_data->name, image_data->data);
+       }
+       printf("BC_Theme::dump 2 image_sets=%d\n", image_sets.size());
+       for( int i=0; i<image_sets.size(); ++i ) {
+               BC_ThemeSet *image_set = image_sets[i];
+               printf("%4d. %s %p\n", i, image_set->title, image_set->data[0]);
+       }
 }
 
 BC_Resources* BC_Theme::get_resources()
@@ -61,11 +66,11 @@ BC_Resources* BC_Theme::get_resources()
 VFrame* BC_Theme::new_image(const char *title, const char *path)
 {
        VFrame *existing_image = title[0] ? get_image(title, 0) : 0;
-       if(existing_image) return existing_image;
+       if( existing_image ) return existing_image;
 
        BC_ThemeSet *result = new BC_ThemeSet(1, 0, title);
        result->data[0] = new VFramePng(get_image_data(path));
-       image_sets.append(result);
+       add_image_set(result);
        return result->data[0];
 }
 
@@ -74,25 +79,20 @@ VFrame* BC_Theme::new_image(const char *path)
        return new_image("", path);
 }
 
-
-
 // These create image sets which are stored in the image_sets table.
 VFrame** BC_Theme::new_image_set(const char *title, int total, va_list *args)
 {
-       if(!total)
-       {
+       if( !total ) {
                printf("BC_Theme::new_image_set %d %s zero number of images\n",
-                       __LINE__,
-                       title);
+                       __LINE__, title);
        }
 
        VFrame **existing_image_set = title[0] ? get_image_set(title, 0) : 0;
-       if(existing_image_set) return existing_image_set;
+       if( existing_image_set ) return existing_image_set;
 
        BC_ThemeSet *result = new BC_ThemeSet(total, 1, title);
-       image_sets.append(result);
-       for(int i = 0; i < total; i++)
-       {
+       add_image_set(result);
+       for( int i=0; i<total; ++i ) {
                char *path = va_arg(*args, char*);
                result->data[i] = new_image(path);
        }
@@ -104,15 +104,15 @@ VFrame** BC_Theme::new_image_set_images(const char *title, int total, ...)
        va_list list;
        va_start(list, total);
        BC_ThemeSet *existing_image_set = title[0] ? get_image_set_object(title) : 0;
-       if(existing_image_set)
-       {
+       if( existing_image_set ) {
                image_sets.remove_object(existing_image_set);
+               last_image_set = 0;
+               last_image_data = 0;
        }
 
        BC_ThemeSet *result = new BC_ThemeSet(total, 0, title);
-       image_sets.append(result);
-       for(int i = 0; i < total; i++)
-       {
+       add_image_set(result);
+       for( int i=0; i<total; ++i ) {
                result->data[i] = va_arg(list, VFrame*);
        }
        va_end(list);
@@ -139,21 +139,64 @@ VFrame** BC_Theme::new_image_set(int total, ...)
        return result;
 }
 
+void BC_Theme::add_image_set(BC_ThemeSet *image_set)
+{
+       image_sets.append(image_set);
+       if( image_sets_start >= 0 ) {
+               printf("BC_Theme::add_image_set image_sets unsorted, lookups degraded\n");
+               image_sets_start = -1;
+       }
+}
+
+int BC_Theme::image_set_cmpr(const void *ap, const void *bp)
+{
+       BC_ThemeSet*a = *(BC_ThemeSet**)ap, *b = *(BC_ThemeSet**)bp;
+        return strcmp(a->title, b->title);
+}
+
+void BC_Theme::sort_image_sets()
+{
+       if( image_sets_start >= 0 ) return;
+       qsort(&image_sets[0], image_sets.size(), sizeof(image_sets[0]), image_set_cmpr);
+// skip over un-titled image sets
+       int i = 0, n = image_sets.size();
+       while( i<n && !image_sets[i]->title[0] ) ++i;
+       image_sets_start = i;
+}
+
 BC_ThemeSet* BC_Theme::get_image_set_object(const char *title)
 {
+       if( last_image_set && !strcmp(title,last_image_set->title) )
+               return last_image_set;
+
+       if( image_sets_start >= 0 ) {
+// binary search for image set
+               int r = image_sets.size(), l = image_sets_start-1;
+               int m = 0, v = -1;
+               while( r-l > 1 ) {
+                       m = (l + r) / 2;
+                       BC_ThemeSet *image_set = image_sets[m];
+                       if( !(v=strcmp(title, image_set->title)) )
+                               return last_image_set = image_set;
+                       if( v > 0 ) l = m; else r = m;
+               }
+       }
+       else {
 // compare title[0],title[1] for faster prefix test
-       const unsigned char *bp = (const unsigned char*)title;
-       unsigned short tval = bp[0];
-       if( tval ) tval |= (bp[1] << 8);
-
-       for( int i=0; i < image_sets.total; ++i ) {
-               const char *tp = image_sets[i]->title;
-               bp = (const unsigned char *) tp;
-               unsigned short val = bp[0];
-               if( val ) val |= (bp[1] << 8);
-               if( val != tval ) continue;
-               if( !strcmp(tp, title) ) return image_sets[i];
+               const unsigned char *tp = (const unsigned char*)title;
+               unsigned short tval = tp[0];
+               if( tval ) tval |= (tp[1] << 8);
+
+               for( int i=0; i<image_sets.size(); ++i ) {
+                       tp = (const unsigned char *)image_sets[i]->title;
+                       unsigned short val = tp[0];
+                       if( val ) val |= (tp[1] << 8);
+                       if( val != tval ) continue;
+                       if( !strcmp((const char *)tp, title) )
+                               return last_image_set = image_sets[i];
+               }
        }
+
        return 0;
 }
 
@@ -164,10 +207,10 @@ VFrame* BC_Theme::get_image(const char *title, int use_default)
 
 
 // Return the first image it can find.  This should always work.
-       if(use_default) {
+       if( use_default ) {
                printf("BC_Theme::get_image: image \"%s\" not found.\n",
                        title);
-               if(image_sets.total)
+               if( image_sets.size() )
                        return image_sets[0]->data[0];
        }
 
@@ -181,22 +224,19 @@ VFrame** BC_Theme::get_image_set(const char *title, int use_default)
        if( tsp ) return tsp->data;
 
 // Get the image set with the largest number of images.
-       if(use_default)
-       {
+       if( use_default ) {
                printf("BC_Theme::get_image_set: image set \"%s\" not found.\n",
                        title);
                int max_total = 0;
                int max_number = -1;
-               for(int i = 0; i < image_sets.total; i++)
-               {
-                       if(image_sets[i]->total > max_total)
-                       {
+               for( int i=0; i<image_sets.size(); ++i ) {
+                       if( image_sets[i]->total > max_total ) {
                                max_total = image_sets[i]->total;
                                max_number = i;
                        }
                }
 
-               if(max_number >= 0)
+               if( max_number >= 0 )
                        return image_sets[max_number]->data;
        }
 
@@ -222,13 +262,12 @@ VFrame** BC_Theme::new_button(const char *overlay_path,
 {
        VFramePng default_data(get_image_data(overlay_path));
        BC_ThemeSet *result = new BC_ThemeSet(3, 1, title ? title : "");
-       if(title) image_sets.append(result);
+       if( title ) add_image_set(result);
 
        result->data[0] = new_image(up_path);
        result->data[1] = new_image(hi_path);
        result->data[2] = new_image(dn_path);
-       for(int i = 0; i < 3; i++)
-       {
+       for( int i=0; i<3; ++i ) {
                overlay(result->data[i], &default_data, -1, -1, (i == 2));
        }
        return result->data;
@@ -244,14 +283,13 @@ VFrame** BC_Theme::new_button4(const char *overlay_path,
 {
        VFramePng default_data(get_image_data(overlay_path));
        BC_ThemeSet *result = new BC_ThemeSet(4, 1, title ? title : "");
-       if(title) image_sets.append(result);
+       if( title ) add_image_set(result);
 
        result->data[0] = new_image(up_path);
        result->data[1] = new_image(hi_path);
        result->data[2] = new_image(dn_path);
        result->data[3] = new_image(disabled_path);
-       for(int i = 0; i < 4; i++)
-       {
+       for( int i=0; i<4; ++i ) {
                overlay(result->data[i], &default_data, -1, -1, (i == 2));
        }
        return result->data;
@@ -266,12 +304,12 @@ VFrame** BC_Theme::new_button(const char *overlay_path,
 {
        VFramePng default_data(get_image_data(overlay_path));
        BC_ThemeSet *result = new BC_ThemeSet(3, 0, title ? title : "");
-       if(title) image_sets.append(result);
+       if( title ) add_image_set(result);
 
        result->data[0] = new VFrame(*up);
        result->data[1] = new VFrame(*hi);
        result->data[2] = new VFrame(*dn);
-       for(int i = 0; i < 3; i++)
+       for( int i=0; i<3; ++i )
                overlay(result->data[i], &default_data, -1, -1, (i == 2));
        return result->data;
 }
@@ -287,14 +325,14 @@ VFrame** BC_Theme::new_toggle(const char *overlay_path,
 {
        VFramePng default_data(get_image_data(overlay_path));
        BC_ThemeSet *result = new BC_ThemeSet(5, 1, title ? title : "");
-       if(title) image_sets.append(result);
+       if( title ) add_image_set(result);
 
        result->data[0] = new_image(up_path);
        result->data[1] = new_image(hi_path);
        result->data[2] = new_image(checked_path);
        result->data[3] = new_image(dn_path);
        result->data[4] = new_image(checkedhi_path);
-       for(int i = 0; i < 5; i++)
+       for( int i=0; i<5; ++i )
                overlay(result->data[i], &default_data, -1, -1, (i == 3));
        return result->data;
 }
@@ -309,14 +347,14 @@ VFrame** BC_Theme::new_toggle(const char *overlay_path,
 {
        VFramePng default_data(get_image_data(overlay_path));
        BC_ThemeSet *result = new BC_ThemeSet(5, 0, title ? title : "");
-       if(title) image_sets.append(result);
+       if( title ) add_image_set(result);
 
        result->data[0] = new VFrame(*up);
        result->data[1] = new VFrame(*hi);
        result->data[2] = new VFrame(*checked);
        result->data[3] = new VFrame(*dn);
        result->data[4] = new VFrame(*checkedhi);
-       for(int i = 0; i < 5; i++)
+       for( int i=0; i<5; ++i )
                overlay(result->data[i], &default_data, -1, -1, (i == 3));
        return result->data;
 }
@@ -328,45 +366,39 @@ void BC_Theme::overlay(VFrame *dst, VFrame *src, int in_x1, int in_x2, int shift
        unsigned char **in_rows;
        unsigned char **out_rows;
 
-       if(in_x1 < 0)
-       {
+       if( in_x1 < 0 ) {
                w = MIN(src->get_w(), dst->get_w());
                h = MIN(dst->get_h(), src->get_h());
                in_x1 = 0;
                in_x2 = w;
        }
-       else
-       {
+       else {
                w = in_x2 - in_x1;
                h = MIN(dst->get_h(), src->get_h());
        }
        in_rows = src->get_rows();
        out_rows = dst->get_rows();
 
-       switch(src->get_color_model())
+       switch( src->get_color_model() )
        {
                case BC_RGBA8888:
-                       switch(dst->get_color_model())
+                       switch( dst->get_color_model() )
                        {
                                case BC_RGBA8888:
-                                       for(int i = shift; i < h; i++)
-                                       {
+                                       for( int i=shift; i<h; ++i ) {
                                                unsigned char *in_row = 0;
                                                unsigned char *out_row;
 
-                                               if(!shift)
-                                               {
+                                               if( !shift ) {
                                                        in_row = in_rows[i] + in_x1 * 4;
                                                        out_row = out_rows[i];
                                                }
-                                               else
-                                               {
+                                               else {
                                                        in_row = in_rows[i - 1] + in_x1 * 4;
                                                        out_row = out_rows[i] + 4;
                                                }
 
-                                               for(int j = shift; j < w; j++)
-                                               {
+                                               for( int j=shift; j<w; ++j ) {
                                                        int opacity = in_row[3];
                                                        int transparency = 0xff - opacity;
 
@@ -381,24 +413,20 @@ void BC_Theme::overlay(VFrame *dst, VFrame *src, int in_x1, int in_x2, int shift
                                        break;
 
                                case BC_RGB888:
-                                       for(int i = shift; i < h; i++)
-                                       {
+                                       for( int i=shift; i<h; ++i ) {
                                                unsigned char *in_row;
                                                unsigned char *out_row = out_rows[i];
 
-                                               if(!shift)
-                                               {
+                                               if( !shift ) {
                                                        in_row = in_rows[i] + in_x1 * 3;
                                                        out_row = out_rows[i];
                                                }
-                                               else
-                                               {
+                                               else {
                                                        in_row = in_rows[i - 1] + in_x1 * 3;
                                                        out_row = out_rows[i] + 3;
                                                }
 
-                                               for(int j = shift; j < w; j++)
-                                               {
+                                               for( int j=shift; j<w; ++j ) {
                                                        int opacity = in_row[3];
                                                        int transparency = 0xff - opacity;
                                                        out_row[0] = (in_row[0] * opacity + out_row[0] * transparency) / 0xff;
@@ -416,58 +444,60 @@ void BC_Theme::overlay(VFrame *dst, VFrame *src, int in_x1, int in_x2, int shift
 
 void BC_Theme::set_data(unsigned char *ptr)
 {
-       contents_ptr = (char*)(ptr + sizeof(int));
-       int contents_size = *(int*)ptr - sizeof(int);
-       data_ptr = contents_ptr + contents_size;
-
-       for(int i = 0; i < contents_size; )
-       {
-               used.append(0);
-               contents.append(contents_ptr + i);
-               while(contents_ptr[i] && i < contents_size)
-                       i++;
-               if(i < contents_size)
-               {
-                       i++;
-                       pointers.append((unsigned char*)data_ptr +
-                               *(unsigned int*)(contents_ptr + i));
-                       i += 4;
-               }
-               else
-               {
-                       pointers.append((unsigned char*)data_ptr);
-                       break;
-               }
+       int hdr_sz = *(int*)ptr - sizeof(int);
+       unsigned char *cp = ptr + sizeof(int);
+       unsigned char *dp = cp + hdr_sz;
+       int start_item = images.size();
+
+       while( cp < dp ) {
+               char *nm = (char *)cp;
+               while( cp < dp && *cp++ );
+               if( cp + sizeof(unsigned) > dp ) break;
+               unsigned ofs = 0;
+               for( int i=sizeof(unsigned); --i>=0; ofs|=cp[i] ) ofs <<= 8;
+               images.append(new BC_ImageData(nm, dp+ofs));
+               cp += sizeof(unsigned);
        }
+
+       int items = images.size() - start_item;
+       data_items.append(items);
+       qsort(&images[start_item], items, sizeof(images[0]), images_cmpr);
 }
 
-unsigned char* BC_Theme::get_image_data(const char *title)
+int BC_Theme::images_cmpr(const void *ap, const void *bp)
 {
-       if(!data_ptr)
-       {
-               fprintf(stderr, "BC_Theme::get_image_data: no data set\n");
-               return 0;
-       }
+       BC_ImageData *a = *(BC_ImageData**)ap, *b = *(BC_ImageData**)bp;
+        return strcmp(a->name, b->name);
+}
 
+unsigned char* BC_Theme::get_image_data(const char *name, int log_errs)
+{
 // Image is the same as the last one
-       if(last_image && !strcasecmp(last_image, title))
-       {
-               return last_pointer;
-       }
-       else
-// Search for image anew.
-       for(int i = 0; i < contents.total; i++)
-       {
-               if(!strcasecmp(contents.values[i], title))
-               {
-                       last_pointer = pointers.values[i];
-                       last_image = contents.values[i];
-                       used.values[i] = 1;
-                       return pointers.values[i];
+       if( last_image_data && !strcmp(last_image_data->name, name) )
+               return last_image_data->data;
+
+// look forwards thru data sets for name
+       int start_item = 0;
+       for( int i=0,n=data_items.size(); i<n; ++i ) {
+               int end_item = start_item + data_items[i];
+               int r = end_item, l = start_item-1;
+// binary search for image
+               int m = 0, v = -1;
+               while( r-l > 1 ) {
+                       m = (l + r) / 2;
+                       BC_ImageData *image_data = images[m];
+                       if( !(v=strcmp(name, image_data->name)) ) {
+                               image_data->used = 1;
+                               last_image_data = image_data;
+                               return image_data->data;
+                       }
+                       if( v > 0 ) l = m; else r = m;
                }
+               start_item = end_item;
        }
 
-       fprintf(stderr, _("Theme::get_image: %s not found.\n"), title);
+       if( log_errs )
+               fprintf(stderr, _("Theme::get_image: %s not found.\n"), name);
        return 0;
 }
 
@@ -476,30 +506,17 @@ void BC_Theme::check_used()
 // Can't use because some images are gotten the old fashioned way.
 return;
        int got_it = 0;
-       for(int i = 0; i < used.total; i++)
-       {
-               if(!used.values[i])
-               {
-                       if(!got_it)
-                               printf(_("BC_Theme::check_used: Images aren't used.\n"));
-                       printf("%s ", contents.values[i]);
+       for( int i=0; i<images.size(); ++i ) {
+               if( !images[i]->used ) {
+                       if( !got_it ) printf(_("BC_Theme::check_used: Images aren't used.\n"));
+                       printf("%s ", images[i]->name);
                        got_it = 1;
                }
        }
-       if(got_it) printf("\n");
+       if( got_it ) printf("\n");
 }
 
 
-
-
-
-
-
-
-
-
-
-
 BC_ThemeSet::BC_ThemeSet(int total, int is_reference, const char *title)
 {
        this->total = total;
@@ -511,11 +528,9 @@ BC_ThemeSet::BC_ThemeSet(int total, int is_reference, const char *title)
 
 BC_ThemeSet::~BC_ThemeSet()
 {
-       if(data)
-       {
-               if(!is_reference)
-               {
-                       for(int i = 0; i < total; i++)
+       if( data ) {
+               if( !is_reference ) {
+                       for( int i = 0; i < total; i++ )
                                delete data[i];
                }
 
@@ -525,7 +540,3 @@ BC_ThemeSet::~BC_ThemeSet()
        delete [] title;
 }
 
-
-
-
-