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"
43 image_sets.remove_all_objects();
44 contents.remove_all();
49 printf("BC_Theme::dump 1 image_sets=%d contents=%d\n",
52 for(int i = 0; i < contents.total; i++)
53 printf(" %s %p\n", contents.values[i], pointers.values[i]);
56 BC_Resources* BC_Theme::get_resources()
58 return BC_WindowBase::get_resources();
61 // These create single images for storage in the image_sets table.
62 VFrame* BC_Theme::new_image(const char *title, const char *path)
64 VFrame *existing_image = title[0] ? get_image(title, 0) : 0;
65 if(existing_image) return existing_image;
67 BC_ThemeSet *result = new BC_ThemeSet(1, 0, title);
68 result->data[0] = new VFramePng(get_image_data(path));
69 image_sets.append(result);
70 return result->data[0];
73 VFrame* BC_Theme::new_image(const char *path)
75 return new_image("", path);
80 // These create image sets which are stored in the image_sets table.
81 VFrame** BC_Theme::new_image_set(const char *title, int total, va_list *args)
85 printf("BC_Theme::new_image_set %d %s zero number of images\n",
90 VFrame **existing_image_set = title[0] ? get_image_set(title, 0) : 0;
91 if(existing_image_set) return existing_image_set;
93 BC_ThemeSet *result = new BC_ThemeSet(total, 1, title);
94 image_sets.append(result);
95 for(int i = 0; i < total; i++)
97 char *path = va_arg(*args, char*);
98 result->data[i] = new_image(path);
103 VFrame** BC_Theme::new_image_set_images(const char *title, int total, ...)
106 va_start(list, total);
107 BC_ThemeSet *existing_image_set = title[0] ? get_image_set_object(title) : 0;
108 if(existing_image_set)
110 image_sets.remove_object(existing_image_set);
113 BC_ThemeSet *result = new BC_ThemeSet(total, 0, title);
114 image_sets.append(result);
115 for(int i = 0; i < total; i++)
117 result->data[i] = va_arg(list, VFrame*);
123 VFrame** BC_Theme::new_image_set(const char *title, int total, ...)
126 va_start(list, total);
127 VFrame **result = new_image_set(title, total, &list);
133 VFrame** BC_Theme::new_image_set(int total, ...)
136 va_start(list, total);
137 VFrame **result = new_image_set("", total, &list);
143 BC_ThemeSet* BC_Theme::get_image_set_object(const char *title)
145 // compare title[0],title[1] for faster prefix test
146 const unsigned char *bp = (const unsigned char*)title;
147 unsigned short tval = bp[0];
148 if( tval ) tval |= (bp[1] << 8);
150 for( int i=0; i < image_sets.total; ++i ) {
151 const char *tp = image_sets[i]->title;
152 bp = (const unsigned char *) tp;
153 unsigned short val = bp[0];
154 if( val ) val |= (bp[1] << 8);
155 if( val != tval ) continue;
156 if( !strcmp(tp, title) ) return image_sets[i];
161 VFrame* BC_Theme::get_image(const char *title, int use_default)
163 BC_ThemeSet* tsp = get_image_set_object(title);
164 if( tsp ) return tsp->data[0];
167 // Return the first image it can find. This should always work.
169 printf("BC_Theme::get_image: image \"%s\" not found.\n",
172 return image_sets[0]->data[0];
175 // Give up and go to a movie.
179 VFrame** BC_Theme::get_image_set(const char *title, int use_default)
181 BC_ThemeSet* tsp = get_image_set_object(title);
182 if( tsp ) return tsp->data;
184 // Get the image set with the largest number of images.
187 printf("BC_Theme::get_image_set: image set \"%s\" not found.\n",
191 for(int i = 0; i < image_sets.total; i++)
193 if(image_sets[i]->total > max_total)
195 max_total = image_sets[i]->total;
201 return image_sets[max_number]->data;
204 // Give up and go to a movie
218 VFrame** BC_Theme::new_button(const char *overlay_path,
224 VFramePng default_data(get_image_data(overlay_path));
225 BC_ThemeSet *result = new BC_ThemeSet(3, 1, title ? title : "");
226 if(title) image_sets.append(result);
228 result->data[0] = new_image(up_path);
229 result->data[1] = new_image(hi_path);
230 result->data[2] = new_image(dn_path);
231 for(int i = 0; i < 3; i++)
233 overlay(result->data[i], &default_data, -1, -1, (i == 2));
239 VFrame** BC_Theme::new_button4(const char *overlay_path,
243 const char *disabled_path,
246 VFramePng default_data(get_image_data(overlay_path));
247 BC_ThemeSet *result = new BC_ThemeSet(4, 1, title ? title : "");
248 if(title) image_sets.append(result);
250 result->data[0] = new_image(up_path);
251 result->data[1] = new_image(hi_path);
252 result->data[2] = new_image(dn_path);
253 result->data[3] = new_image(disabled_path);
254 for(int i = 0; i < 4; i++)
256 overlay(result->data[i], &default_data, -1, -1, (i == 2));
262 VFrame** BC_Theme::new_button(const char *overlay_path,
268 VFramePng default_data(get_image_data(overlay_path));
269 BC_ThemeSet *result = new BC_ThemeSet(3, 0, title ? title : "");
270 if(title) image_sets.append(result);
272 result->data[0] = new VFrame(*up);
273 result->data[1] = new VFrame(*hi);
274 result->data[2] = new VFrame(*dn);
275 for(int i = 0; i < 3; i++)
276 overlay(result->data[i], &default_data, -1, -1, (i == 2));
281 VFrame** BC_Theme::new_toggle(const char *overlay_path,
284 const char *checked_path,
286 const char *checkedhi_path,
289 VFramePng default_data(get_image_data(overlay_path));
290 BC_ThemeSet *result = new BC_ThemeSet(5, 1, title ? title : "");
291 if(title) image_sets.append(result);
293 result->data[0] = new_image(up_path);
294 result->data[1] = new_image(hi_path);
295 result->data[2] = new_image(checked_path);
296 result->data[3] = new_image(dn_path);
297 result->data[4] = new_image(checkedhi_path);
298 for(int i = 0; i < 5; i++)
299 overlay(result->data[i], &default_data, -1, -1, (i == 3));
303 VFrame** BC_Theme::new_toggle(const char *overlay_path,
311 VFramePng default_data(get_image_data(overlay_path));
312 BC_ThemeSet *result = new BC_ThemeSet(5, 0, title ? title : "");
313 if(title) image_sets.append(result);
315 result->data[0] = new VFrame(*up);
316 result->data[1] = new VFrame(*hi);
317 result->data[2] = new VFrame(*checked);
318 result->data[3] = new VFrame(*dn);
319 result->data[4] = new VFrame(*checkedhi);
320 for(int i = 0; i < 5; i++)
321 overlay(result->data[i], &default_data, -1, -1, (i == 3));
325 void BC_Theme::overlay(VFrame *dst, VFrame *src, int in_x1, int in_x2, int shift)
329 unsigned char **in_rows;
330 unsigned char **out_rows;
334 w = MIN(src->get_w(), dst->get_w());
335 h = MIN(dst->get_h(), src->get_h());
342 h = MIN(dst->get_h(), src->get_h());
344 in_rows = src->get_rows();
345 out_rows = dst->get_rows();
347 switch(src->get_color_model())
350 switch(dst->get_color_model())
353 for(int i = shift; i < h; i++)
355 unsigned char *in_row = 0;
356 unsigned char *out_row;
360 in_row = in_rows[i] + in_x1 * 4;
361 out_row = out_rows[i];
365 in_row = in_rows[i - 1] + in_x1 * 4;
366 out_row = out_rows[i] + 4;
369 for(int j = shift; j < w; j++)
371 int opacity = in_row[3];
372 int transparency = 0xff - opacity;
374 out_row[0] = (in_row[0] * opacity + out_row[0] * transparency) / 0xff;
375 out_row[1] = (in_row[1] * opacity + out_row[1] * transparency) / 0xff;
376 out_row[2] = (in_row[2] * opacity + out_row[2] * transparency) / 0xff;
377 out_row[3] = MAX(in_row[3], out_row[3]);
385 for(int i = shift; i < h; i++)
387 unsigned char *in_row;
388 unsigned char *out_row = out_rows[i];
392 in_row = in_rows[i] + in_x1 * 3;
393 out_row = out_rows[i];
397 in_row = in_rows[i - 1] + in_x1 * 3;
398 out_row = out_rows[i] + 3;
401 for(int j = shift; j < w; j++)
403 int opacity = in_row[3];
404 int transparency = 0xff - opacity;
405 out_row[0] = (in_row[0] * opacity + out_row[0] * transparency) / 0xff;
406 out_row[1] = (in_row[1] * opacity + out_row[1] * transparency) / 0xff;
407 out_row[2] = (in_row[2] * opacity + out_row[2] * transparency) / 0xff;
418 void BC_Theme::set_data(unsigned char *ptr)
420 contents_ptr = (char*)(ptr + sizeof(int));
421 int contents_size = *(int*)ptr - sizeof(int);
422 data_ptr = contents_ptr + contents_size;
424 for(int i = 0; i < contents_size; )
427 contents.append(contents_ptr + i);
428 while(contents_ptr[i] && i < contents_size)
430 if(i < contents_size)
433 pointers.append((unsigned char*)data_ptr +
434 *(unsigned int*)(contents_ptr + i));
439 pointers.append((unsigned char*)data_ptr);
445 unsigned char* BC_Theme::get_image_data(const char *title)
449 fprintf(stderr, "BC_Theme::get_image_data: no data set\n");
453 // Image is the same as the last one
454 if(last_image && !strcasecmp(last_image, title))
459 // Search for image anew.
460 for(int i = 0; i < contents.total; i++)
462 if(!strcasecmp(contents.values[i], title))
464 last_pointer = pointers.values[i];
465 last_image = contents.values[i];
467 return pointers.values[i];
471 fprintf(stderr, _("Theme::get_image: %s not found.\n"), title);
475 void BC_Theme::check_used()
477 // Can't use because some images are gotten the old fashioned way.
480 for(int i = 0; i < used.total; i++)
485 printf(_("BC_Theme::check_used: Images aren't used.\n"));
486 printf("%s ", contents.values[i]);
490 if(got_it) printf("\n");
504 BC_ThemeSet::BC_ThemeSet(int total, int is_reference, const char *title)
507 this->title = new char[strlen(title) + 1];
508 strcpy(this->title, title);
509 this->is_reference = is_reference;
510 data = new VFrame*[total];
513 BC_ThemeSet::~BC_ThemeSet()
519 for(int i = 0; i < total; i++)