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()
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];
}
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);
}
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);
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;
}
// 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];
}
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;
}
-VFrame** BC_Theme::new_button(const char *overlay_path,
- const char *up_path,
- const char *hi_path,
+VFrame** BC_Theme::new_button(const char *overlay_path,
+ const char *up_path,
+ const char *hi_path,
const char *dn_path,
const char *title)
{
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;
}
-VFrame** BC_Theme::new_button4(const char *overlay_path,
- const char *up_path,
- const char *hi_path,
+VFrame** BC_Theme::new_button4(const char *overlay_path,
+ const char *up_path,
+ const char *hi_path,
const char *dn_path,
const char *disabled_path,
const char *title)
{
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;
}
-VFrame** BC_Theme::new_button(const char *overlay_path,
+VFrame** BC_Theme::new_button(const char *overlay_path,
VFrame *up,
VFrame *hi,
VFrame *dn,
{
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;
}
-VFrame** BC_Theme::new_toggle(const char *overlay_path,
+VFrame** BC_Theme::new_toggle(const char *overlay_path,
const char *up_path,
const char *hi_path,
const char *checked_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;
}
-VFrame** BC_Theme::new_toggle(const char *overlay_path,
+VFrame** BC_Theme::new_toggle(const char *overlay_path,
VFrame *up,
VFrame *hi,
VFrame *checked,
{
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;
}
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;
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;
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;
}
// 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;
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];
}
delete [] title;
}
-
-
-
-