upnp: remove m_server_list_lock, p_server_list is already protected by s_lock
[vlc.git] / modules / video_filter / puzzle_lib.c
1 /*****************************************************************************
2  * puzzle_lib.c : Useful functions used by puzzle game filter
3  *****************************************************************************
4  * Copyright (C) 2005-2009 VLC authors and VideoLAN
5  * Copyright (C) 2013      Vianney Boyer
6  * $Id$
7  *
8  * Authors: Antoine Cellerier <dionoea -at- videolan -dot- org>
9  *          Vianney Boyer <vlcvboyer -at- gmail -dot- com>
10  *
11  * This program is free software; you can redistribute it and/or modify it
12  * under the terms of the GNU Lesser General Public License as published by
13  * the Free Software Foundation; either version 2.1 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33 #include <math.h>
34
35 #include <vlc_common.h>
36 #include <vlc_plugin.h>
37 #include <vlc_filter.h>
38 #include <vlc_rand.h>
39
40 #include "filter_picture.h"
41
42 #include "puzzle_lib.h"
43
44 const char *ppsz_shuffle_button[SHUFFLE_LINES] =
45 {
46 "ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
47 "oooooooooooooo  oooooooooooooooooooooooooooo   oooooooo   oooooo  ooooooooooooooo",
48 "oooooooooooooo  ooooooooooooooooooooooooooo  ooooooooo  oooooooo  ooooooooooooooo",
49 "oooooooooooooo  ooooooooooooooooooooooooooo  ooooooooo  oooooooo  ooooooooooooooo",
50 "oo     ooooooo  o    ooooooo  oooo  oooooo     oooooo     oooooo  oooooooo    ooo",
51 "o  oooo oooooo   ooo  oooooo  oooo  ooooooo  ooooooooo  oooooooo  ooooooo  oo  oo",
52 "o  ooooooooooo  oooo  oooooo  oooo  ooooooo  ooooooooo  oooooooo  oooooo  oooo  o",
53 "o      ooooooo  oooo  oooooo  oooo  ooooooo  ooooooooo  oooooooo  oooooo        o",
54 "oo      oooooo  oooo  oooooo  oooo  ooooooo  ooooooooo  oooooooo  oooooo  ooooooo",
55 "oooooo  oooooo  oooo  oooooo  oooo  ooooooo  ooooooooo  oooooooo  oooooo  ooooooo",
56 "o oooo  oooooo  oooo  oooooo  ooo   ooooooo  ooooooooo  oooooooo  ooooooo  oooo o",
57 "oo     ooooooo  oooo  ooooooo    o  ooooooo  ooooooooo  oooooooo  oooooooo     oo",
58 "ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
59 };
60
61 const char *ppsz_rot_arrow_sign[ARROW_LINES] =
62 {
63 "    .ooo.    ",
64 "   .o. .oo.  ",
65 "  .o.    .o. ",
66 " .o.      .o.",
67 " o.        .o",
68 ".o          .",
69 ".o   .       ",
70 " o. .o.      ",
71 " .o..o.      ",
72 "  o..o       ",
73 "   .o.       ",
74 "ooooo.       ",
75 "  ..         "
76 };
77
78 const char *ppsz_mir_arrow_sign[ARROW_LINES] =
79 {
80 "             ",
81 "             ",
82 "    .   .    ",
83 "  .o.   .o.  ",
84 " .o.     .o. ",
85 ".o.       .o.",
86 "ooooooooooooo",
87 ".o.       .o.",
88 " .o.     .o. ",
89 "  .o.   .o.  ",
90 "    .   .    ",
91 "             ",
92 "             "
93 };
94
95 /*****************************************************************************
96  * fill target image (clean memory)
97  *****************************************************************************/
98 void puzzle_preset_desk_background( picture_t *p_pic_out, uint8_t Y, uint8_t U, uint8_t V)
99 {
100     uint8_t i_c;
101
102     for( uint8_t i_plane = 0; i_plane < p_pic_out->i_planes; i_plane++ ) {
103         if (i_plane == Y_PLANE)
104             i_c = Y;
105         else if (i_plane == U_PLANE)
106             i_c = U;
107         else if (i_plane == V_PLANE)
108             i_c = V;
109
110         const int32_t i_dst_pitch = p_pic_out->p[i_plane].i_pitch;
111         const int32_t i_dst_lines = p_pic_out->p[i_plane].i_lines;
112
113         uint8_t *p_dst = p_pic_out->p[i_plane].p_pixels;
114
115         for (int32_t y = 0; y < i_dst_lines; y++)
116             memset(&p_dst[y * i_dst_pitch], i_c, i_dst_pitch);
117     }
118 }
119
120 /*****************************************************************************
121  * draw the borders around the visible desk
122  *****************************************************************************/
123 void puzzle_draw_borders( filter_t *p_filter, picture_t *p_pic_in, picture_t *p_pic_out)
124 {
125     filter_sys_t *p_sys = p_filter->p_sys;
126
127     for( uint8_t i_plane = 0; i_plane < p_pic_out->i_planes; i_plane++ ) {
128         const int32_t i_in_pitch      = p_sys->ps_pict_planes[i_plane].i_pitch;
129         const int32_t i_out_pitch     = p_sys->ps_desk_planes[i_plane].i_pitch;
130         const int32_t i_lines         = p_sys->ps_desk_planes[i_plane].i_lines;
131         const int32_t i_visible_pitch = p_sys->ps_desk_planes[i_plane].i_visible_pitch;
132         const int32_t i_border_pitch  = p_sys->ps_desk_planes[i_plane].i_border_width * p_sys->ps_desk_planes[i_plane].i_pixel_pitch;
133         const int32_t i_border_lines  = p_sys->ps_desk_planes[i_plane].i_border_lines;
134
135         uint8_t *p_src = p_pic_in->p[i_plane].p_pixels;
136         uint8_t *p_dst = p_pic_out->p[i_plane].p_pixels;
137
138         for (int32_t y = 0 ; y < i_border_lines; y++)
139             memcpy( &p_dst[y * i_out_pitch], &p_src[y * i_in_pitch], i_visible_pitch);
140
141         for (int32_t y = i_lines - i_border_lines ; y < i_lines; y++)
142             memcpy( &p_dst[y * i_out_pitch], &p_src[y * i_in_pitch], i_visible_pitch);
143
144         for (int32_t y = i_border_lines ; y < i_lines - i_border_lines; y++) {
145             memcpy( &p_dst[y * i_out_pitch], &p_src[y * i_in_pitch], i_border_pitch);
146             memcpy( &p_dst[y * i_out_pitch + i_visible_pitch - i_border_pitch], &p_src[y * i_in_pitch + i_visible_pitch - i_border_pitch], i_border_pitch);
147         }
148     }
149 }
150
151 /*****************************************************************************
152  * draw preview in a corner of the desk
153  *****************************************************************************/
154 void puzzle_draw_preview( filter_t *p_filter, picture_t *p_pic_in, picture_t *p_pic_out)
155 {
156     filter_sys_t *p_sys = p_filter->p_sys;
157
158     for( uint8_t  i_plane = 0; i_plane < p_pic_out->i_planes; i_plane++ ) {
159         int32_t i_preview_offset = 0;
160         int32_t i_preview_width  = p_sys->ps_desk_planes[i_plane].i_width * p_sys->s_current_param.i_preview_size / 100;
161         int32_t i_preview_lines  = p_pic_out->p[i_plane].i_visible_lines * p_sys->s_current_param.i_preview_size / 100;
162         int32_t i_pixel_pitch    = p_pic_out->p[i_plane].i_pixel_pitch;
163
164         const int32_t i_src_pitch  = p_pic_in->p[i_plane].i_pitch;
165         const int32_t i_dst_pitch  = p_pic_out->p[i_plane].i_pitch;
166
167         uint8_t *p_src = p_pic_in->p[i_plane].p_pixels;
168         uint8_t *p_dst = p_pic_out->p[i_plane].p_pixels;
169
170         switch ( p_sys->i_preview_pos ) {
171         case 0:
172             i_preview_offset = 0;
173             break;
174         case 1:
175             i_preview_offset =
176                 (p_sys->ps_desk_planes[i_plane].i_width - 1 - i_preview_width) * i_pixel_pitch;
177             break;
178         case 2:
179             i_preview_offset =
180                 (p_sys->ps_desk_planes[i_plane].i_width - 1 - i_preview_width) * i_pixel_pitch
181                 + ((int32_t) ( p_sys->ps_desk_planes[i_plane].i_lines - 1 - i_preview_lines )) * i_dst_pitch;
182             break;
183         case 3:
184             i_preview_offset = ((int32_t) ( p_sys->ps_desk_planes[i_plane].i_lines - 1 - i_preview_lines )) * i_dst_pitch;
185             break;
186         default:
187             i_preview_offset = 0;
188             break;
189         }
190
191         for ( int32_t y = 0; y < i_preview_lines; y++ )
192             for ( int32_t x = 0; x < i_preview_width; x++ )
193                 memcpy( &p_dst[ y * i_dst_pitch + x * i_pixel_pitch + i_preview_offset ],
194                         &p_src[ ( y * 100 / p_sys->s_current_param.i_preview_size ) * i_src_pitch
195                                 + ( x * 100 / p_sys->s_current_param.i_preview_size ) * i_pixel_pitch ],
196                         i_pixel_pitch );
197     }
198 }
199
200 /*****************************************************************************
201  * draw sign/icon/symbol in the output picture
202  *****************************************************************************/
203 void puzzle_draw_sign(picture_t *p_pic_out, int32_t i_x, int32_t i_y, int32_t i_width, int32_t i_lines, const char **ppsz_sign, bool b_reverse)
204 {
205     plane_t *p_out = &p_pic_out->p[Y_PLANE];
206     int32_t i_pixel_pitch    = p_pic_out->p[Y_PLANE].i_pixel_pitch;
207
208     uint8_t i_Y;
209
210     i_Y = ( p_out->p_pixels[ i_y * p_out->i_pitch + i_x ] >= 0x7F ) ? 0x00 : 0xFF;
211
212     for( int32_t y = 0; y < i_lines ; y++ )
213         for( int32_t x = 0; x < i_width; x++ ) {
214             int32_t i_dst_x = ( x + i_x ) * i_pixel_pitch;
215             int32_t i_dst_y = y + i_y;
216             if ( ppsz_sign[y][b_reverse?i_width-1-x:x] == 'o' ) {
217                 if ((i_dst_x < p_out->i_visible_pitch) && (i_dst_y < p_out->i_visible_lines) && (i_dst_x >= 0 ) && (i_dst_y >= 0))
218                     memset( &p_out->p_pixels[ i_dst_y * p_out->i_pitch + i_dst_x ],   i_Y,  p_out->i_pixel_pitch );
219             }
220             else if ( ppsz_sign[y][b_reverse?i_width-1-x:x] == '.' ) {
221                 if ((i_dst_x < p_out->i_visible_pitch) && (i_dst_y < p_out->i_visible_lines) && (i_dst_x >= 0 ) && (i_dst_y >= 0))
222                     p_out->p_pixels[ i_dst_y * p_out->i_pitch + i_dst_x ] = p_out->p_pixels[ i_dst_y * p_out->i_pitch + i_dst_x ] / 2 + i_Y / 2;
223             }
224         }
225 }
226
227 /*****************************************************************************
228  * draw outline rectangle in output picture
229  *****************************************************************************/
230 void puzzle_draw_rectangle(picture_t *p_pic_out, int32_t i_x, int32_t i_y, int32_t i_w, int32_t i_h, uint8_t i_Y, uint8_t i_U, uint8_t i_V )
231 {
232     uint8_t i_c;
233
234     for( uint8_t i_plane = 0; i_plane < p_pic_out->i_planes; i_plane++ ) {
235         plane_t *p_oyp = &p_pic_out->p[i_plane];
236         int32_t i_pixel_pitch    = p_pic_out->p[i_plane].i_pixel_pitch;
237
238         if (i_plane == Y_PLANE)
239             i_c = i_Y;
240         else if (i_plane == U_PLANE)
241             i_c = i_U;
242         else if (i_plane == V_PLANE)
243             i_c = i_V;
244
245         int32_t i_x_min = (      i_x    * p_oyp->i_visible_pitch / p_pic_out->p[0].i_visible_pitch ) * i_pixel_pitch;
246         int32_t i_x_max = ( (i_x + i_w) * p_oyp->i_visible_pitch / p_pic_out->p[0].i_visible_pitch ) * i_pixel_pitch;
247         int32_t i_y_min =        i_y    * p_oyp->i_visible_lines / p_pic_out->p[0].i_visible_lines;
248         int32_t i_y_max =   (i_y + i_h) * p_oyp->i_visible_lines / p_pic_out->p[0].i_visible_lines;
249
250         /* top line */
251         memset( &p_oyp->p_pixels[i_y_min * p_oyp->i_pitch + i_x_min], i_c,  i_x_max - i_x_min);
252
253         /* left and right */
254         for( int32_t i_dy = 1; i_dy < i_y_max - i_y_min - 1; i_dy++ ) {
255             memset( &p_oyp->p_pixels[ (i_y_min + i_dy) * p_oyp->i_pitch + i_x_min ],   i_c,  p_oyp->i_pixel_pitch );
256             memset( &p_oyp->p_pixels[(i_y_min + i_dy) * p_oyp->i_pitch + i_x_max - 1], i_c,  p_oyp->i_pixel_pitch );
257         }
258
259         /* bottom line */
260         memset( &p_oyp->p_pixels[(i_y_max - 1) * p_oyp->i_pitch + i_x_min], i_c,  i_x_max - i_x_min);
261     }
262 }
263
264 /*****************************************************************************
265  * draw bold rectangle in output picture
266  *****************************************************************************/
267 void puzzle_fill_rectangle(picture_t *p_pic_out, int32_t i_x, int32_t i_y, int32_t i_w, int32_t i_h, uint8_t i_Y, uint8_t i_U, uint8_t i_V )
268 {
269     uint8_t i_c;
270
271     for( uint8_t i_plane = 0; i_plane < p_pic_out->i_planes; i_plane++ ) {
272         plane_t *p_oyp = &p_pic_out->p[i_plane];
273         int32_t i_pixel_pitch    = p_pic_out->p[i_plane].i_pixel_pitch;
274
275         if (i_plane == Y_PLANE)
276             i_c = i_Y;
277         else if (i_plane == U_PLANE)
278             i_c = i_U;
279         else if (i_plane == V_PLANE)
280             i_c = i_V;
281
282         int32_t i_x_min = (     i_x     * p_oyp->i_visible_pitch / p_pic_out->p[0].i_visible_pitch ) * i_pixel_pitch;
283         int32_t i_x_max = ( (i_x + i_w) * p_oyp->i_visible_pitch / p_pic_out->p[0].i_visible_pitch ) * i_pixel_pitch;
284         int32_t i_y_min =       i_y     * p_oyp->i_visible_lines / p_pic_out->p[0].i_visible_lines;
285         int32_t i_y_max =   (i_y + i_h) * p_oyp->i_visible_lines / p_pic_out->p[0].i_visible_lines;
286
287         for( int32_t i_dy = 0; i_dy < i_y_max - i_y_min; i_dy++ )
288             memset( &p_oyp->p_pixels[(i_y_min + i_dy) * p_oyp->i_pitch + i_x_min], i_c,  i_x_max - i_x_min);
289     }
290 }