r1015: Add a shortcut 'e' that toggles between selection and drag&drop edit modes.
[cinelerra_cv/ct.git] / guicast / bctheme.C
blob893ef5d7098af58b8ba0710fb1560d130af29595
1 #include "bctheme.h"
2 #include "bcwindowbase.h"
3 #include "clip.h"
4 #include "language.h"
5 #include "vframe.h"
7 #include <errno.h>
8 #include <stdio.h>
9 #include <string.h>
11 BC_Theme::BC_Theme()
13         data_ptr = 0;
14         contents_ptr = 0;
15         last_image = 0;
16         last_pointer = 0;
19 BC_Theme::~BC_Theme()
21         image_sets.remove_all_objects();
24 void BC_Theme::dump()
26         printf("BC_Theme::dump 1 image_sets=%d contents=%d\n", 
27                 image_sets.total, 
28                 contents.total);
29         for(int i = 0; i < contents.total; i++)
30                 printf("    %s %p\n", contents.values[i], pointers.values[i]);
33 BC_Resources* BC_Theme::get_resources()
35         return BC_WindowBase::get_resources();
39 // These create single images for storage in the image_sets table.
40 VFrame* BC_Theme::new_image(char *title, char *path)
42         VFrame *existing_image = title[0] ? get_image(title, 0) : 0;
43         if(existing_image) return existing_image;
45         BC_ThemeSet *result = new BC_ThemeSet(1, 0, title);
46         result->data[0] = new VFrame(get_image_data(path));
47         image_sets.append(result);
48         return result->data[0];
51 VFrame* BC_Theme::new_image(char *path)
53         return new_image("", path);
58 // These create image sets which are stored in the image_sets table.
59 VFrame** BC_Theme::new_image_set(char *title, int total, va_list *args)
61         VFrame **existing_image_set = title[0] ? get_image_set(title, 0) : 0;
62         if(existing_image_set) return existing_image_set;
64         BC_ThemeSet *result = new BC_ThemeSet(total, 1, title);
65         image_sets.append(result);
66         for(int i = 0; i < total; i++)
67         {
68                 char *path = va_arg(*args, char*);
69                 result->data[i] = new_image(path);
70         }
71         return result->data;
74 VFrame** BC_Theme::new_image_set_images(char *title, int total, ...)
76         va_list list;
77         va_start(list, total);
78         BC_ThemeSet *existing_image_set = title[0] ? get_image_set_object(title) : 0;
79         if(existing_image_set)
80         {
81                 image_sets.remove_object(existing_image_set);
82         }
84         BC_ThemeSet *result = new BC_ThemeSet(total, 0, title);
85         image_sets.append(result);
86         for(int i = 0; i < total; i++)
87         {
88                 result->data[i] = va_arg(list, VFrame*);
89         }
90         return result->data;
93 VFrame** BC_Theme::new_image_set(char *title, int total, ...)
95         va_list list;
96         va_start(list, total);
97         VFrame **result = new_image_set(title, total, &list);
98         va_end(list);
100         return result;
103 VFrame** BC_Theme::new_image_set(int total, ...)
105         va_list list;
106         va_start(list, total);
107         VFrame **result = new_image_set("", total, &list);
108         va_end(list);
110         return result;
113 VFrame* BC_Theme::get_image(char *title, int use_default)
115         for(int i = 0; i < image_sets.total; i++)
116         {
117                 if(!strcmp(image_sets.values[i]->title, title))
118                 {
119                         return image_sets.values[i]->data[0];
120                 }
121         }
125 // Return the first image it can find.  This should always work.
126         if(use_default)
127         {
128                 printf("BC_Theme::get_image: image \"%s\" not found.\n",
129                         title);
130                 if(image_sets.total)
131                 {
132                         return image_sets.values[0]->data[0];
133                 }
134         }
136 // Give up and go to a movie.
137         return 0;
140 VFrame** BC_Theme::get_image_set(char *title, int use_default)
142         for(int i = 0; i < image_sets.total; i++)
143         {
144                 if(!strcmp(image_sets.values[i]->title, title))
145                 {
146                         return image_sets.values[i]->data;
147                 }
148         }
150 // Get the image set with the largest number of images.
151         if(use_default)
152         {
153                 printf("BC_Theme::get_image_set: image set \"%s\" not found.\n",
154                         title);
155                 int max_total = 0;
156                 int max_number = -1;
157                 for(int i = 0; i < image_sets.total; i++)
158                 {
159                         if(image_sets.values[i]->total > max_total)
160                         {
161                                 max_total = image_sets.values[i]->total;
162                                 max_number = i;
163                         }
164                 }
166                 if(max_number >= 0)
167                         return image_sets.values[max_number]->data;
168         }
170 // Give up and go to a movie
171         return 0;
174 BC_ThemeSet* BC_Theme::get_image_set_object(char *title)
176         for(int i = 0; i < image_sets.total; i++)
177         {
178                 if(!strcmp(image_sets.values[i]->title, title))
179                 {
180                         return image_sets.values[i];
181                 }
182         }
183         return 0;
196 VFrame** BC_Theme::new_button(char *overlay_path, 
197         char *up_path, 
198         char *hi_path, 
199         char *dn_path,
200         char *title)
202         VFrame default_data(get_image_data(overlay_path));
203         BC_ThemeSet *result = new BC_ThemeSet(3, 1, title ? title : (char*)"");
204         if(title) image_sets.append(result);
206         result->data[0] = new_image(up_path);
207         result->data[1] = new_image(hi_path);
208         result->data[2] = new_image(dn_path);
209         for(int i = 0; i < 3; i++)
210         {
211                 overlay(result->data[i], &default_data, -1, -1, (i == 2));
212         }
213         return result->data;
217 VFrame** BC_Theme::new_button4(char *overlay_path, 
218         char *up_path, 
219         char *hi_path, 
220         char *dn_path,
221         char *disabled_path,
222         char *title)
224         VFrame default_data(get_image_data(overlay_path));
225         BC_ThemeSet *result = new BC_ThemeSet(4, 1, title ? title : (char*)"");
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         result->data[3] = new_image(disabled_path);
232         for(int i = 0; i < 4; i++)
233         {
234                 overlay(result->data[i], &default_data, -1, -1, (i == 2));
235         }
236         return result->data;
240 VFrame** BC_Theme::new_button(char *overlay_path, 
241         VFrame *up,
242         VFrame *hi,
243         VFrame *dn,
244         char *title)
246         VFrame default_data(get_image_data(overlay_path));
247         BC_ThemeSet *result = new BC_ThemeSet(3, 0, title ? title : (char*)"");
248         if(title) image_sets.append(result);
250         result->data[0] = new VFrame(*up);
251         result->data[1] = new VFrame(*hi);
252         result->data[2] = new VFrame(*dn);
253         for(int i = 0; i < 3; i++)
254                 overlay(result->data[i], &default_data, -1, -1, (i == 2));
255         return result->data;
259 VFrame** BC_Theme::new_toggle(char *overlay_path, 
260         char *up_path,
261         char *hi_path,
262         char *checked_path,
263         char *dn_path,
264         char *checkedhi_path,
265         char *title)
267         VFrame default_data(get_image_data(overlay_path));
268         BC_ThemeSet *result = new BC_ThemeSet(5, 1, title ? title : (char*)"");
269         if(title) image_sets.append(result);
271         result->data[0] = new_image(up_path);
272         result->data[1] = new_image(hi_path);
273         result->data[2] = new_image(checked_path);
274         result->data[3] = new_image(dn_path);
275         result->data[4] = new_image(checkedhi_path);
276         for(int i = 0; i < 5; i++)
277                 overlay(result->data[i], &default_data, -1, -1, (i == 3));
278         return result->data;
281 VFrame** BC_Theme::new_toggle(char *overlay_path, 
282         VFrame *up,
283         VFrame *hi,
284         VFrame *checked,
285         VFrame *dn,
286         VFrame *checkedhi,
287         char *title)
289         VFrame default_data(get_image_data(overlay_path));
290         BC_ThemeSet *result = new BC_ThemeSet(5, 0, title ? title : (char*)"");
291         if(title) image_sets.append(result);
293         result->data[0] = new VFrame(*up);
294         result->data[1] = new VFrame(*hi);
295         result->data[2] = new VFrame(*checked);
296         result->data[3] = new VFrame(*dn);
297         result->data[4] = new VFrame(*checkedhi);
298         for(int i = 0; i < 5; i++)
299                 overlay(result->data[i], &default_data, -1, -1, (i == 3));
300         return result->data;
303 void BC_Theme::overlay(VFrame *dst, VFrame *src, int in_x1, int in_x2, int shift)
305         int w;
306         int h;
307         unsigned char **in_rows;
308         unsigned char **out_rows;
310         if(in_x1 < 0)
311         {
312                 w = MIN(src->get_w(), dst->get_w());
313                 h = MIN(dst->get_h(), src->get_h());
314                 in_x1 = 0;
315                 in_x2 = w;
316         }
317         else
318         {
319                 w = in_x2 - in_x1;
320                 h = MIN(dst->get_h(), src->get_h());
321         }
322         in_rows = src->get_rows();
323         out_rows = dst->get_rows();
325         switch(src->get_color_model())
326         {
327                 case BC_RGBA8888:
328                         switch(dst->get_color_model())
329                         {
330                                 case BC_RGBA8888:
331                                         for(int i = shift; i < h; i++)
332                                         {
333                                                 unsigned char *in_row = 0;
334                                                 unsigned char *out_row;
336                                                 if(!shift)
337                                                 {
338                                                         in_row = in_rows[i] + in_x1 * 4;
339                                                         out_row = out_rows[i];
340                                                 }
341                                                 else
342                                                 {
343                                                         in_row = in_rows[i - 1] + in_x1 * 4;
344                                                         out_row = out_rows[i] + 4;
345                                                 }
347                                                 for(int j = shift; j < w; j++)
348                                                 {
349                                                         int opacity = in_row[3];
350                                                         int transparency = 0xff - opacity;
352                                                         out_row[0] = (in_row[0] * opacity + out_row[0] * transparency) / 0xff;
353                                                         out_row[1] = (in_row[1] * opacity + out_row[1] * transparency) / 0xff;
354                                                         out_row[2] = (in_row[2] * opacity + out_row[2] * transparency) / 0xff;
355                                                         out_row[3] = MAX(in_row[3], out_row[3]);
356                                                         out_row += 4;
357                                                         in_row += 4;
358                                                 }
359                                         }
360                                         break;
362                                 case BC_RGB888:
363                                         for(int i = shift; i < h; i++)
364                                         {
365                                                 unsigned char *in_row;
366                                                 unsigned char *out_row = out_rows[i];
368                                                 if(!shift)
369                                                 {
370                                                         in_row = in_rows[i] + in_x1 * 3;
371                                                         out_row = out_rows[i];
372                                                 }
373                                                 else
374                                                 {
375                                                         in_row = in_rows[i - 1] + in_x1 * 3;
376                                                         out_row = out_rows[i] + 3;
377                                                 }
379                                                 for(int j = shift; j < w; j++)
380                                                 {
381                                                         int opacity = in_row[3];
382                                                         int transparency = 0xff - opacity;
383                                                         out_row[0] = (in_row[0] * opacity + out_row[0] * transparency) / 0xff;
384                                                         out_row[1] = (in_row[1] * opacity + out_row[1] * transparency) / 0xff;
385                                                         out_row[2] = (in_row[2] * opacity + out_row[2] * transparency) / 0xff;
386                                                         out_row += 3;
387                                                         in_row += 4;
388                                                 }
389                                         }
390                                         break;
391                         }
392                         break;
393         }
396 void BC_Theme::set_data(unsigned char *ptr)
398         contents_ptr = (char*)(ptr + sizeof(int));
399         int contents_size = *(int*)ptr - sizeof(int);
400         data_ptr = contents_ptr + contents_size;
402         for(int i = 0; i < contents_size; )
403         {
404                 used.append(0);
405                 contents.append(contents_ptr + i);
406                 while(contents_ptr[i] && i < contents_size)
407                         i++;
408                 if(i < contents_size)
409                 {
410                         i++;
411                         pointers.append((unsigned char*)data_ptr + 
412                                 *(unsigned int*)(contents_ptr + i));
413                         i += 4;
414                 }
415                 else
416                 {
417                         pointers.append((unsigned char*)data_ptr);
418                         break;
419                 }
420         }
423 unsigned char* BC_Theme::get_image_data(char *title)
425         if(!data_ptr)
426         {
427                 fprintf(stderr, "BC_Theme::get_image_data: no data set\n");
428                 return 0;
429         }
431 // Image is the same as the last one
432         if(last_image && !strcasecmp(last_image, title))
433         {
434                 return last_pointer;
435         }
436         else
437 // Search for image anew.
438         for(int i = 0; i < contents.total; i++)
439         {
440                 if(!strcasecmp(contents.values[i], title))
441                 {
442                         last_pointer = pointers.values[i];
443                         last_image = contents.values[i];
444                         used.values[i] = 1;
445                         return pointers.values[i];
446                 }
447         }
449         fprintf(stderr, _("Theme::get_image: %s not found.\n"), title);
450         return 0;
453 void BC_Theme::check_used()
455 // Can't use because some images are gotten the old fashioned way.
456 return;
457         int got_it = 0;
458         for(int i = 0; i < used.total; i++)
459         {
460                 if(!used.values[i])
461                 {
462                         if(!got_it)
463                                 printf(_("BC_Theme::check_used: Images aren't used.\n"));
464                         printf("%s ", contents.values[i]);
465                         got_it = 1;
466                 }
467         }
468         if(got_it) printf("\n");
482 BC_ThemeSet::BC_ThemeSet(int total, int is_reference, char *title)
484         this->total = total;
485         this->title = new char[strlen(title) + 1];
486         strcpy(this->title, title);
487         this->is_reference = is_reference;
488         data = new VFrame*[total];
491 BC_ThemeSet::~BC_ThemeSet()
493         if(data) 
494         {
495                 if(!is_reference)
496                 {
497                         for(int i = 0; i < total; i++)
498                                 delete data[i];
499                 }
501                 delete [] data;
502         }
504         delete [] title;