r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / guicast / bctheme.C
blob63d639ea694eb01d3c6662c04424478370c96e47
1 #include "bctheme.h"
2 #include "bcwindowbase.h"
3 #include "clip.h"
4 #include "vframe.h"
6 #include <errno.h>
7 #include <stdarg.h>
8 #include <stdio.h>
9 #include <string.h>
11 #include <libintl.h>
12 #define _(String) gettext(String)
13 #define gettext_noop(String) String
14 #define N_(String) gettext_noop (String)
16 BC_Theme::BC_Theme()
18         char *path_env = getenv("PATH");
19         char default_path[BCTEXTLEN];
20         char *path_ptr = path_env;
22 // Get location of executable
23         FILE *fd = fopen("/proc/self/cmdline", "r");
24         if(!fd)
25         {
26                 perror(_("BC_Theme::BC_Theme: can't open /proc/self/cmdline.\n"));
27                 return;
28         }
29         else
30         {
31                 fread(default_path, 1, BCTEXTLEN, fd);
32                 strcpy(path, default_path);
33                 fclose(fd);
34         }
36         int done = 0;
37         fd = 0;
38         do
39         {
40                 fd = fopen(path, "r");
43                 if(!fd)
44                 {
45 // Get next entry out of path_env
46                         while(*path_ptr)
47                         {
48                                 if(*path_ptr != ':') 
49                                         break;
50                                 else
51                                         path_ptr++;
52                         }
54                         if(!*path_ptr) break;
56                         char *new_ptr = path;
57                         while(*path_ptr)
58                         {
59                                 if(*path_ptr == ':')
60                                         break;
61                                 else
62                                         *new_ptr++ = *path_ptr++;
63                         }
65                         *new_ptr = 0;
66                         if(new_ptr - path > 0 && *(new_ptr - 1) != '/')
67                         {
68                                 *new_ptr++ = '/';
69                                 *new_ptr = 0;
70                         }
71                         strcat(path, default_path);
72                 }
73                 else
74                 {
75                         fclose(fd);
76                         done = 1;
77                 }
78         }while(!done);
81         data_buffer = 0;
82         contents_buffer = 0;
83         last_image = 0;
86 BC_Theme::~BC_Theme()
88         for(int i = 0; i < image_sets.total; i++)
89                 delete image_sets.values[i];
90         for(int i = 0; i < images.total; i++)
91                 delete images.values[i];
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 images=%d sets=%d path=%s contents=%d\n", 
99                 images.total, 
100                 image_sets.total, 
101                 path, 
102                 contents.total);
103         for(int i = 0; i < contents.total; i++)
104                 printf("    %s %x\n", contents.values[i], offsets.values[i]);
107 BC_Resources* BC_Theme::get_resources()
109         return BC_WindowBase::get_resources();
112 // These create image sets which are stored in the caches.
113 VFrame** BC_Theme::new_image_set(int total, ...)
115         va_list list;
116         BC_ThemeSet *result = new BC_ThemeSet(total);
117         image_sets.append(result);
120         va_start(list, total);
121         for(int i = 0; i < total; i++)
122         {
123                 char *path = va_arg(list, char*);
124                 result->data[i] = new_image(path);
125         }
126         va_end(list);
128         return result->data;
131 VFrame** BC_Theme::new_button(char *overlay_path, 
132         char *up_path, 
133         char *hi_path, 
134         char *dn_path)
136         VFrame default_data(get_image_data(overlay_path));
137         BC_ThemeSet *result = new BC_ThemeSet(3);
139         result->data[0] = new_image(up_path);
140         result->data[1] = new_image(hi_path);
141         result->data[2] = new_image(dn_path);
142         for(int i = 0; i < 3; i++)
143                 overlay(result->data[i], &default_data);
144         return result->data;
148 VFrame** BC_Theme::new_button(char *overlay_path, 
149         VFrame *up,
150         VFrame *hi,
151         VFrame *dn)
153         VFrame default_data(get_image_data(overlay_path));
154         BC_ThemeSet *result = new BC_ThemeSet(3);
156         result->data[0] = new VFrame(*up);
157         result->data[1] = new VFrame(*hi);
158         result->data[2] = new VFrame(*dn);
159         for(int i = 0; i < 3; i++)
160                 overlay(result->data[i], &default_data);
161         return result->data;
165 VFrame** BC_Theme::new_toggle(char *overlay_path, 
166         char *up_path,
167         char *hi_path,
168         char *checked_path,
169         char *dn_path,
170         char *checkedhi_path)
172         VFrame default_data(get_image_data(overlay_path));
173         BC_ThemeSet *result = new BC_ThemeSet(5);
175         result->data[0] = new_image(up_path);
176         result->data[1] = new_image(hi_path);
177         result->data[2] = new_image(checked_path);
178         result->data[3] = new_image(dn_path);
179         result->data[4] = new_image(checkedhi_path);
180         for(int i = 0; i < 5; i++)
181                 overlay(result->data[i], &default_data);
182         return result->data;
185 VFrame** BC_Theme::new_toggle(char *overlay_path, 
186         VFrame *up,
187         VFrame *hi,
188         VFrame *checked,
189         VFrame *dn,
190         VFrame *checkedhi)
192         VFrame default_data(get_image_data(overlay_path));
193         BC_ThemeSet *result = new BC_ThemeSet(5);
195         result->data[0] = new VFrame(*up);
196         result->data[1] = new VFrame(*hi);
197         result->data[2] = new VFrame(*checked);
198         result->data[3] = new VFrame(*dn);
199         result->data[4] = new VFrame(*checkedhi);
200         for(int i = 0; i < 5; i++)
201                 overlay(result->data[i], &default_data);
202         return result->data;
204 void BC_Theme::overlay(VFrame *dst, VFrame *src, int in_x1, int in_x2)
206         int w;
207         int h;
208         unsigned char **in_rows;
209         unsigned char **out_rows;
211         if(in_x1 < 0)
212         {
213                 w = MIN(src->get_w(), dst->get_w());
214                 h = MIN(dst->get_h(), src->get_h());
215                 in_x1 = 0;
216                 in_x2 = w;
217         }
218         else
219         {
220                 w = in_x2 - in_x1;
221                 h = MIN(dst->get_h(), src->get_h());
222         }
223         in_rows = src->get_rows();
224         out_rows = dst->get_rows();
226         switch(src->get_color_model())
227         {
228                 case BC_RGBA8888:
229                         switch(dst->get_color_model())
230                         {
231                                 case BC_RGBA8888:
232                                         for(int i = 0; i < h; i++)
233                                         {
234                                                 unsigned char *in_row = in_rows[i] + in_x1 * 4;
235                                                 unsigned char *out_row = out_rows[i];
236                                                 for(int j = 0; j < w; j++)
237                                                 {
238                                                         int opacity = in_row[3];
239                                                         int transparency = 0xff - opacity;
240                                                         out_row[0] = (in_row[0] * opacity + out_row[0] * transparency) / 0xff;
241                                                         out_row[1] = (in_row[1] * opacity + out_row[1] * transparency) / 0xff;
242                                                         out_row[2] = (in_row[2] * opacity + out_row[2] * transparency) / 0xff;
243                                                         out_row[3] = MAX(in_row[3], out_row[3]);
244                                                         out_row += 4;
245                                                         in_row += 4;
246                                                 }
247                                         }
248                                         break;
249                                 case BC_RGB888:
250                                         for(int i = 0; i < h; i++)
251                                         {
252                                                 unsigned char *in_row = in_rows[i] + in_x1 * 4;
253                                                 unsigned char *out_row = out_rows[i];
254                                                 for(int j = 0; j < w; j++)
255                                                 {
256                                                         int opacity = in_row[3];
257                                                         int transparency = 0xff - opacity;
258                                                         out_row[0] = (in_row[0] * opacity + out_row[0] * transparency) / 0xff;
259                                                         out_row[1] = (in_row[1] * opacity + out_row[1] * transparency) / 0xff;
260                                                         out_row[2] = (in_row[2] * opacity + out_row[2] * transparency) / 0xff;
261                                                         out_row += 3;
262                                                         in_row += 4;
263                                                 }
264                                         }
265                                         break;
266                         }
267                         break;
268         }
271 VFrame* BC_Theme::new_image(char *title)
273         VFrame *result = new VFrame(get_image_data(title));
274         images.append(result);
275         return result;
278 void BC_Theme::set_path(char *path)
280         strcpy(this->path, path);
283 unsigned char* BC_Theme::get_image_data(char *title)
285 // Read contents
286         if(!data_buffer)
287         {
288                 FILE *fd = fopen(path, "r");
290                 if(!fd)
291                 {
292                         fprintf(stderr, _("Theme::get_image: %s when opening %s\n"), strerror(errno), path);
293                 }
294                 int data_offset, contents_offset;
295                 int total_bytes;
296                 int data_size;
297                 int contents_size;
299                 fseek(fd, -8, SEEK_END);
300                 total_bytes = ftell(fd);
301                 fread(&data_offset, 1, 4, fd);
302                 fread(&contents_offset, 1, 4, fd);
305                 fseek(fd, data_offset, SEEK_SET);
306                 data_size = contents_offset - data_offset;
307                 data_buffer = new char[data_size];
308                 fread(data_buffer, 1, data_size, fd);
310                 fseek(fd, contents_offset, SEEK_SET);
311                 contents_size = total_bytes - contents_offset;
312                 contents_buffer = new char[contents_size];
313                 fread(contents_buffer, 1, contents_size, fd);
315                 char *start_of_title = contents_buffer;
316                 for(int i = 0; i < contents_size; )
317                 {
318                         if(contents_buffer[i] == 0)
319                         {
320                                 contents.append(start_of_title);
321                                 i++;
322                                 offsets.append(*(int*)(contents_buffer + i));
323                                 i += 4;
324                                 start_of_title = contents_buffer + i;
325                                 used.append(0);
326                         }
327                         else
328                                 i++;
329                 }
330                 fclose(fd);
331         }
333 // Image is the same as the last one
334         if(last_image && !strcasecmp(last_image, title))
335         {
336                 return (unsigned char*)(data_buffer + last_offset);
337         }
338         else
339 // Search for image anew.
340         for(int i = 0; i < contents.total; i++)
341         {
342                 if(!strcasecmp(contents.values[i], title))
343                 {
344                         last_offset = offsets.values[i];
345                         last_image = contents.values[i];
346                         used.values[i] = 1;
347                         return (unsigned char*)(data_buffer + offsets.values[i]);
348                 }
349         }
351         fprintf(stderr, _("Theme::get_image: %s not found.\n"), title);
352         return 0;
355 void BC_Theme::check_used()
357 // Can't use because some images are gotten the old fashioned way.
358 return;
359         int got_it = 0;
360         for(int i = 0; i < used.total; i++)
361         {
362                 if(!used.values[i])
363                 {
364                         if(!got_it)
365                                 printf(_("BC_Theme::check_used: Images aren't used.\n"));
366                         printf("%s ", contents.values[i]);
367                         got_it = 1;
368                 }
369         }
370         if(got_it) printf("\n");
384 BC_ThemeSet::BC_ThemeSet(int total)
386         data = new VFrame*[total];
389 BC_ThemeSet::~BC_ThemeSet()
391         if(data) delete [] data;