1 /*****************************************************************************
2 * puzzle_pce.c : Puzzle game filter - pieces functions
3 *****************************************************************************
4 * Copyright (C) 2013 Vianney Boyer
7 * Author: Vianney Boyer <vlcvboyer -at- gmail -dot- com>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_filter.h>
36 #include <vlc_picture.h>
39 #include "filter_picture.h"
41 #include "puzzle_bezier.h"
42 #include "puzzle_lib.h"
43 #include "puzzle_pce.h"
46 #define PIECE_TYPE_NBR (4*2*(1+SHAPES_QTY))
48 /*****************************************************************************
49 * puzzle_bake_pieces_shapes: allocate and compute shapes
50 *****************************************************************************/
51 int puzzle_bake_pieces_shapes( filter_t
*p_filter
)
54 * piece_shape_t **ps_pieces_shapes; * array [each piece type (PCE_TYPE_NBR * 4 ( * negative ): top, left,right,btm)][each plane] of piece definition
56 * 1 => left border (negative, never used)
60 * 9 => bezier left negative
62 * 11 => bezier top negative
64 * 13 => bezier btm negative
66 * 15 => bezier right negative
70 filter_sys_t
*p_sys
= p_filter
->p_sys
;
72 puzzle_free_ps_pieces_shapes(p_filter
);
73 p_sys
->ps_pieces_shapes
= malloc( sizeof( piece_shape_t
*) * PIECE_TYPE_NBR
);
74 if( !p_sys
->ps_pieces_shapes
)
77 for (int32_t i_piece
= 0; i_piece
< PIECE_TYPE_NBR
; i_piece
++) {
78 p_sys
->ps_pieces_shapes
[i_piece
] = malloc( sizeof( piece_shape_t
) * p_sys
->s_allocated
.i_planes
);
79 if( !p_sys
->ps_pieces_shapes
[i_piece
] )
81 for (uint8_t i_plane
= 0; i_plane
< p_filter
->p_sys
->s_allocated
.i_planes
; i_plane
++) {
82 p_sys
->ps_pieces_shapes
[i_piece
][i_plane
].i_row_nbr
= 0;
83 p_sys
->ps_pieces_shapes
[i_piece
][i_plane
].ps_piece_shape_row
= NULL
;
87 int32_t i_currect_shape
= 0;
89 for (uint8_t i_plane
= 0; i_plane
< p_filter
->p_sys
->s_allocated
.i_planes
; i_plane
++) {
91 i_ret
= puzzle_generate_sect_border( p_filter
, &p_sys
->ps_pieces_shapes
[i_currect_shape
+0][i_plane
], i_plane
, puzzle_SHAPE_LEFT
);
92 if (i_ret
!= VLC_SUCCESS
) return i_ret
;
93 i_ret
= puzzle_generate_sect_border( p_filter
, &p_sys
->ps_pieces_shapes
[i_currect_shape
+1][i_plane
], i_plane
, puzzle_SHAPE_LEFT
);
94 if (i_ret
!= VLC_SUCCESS
) return i_ret
;
95 i_ret
= puzzle_generate_sect_border( p_filter
, &p_sys
->ps_pieces_shapes
[i_currect_shape
+2][i_plane
], i_plane
, puzzle_SHAPE_TOP
);
96 if (i_ret
!= VLC_SUCCESS
) return i_ret
;
97 i_ret
= puzzle_generate_sect_border( p_filter
, &p_sys
->ps_pieces_shapes
[i_currect_shape
+3][i_plane
], i_plane
, puzzle_SHAPE_TOP
);
98 if (i_ret
!= VLC_SUCCESS
) return i_ret
;
99 i_ret
= puzzle_generate_sect_border( p_filter
, &p_sys
->ps_pieces_shapes
[i_currect_shape
+4][i_plane
], i_plane
, puzzle_SHAPE_BTM
);
100 if (i_ret
!= VLC_SUCCESS
) return i_ret
;
101 i_ret
= puzzle_generate_sect_border( p_filter
, &p_sys
->ps_pieces_shapes
[i_currect_shape
+5][i_plane
], i_plane
, puzzle_SHAPE_BTM
);
102 if (i_ret
!= VLC_SUCCESS
) return i_ret
;
103 i_ret
= puzzle_generate_sect_border( p_filter
, &p_sys
->ps_pieces_shapes
[i_currect_shape
+6][i_plane
], i_plane
, puzzle_SHAPE_RIGHT
);
104 if (i_ret
!= VLC_SUCCESS
) return i_ret
;
105 i_ret
= puzzle_generate_sect_border( p_filter
, &p_sys
->ps_pieces_shapes
[i_currect_shape
+7][i_plane
], i_plane
, puzzle_SHAPE_RIGHT
);
106 if (i_ret
!= VLC_SUCCESS
) return i_ret
;
109 i_currect_shape
+= 8;
111 int32_t i_width
= p_sys
->ps_desk_planes
[0].i_pce_max_width
;
112 int32_t i_lines
= p_sys
->ps_desk_planes
[0].i_pce_max_lines
;
114 for (int32_t i_shape
= 0; i_shape
<SHAPES_QTY
; i_shape
++) {
116 point_t
*ps_scale_pts_H
= puzzle_scale_curve_H(i_width
, i_lines
, 7, p_sys
->ps_bezier_pts_H
[i_shape
], p_sys
->s_allocated
.i_shape_size
);
117 point_t
*ps_scale_pts_V
= puzzle_H_2_scale_curve_V(i_width
, i_lines
, 7, p_sys
->ps_bezier_pts_H
[i_shape
], p_sys
->s_allocated
.i_shape_size
);
118 point_t
*ps_neg_pts_H
= puzzle_curve_H_2_negative(7, ps_scale_pts_H
);
119 point_t
*ps_neg_pts_V
= puzzle_curve_V_2_negative(7, ps_scale_pts_V
);
121 if (!ps_scale_pts_H
|| !ps_scale_pts_V
|| !ps_neg_pts_H
|| !ps_neg_pts_V
) {
122 free(ps_scale_pts_H
);
123 free(ps_scale_pts_V
);
130 for (uint8_t i_plane
= 0; i_plane
< p_filter
->p_sys
->s_allocated
.i_planes
; i_plane
++) {
131 i_ret
= puzzle_generate_sect_bezier( p_filter
, &p_sys
->ps_pieces_shapes
[i_currect_shape
][i_plane
], 7, ps_scale_pts_V
, i_plane
, puzzle_SHAPE_LEFT
);
132 if (i_ret
!= VLC_SUCCESS
) break;
133 i_ret
= puzzle_generate_sect_bezier( p_filter
, &p_sys
->ps_pieces_shapes
[i_currect_shape
+1][i_plane
], 7, ps_neg_pts_V
, i_plane
, puzzle_SHAPE_LEFT
);
134 if (i_ret
!= VLC_SUCCESS
) break;
135 i_ret
= puzzle_generate_sect_bezier( p_filter
, &p_sys
->ps_pieces_shapes
[i_currect_shape
+2][i_plane
], 7, ps_scale_pts_H
, i_plane
, puzzle_SHAPE_TOP
);
136 if (i_ret
!= VLC_SUCCESS
) break;
137 i_ret
= puzzle_generate_sect_bezier( p_filter
, &p_sys
->ps_pieces_shapes
[i_currect_shape
+3][i_plane
], 7, ps_neg_pts_H
, i_plane
, puzzle_SHAPE_TOP
);
138 if (i_ret
!= VLC_SUCCESS
) break;
140 i_ret
= puzzle_generate_sectTop2Btm( p_filter
, &p_sys
->ps_pieces_shapes
[i_currect_shape
+4][i_plane
], &p_sys
->ps_pieces_shapes
[i_currect_shape
+2][i_plane
], i_plane
);
141 if (i_ret
!= VLC_SUCCESS
) break;
142 i_ret
= puzzle_generate_sectTop2Btm( p_filter
, &p_sys
->ps_pieces_shapes
[i_currect_shape
+5][i_plane
], &p_sys
->ps_pieces_shapes
[i_currect_shape
+3][i_plane
], i_plane
);
143 if (i_ret
!= VLC_SUCCESS
) break;
144 i_ret
= puzzle_generate_sectLeft2Right( p_filter
, &p_sys
->ps_pieces_shapes
[i_currect_shape
+6][i_plane
], &p_sys
->ps_pieces_shapes
[i_currect_shape
][i_plane
], i_plane
);
145 if (i_ret
!= VLC_SUCCESS
) break;
146 i_ret
= puzzle_generate_sectLeft2Right( p_filter
, &p_sys
->ps_pieces_shapes
[i_currect_shape
+7][i_plane
], &p_sys
->ps_pieces_shapes
[i_currect_shape
+1][i_plane
], i_plane
);
147 if (i_ret
!= VLC_SUCCESS
) break;
150 free(ps_scale_pts_H
);
151 free(ps_scale_pts_V
);
155 if (i_ret
!= VLC_SUCCESS
) return i_ret
;
157 i_currect_shape
+= 8;
160 p_sys
->b_shape_init
= true;
165 /* free allocated shapes data */
166 void puzzle_free_ps_pieces_shapes( filter_t
*p_filter
)
168 filter_sys_t
*p_sys
= p_filter
->p_sys
;
170 if (p_sys
->ps_pieces_shapes
== NULL
)
173 for (int32_t p
= 0; p
< p_sys
->s_allocated
.i_piece_types
; p
++) {
174 for (uint8_t i_plane
= 0; i_plane
< p_sys
->s_allocated
.i_planes
; i_plane
++) {
175 for (int32_t r
= 0; r
< p_sys
->ps_pieces_shapes
[p
][i_plane
].i_row_nbr
; r
++)
176 free( p_sys
->ps_pieces_shapes
[p
][i_plane
].ps_piece_shape_row
[r
].ps_row_section
);
177 free( p_sys
->ps_pieces_shapes
[p
][i_plane
].ps_piece_shape_row
);
179 free( p_sys
->ps_pieces_shapes
[p
] );
181 free( p_sys
->ps_pieces_shapes
);
182 p_sys
->ps_pieces_shapes
= NULL
;
185 /*****************************************************************************
186 * puzzle_find_piece: use piece corners to find the piece selected
188 *****************************************************************************/
189 int puzzle_find_piece( filter_t
*p_filter
, int32_t i_x
, int32_t i_y
, int32_t i_except
) {
190 filter_sys_t
*p_sys
= p_filter
->p_sys
;
192 for (uint32_t i
= 0; i
< p_sys
->s_allocated
.i_pieces_nbr
; i
++) {
193 piece_t
*ps_current_piece
= &p_sys
->ps_pieces
[i
];
194 if (( ps_current_piece
->i_min_x
<= i_x
) &&
195 ( ps_current_piece
->i_max_x
>= i_x
) &&
196 ( ps_current_piece
->i_min_y
<= i_y
) &&
197 ( ps_current_piece
->i_max_y
>= i_y
) &&
198 ( (int32_t)i
!= i_except
) )
206 /*****************************************************************************
207 * puzzle_calculate_corners: calculate corners location & regen geometry data
208 *****************************************************************************/
209 void puzzle_calculate_corners( filter_t
*p_filter
, int32_t i_piece
)
211 filter_sys_t
*p_sys
= p_filter
->p_sys
;
212 piece_t
*ps_piece
= &p_sys
->ps_pieces
[i_piece
];
214 switch ( ps_piece
->i_actual_angle
)
217 ps_piece
->i_step_x_x
= ps_piece
->i_actual_mirror
;
218 ps_piece
->i_step_x_y
= 0;
219 ps_piece
->i_step_y_y
= 1;
220 ps_piece
->i_step_y_x
= 0;
223 ps_piece
->i_step_x_x
= 0;
224 ps_piece
->i_step_x_y
= -ps_piece
->i_actual_mirror
; /* x offset on original pict creates negative y offset on desk */
225 ps_piece
->i_step_y_y
= 0;
226 ps_piece
->i_step_y_x
= 1;
229 ps_piece
->i_step_x_x
= -ps_piece
->i_actual_mirror
;
230 ps_piece
->i_step_x_y
= 0;
231 ps_piece
->i_step_y_y
= -1;
232 ps_piece
->i_step_y_x
= 0;
235 ps_piece
->i_step_x_x
= 0;
236 ps_piece
->i_step_x_y
= ps_piece
->i_actual_mirror
;
237 ps_piece
->i_step_y_y
= 0;
238 ps_piece
->i_step_y_x
= -1;
243 for (uint8_t i_plane
= 1; i_plane
< p_sys
->s_allocated
.i_planes
; i_plane
++) {
244 ps_piece
->ps_piece_in_plane
[i_plane
].i_actual_x
=
245 ps_piece
->ps_piece_in_plane
[0].i_actual_x
* p_sys
->ps_desk_planes
[i_plane
].i_width
/ p_sys
->ps_desk_planes
[0].i_width
;
246 ps_piece
->ps_piece_in_plane
[i_plane
].i_actual_y
=
247 ps_piece
->ps_piece_in_plane
[0].i_actual_y
* p_sys
->ps_desk_planes
[i_plane
].i_lines
/ p_sys
->ps_desk_planes
[0].i_lines
;
250 /* regen location of grabed piece's corners */
251 int32_t i_width
= ps_piece
->ps_piece_in_plane
[0].i_width
;
252 int32_t i_lines
= ps_piece
->ps_piece_in_plane
[0].i_lines
;
254 ps_piece
->i_TLx
= ps_piece
->ps_piece_in_plane
[0].i_actual_x
;
255 ps_piece
->i_TLy
= ps_piece
->ps_piece_in_plane
[0].i_actual_y
;
256 ps_piece
->i_TRx
= ps_piece
->i_TLx
+ ( i_width
- 1 ) * ps_piece
->i_step_x_x
;
257 ps_piece
->i_TRy
= ps_piece
->i_TLy
+ ( i_width
- 1 ) * ps_piece
->i_step_x_y
;
258 ps_piece
->i_BRx
= ps_piece
->i_TLx
+ ( i_width
- 1 ) * ps_piece
->i_step_x_x
+ ( i_lines
- 1 ) * ps_piece
->i_step_y_x
;
259 ps_piece
->i_BRy
= ps_piece
->i_TLy
+ ( i_width
- 1 ) * ps_piece
->i_step_x_y
+ ( i_lines
- 1 ) * ps_piece
->i_step_y_y
;
260 ps_piece
->i_BLx
= ps_piece
->i_TLx
+ ( i_lines
- 1 ) * ps_piece
->i_step_y_x
;
261 ps_piece
->i_BLy
= ps_piece
->i_TLy
+ ( i_lines
- 1 ) * ps_piece
->i_step_y_y
;
263 ps_piece
->i_max_x
= __MAX( __MAX( ps_piece
->i_TLx
, ps_piece
->i_TRx
), __MAX( ps_piece
->i_BLx
, ps_piece
->i_BRx
) );
264 ps_piece
->i_min_x
= __MIN( __MIN( ps_piece
->i_TLx
, ps_piece
->i_TRx
), __MIN( ps_piece
->i_BLx
, ps_piece
->i_BRx
) );
265 ps_piece
->i_max_y
= __MAX( __MAX( ps_piece
->i_TLy
, ps_piece
->i_TRy
), __MAX( ps_piece
->i_BLy
, ps_piece
->i_BRy
) );
266 ps_piece
->i_min_y
= __MIN( __MIN( ps_piece
->i_TLy
, ps_piece
->i_TRy
), __MIN( ps_piece
->i_BLy
, ps_piece
->i_BRy
) );
268 ps_piece
->i_center_x
= ( ps_piece
->i_max_x
+ ps_piece
->i_min_x
) / 2;
269 ps_piece
->i_center_y
= ( ps_piece
->i_max_y
+ ps_piece
->i_min_y
) / 2;
271 int32_t pce_overlap
= puzzle_find_piece( p_filter
, ps_piece
->i_center_x
, ps_piece
->i_center_y
, i_piece
);
273 if ( ( pce_overlap
!= NO_PCE
) && ( p_sys
->pi_group_qty
[ps_piece
->i_group_ID
] == 1 ) )
274 ps_piece
->b_overlap
= true;
277 /*****************************************************************************
278 * rotate piece when user click on mouse
279 *****************************************************************************/
280 void puzzle_rotate_pce( filter_t
*p_filter
, int32_t i_piece
, int8_t i_rotate_mirror
, int32_t i_center_x
, int32_t i_center_y
, bool b_avoid_mirror
)
282 filter_sys_t
*p_sys
= p_filter
->p_sys
;
283 piece_t
*ps_piece
= &p_sys
->ps_pieces
[i_piece
];
285 if ( p_sys
->s_current_param
.i_rotate
== 0 )
288 if ( p_sys
->s_current_param
.i_rotate
== 1 && (i_rotate_mirror
!= 2) )
291 for ( uint8_t i
=0; i
< abs( i_rotate_mirror
); i
++) {
292 int32_t i_tempx
, i_tempy
;
294 /* piece has to be rotated by 90° */
295 if ( i_rotate_mirror
> 0 ) {
296 ps_piece
->i_actual_angle
++;
297 ps_piece
->i_actual_angle
&= 0x03;
299 i_tempx
= -( i_center_y
- ps_piece
->ps_piece_in_plane
[0].i_actual_y
) + i_center_x
;
300 i_tempy
= +( i_center_x
- ps_piece
->ps_piece_in_plane
[0].i_actual_x
) + i_center_y
;
303 ps_piece
->i_actual_angle
--;
304 ps_piece
->i_actual_angle
&= 0x03;
306 i_tempx
= +( i_center_y
- ps_piece
->ps_piece_in_plane
[0].i_actual_y
) + i_center_x
;
307 i_tempy
= -( i_center_x
- ps_piece
->ps_piece_in_plane
[0].i_actual_x
) + i_center_y
;
310 ps_piece
->ps_piece_in_plane
[0].i_actual_x
= i_tempx
;
311 ps_piece
->ps_piece_in_plane
[0].i_actual_y
= i_tempy
;
313 if ( ps_piece
->i_actual_angle
== 0 && p_sys
->s_current_param
.i_rotate
== 3 && !b_avoid_mirror
) {
314 ps_piece
->ps_piece_in_plane
[0].i_actual_x
= 2 * i_center_x
- ps_piece
->ps_piece_in_plane
[0].i_actual_x
;
315 ps_piece
->i_actual_mirror
*= -1;
317 puzzle_calculate_corners( p_filter
, i_piece
);
321 /*****************************************************************************
322 * move group of joined pieces when user drag'n drop it with mouse
323 *****************************************************************************/
324 void puzzle_move_group( filter_t
*p_filter
, int32_t i_piece
, int32_t i_dx
, int32_t i_dy
)
326 filter_sys_t
*p_sys
= p_filter
->p_sys
;
327 uint32_t i_group_ID
= p_sys
->ps_pieces
[i_piece
].i_group_ID
;
328 for (uint32_t i
= 0; i
< p_sys
->s_allocated
.i_pieces_nbr
; i
++) {
329 piece_t
*ps_piece
= &p_sys
->ps_pieces
[i
];
330 if (ps_piece
->i_group_ID
== i_group_ID
) {
331 ps_piece
->b_finished
= false;
332 ps_piece
->ps_piece_in_plane
[0].i_actual_x
+= i_dx
;
333 ps_piece
->ps_piece_in_plane
[0].i_actual_y
+= i_dy
;
335 puzzle_calculate_corners( p_filter
, i
);
340 /*****************************************************************************
341 * draw straight rectangular piece in the specified plane
342 *****************************************************************************/
343 void puzzle_drw_basic_pce_in_plane( filter_t
*p_filter
, picture_t
*p_pic_in
, picture_t
*p_pic_out
, uint8_t i_plane
, piece_t
*ps_piece
)
345 /* basic version rectangular & angle = 0 */
346 filter_sys_t
*p_sys
= p_filter
->p_sys
;
348 if ((p_sys
->ps_puzzle_array
== NULL
) || (p_sys
->ps_pieces
== NULL
) || (ps_piece
== NULL
))
351 const int32_t i_src_pitch
= p_pic_in
->p
[i_plane
].i_pitch
;
352 const int32_t i_dst_pitch
= p_pic_out
->p
[i_plane
].i_pitch
;
353 const int32_t i_src_width
= p_pic_in
->p
[i_plane
].i_pitch
/ p_pic_in
->p
[i_plane
].i_pixel_pitch
;
354 const int32_t i_dst_width
= p_pic_out
->p
[i_plane
].i_pitch
/ p_pic_out
->p
[i_plane
].i_pixel_pitch
;
355 const int32_t i_pixel_pitch
= p_pic_out
->p
[i_plane
].i_pixel_pitch
;
356 const int32_t i_src_visible_lines
= p_pic_in
->p
[i_plane
].i_visible_lines
;
357 const int32_t i_dst_visible_lines
= p_pic_out
->p
[i_plane
].i_visible_lines
;
358 uint8_t *p_src
= p_pic_in
->p
[i_plane
].p_pixels
;
359 uint8_t *p_dst
= p_pic_out
->p
[i_plane
].p_pixels
;
361 const int32_t i_desk_start_x
= ps_piece
->ps_piece_in_plane
[i_plane
].i_actual_x
;
362 const int32_t i_desk_start_y
= ps_piece
->ps_piece_in_plane
[i_plane
].i_actual_y
;
363 const int32_t i_pic_start_x
= ps_piece
->ps_piece_in_plane
[i_plane
].i_original_x
;
364 const int32_t i_pic_start_y
= ps_piece
->ps_piece_in_plane
[i_plane
].i_original_y
;
365 const int32_t i_width
= ps_piece
->ps_piece_in_plane
[i_plane
].i_width
;
366 const int32_t i_lines
= ps_piece
->ps_piece_in_plane
[i_plane
].i_lines
;
368 const int32_t i_ofs_x
= __MAX(0, __MAX(-i_desk_start_x
,-i_pic_start_x
));
369 const int32_t i_count_x
= i_width
- __MAX(0, __MAX(i_desk_start_x
+ i_width
- i_dst_width
, i_pic_start_x
+ i_width
- i_src_width
));
370 const int32_t i_ofs_y
= __MAX(0, __MAX(-i_desk_start_y
,-i_pic_start_y
));
371 const int32_t i_count_y
= i_lines
- __MAX(0, __MAX(i_desk_start_y
+ i_lines
- i_dst_visible_lines
, i_pic_start_y
+ i_lines
- i_src_visible_lines
));
373 for (int32_t i_y
= i_ofs_y
; i_y
< i_count_y
; i_y
++) {
374 memcpy( p_dst
+ (i_desk_start_y
+ i_y
) * i_dst_pitch
+ ( i_desk_start_x
+ i_ofs_x
) * i_pixel_pitch
,
375 p_src
+ (i_pic_start_y
+ i_y
) * i_src_pitch
+ ( i_pic_start_x
+ i_ofs_x
) * i_pixel_pitch
,
376 ( i_count_x
- i_ofs_x
) * i_pixel_pitch
);
382 /*****************************************************************************
383 * draw oriented rectangular piece in the specified plane
384 *****************************************************************************/
385 void puzzle_drw_adv_pce_in_plane( filter_t
*p_filter
, picture_t
*p_pic_in
, picture_t
*p_pic_out
, uint8_t i_plane
, piece_t
*ps_piece
)
387 /* here we still have rectangular shape but angle is not 0 */
388 filter_sys_t
*p_sys
= p_filter
->p_sys
;
390 if ((p_sys
->ps_puzzle_array
== NULL
) || (p_sys
->ps_pieces
== NULL
) || (ps_piece
== NULL
))
393 const int32_t i_src_pitch
= p_pic_in
->p
[i_plane
].i_pitch
;
394 const int32_t i_dst_pitch
= p_pic_out
->p
[i_plane
].i_pitch
;
395 const int32_t i_src_width
= p_pic_in
->p
[i_plane
].i_pitch
/ p_pic_in
->p
[i_plane
].i_pixel_pitch
;
396 const int32_t i_dst_width
= p_pic_out
->p
[i_plane
].i_pitch
/ p_pic_out
->p
[i_plane
].i_pixel_pitch
;
397 const int32_t i_pixel_pitch
= p_pic_out
->p
[i_plane
].i_pixel_pitch
;
398 const int32_t i_src_visible_lines
= p_pic_in
->p
[i_plane
].i_visible_lines
;
399 const int32_t i_dst_visible_lines
= p_pic_out
->p
[i_plane
].i_visible_lines
;
400 uint8_t *p_src
= p_pic_in
->p
[i_plane
].p_pixels
;
401 uint8_t *p_dst
= p_pic_out
->p
[i_plane
].p_pixels
;
403 const int32_t i_desk_start_x
= ps_piece
->ps_piece_in_plane
[i_plane
].i_actual_x
;
404 const int32_t i_desk_start_y
= ps_piece
->ps_piece_in_plane
[i_plane
].i_actual_y
;
405 const int32_t i_pic_start_x
= ps_piece
->ps_piece_in_plane
[i_plane
].i_original_x
;
406 const int32_t i_pic_start_y
= ps_piece
->ps_piece_in_plane
[i_plane
].i_original_y
;
407 const int32_t i_width
= ps_piece
->ps_piece_in_plane
[i_plane
].i_width
;
408 const int32_t i_lines
= ps_piece
->ps_piece_in_plane
[i_plane
].i_lines
;
410 for (int32_t i_y
= 0; i_y
< i_lines
; i_y
++) {
411 int32_t i_current_src_y
= i_pic_start_y
+ i_y
;
413 if ( ( i_current_src_y
>= 0 ) && ( i_current_src_y
< i_src_visible_lines
) ) {
414 for (int32_t i_x
= 0; i_x
< i_width
; i_x
++) {
415 int32_t i_current_dst_x
= i_desk_start_x
+ i_x
* ps_piece
->i_step_x_x
+ i_y
* ps_piece
->i_step_y_x
;
416 int32_t i_current_dst_y
= i_desk_start_y
+ i_x
* ps_piece
->i_step_x_y
+ i_y
* ps_piece
->i_step_y_y
;
417 int32_t i_current_src_x
= i_pic_start_x
+ i_x
;
419 if ( ( i_current_dst_x
>= 0 ) && ( i_current_src_x
>= 0 )
420 && ( i_current_dst_x
< i_dst_width
) && ( i_current_src_x
< i_src_width
)
421 && ( i_current_dst_y
>= 0 ) && ( i_current_dst_y
< i_dst_visible_lines
) )
423 memcpy( p_dst
+ i_current_dst_y
* i_dst_pitch
+ i_current_dst_x
* i_pixel_pitch
,
424 p_src
+ i_current_src_y
* i_src_pitch
+ i_current_src_x
* i_pixel_pitch
,
434 /*****************************************************************************
435 * draw complex shape in the specified plane
436 *****************************************************************************/
437 void puzzle_drw_complex_pce_in_plane( filter_t
*p_filter
, picture_t
*p_pic_in
, picture_t
*p_pic_out
, uint8_t i_plane
, piece_t
*ps_piece
, uint32_t i_pce
)
439 /* "puzzle" shape and maybe angle != 0 */
440 filter_sys_t
*p_sys
= p_filter
->p_sys
;
442 if ((p_sys
->ps_puzzle_array
== NULL
) || (p_sys
->ps_pieces
== NULL
) || (ps_piece
== NULL
))
445 const int32_t i_src_pitch
= p_pic_in
->p
[i_plane
].i_pitch
;
446 const int32_t i_dst_pitch
= p_pic_out
->p
[i_plane
].i_pitch
;
447 const int32_t i_src_width
= p_pic_in
->p
[i_plane
].i_pitch
/ p_pic_in
->p
[i_plane
].i_pixel_pitch
;
448 const int32_t i_dst_width
= p_pic_out
->p
[i_plane
].i_pitch
/ p_pic_out
->p
[i_plane
].i_pixel_pitch
;
449 const int32_t i_pixel_pitch
= p_pic_out
->p
[i_plane
].i_pixel_pitch
;
450 const int32_t i_src_visible_lines
= p_pic_in
->p
[i_plane
].i_visible_lines
;
451 const int32_t i_dst_visible_lines
= p_pic_out
->p
[i_plane
].i_visible_lines
;
452 uint8_t *p_src
= p_pic_in
->p
[i_plane
].p_pixels
;
453 uint8_t *p_dst
= p_pic_out
->p
[i_plane
].p_pixels
;
455 const int32_t i_desk_start_x
= ps_piece
->ps_piece_in_plane
[i_plane
].i_actual_x
;
456 const int32_t i_desk_start_y
= ps_piece
->ps_piece_in_plane
[i_plane
].i_actual_y
;
457 const int32_t i_pic_start_x
= ps_piece
->ps_piece_in_plane
[i_plane
].i_original_x
;
458 const int32_t i_pic_start_y
= ps_piece
->ps_piece_in_plane
[i_plane
].i_original_y
;
460 piece_shape_t
*ps_top_shape
= &p_sys
->ps_pieces_shapes
[ps_piece
->i_top_shape
][i_plane
];
461 piece_shape_t
*ps_btm_shape
= &p_sys
->ps_pieces_shapes
[ps_piece
->i_btm_shape
][i_plane
];
462 piece_shape_t
*ps_right_shape
= &p_sys
->ps_pieces_shapes
[ps_piece
->i_right_shape
][i_plane
];
463 piece_shape_t
*ps_left_shape
= &p_sys
->ps_pieces_shapes
[ps_piece
->i_left_shape
][i_plane
];
464 piece_shape_t
*ps_shape
;
466 int32_t i_min_y
= ps_top_shape
->i_first_row_offset
;
467 int32_t i_max_y
= ps_btm_shape
->i_first_row_offset
+ ps_btm_shape
->i_row_nbr
- 1;
469 for (int32_t i_y
= i_min_y
; i_y
<= i_max_y
; i_y
++) {
470 int32_t i_current_src_y
= i_pic_start_y
+ i_y
;
472 if ( ( i_current_src_y
>= 0 ) && ( i_current_src_y
< i_src_visible_lines
) ) {
473 int32_t i_sect_start_x
= 0;
475 /* process each sub shape (each quarter) */
476 for (int8_t i_shape
=0; i_shape
< 4; i_shape
++) {
480 ps_shape
= ps_left_shape
;
483 ps_shape
= ps_top_shape
;
486 ps_shape
= ps_btm_shape
;
489 ps_shape
= ps_right_shape
;
493 int32_t i_r
= i_y
- ps_shape
->i_first_row_offset
;
495 if (i_r
<0 || i_r
>= ps_shape
->i_row_nbr
)
498 piece_shape_row_t
*ps_piece_shape_row
= &ps_shape
->ps_piece_shape_row
[i_r
];
500 for (int32_t i_s
= 0; i_s
< ps_piece_shape_row
->i_section_nbr
; i_s
++) {
501 uint8_t i_type
= ps_piece_shape_row
->ps_row_section
[i_s
].i_type
;
502 int32_t i_width
= ps_piece_shape_row
->ps_row_section
[i_s
].i_width
;
504 /* copy pixel line from input image to puzzle desk */
505 for (int32_t i_x
= 0; i_x
< i_width
; i_x
++) {
506 int32_t i_current_dst_x
= i_desk_start_x
+ (i_sect_start_x
+ i_x
) * ps_piece
->i_step_x_x
+ i_y
* ps_piece
->i_step_y_x
;
507 int32_t i_current_dst_y
= i_desk_start_y
+ (i_sect_start_x
+ i_x
) * ps_piece
->i_step_x_y
+ i_y
* ps_piece
->i_step_y_y
;
508 int32_t i_current_src_x
= i_pic_start_x
+ (i_sect_start_x
+ i_x
);
510 if ( i_current_dst_x
< 0 || i_current_dst_x
>= i_dst_width
511 || i_current_src_x
< 0 || i_current_src_x
>= i_src_width
512 || i_current_dst_y
< 0 || i_current_dst_y
>= i_dst_visible_lines
)
515 memcpy( p_dst
+ i_current_dst_y
* i_dst_pitch
+ i_current_dst_x
* i_pixel_pitch
,
516 p_src
+ i_current_src_y
* i_src_pitch
+ i_current_src_x
* i_pixel_pitch
,
519 /* Check if mouse pointer is over this pixel
520 * Yes: set i_pointed_pce = current drawn piece
522 if ((i_plane
== 0) && (p_sys
->i_mouse_x
== i_current_dst_x
)
523 && (p_sys
->i_mouse_y
== i_current_dst_y
))
524 p_sys
->i_pointed_pce
= i_pce
;
527 i_sect_start_x
+= i_width
;
536 /*****************************************************************************
537 * draw all puzzle pieces on the desk
538 *****************************************************************************/
539 void puzzle_draw_pieces( filter_t
*p_filter
, picture_t
*p_pic_in
, picture_t
*p_pic_out
)
541 filter_sys_t
*p_sys
= p_filter
->p_sys
;
543 if ((p_sys
->ps_puzzle_array
== NULL
) || (p_sys
->ps_pieces
== NULL
))
546 for( uint8_t i_plane
= 0; i_plane
< p_pic_out
->i_planes
; i_plane
++ ) {
547 for ( int32_t i
= p_sys
->s_allocated
.i_pieces_nbr
-1; i
>= 0 ; i
-- ) {
548 piece_t
*ps_piece
= &p_sys
->ps_pieces
[i
];
550 if (!p_sys
->s_current_param
.b_advanced
551 || (ps_piece
->i_actual_mirror
== 1 && ps_piece
->i_actual_angle
== 0
552 && p_sys
->s_current_param
.i_shape_size
== 0))
554 puzzle_drw_basic_pce_in_plane(p_filter
, p_pic_in
, p_pic_out
, i_plane
, ps_piece
);
556 else if ( ( p_sys
->s_current_param
.i_shape_size
== 0) ||
557 (p_sys
->ps_pieces_shapes
== NULL
) || (!p_sys
->b_shape_init
) )
559 puzzle_drw_adv_pce_in_plane(p_filter
, p_pic_in
, p_pic_out
, i_plane
, ps_piece
);
562 puzzle_drw_complex_pce_in_plane(p_filter
, p_pic_in
, p_pic_out
, i_plane
, ps_piece
, i
);
570 /*****************************************************************************
571 * when generating shape data: determine limit between sectors to be drawn
572 *****************************************************************************/
573 int32_t puzzle_diagonal_limit( filter_t
*p_filter
, int32_t i_y
, bool b_left
, uint8_t i_plane
)
575 filter_sys_t
*p_sys
= p_filter
->p_sys
;
577 if (b_left
^ (i_y
>= p_sys
->ps_desk_planes
[i_plane
].i_pce_max_lines
/ 2))
578 return ( i_y
* p_sys
->ps_desk_planes
[i_plane
].i_pce_max_width
) / p_sys
->ps_desk_planes
[i_plane
].i_pce_max_lines
;
580 return p_sys
->ps_desk_planes
[i_plane
].i_pce_max_width
- ( ( i_y
* p_sys
->ps_desk_planes
[i_plane
].i_pce_max_width
) / p_sys
->ps_desk_planes
[i_plane
].i_pce_max_lines
);
585 /*****************************************************************************
586 * generate data which will be used to draw each line of a piece sector with
588 *****************************************************************************/
589 int puzzle_generate_sect_border( filter_t
*p_filter
, piece_shape_t
*ps_piece_shape
, uint8_t i_plane
, uint8_t i_border
)
591 /* generate data required to draw a sector of border puzzle piece */
595 filter_sys_t
*p_sys
= p_filter
->p_sys
;
597 int32_t i_width
= p_sys
->ps_desk_planes
[i_plane
].i_pce_max_width
;
598 int32_t i_lines
= p_sys
->ps_desk_planes
[i_plane
].i_pce_max_lines
;
600 /* process each horizontal pixel lines */
601 int32_t i_min_y
= (i_border
!= puzzle_SHAPE_BTM
) ? 0 : floor( i_lines
/ 2 );
603 int32_t i_nb_y
= (i_border
!= puzzle_SHAPE_TOP
)?
604 (i_lines
- i_min_y
) : (i_lines
/2 - i_min_y
);
606 /* allocate memory */
607 ps_piece_shape
->i_row_nbr
= i_nb_y
;
608 ps_piece_shape
->i_first_row_offset
= i_min_y
;
609 ps_piece_shape
->ps_piece_shape_row
= malloc( sizeof( piece_shape_row_t
) * i_nb_y
);
610 if (!ps_piece_shape
->ps_piece_shape_row
)
613 for (int32_t i_y
= i_min_y
; i_y
< i_nb_y
+ i_min_y
; i_y
++) {
615 int32_t pi_sects
[MAX_SECT
];
616 int32_t i_row
= i_y
- i_min_y
;
618 /* ...fill from border to next junction */
621 case puzzle_SHAPE_TOP
:
622 case puzzle_SHAPE_BTM
:
623 pi_sects
[i_sect
] = puzzle_diagonal_limit( p_filter
, i_y
, false, i_plane
) - 1
624 - (puzzle_diagonal_limit( p_filter
, i_y
, true, i_plane
) - 1);
626 case puzzle_SHAPE_RIGHT
:
627 pi_sects
[i_sect
] = i_width
- puzzle_diagonal_limit( p_filter
, i_y
, false, i_plane
);
629 case puzzle_SHAPE_LEFT
:
631 pi_sects
[i_sect
] = puzzle_diagonal_limit( p_filter
, i_y
, true, i_plane
);
635 /* ...allocate memory and copy final values */
636 ps_piece_shape
->ps_piece_shape_row
[i_row
].i_section_nbr
= i_sect
;
637 ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
= malloc ( sizeof(row_section_t
) * i_sect
);
638 if (!ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
) {
639 for (uint8_t i
=0; i
<i_row
;i
++)
640 free(ps_piece_shape
->ps_piece_shape_row
[i
].ps_row_section
);
641 free(ps_piece_shape
->ps_piece_shape_row
);
642 ps_piece_shape
->ps_piece_shape_row
= NULL
;
646 for (uint8_t i
=0; i
< i_sect
; i
++) {
647 ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
[i
].i_type
= i
% 2; /* 0 = fill ; 1 = offset */
648 ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
[i
].i_width
= pi_sects
[i
];
654 /*****************************************************************************
655 * generate data which will be used to draw each line of a piece sector based
657 *****************************************************************************/
658 int puzzle_generate_sect_bezier( filter_t
*p_filter
, piece_shape_t
*ps_piece_shape
, uint8_t i_pts_nbr
, point_t
*ps_pt
, uint8_t i_plane
, uint8_t i_border
)
660 /* generate data required to draw a sector of puzzle piece using bezier shape */
661 if ((!ps_pt
) || (!ps_piece_shape
))
664 filter_sys_t
*p_sys
= p_filter
->p_sys
;
666 int32_t i_width
= p_sys
->ps_desk_planes
[i_plane
].i_pce_max_width
;
667 int32_t i_lines
= p_sys
->ps_desk_planes
[i_plane
].i_pce_max_lines
;
668 int32_t i_size_x_0
= p_sys
->ps_desk_planes
[0].i_pce_max_width
;
669 int32_t i_size_y_0
= p_sys
->ps_desk_planes
[0].i_pce_max_lines
;
671 float f_x_ratio
= ((float) i_width
) / ((float) i_size_x_0
);
672 float f_y_ratio
= ((float) i_lines
) / ((float) i_size_y_0
);
674 /* first: get min x and min y */
675 float f_min_curve_x
, f_min_curve_y
;
676 puzzle_get_min_bezier(&f_min_curve_x
, &f_min_curve_y
, f_x_ratio
, f_y_ratio
, ps_pt
, i_pts_nbr
);
678 f_min_curve_y
= __MIN(0,floor(f_min_curve_y
));
679 f_min_curve_x
= __MIN(0,floor(f_min_curve_x
));
681 /* next: process each horizontal pixel lines */
682 int32_t i_min_y
= (i_border
==puzzle_SHAPE_TOP
)?floor(f_min_curve_y
):0;
683 int32_t i_nb_y
= (i_border
==puzzle_SHAPE_TOP
)?(i_lines
/ 2 - i_min_y
):i_lines
;
685 /* allocate memory */
686 ps_piece_shape
->i_row_nbr
= i_nb_y
;
687 ps_piece_shape
->i_first_row_offset
= i_min_y
;
688 ps_piece_shape
->ps_piece_shape_row
= malloc( sizeof( piece_shape_row_t
) * ps_piece_shape
->i_row_nbr
);
689 if (!ps_piece_shape
->ps_piece_shape_row
)
692 return puzzle_generate_shape_lines(p_filter
, ps_piece_shape
, i_min_y
, i_nb_y
, f_x_ratio
, f_y_ratio
, ps_pt
, i_pts_nbr
, i_border
, i_plane
);
695 /*****************************************************************************
696 * when generating shape data: determine minimum bezier value
697 *****************************************************************************/
698 void puzzle_get_min_bezier(float *f_min_curve_x
, float *f_min_curve_y
, float f_x_ratio
, float f_y_ratio
, point_t
*ps_pt
, uint8_t i_pts_nbr
)
700 *f_min_curve_y
= ps_pt
[0].f_y
* f_y_ratio
;
701 *f_min_curve_x
= ps_pt
[0].f_x
* f_x_ratio
;
703 for (float f_t
= 0; f_t
<= i_pts_nbr
- 1; f_t
+= 0.1 ) {
704 int8_t i_main_t
= floor(f_t
);
705 if ( i_main_t
== i_pts_nbr
- 1 )
706 i_main_t
= i_pts_nbr
- 2;
707 float f_sub_t
= f_t
- i_main_t
;
709 *f_min_curve_x
= __MIN(*f_min_curve_x
,bezier_val(ps_pt
,f_sub_t
,i_main_t
,x
) * f_x_ratio
);
710 *f_min_curve_y
= __MIN(*f_min_curve_y
,bezier_val(ps_pt
,f_sub_t
,i_main_t
,y
) * f_y_ratio
);
714 /*****************************************************************************
715 * proceed with each line in order to generate data which will be used
716 * to draw each line of a piece sector
717 *****************************************************************************/
718 int puzzle_generate_shape_lines( filter_t
*p_filter
, piece_shape_t
*ps_piece_shape
, int32_t i_min_y
, int32_t i_nb_y
, float f_x_ratio
, float f_y_ratio
, point_t
*ps_pt
, uint8_t i_pts_nbr
, uint8_t i_border
, uint8_t i_plane
)
720 /* generate data required to draw a line of a piece sector */
721 for (int32_t i_y
= i_min_y
; i_y
< i_nb_y
+ i_min_y
; i_y
++) {
722 int32_t i_row
= i_y
- i_min_y
;
724 int32_t pi_sects
[MAX_SECT
];
726 uint8_t i_sect
= puzzle_detect_curve( p_filter
, i_y
, f_x_ratio
, f_y_ratio
, ps_pt
, i_pts_nbr
, i_border
, i_plane
, pi_sects
);
728 /* ...we have to convert absolute values to offsets and take into account min_curve_x */
730 int32_t i_last_x
= (i_border
==puzzle_SHAPE_TOP
&& (i_y
>=0))?puzzle_diagonal_limit( p_filter
, i_y
, true, i_plane
):0;
732 for (i_s
= 0; i_s
<i_sect
; i_s
++) {
733 int32_t i_current_x
= pi_sects
[i_s
];
734 int32_t i_delta
= i_current_x
- i_last_x
;
735 pi_sects
[i_s
] = i_delta
;
737 i_last_x
= i_current_x
;
742 case puzzle_SHAPE_TOP
:
743 /* ...allocate memory and copy final values */
744 /* note for y > 0 we have to ignore the first offset as it is included in "Left" piece shape */
746 ps_piece_shape
->ps_piece_shape_row
[i_row
].i_section_nbr
= i_sect
;
747 ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
= malloc ( sizeof(row_section_t
) * i_sect
);
748 if (!ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
) {
749 for (uint8_t i
=0; i
<i_row
;i
++)
750 free(ps_piece_shape
->ps_piece_shape_row
[i
].ps_row_section
);
751 free(ps_piece_shape
->ps_piece_shape_row
);
752 ps_piece_shape
->ps_piece_shape_row
= NULL
;
755 for (uint8_t i
=0; i
< i_sect
; i
++) {
756 ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
[i
].i_type
= i
% 2; /* 0 = fill ; 1 = offset */
757 ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
[i
].i_width
= pi_sects
[i
];
761 ps_piece_shape
->ps_piece_shape_row
[i_row
].i_section_nbr
= i_sect
;
762 ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
= malloc ( sizeof(row_section_t
) * i_sect
);
763 if (!ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
) {
764 for (uint8_t i
=0; i
<i_row
;i
++)
765 free(ps_piece_shape
->ps_piece_shape_row
[i
].ps_row_section
);
766 free(ps_piece_shape
->ps_piece_shape_row
);
767 ps_piece_shape
->ps_piece_shape_row
= NULL
;
770 for (uint8_t i
=0; i
< i_sect
; i
++) {
771 ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
[i
].i_type
= (i
+ 1) % 2; /* 0 = fill ; 1 = offset */
772 ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
[i
].i_width
= pi_sects
[i
];
776 case puzzle_SHAPE_LEFT
:
777 /* ...allocate memory and copy final values */
778 /* note for y > 0 we have to ignore the first offset as it is included in "Left" piece shape */
779 ps_piece_shape
->ps_piece_shape_row
[i_row
].i_section_nbr
= i_sect
;
780 ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
= malloc ( sizeof(row_section_t
) * i_sect
);
781 if (!ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
) {
782 for (uint8_t i
=0; i
<i_row
;i
++)
783 free(ps_piece_shape
->ps_piece_shape_row
[i
].ps_row_section
);
784 free(ps_piece_shape
->ps_piece_shape_row
);
785 ps_piece_shape
->ps_piece_shape_row
= NULL
;
788 for (uint8_t i
=0; i
< i_sect
; i
++) {
789 ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
[i
].i_type
= (i
+1) % 2; /* 0 = fill ; 1 = offset */
790 ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
[i
].i_width
= pi_sects
[i
];
797 /*****************************************************************************
798 * when generating shape data: detect all bezier curve intersections with
800 *****************************************************************************/
801 int puzzle_detect_curve( filter_t
*p_filter
, int32_t i_y
, float f_x_ratio
, float f_y_ratio
, point_t
*ps_pt
, uint8_t i_pts_nbr
, uint8_t i_border
, uint8_t i_plane
, int32_t *pi_sects
)
805 float f_xo
= ps_pt
[0].f_x
* f_x_ratio
;
806 float f_yo
= ps_pt
[0].f_y
* f_y_ratio
;
809 for (float f_t
= 0; f_t
<= i_pts_nbr
- 1; f_t
+= 0.1 ) {
810 i_main_t
= floor(f_t
);
811 if ( i_main_t
== i_pts_nbr
- 1 )
812 i_main_t
= i_pts_nbr
- 2;
813 float f_sub_t
= f_t
- i_main_t
;
815 f_xd
= bezier_val(ps_pt
,f_sub_t
,i_main_t
,x
) * f_x_ratio
;
816 f_yd
= bezier_val(ps_pt
,f_sub_t
,i_main_t
,y
) * f_y_ratio
;
818 if ((f_yo
< (float)i_y
+0.5 && f_yd
>= (float)i_y
+0.5) || (f_yo
> (float)i_y
+0.5 && f_yd
<= (float)i_y
+0.5)) {
819 pi_sects
[i_sect
] = floor(((float)i_y
+0.5 - f_yo
) * (f_xd
- f_xo
) / (f_yd
- f_yo
) + f_xo
);
820 if (i_sect
< MAX_SECT
- 1)
827 f_xd
= ps_pt
[i_pts_nbr
- 1].f_x
* f_x_ratio
;
828 f_yd
= ps_pt
[i_pts_nbr
- 1].f_y
* f_y_ratio
;
830 /* ...fill from this junction to next junction */
832 /* last diagonal intersection */
833 pi_sects
[i_sect
] = (i_border
==puzzle_SHAPE_TOP
)?puzzle_diagonal_limit( p_filter
, i_y
, false, i_plane
)
834 :puzzle_diagonal_limit( p_filter
, i_y
, true, i_plane
);
835 if (i_sect
< MAX_SECT
- 1)
839 /* ...reorder the list of intersection */
842 while (i_s
< (i_sect
- 1)) {
843 if (pi_sects
[i_s
] > pi_sects
[i_s
+1]) {
844 uint32_t i_temp
= pi_sects
[i_s
];
845 pi_sects
[i_s
] = pi_sects
[i_s
+1];
846 pi_sects
[i_s
+1] = i_temp
;
857 /*****************************************************************************
858 * generate Right shape data from Left shape data
859 *****************************************************************************/
860 int puzzle_generate_sectLeft2Right( filter_t
*p_filter
, piece_shape_t
*ps_piece_shape
, piece_shape_t
*ps_left_piece_shape
, uint8_t i_plane
)
862 if ((!ps_piece_shape
) || (!ps_left_piece_shape
))
865 filter_sys_t
*p_sys
= p_filter
->p_sys
;
867 int32_t i_min_y
= ps_left_piece_shape
->i_first_row_offset
;
868 int32_t i_nb_y
= ps_left_piece_shape
->i_row_nbr
;
870 /* allocate memory */
871 ps_piece_shape
->i_row_nbr
= i_nb_y
;
872 ps_piece_shape
->i_first_row_offset
= i_min_y
;
873 ps_piece_shape
->ps_piece_shape_row
= malloc( sizeof( piece_shape_row_t
) * i_nb_y
);
874 if (!ps_piece_shape
->ps_piece_shape_row
)
877 for (int32_t i_y
= i_min_y
; i_y
< i_nb_y
+ i_min_y
; i_y
++) {
878 int32_t i_row
= i_y
- i_min_y
;
880 int32_t i_width
= p_sys
->ps_desk_planes
[i_plane
].i_pce_max_width
;
881 int32_t i_left_width
= puzzle_diagonal_limit( p_filter
, i_y
, true, i_plane
);
882 int32_t i_right_width
= i_width
- puzzle_diagonal_limit( p_filter
, i_y
, false, i_plane
);
883 int16_t i_section_nbr
= ps_left_piece_shape
->ps_piece_shape_row
[i_row
].i_section_nbr
;
885 ps_piece_shape
->ps_piece_shape_row
[i_row
].i_section_nbr
= i_section_nbr
;
886 ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
= malloc ( sizeof(row_section_t
) * i_section_nbr
);
887 if (!ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
) {
888 for (uint8_t i
=0; i
<i_row
;i
++)
889 free(ps_piece_shape
->ps_piece_shape_row
[i
].ps_row_section
);
890 free(ps_piece_shape
->ps_piece_shape_row
);
891 ps_piece_shape
->ps_piece_shape_row
= NULL
;
895 ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
[0].i_type
=
896 ps_left_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
[0].i_type
;
897 ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
[0].i_width
=
898 ps_left_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
[0].i_width
+ i_right_width
- i_left_width
;
900 for (int8_t i_s
=0; i_s
<i_section_nbr
;i_s
++) {
901 ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
[i_s
].i_type
=
902 ps_left_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
[i_section_nbr
- 1 - i_s
].i_type
;
903 ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
[i_s
].i_width
=
904 ps_left_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
[i_section_nbr
- 1 - i_s
].i_width
905 + (i_s
== 0 ? i_right_width
- i_left_width
: 0);
911 /*****************************************************************************
912 * generates Bottom shape data from Top shape data
913 *****************************************************************************/
914 int puzzle_generate_sectTop2Btm( filter_t
*p_filter
, piece_shape_t
*ps_piece_shape
, piece_shape_t
*ps_top_piece_shape
, uint8_t i_plane
)
916 if ((!ps_piece_shape
) || (!ps_top_piece_shape
))
919 filter_sys_t
*p_sys
= p_filter
->p_sys
;
921 int32_t i_top_min_y
= ps_top_piece_shape
->i_first_row_offset
;
922 int32_t i_top_nb_y
= ps_top_piece_shape
->i_row_nbr
;
923 int32_t i_lines
= p_sys
->ps_desk_planes
[i_plane
].i_pce_max_lines
;
924 int32_t i_max_y
= p_sys
->ps_desk_planes
[i_plane
].i_pce_max_lines
- i_top_min_y
;
926 int32_t i_min_y
= i_lines
/ 2;
927 int32_t i_nb_y
= i_max_y
- i_min_y
;
929 /* allocate memory */
930 ps_piece_shape
->i_row_nbr
= i_nb_y
;
931 ps_piece_shape
->i_first_row_offset
= i_min_y
;
932 ps_piece_shape
->ps_piece_shape_row
= malloc( sizeof( piece_shape_row_t
) * i_nb_y
);
933 if (!ps_piece_shape
->ps_piece_shape_row
)
936 for (int32_t i_y
= i_min_y
; i_y
< i_nb_y
+ i_min_y
; i_y
++) {
937 int32_t i_top_y
= 2 * i_min_y
- i_y
+ (i_nb_y
- i_top_nb_y
);
938 int32_t i_row
= i_y
- i_min_y
;
939 int32_t i_top_row
= i_top_y
- i_top_min_y
;
941 if ( i_top_row
< 0 || i_top_row
>= i_top_nb_y
) { /* the line does not exist in top */
942 ps_piece_shape
->ps_piece_shape_row
[i_row
].i_section_nbr
= 1;
943 ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
= malloc ( sizeof(row_section_t
) * 1);
944 if (!ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
) {
945 for (uint8_t i
=0; i
<i_row
;i
++)
946 free(ps_piece_shape
->ps_piece_shape_row
[i
].ps_row_section
);
947 free(ps_piece_shape
->ps_piece_shape_row
);
948 ps_piece_shape
->ps_piece_shape_row
= NULL
;
951 ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
[0].i_type
= 0;
952 ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
[0].i_width
=
953 puzzle_diagonal_limit( p_filter
, i_y
, false, i_plane
) - 1 - (puzzle_diagonal_limit( p_filter
, i_y
, true, i_plane
) - 1);
955 else { /* copy the line from TopShape */
956 int32_t i_top_width
=
957 puzzle_diagonal_limit( p_filter
, i_top_y
, false, i_plane
) - 1 - (puzzle_diagonal_limit( p_filter
, i_top_y
, true, i_plane
) - 1);
959 puzzle_diagonal_limit( p_filter
, i_y
, false, i_plane
) - 1 - (puzzle_diagonal_limit( p_filter
, i_y
, true, i_plane
) - 1);
960 int32_t i_left_adjust
= ( i_width
- i_top_width
) / 2;
961 int32_t i_right_adjust
= ( i_width
- i_top_width
) - i_left_adjust
;
963 int8_t i_section_nbr
= ps_top_piece_shape
->ps_piece_shape_row
[i_top_row
].i_section_nbr
;
964 ps_piece_shape
->ps_piece_shape_row
[i_row
].i_section_nbr
= i_section_nbr
;
965 ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
= malloc ( sizeof(row_section_t
) * i_section_nbr
);
966 if (!ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
) {
967 for (uint8_t i
=0; i
<i_row
;i
++)
968 free(ps_piece_shape
->ps_piece_shape_row
[i
].ps_row_section
);
969 free(ps_piece_shape
->ps_piece_shape_row
);
970 ps_piece_shape
->ps_piece_shape_row
= NULL
;
974 for (int8_t i_s
=0; i_s
<i_section_nbr
; i_s
++) {
975 ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
[i_s
].i_type
=
976 ps_top_piece_shape
->ps_piece_shape_row
[i_top_row
].ps_row_section
[i_s
].i_type
;
977 ps_piece_shape
->ps_piece_shape_row
[i_row
].ps_row_section
[i_s
].i_width
=
978 ps_top_piece_shape
->ps_piece_shape_row
[i_top_row
].ps_row_section
[i_s
].i_width
979 + (i_s
== 0 ? i_left_adjust
: (i_s
== i_section_nbr
-1 ? i_right_adjust
: 0));