1 /*****************************************************************
2  * gmerlin - a general purpose multimedia framework and applications
3  *
4  * Copyright (c) 2001 - 2011 Members of the Gmerlin project
5  * gmerlin-general@lists.sourceforge.net
6  * http://gmerlin.sourceforge.net
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  * *****************************************************************/
21 
22 #include <x11/x11.h>
23 #include <x11/x11_window_private.h>
24 
25 /* Warning: These functions are not optimized and not intended to
26    be used very often */
27 
make_icon(bg_x11_window_t * win,const gavl_video_frame_t * icon,const gavl_video_format_t * format)28 static Pixmap make_icon(bg_x11_window_t * win,
29                         const gavl_video_frame_t * icon,
30                         const gavl_video_format_t * format)
31   {
32   XImage * im;
33   gavl_video_format_t out_format;
34   gavl_video_converter_t * cnv;
35   gavl_video_options_t * opt;
36   int do_convert;
37   const gavl_video_frame_t * image_frame;
38   gavl_video_frame_t * out_frame;
39 
40   Pixmap ret;
41 
42   /* Create converter */
43   cnv = gavl_video_converter_create();
44   opt = gavl_video_converter_get_options(cnv);
45   gavl_video_options_set_alpha_mode(opt, GAVL_ALPHA_IGNORE);
46 
47   /* Create pixmap */
48   ret = XCreatePixmap(win->dpy, win->root, format->image_width,
49                       format->image_height, win->depth);
50 
51   /* Set up format and converter */
52   gavl_video_format_copy(&out_format, format);
53   out_format.pixelformat =
54     bg_x11_window_get_pixelformat(win->dpy, win->visual, win->depth);
55 
56   do_convert = gavl_video_converter_init(cnv, format, &out_format);
57   if(do_convert)
58     {
59     out_frame = gavl_video_frame_create(&out_format);
60     image_frame = out_frame;
61     gavl_video_convert(cnv, icon, out_frame);
62     }
63   else
64     {
65     image_frame = icon;
66     out_frame = NULL;
67     }
68 
69   /* Make image */
70 
71   im = XCreateImage(win->dpy, win->visual, win->depth,
72                     ZPixmap,
73                     0, (char*)(image_frame->planes[0]),
74                     format->image_width,
75                     format->image_height,
76                     32,
77                     image_frame->strides[0]);
78 
79   XPutImage(win->dpy,            /* dpy        */
80             ret, /* d          */
81             win->gc,             /* gc         */
82             im, /* image      */
83             0,    /* src_x      */
84             0,    /* src_y      */
85             0,          /* dst_x      */
86             0,          /* dst_y      */
87             format->image_width,    /* src_width  */
88             format->image_height);  /* src_height */
89 
90   /* Cleanup */
91   gavl_video_converter_destroy(cnv);
92   if(out_frame)
93     gavl_video_frame_destroy(out_frame);
94 
95   im->data = NULL;
96   XDestroyImage(im);
97 
98   /* Return */
99   return ret;
100 
101   }
102 
create_mask_8(gavl_video_format_t * format,gavl_video_frame_t * frame,char * im,int bytes_per_line)103 static void create_mask_8(gavl_video_format_t * format,
104                           gavl_video_frame_t * frame,
105                           char * im, int bytes_per_line)
106   {
107   int i, j;
108   uint8_t * ptr;
109   uint8_t * im_ptr;
110   int shift;
111 
112   for(i = 0; i < format->image_height; i++)
113     {
114     ptr = frame->planes[0] + i * frame->strides[0];
115     im_ptr = (uint8_t*)(im + i * bytes_per_line);
116     shift = 0;
117 
118     for(j = 0; j < format->image_width; j++)
119       {
120       if(*ptr >= 0x80)
121         *im_ptr |= 1 << shift;
122       if(shift == 7)
123         {
124         im_ptr++;
125         shift = 0;
126         }
127       else
128         shift++;
129       ptr++;
130       }
131     }
132 
133   }
134 
create_mask_16(gavl_video_format_t * format,gavl_video_frame_t * frame,char * im,int bytes_per_line)135 static void create_mask_16(gavl_video_format_t * format,
136                            gavl_video_frame_t * frame,
137                            char * im, int bytes_per_line)
138   {
139   int i, j;
140   uint16_t * ptr;
141   uint8_t * im_ptr;
142   int shift;
143 
144   for(i = 0; i < format->image_height; i++)
145     {
146     ptr = (uint16_t*)(frame->planes[0] + i * frame->strides[0]);
147     im_ptr = (uint8_t*)(im + i * bytes_per_line);
148     shift = 0;
149 
150     for(j = 0; j < format->image_width; j++)
151       {
152       if(*ptr >= 0x8000)
153         *im_ptr |= 1 << shift;
154       if(shift == 7)
155         {
156         im_ptr++;
157         shift = 0;
158         }
159       else
160         shift++;
161       ptr++;
162       }
163     }
164 
165   }
166 
create_mask_float(gavl_video_format_t * format,gavl_video_frame_t * frame,char * im,int bytes_per_line)167 static void create_mask_float(gavl_video_format_t * format,
168                               gavl_video_frame_t * frame,
169                               char * im, int bytes_per_line)
170   {
171   int i, j;
172   float * ptr;
173   uint8_t * im_ptr;
174   int shift;
175 
176   for(i = 0; i < format->image_height; i++)
177     {
178     ptr = (float*)(frame->planes[0] + i * frame->strides[0]);
179     im_ptr = (uint8_t*)(im + i * bytes_per_line);
180     shift = 0;
181 
182     for(j = 0; j < format->image_width; j++)
183       {
184       if(*ptr >= 0.5)
185         *im_ptr |= 1 << shift;
186       if(shift == 7)
187         {
188         im_ptr++;
189         shift = 0;
190         }
191       else
192         shift++;
193       ptr++;
194       }
195     }
196 
197   }
198 
make_mask(bg_x11_window_t * win,const gavl_video_frame_t * icon,const gavl_video_format_t * format)199 static Pixmap make_mask(bg_x11_window_t * win,
200                         const gavl_video_frame_t * icon,
201                         const gavl_video_format_t * format)
202   {
203   gavl_video_frame_t * alpha_frame;
204   gavl_video_format_t alpha_format;
205   char * image_data;
206 
207   Pixmap ret;
208   int bytes_per_line;
209 
210   /* Extract alpha */
211   if(!gavl_get_color_channel_format(format,
212                                     &alpha_format,
213                                     GAVL_CCH_ALPHA))
214     return None; /* No alpha */
215 
216   alpha_frame = gavl_video_frame_create(&alpha_format);
217 
218   gavl_video_frame_extract_channel(format,
219                                    GAVL_CCH_ALPHA,
220                                    icon,
221                                    alpha_frame);
222 
223   /* Create image */
224 
225   bytes_per_line = (format->image_width + 7) / 8;
226   image_data = calloc(1, bytes_per_line * format->image_height);
227 
228   switch(alpha_format.pixelformat)
229     {
230     case GAVL_GRAY_8:
231       create_mask_8(&alpha_format, alpha_frame, image_data, bytes_per_line);
232       break;
233     case GAVL_GRAY_16:
234       create_mask_16(&alpha_format, alpha_frame, image_data, bytes_per_line);
235       break;
236     case GAVL_GRAY_FLOAT:
237       create_mask_float(&alpha_format, alpha_frame, image_data, bytes_per_line);
238       break;
239     default:
240       break;
241     }
242   ret = XCreateBitmapFromData(win->dpy, win->root,
243                               image_data,
244                               format->image_width,
245                               format->image_height);
246 
247   gavl_video_frame_destroy(alpha_frame);
248   free(image_data);
249   return ret;
250   }
251 
bg_x11_window_make_icon(bg_x11_window_t * win,const gavl_video_frame_t * icon,const gavl_video_format_t * format,Pixmap * icon_ret,Pixmap * mask_ret)252 void bg_x11_window_make_icon(bg_x11_window_t * win,
253                              const gavl_video_frame_t * icon,
254                              const gavl_video_format_t * format,
255                              Pixmap * icon_ret, Pixmap * mask_ret)
256   {
257   if(icon_ret)
258     *icon_ret = make_icon(win, icon, format);
259 
260   if(mask_ret)
261     *mask_ret = make_mask(win, icon, format);
262   }
263 
264