r136: This commit was manufactured by cvs2svn to create tag 'hv_1_1_8'.
[cinelerra_cv/ct.git] / hvirtual / guicast / bctheme.C
blobd1635a3251622f4260979d0ee34b54feb6751f78
1 #include "bctheme.h"
2 #include "bcwindowbase.h"
3 #include "clip.h"
4 #include "filesystem.h"
5 #include "language.h"
6 #include "vframe.h"
8 #include <errno.h>
9 #include <stdio.h>
10 #include <string.h>
12 BC_Theme::BC_Theme()
14         char *path_env = getenv("PATH");
15         char executable_name[BCTEXTLEN];
16         char *path_ptr = path_env;
18 // Get location of executable
19         FILE *fd = fopen("/proc/self/cmdline", "r");
20         if(!fd)
21         {
22                 perror(_("BC_Theme::BC_Theme: can't open /proc/self/cmdline.\n"));
23                 return;
24         }
25         else
26         {
27                 fread(executable_name, 1, BCTEXTLEN, fd);
28                 strcpy(path, executable_name);
29                 fclose(fd);
30         }
32         int done = 0;
33         fd = 0;
35 // Search path environment for executable
36         do
37         {
38                 FileSystem fs;
39 // Ignore directories
40                 if(!fs.is_dir(path))
41                         fd = 0;
42                 else
43                         fd = fopen(path, "r");
46                 if(!fd)
47                 {
48 // Get next entry out of path_env
49                         while(*path_ptr)
50                         {
51                                 if(*path_ptr != ':') 
52                                         break;
53                                 else
54                                         path_ptr++;
55                         }
57                         if(!*path_ptr) break;
59                         char *new_ptr = path;
60                         while(*path_ptr)
61                         {
62                                 if(*path_ptr == ':')
63                                         break;
64                                 else
65                                         *new_ptr++ = *path_ptr++;
66                         }
68                         *new_ptr = 0;
69                         if(new_ptr - path > 0 && *(new_ptr - 1) != '/')
70                         {
71                                 *new_ptr++ = '/';
72                                 *new_ptr = 0;
73                         }
74                         strcat(path, executable_name);
75                 }
76                 else
77                 {
78                         fclose(fd);
79                         done = 1;
80                 }
81         }while(!done);
83         strcpy(default_path, path);
84         data_buffer = 0;
85         contents_buffer = 0;
86         last_image = 0;
89 BC_Theme::~BC_Theme()
91         image_sets.remove_all_objects();
92         if(data_buffer) delete [] data_buffer;
93         if(contents_buffer) delete [] contents_buffer;
96 void BC_Theme::dump()
98         printf("BC_Theme::dump 1 image_sets=%d path=%s contents=%d\n", 
99                 image_sets.total, 
100                 path, 
101                 contents.total);
102         for(int i = 0; i < contents.total; i++)
103                 printf("    %s %x\n", contents.values[i], offsets.values[i]);
106 BC_Resources* BC_Theme::get_resources()
108         return BC_WindowBase::get_resources();
112 // These create single images for storage in the image_sets table.
113 VFrame* BC_Theme::new_image(char *title, char *path)
115         VFrame *existing_image = title[0] ? get_image(title) : 0;
116         if(existing_image) return existing_image;
118         BC_ThemeSet *result = new BC_ThemeSet(1, 0, title);
119         result->data[0] = new VFrame(get_image_data(path));
120         image_sets.append(result);
121         return result->data[0];
124 VFrame* BC_Theme::new_image(char *path)
126         return new_image("", path);
129 // These create image sets which are stored in the image_sets table.
130 VFrame** BC_Theme::new_image_set(char *title, int total, va_list *args)
132         VFrame **existing_image_set = title[0] ? get_image_set(title) : 0;
133         if(existing_image_set) return existing_image_set;
135         BC_ThemeSet *result = new BC_ThemeSet(total, 1, title);
136         image_sets.append(result);
137         for(int i = 0; i < total; i++)
138         {
139                 char *path = va_arg(*args, char*);
140                 result->data[i] = new_image(path);
141         }
142         return result->data;
145 VFrame** BC_Theme::new_image_set(char *title, int total, ...)
147         va_list list;
148         va_start(list, total);
149         VFrame **result = new_image_set(title, total, &list);
150         va_end(list);
152         return result;
155 VFrame** BC_Theme::new_image_set(int total, ...)
157         va_list list;
158         va_start(list, total);
159         VFrame **result = new_image_set("", total, &list);
160         va_end(list);
162         return result;
165 VFrame* BC_Theme::get_image(char *title)
167         for(int i = 0; i < image_sets.total; i++)
168         {
169                 if(!strcmp(image_sets.values[i]->title, title))
170                 {
171                         return image_sets.values[i]->data[0];
172                 }
173         }
177 // TODO: Need to return a default image
178         return 0;
181 VFrame** BC_Theme::get_image_set(char *title)
183         for(int i = 0; i < image_sets.total; i++)
184         {
185                 if(!strcmp(image_sets.values[i]->title, title))
186                 {
187                         return image_sets.values[i]->data;
188                 }
189         }
193 // TODO: Need to return a default image set
194         return 0;
209 VFrame** BC_Theme::new_button(char *overlay_path, 
210         char *up_path, 
211         char *hi_path, 
212         char *dn_path)
214         VFrame default_data(get_image_data(overlay_path));
215         BC_ThemeSet *result = new BC_ThemeSet(3, 1, "");
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);
222         return result->data;
226 VFrame** BC_Theme::new_button(char *overlay_path, 
227         VFrame *up,
228         VFrame *hi,
229         VFrame *dn)
231         VFrame default_data(get_image_data(overlay_path));
232         BC_ThemeSet *result = new BC_ThemeSet(3, 0, "");
234         result->data[0] = new VFrame(*up);
235         result->data[1] = new VFrame(*hi);
236         result->data[2] = new VFrame(*dn);
237         for(int i = 0; i < 3; i++)
238                 overlay(result->data[i], &default_data);
239         return result->data;
243 VFrame** BC_Theme::new_toggle(char *overlay_path, 
244         char *up_path,
245         char *hi_path,
246         char *checked_path,
247         char *dn_path,
248         char *checkedhi_path)
250         VFrame default_data(get_image_data(overlay_path));
251         BC_ThemeSet *result = new BC_ThemeSet(5, 1, "");
253         result->data[0] = new_image(up_path);
254         result->data[1] = new_image(hi_path);
255         result->data[2] = new_image(checked_path);
256         result->data[3] = new_image(dn_path);
257         result->data[4] = new_image(checkedhi_path);
258         for(int i = 0; i < 5; i++)
259                 overlay(result->data[i], &default_data);
260         return result->data;
263 VFrame** BC_Theme::new_toggle(char *overlay_path, 
264         VFrame *up,
265         VFrame *hi,
266         VFrame *checked,
267         VFrame *dn,
268         VFrame *checkedhi)
270         VFrame default_data(get_image_data(overlay_path));
271         BC_ThemeSet *result = new BC_ThemeSet(5, 0, "");
273         result->data[0] = new VFrame(*up);
274         result->data[1] = new VFrame(*hi);
275         result->data[2] = new VFrame(*checked);
276         result->data[3] = new VFrame(*dn);
277         result->data[4] = new VFrame(*checkedhi);
278         for(int i = 0; i < 5; i++)
279                 overlay(result->data[i], &default_data);
280         return result->data;
282 void BC_Theme::overlay(VFrame *dst, VFrame *src, int in_x1, int in_x2)
284         int w;
285         int h;
286         unsigned char **in_rows;
287         unsigned char **out_rows;
289         if(in_x1 < 0)
290         {
291                 w = MIN(src->get_w(), dst->get_w());
292                 h = MIN(dst->get_h(), src->get_h());
293                 in_x1 = 0;
294                 in_x2 = w;
295         }
296         else
297         {
298                 w = in_x2 - in_x1;
299                 h = MIN(dst->get_h(), src->get_h());
300         }
301         in_rows = src->get_rows();
302         out_rows = dst->get_rows();
304         switch(src->get_color_model())
305         {
306                 case BC_RGBA8888:
307                         switch(dst->get_color_model())
308                         {
309                                 case BC_RGBA8888:
310                                         for(int i = 0; i < h; i++)
311                                         {
312                                                 unsigned char *in_row = in_rows[i] + in_x1 * 4;
313                                                 unsigned char *out_row = out_rows[i];
314                                                 for(int j = 0; j < w; j++)
315                                                 {
316                                                         int opacity = in_row[3];
317                                                         int transparency = 0xff - opacity;
318                                                         out_row[0] = (in_row[0] * opacity + out_row[0] * transparency) / 0xff;
319                                                         out_row[1] = (in_row[1] * opacity + out_row[1] * transparency) / 0xff;
320                                                         out_row[2] = (in_row[2] * opacity + out_row[2] * transparency) / 0xff;
321                                                         out_row[3] = MAX(in_row[3], out_row[3]);
322                                                         out_row += 4;
323                                                         in_row += 4;
324                                                 }
325                                         }
326                                         break;
327                                 case BC_RGB888:
328                                         for(int i = 0; i < h; i++)
329                                         {
330                                                 unsigned char *in_row = in_rows[i] + in_x1 * 4;
331                                                 unsigned char *out_row = out_rows[i];
332                                                 for(int j = 0; j < w; j++)
333                                                 {
334                                                         int opacity = in_row[3];
335                                                         int transparency = 0xff - opacity;
336                                                         out_row[0] = (in_row[0] * opacity + out_row[0] * transparency) / 0xff;
337                                                         out_row[1] = (in_row[1] * opacity + out_row[1] * transparency) / 0xff;
338                                                         out_row[2] = (in_row[2] * opacity + out_row[2] * transparency) / 0xff;
339                                                         out_row += 3;
340                                                         in_row += 4;
341                                                 }
342                                         }
343                                         break;
344                         }
345                         break;
346         }
349 void BC_Theme::set_path(char *path)
351         strcpy(this->path, path);
354 void BC_Theme::unset_path()
356         strcpy(this->path, default_path);
357         if(data_buffer) delete [] data_buffer;
358         if(contents_buffer) delete [] contents_buffer;
359         data_buffer = 0;
360         contents_buffer = 0;
361         last_image = 0;
364 unsigned char* BC_Theme::get_image_data(char *title)
366 // Read contents
367         if(!data_buffer)
368         {
369                 FileSystem fs;
370                 if(!fs.is_dir(path))
371                 {
372                         fprintf(stderr, _("Theme::get_image: %s is a directory.\n"), path);
373                         return 0;
374                 }
375                 FILE *fd = fopen(path, "r");
376                 int result = 0;
378                 if(!fd)
379                 {
380                         fprintf(stderr, _("Theme::get_image: %s when opening %s\n"), strerror(errno), path);
381                 }
382                 int data_offset, contents_offset;
383                 int total_bytes;
384                 int data_size;
385                 int contents_size;
387                 if(fseek(fd, -8, SEEK_END) < 0)
388                 {
389                         fprintf(stderr, _("BC_Theme::get_image_data fseek %s\n"), strerror(errno));
390                         return 0;
391                 }
392                 total_bytes = ftell(fd);
393                 if(fread(&data_offset, 1, 4, fd) != 4)
394                 {
395                         fprintf(stderr, _("BC_Theme::get_image_data fread 1 %s\n"), strerror(errno));
396                         return 0;
397                 }
398                 if(fread(&contents_offset, 1, 4, fd) != 4)
399                 {
400                         fprintf(stderr, _("BC_Theme::get_image_data fread 2 %s\n"), strerror(errno));
401                         return 0;
402                 }
405                 fseek(fd, data_offset, SEEK_SET);
406                 data_size = contents_offset - data_offset;
407                 data_buffer = new char[data_size];
408                 fread(data_buffer, 1, data_size, fd);
410                 fseek(fd, contents_offset, SEEK_SET);
411                 contents_size = total_bytes - contents_offset;
412                 contents_buffer = new char[contents_size];
413                 fread(contents_buffer, 1, contents_size, fd);
415                 char *start_of_title = contents_buffer;
416                 for(int i = 0; i < contents_size; )
417                 {
418                         if(contents_buffer[i] == 0)
419                         {
420                                 contents.append(start_of_title);
421                                 i++;
422                                 offsets.append(*(int*)(contents_buffer + i));
423                                 i += 4;
424                                 start_of_title = contents_buffer + i;
425                                 used.append(0);
426                         }
427                         else
428                                 i++;
429                 }
430                 fclose(fd);
431         }
433 // Image is the same as the last one
434         if(last_image && !strcasecmp(last_image, title))
435         {
436                 return (unsigned char*)(data_buffer + last_offset);
437         }
438         else
439 // Search for image anew.
440         for(int i = 0; i < contents.total; i++)
441         {
442                 if(!strcasecmp(contents.values[i], title))
443                 {
444                         last_offset = offsets.values[i];
445                         last_image = contents.values[i];
446                         used.values[i] = 1;
447                         return (unsigned char*)(data_buffer + offsets.values[i]);
448                 }
449         }
451         fprintf(stderr, _("Theme::get_image: %s not found.\n"), title);
452         return 0;
455 void BC_Theme::check_used()
457 // Can't use because some images are gotten the old fashioned way.
458 return;
459         int got_it = 0;
460         for(int i = 0; i < used.total; i++)
461         {
462                 if(!used.values[i])
463                 {
464                         if(!got_it)
465                                 printf(_("BC_Theme::check_used: Images aren't used.\n"));
466                         printf("%s ", contents.values[i]);
467                         got_it = 1;
468                 }
469         }
470         if(got_it) printf("\n");
484 BC_ThemeSet::BC_ThemeSet(int total, int is_reference, char *title)
486         this->total = total;
487         this->title = title;
488         this->is_reference = is_reference;
489         data = new VFrame*[total];
492 BC_ThemeSet::~BC_ThemeSet()
494         if(data) 
495         {
496                 if(!is_reference)
497                 {
498                         for(int i = 0; i < total; i++)
499                                 delete data[i];
500                 }
502                 delete [] data;
503         }