4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "bcresources.h"
24 #include "bcwindowbase.h"
41 image_sets.remove_all_objects();
42 images.remove_all_objects();
47 printf("BC_Theme::dump 1 image_sets=%d images=%d\n",
48 image_sets.size(), images.size());
49 for( int i=0; i<images.size(); ++i ) {
50 image_item *item = images[i];
51 printf(" %s %p\n", item->name, item->data);
55 BC_Resources* BC_Theme::get_resources()
57 return BC_WindowBase::get_resources();
60 // These create single images for storage in the image_sets table.
61 VFrame* BC_Theme::new_image(const char *title, const char *path)
63 VFrame *existing_image = title[0] ? get_image(title, 0) : 0;
64 if( existing_image ) return existing_image;
66 BC_ThemeSet *result = new BC_ThemeSet(1, 0, title);
67 result->data[0] = new VFramePng(get_image_data(path));
68 image_sets.append(result);
69 return result->data[0];
72 VFrame* BC_Theme::new_image(const char *path)
74 return new_image("", path);
77 // These create image sets which are stored in the image_sets table.
78 VFrame** BC_Theme::new_image_set(const char *title, int total, va_list *args)
81 printf("BC_Theme::new_image_set %d %s zero number of images\n",
85 VFrame **existing_image_set = title[0] ? get_image_set(title, 0) : 0;
86 if( existing_image_set ) return existing_image_set;
88 BC_ThemeSet *result = new BC_ThemeSet(total, 1, title);
89 image_sets.append(result);
90 for( int i=0; i<total; ++i ) {
91 char *path = va_arg(*args, char*);
92 result->data[i] = new_image(path);
97 VFrame** BC_Theme::new_image_set_images(const char *title, int total, ...)
100 va_start(list, total);
101 BC_ThemeSet *existing_image_set = title[0] ? get_image_set_object(title) : 0;
102 if( existing_image_set ) {
103 image_sets.remove_object(existing_image_set);
106 BC_ThemeSet *result = new BC_ThemeSet(total, 0, title);
107 image_sets.append(result);
108 for( int i=0; i<total; ++i ) {
109 result->data[i] = va_arg(list, VFrame*);
115 VFrame** BC_Theme::new_image_set(const char *title, int total, ...)
118 va_start(list, total);
119 VFrame **result = new_image_set(title, total, &list);
125 VFrame** BC_Theme::new_image_set(int total, ...)
128 va_start(list, total);
129 VFrame **result = new_image_set("", total, &list);
135 BC_ThemeSet* BC_Theme::get_image_set_object(const char *title)
137 // compare title[0],title[1] for faster prefix test
138 const unsigned char *bp = (const unsigned char*)title;
139 unsigned short tval = bp[0];
140 if( tval ) tval |= (bp[1] << 8);
142 for( int i=0; i<image_sets.size(); ++i ) {
143 const char *tp = image_sets[i]->title;
144 bp = (const unsigned char *) tp;
145 unsigned short val = bp[0];
146 if( val ) val |= (bp[1] << 8);
147 if( val != tval ) continue;
148 if( !strcmp(tp, title) ) return image_sets[i];
153 VFrame* BC_Theme::get_image(const char *title, int use_default)
155 BC_ThemeSet* tsp = get_image_set_object(title);
156 if( tsp ) return tsp->data[0];
159 // Return the first image it can find. This should always work.
161 printf("BC_Theme::get_image: image \"%s\" not found.\n",
163 if( image_sets.size() )
164 return image_sets[0]->data[0];
167 // Give up and go to a movie.
171 VFrame** BC_Theme::get_image_set(const char *title, int use_default)
173 BC_ThemeSet* tsp = get_image_set_object(title);
174 if( tsp ) return tsp->data;
176 // Get the image set with the largest number of images.
178 printf("BC_Theme::get_image_set: image set \"%s\" not found.\n",
182 for( int i=0; i<image_sets.size(); ++i ) {
183 if( image_sets[i]->total > max_total ) {
184 max_total = image_sets[i]->total;
189 if( max_number >= 0 )
190 return image_sets[max_number]->data;
193 // Give up and go to a movie
207 VFrame** BC_Theme::new_button(const char *overlay_path,
213 VFramePng default_data(get_image_data(overlay_path));
214 BC_ThemeSet *result = new BC_ThemeSet(3, 1, title ? title : "");
215 if( title ) image_sets.append(result);
217 result->data[0] = new_image(up_path);
218 result->data[1] = new_image(hi_path);
219 result->data[2] = new_image(dn_path);
220 for( int i=0; i<3; ++i ) {
221 overlay(result->data[i], &default_data, -1, -1, (i == 2));
227 VFrame** BC_Theme::new_button4(const char *overlay_path,
231 const char *disabled_path,
234 VFramePng default_data(get_image_data(overlay_path));
235 BC_ThemeSet *result = new BC_ThemeSet(4, 1, title ? title : "");
236 if( title ) image_sets.append(result);
238 result->data[0] = new_image(up_path);
239 result->data[1] = new_image(hi_path);
240 result->data[2] = new_image(dn_path);
241 result->data[3] = new_image(disabled_path);
242 for( int i=0; i<4; ++i ) {
243 overlay(result->data[i], &default_data, -1, -1, (i == 2));
249 VFrame** BC_Theme::new_button(const char *overlay_path,
255 VFramePng default_data(get_image_data(overlay_path));
256 BC_ThemeSet *result = new BC_ThemeSet(3, 0, title ? title : "");
257 if( title ) image_sets.append(result);
259 result->data[0] = new VFrame(*up);
260 result->data[1] = new VFrame(*hi);
261 result->data[2] = new VFrame(*dn);
262 for( int i=0; i<3; ++i )
263 overlay(result->data[i], &default_data, -1, -1, (i == 2));
268 VFrame** BC_Theme::new_toggle(const char *overlay_path,
271 const char *checked_path,
273 const char *checkedhi_path,
276 VFramePng default_data(get_image_data(overlay_path));
277 BC_ThemeSet *result = new BC_ThemeSet(5, 1, title ? title : "");
278 if( title ) image_sets.append(result);
280 result->data[0] = new_image(up_path);
281 result->data[1] = new_image(hi_path);
282 result->data[2] = new_image(checked_path);
283 result->data[3] = new_image(dn_path);
284 result->data[4] = new_image(checkedhi_path);
285 for( int i=0; i<5; ++i )
286 overlay(result->data[i], &default_data, -1, -1, (i == 3));
290 VFrame** BC_Theme::new_toggle(const char *overlay_path,
298 VFramePng default_data(get_image_data(overlay_path));
299 BC_ThemeSet *result = new BC_ThemeSet(5, 0, title ? title : "");
300 if( title ) image_sets.append(result);
302 result->data[0] = new VFrame(*up);
303 result->data[1] = new VFrame(*hi);
304 result->data[2] = new VFrame(*checked);
305 result->data[3] = new VFrame(*dn);
306 result->data[4] = new VFrame(*checkedhi);
307 for( int i=0; i<5; ++i )
308 overlay(result->data[i], &default_data, -1, -1, (i == 3));
312 void BC_Theme::overlay(VFrame *dst, VFrame *src, int in_x1, int in_x2, int shift)
316 unsigned char **in_rows;
317 unsigned char **out_rows;
320 w = MIN(src->get_w(), dst->get_w());
321 h = MIN(dst->get_h(), src->get_h());
327 h = MIN(dst->get_h(), src->get_h());
329 in_rows = src->get_rows();
330 out_rows = dst->get_rows();
332 switch( src->get_color_model() )
335 switch( dst->get_color_model() )
338 for( int i=shift; i<h; ++i ) {
339 unsigned char *in_row = 0;
340 unsigned char *out_row;
343 in_row = in_rows[i] + in_x1 * 4;
344 out_row = out_rows[i];
347 in_row = in_rows[i - 1] + in_x1 * 4;
348 out_row = out_rows[i] + 4;
351 for( int j=shift; j<w; ++j ) {
352 int opacity = in_row[3];
353 int transparency = 0xff - opacity;
355 out_row[0] = (in_row[0] * opacity + out_row[0] * transparency) / 0xff;
356 out_row[1] = (in_row[1] * opacity + out_row[1] * transparency) / 0xff;
357 out_row[2] = (in_row[2] * opacity + out_row[2] * transparency) / 0xff;
358 out_row[3] = MAX(in_row[3], out_row[3]);
366 for( int i=shift; i<h; ++i ) {
367 unsigned char *in_row;
368 unsigned char *out_row = out_rows[i];
371 in_row = in_rows[i] + in_x1 * 3;
372 out_row = out_rows[i];
375 in_row = in_rows[i - 1] + in_x1 * 3;
376 out_row = out_rows[i] + 3;
379 for( int j=shift; j<w; ++j ) {
380 int opacity = in_row[3];
381 int transparency = 0xff - opacity;
382 out_row[0] = (in_row[0] * opacity + out_row[0] * transparency) / 0xff;
383 out_row[1] = (in_row[1] * opacity + out_row[1] * transparency) / 0xff;
384 out_row[2] = (in_row[2] * opacity + out_row[2] * transparency) / 0xff;
395 void BC_Theme::set_data(unsigned char *ptr)
397 int hdr_sz = *(int*)ptr - sizeof(int);
398 unsigned char *cp = ptr + sizeof(int);
399 unsigned char *dp = cp + hdr_sz;
402 char *nm = (char *)cp;
403 while( cp < dp && *cp++ );
404 if( cp + sizeof(unsigned) > dp ) break;
406 for( int i=sizeof(unsigned); --i>=0; ofs|=cp[i] ) ofs <<= 8;
407 images.append(new image_item(nm, dp+ofs));
408 cp += sizeof(unsigned);
414 int BC_Theme::images_cmpr(const void *ap, const void *bp)
416 image_item *a = *(image_item**)ap, *b = *(image_item**)bp;
417 return strcasecmp(a->name, b->name);
420 unsigned char* BC_Theme::get_image_data(const char *name)
424 qsort(&images[0], images.size(), sizeof(images[0]), images_cmpr);
428 // Image is the same as the last one
429 if( last_image && !strcasecmp(last_image->name, name) )
430 return last_image->data;
432 // Search for image anew.
433 int l = -1, r = images.size();
437 image_item *item = images[m];
438 if( !(n=strcasecmp(name, item->name)) ) {
443 if( n > 0 ) l = m; else r = m;
446 fprintf(stderr, _("Theme::get_image: %s not found.\n"), name);
450 void BC_Theme::check_used()
452 // Can't use because some images are gotten the old fashioned way.
455 for( int i=0; i<images.size(); ++i ) {
456 if( !images[i]->used ) {
457 if( !got_it ) printf(_("BC_Theme::check_used: Images aren't used.\n"));
458 printf("%s ", images[i]->name);
462 if( got_it ) printf("\n");
466 BC_ThemeSet::BC_ThemeSet(int total, int is_reference, const char *title)
469 this->title = new char[strlen(title) + 1];
470 strcpy(this->title, title);
471 this->is_reference = is_reference;
472 data = new VFrame*[total];
475 BC_ThemeSet::~BC_ThemeSet()
478 if( !is_reference ) {
479 for( int i = 0; i < total; i++ )