[vlc-devel] [PATCH] Puzzle filter enhancement
Vianney BOYER
vlcvboyer at gmail.com
Fri Jan 18 08:15:30 CET 2013
PART 2/3 : code patch
---
AUTHORS | 1 +
modules/gui/qt4/ui/video_effects.ui | 335 ++-
modules/gui/qt4/components/extended_panels.cpp | 10 +
modules/video_filter/puzzle.c | 3266 ++++++++++++++++++++++--
4 files changed, 3302 insertions(+), 310 deletions(-)
diff --git a/AUTHORS b/AUTHORS
index eac402c..6ffcd40 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -557,6 +557,7 @@ Tim Schuerewegen
Tong Ka Man
Torsten Spindler
Udo Richter
+Vianney Boyer
Vincent Dimar
Vincent Penne
Vitalijus Slavinskas
diff --git a/modules/gui/qt4/components/extended_panels.cpp b/modules/gui/qt4/components/extended_panels.cpp
index f6b28c9..48f64b0 100644
--- a/modules/gui/qt4/components/extended_panels.cpp
+++ b/modules/gui/qt4/components/extended_panels.cpp
@@ -188,6 +188,15 @@ ExtVideo::ExtVideo( intf_thread_t *_p_intf, QTabWidget *_parent ) :
SETUP_VFILTER_OPTION( puzzleRowsSpin, valueChanged( int ) )
SETUP_VFILTER_OPTION( puzzleColsSpin, valueChanged( int ) )
SETUP_VFILTER_OPTION( puzzleBlackSlotCheck, stateChanged( int ) )
+ SETUP_VFILTER_OPTION( puzzleNearCheck, stateChanged( int ) )
+ SETUP_VFILTER_OPTION( puzzleBorderSlider, valueChanged( int ) )
+ SETUP_VFILTER_OPTION( puzzlePreviewCheck, stateChanged( int ) )
+ SETUP_VFILTER_OPTION( puzzlePreviewSizeSlider, valueChanged( int ) )
+ SETUP_VFILTER_OPTION( puzzleShapeSizeSlider, valueChanged( int ) )
+ SETUP_VFILTER_OPTION( puzzleAdvancedGameCheck, stateChanged( int ) )
+ SETUP_VFILTER_OPTION( puzzleAutoShuffleSlider, valueChanged( int ) )
+ SETUP_VFILTER_OPTION( puzzleAutoSolveSlider, valueChanged( int ) )
+ SETUP_VFILTER_OPTION( puzzleRotationCombo, currentIndexChanged( int ) )
SETUP_VFILTER( magnify )
@@ -1398,6 +1407,7 @@ Compressor::Compressor( intf_thread_t *p_intf, QWidget *parent )
* Spatializer
**********************************************************************/
+
Spatializer::Spatializer( intf_thread_t *p_intf, QWidget *parent )
: AudioFilterControlWidget( p_intf, parent, "spatializer" )
{
diff --git a/modules/video_filter/puzzle.c b/modules/video_filter/puzzle.c
index 713d1f2..34ce24c 100644
--- a/modules/video_filter/puzzle.c
+++ b/modules/video_filter/puzzle.c
@@ -5,6 +5,7 @@
* $Id$
*
* Authors: Antoine Cellerier <dionoea -at- videolan -dot- org>
+ * Vianney Boyer <vlcvboyer -at- gmail -dot- com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
@@ -46,9 +47,34 @@
#define COLS_LONGTEXT N_("Number of puzzle columns")
#define BLACKSLOT_TEXT N_("Make one tile a black slot")
#define BLACKSLOT_LONGTEXT N_("Make one slot black. Other tiles can only be swapped with the black slot.")
+#define NEAR_TEXT N_("Near")
+#define NEAR_LONGTEXT N_("Can only change two touching tiles.")
+#define BORDER_TEXT N_("Border")
+#define BORDER_LONGTEXT N_("Unshuffled Border width.")
+#define PREVIEW_TEXT N_("Small preview")
+#define PREVIEW_LONGTEXT N_("Show small preview.")
+#define PREVIEWSIZE_TEXT N_("Small preview size")
+#define PREVIEWSIZE_LONGTEXT N_("Show small preview size (percent of source).")
+#define SHAPE_SIZE_TEXT N_("Piece edge shape size")
+#define SHAPE_SIZE_LONGTEXT N_("Size of the curve along the piece's edge")
+#define ADVANCED_GAME_TEXT N_("Advanced game mode")
+#define ADVANCED_GAME_LONGTEXT N_("Advanced game mode with curved shapes, rotation, drag'n drop...")
+#define AUTO_SHUFFLE_TEXT N_("Auto shuffle")
+#define AUTO_SHUFFLE_LONGTEXT N_("Auto shuffle delay during game")
+#define AUTO_SOLVE_TEXT N_("Auto solve")
+#define AUTO_SOLVE_LONGTEXT N_("Auto solve delay during game")
+#define ROTATION_TEXT N_("Rotation")
+#define ROTATION_LONGTEXT N_("Rotation parameter: none;180;90-270;mirror")
+
+static const int pi_rotation_values[] = { (int) 0, (int) 1, (int) 2, (int) 3 };
+static const char *const ppsz_rotation_descriptions[] = { N_("0"), N_("0/180"), N_("0/90/180/270"), N_("0/90/180/270/mirror") };
#define CFG_PREFIX "puzzle-"
+#define SHAPES_QTY 20
+#define PIECE_TYPE_NBR (4*2*(1+SHAPES_QTY))
+#define NO_PCE -1
+
static int Open ( vlc_object_t * );
static void Close( vlc_object_t * );
@@ -65,65 +91,289 @@ vlc_module_begin()
COLS_TEXT, COLS_LONGTEXT, false )
add_bool( CFG_PREFIX "black-slot", false,
BLACKSLOT_TEXT, BLACKSLOT_LONGTEXT, false )
+ add_bool( CFG_PREFIX "near", false,
+ NEAR_TEXT, NEAR_LONGTEXT, false )
+ add_integer_with_range( CFG_PREFIX "border", 3, 0, 40,
+ BORDER_TEXT, BORDER_LONGTEXT, false )
+ add_bool( CFG_PREFIX "preview", false,
+ PREVIEW_TEXT, PREVIEW_LONGTEXT, false )
+ add_integer_with_range( CFG_PREFIX "preview-size", 15, 0, 100,
+ PREVIEWSIZE_TEXT, PREVIEWSIZE_LONGTEXT, false )
+ add_integer_with_range( CFG_PREFIX "shape-size", 90, 0, 100,
+ SHAPE_SIZE_TEXT, SHAPE_SIZE_LONGTEXT, false )
+ add_bool( CFG_PREFIX "advanced-game", true,
+ ADVANCED_GAME_TEXT, ADVANCED_GAME_LONGTEXT, false )
+ add_integer_with_range( CFG_PREFIX "auto-shuffle", 0, 0, 30000,
+ AUTO_SHUFFLE_TEXT, AUTO_SHUFFLE_LONGTEXT, false )
+ add_integer_with_range( CFG_PREFIX "auto-solve", 0, 0, 30000,
+ AUTO_SOLVE_TEXT, AUTO_SOLVE_LONGTEXT, false )
+ add_integer( CFG_PREFIX "rotation", 0,
+ ROTATION_TEXT, ROTATION_LONGTEXT, false )
+ change_integer_list(pi_rotation_values, ppsz_rotation_descriptions )
set_callbacks( Open, Close )
vlc_module_end()
-
/*****************************************************************************
* Local prototypes
*****************************************************************************/
+
static const char *const ppsz_filter_options[] = {
- "rows", "cols", "black-slot", NULL
+ "rows", "cols", "black-slot", "near", "border", "preview", "preview-size", "advanced-game", "shape-size", "auto-shuffle", "auto-solve", "rotation", NULL
};
-static picture_t *Filter( filter_t *, picture_t * );
-static int Mouse( filter_t *, vlc_mouse_t *, const vlc_mouse_t *, const vlc_mouse_t * );
+typedef struct {
+ float f_x, f_y;
+ } point_t;
-static bool IsFinished( filter_sys_t * );
-static void Shuffle( filter_sys_t * );
-static int PuzzleCallback( vlc_object_t *, char const *,
- vlc_value_t, vlc_value_t, void * );
+typedef struct {
+ int32_t i_preview_size_x, i_preview_size_y;
-struct filter_sys_t
-{
- /* */
- int i_cols;
- int i_rows;
+ int32_t i_border_size_x, i_border_size_y;
+ int32_t i_pieces_max_x, i_pieces_max_y;
+
+ int32_t i_lines, i_pitch;
+ int32_t i_visible_lines, i_visible_pitch;
+} puzzle_plane_t;
+
+typedef struct {
+ int32_t i_x, i_y;
+ int32_t i_size_x, i_size_y;
+} puzzle_array_t;
+
+typedef struct {
+ uint8_t i_type; // 0 = fill ; 1 = offset
+ int32_t i_width;
+} row_section_t;
+
+typedef struct {
+ int32_t i_section_nbr;
+ row_section_t *ps_row_section;
+} piece_shape_row_t;
+
+typedef struct {
+ int32_t i_row_nbr;
+ int32_t i_first_row_offset;
+ piece_shape_row_t *ps_piece_shape_row;
+} piece_shape_t;
+
+typedef struct {
+ int32_t i_original_x, i_original_y;
+ int32_t i_actual_x, i_actual_y;
+ int32_t i_size_x, i_size_y;
+} piece_in_plane_t;
+
+typedef struct {
+ int32_t i_original_row, i_original_col;
+
+ int32_t i_top_shape, i_btm_shape, i_right_shape, i_left_shape;
+
+ piece_in_plane_t *ps_piece_in_plane;
+
+ bool b_finished;
+ bool b_overlap;
+
+ int8_t i_actual_angle; // 0 = 0°, 1 = 90°... rotation center = top-left corner
+ int32_t i_actual_mirror; // +1 = without mirror ; -1 = with mirror
+ int32_t i_step_x_x, i_step_x_y, i_step_y_y, i_step_y_x;
+ int32_t i_ORx, i_OTy, i_OLx, i_OBy; // location of original piece's edges
+ int32_t i_TLx, i_TLy, i_TRx, i_TRy, i_BLx, i_BLy, i_BRx, i_BRy; // location of grabed piece's corners
+ int32_t i_max_x, i_min_x, i_max_y, i_min_y, i_center_x, i_center_y;
+
+ uint32_t i_group_ID;
+} piece_t;
+
+typedef struct {
+ int32_t i_original_row, i_original_col;
+ int32_t i_top_shape, i_btm_shape, i_right_shape, i_left_shape;
+ float f_pos_x, f_pos_y;
+ int8_t i_actual_angle; // 0 = 0°, 1 = 90°... rotation center = top-left corner
+ int32_t i_actual_mirror; // +1 = without mirror ; -1 = with mirror
+} save_piece_t;
+
+typedef struct {
+ int32_t i_rows, i_cols;
+ uint8_t i_rotate;
+ save_piece_t *ps_pieces;
+} save_game_t;
+
+typedef struct {
+ int32_t i_rows, i_cols;
+ int32_t i_pict_width, i_pict_height;
+ int32_t i_desk_width, i_desk_height;
+ int32_t i_piece_types;
+ uint32_t i_pieces_nbr;
+ int32_t i_preview_size;
+ int32_t i_shape_size;
+ int32_t i_border;
+ uint8_t i_planes;
+ // game settings
+ bool b_preview;
bool b_blackslot;
- int *pi_order;
- int i_selected;
+ bool b_near;
+ bool b_advanced;
+ uint8_t i_rotate; // 0=none, 1=0/180, 2=0/90/180/270, 3=0/90/180/270 w/ mirror
+ int32_t i_auto_shuffle_speed, i_auto_solve_speed;
+} param_t;
+
+struct filter_sys_t {
+ bool b_init;
+ bool b_bake_request;
+ bool b_shape_init;
+ bool b_change_param;
bool b_finished;
+ bool b_shuffleRqst;
+ bool b_mouse_drag;
+ bool b_mouse_mvt;
- /* */
- struct
- {
- atomic_flag b_uptodate;
- atomic_bool b_blackslot;
- atomic_uint i_cols;
- atomic_uint i_rows;
- } change;
+ param_t s_allocated;
+ param_t s_current_param;
+ param_t s_new_param;
+
+ uint32_t i_done_count, i_tmp_done_count;
+
+ int32_t i_mouse_drag_pce;
+ int32_t i_mouse_x, i_mouse_y;
+ int16_t i_pointed_pce;
+ int8_t i_mouse_action;
+
+ uint32_t i_solve_acc_loop, i_solve_grp_loop, i_calc_corn_loop;
+ int32_t i_magnet_accuracy;
+ int32_t *pi_group_qty;
+
+ int32_t *pi_order; //array which contains final pieces location (used in BASIC GAME MODE)
+ puzzle_array_t ***ps_puzzle_array; // array [row][col][plane] preset of location & size of each piece in the original image
+ piece_shape_t **ps_pieces_shapes; // array [each piece type (PCE_TYPE_NBR * negative * 4: top...)][each plane] of piece definition
+ piece_t *ps_pieces; // list [piece] of pieces data.
+ piece_t *ps_pieces_tmp; // used when sorting layers
+
+ puzzle_plane_t *ps_desk_planes;
+ puzzle_plane_t *ps_pict_planes;
+
+ uint8_t i_preview_pos;
+ int32_t i_selected;
+
+ vlc_mutex_t lock, pce_lock;
+
+ int32_t i_auto_shuffle_countdown_val, i_auto_solve_countdown_val;
+
+ point_t **ps_bezier_pts_H;
};
+static picture_t *Filter( filter_t *, picture_t * );
+static int PuzzleCallback( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * );
+static int Mouse( filter_t *, vlc_mouse_t *, const vlc_mouse_t *, const vlc_mouse_t * );
+
+static int bake_puzzle ( filter_t *, picture_t * , picture_t * );
+static int bake_puzzle_array ( filter_t *, picture_t * , picture_t * );
+static void free_ps_puzzle_array ( filter_t * );
+static int bake_piece ( filter_t * );
+static void free_ps_pieces ( filter_t * );
+static int bake_pieces_shapes ( filter_t * );
+static void free_ps_pieces_shapes ( filter_t * );
+
+static bool IsValid( filter_sys_t *p_sys, int32_t *pi_pce_lst );
+static void Shuffle( filter_t * );
+static void generate_rand_pce_list( filter_t *p_filter, int32_t **pi_pce_lst );
+static bool IsFinished( filter_sys_t *, int32_t *pi_pce_lst );
+static int find_piece( filter_t *p_filter, int32_t i_x, int32_t i_y, int32_t i_except);
+static void calculate_corners( filter_t *, int32_t i_piece );
+static void piece_foreground( filter_t *p_filter, int32_t i_piece);
+static void count_pce_group( filter_t *p_filter);
+static void solve_pces_group( filter_t *p_filter);
+static void solve_pces_accuracy( filter_t *p_filter);
+static void sort_layers( filter_t *p_filter);
+static void 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 );
+static void move_group( filter_t *p_filter, int32_t i_piece, int32_t i_dx, int32_t i_dy);
+
+static void auto_solve( filter_t *p_filter);
+static void auto_shuffle( filter_t *p_filter);
+
+static void puzzle_preset_background(picture_t *p_pic_dst, uint8_t Y, uint8_t U, uint8_t V);
+static void puzzle_draw_borders( filter_t *p_filter, picture_t *p_pic, picture_t *p_pic_dst);
+static void puzzle_draw_preview( filter_t *p_filter, picture_t *p_pic, picture_t *p_pic_dst);
+static void puzzle_draw_pieces( filter_t *p_filter, picture_t *p_pic, picture_t *p_pic_dst);
+static void draw_sign(picture_t *p_pic_dst, int32_t i_x, int32_t i_y, int32_t i_size_x, int32_t i_size_y, const char **ppsz_sign, bool b_reverse);
+static void draw_rectangle(picture_t *p_pic_dst, int32_t x, int32_t y, int32_t i_w, int32_t i_h, uint8_t Y, uint8_t U, uint8_t V );
+static void fill_rectangle(picture_t *p_pic_dst, int32_t x, int32_t y, int32_t i_w, int32_t i_h, uint8_t Y, uint8_t U, uint8_t V );
+
+static int32_t diagonal_limit( filter_t *p_filter, int32_t i_y, bool b_left, uint8_t i_plane );
+
+static point_t *scale_curve_H(int32_t i_size_x, int32_t i_size_y, uint8_t i_pts_nbr, point_t *ps_pt, int32_t i_shape_size);
+static point_t *H_2_scale_curve_V(int32_t i_size_x, int32_t i_size_y, uint8_t i_pts_nbr, point_t *ps_pt, int32_t i_shape_size);
+static point_t *curve_H_2_V(uint8_t i_pts_nbr, point_t *ps_pt);
+static point_t *curve_H_2_negative(uint8_t i_pts_nbr, point_t *ps_pt);
+static point_t *curve_V_2_negative(uint8_t i_pts_nbr, point_t *ps_pt);
+static point_t *rand_bezier(uint8_t i_pts_nbr);
+static void generate_sectTopB( filter_t *p_filter, piece_shape_t *ps_piece_shape, uint8_t i_plane);
+static void generate_sectLeftB( filter_t *p_filter, piece_shape_t *ps_piece_shape, uint8_t i_plane);
+static void generate_sectRightB( filter_t *p_filter, piece_shape_t *ps_piece_shape, uint8_t i_plane);
+static void generate_sectBtmB( filter_t *p_filter, piece_shape_t *ps_piece_shape, uint8_t i_plane);
+static void generate_sectTop( filter_t *p_filter, piece_shape_t *ps_piece_shape, uint8_t i_pts_nbr, point_t *ps_pt, uint8_t i_plane);
+static void generate_sectLeft( filter_t *p_filter, piece_shape_t *ps_piece_shape, uint8_t i_pts_nbr, point_t *ps_pt, uint8_t i_plane);
+static void generate_sectLeft2Right( filter_t *p_filter, piece_shape_t *ps_piece_shape, piece_shape_t *ps_left_piece_shape, uint8_t i_plane);
+static void generate_sectTop2Btm( filter_t *p_filter, piece_shape_t *ps_piece_shape, piece_shape_t *ps_top_piece_shape, uint8_t i_plane);
+
+static save_game_t* save(filter_t *p_filter);
+static void load( filter_t *p_filter, save_game_t *ps_save_game);
+
+static inline int32_t init_countdown(int32_t init_val) {
+ return ( ( __MAX( 1, 30000 - init_val)/20 ) / 2 + ((unsigned) vlc_mrand48() ) % ( __MAX( 1, ((30000 - init_val)/20) ) ) ); }
+
#define SHUFFLE_WIDTH 81
#define SHUFFLE_HEIGHT 13
-static const char *shuffle_button[] =
-{
-".................................................................................",
-".............. ............................ ........ ...... ...............",
-".............. ........................... ......... ........ ...............",
-".............. ........................... ......... ........ ...............",
-".. ....... . ....... .... ...... ...... ...... ........ ...",
-". .... ...... ... ...... .... ....... ......... ........ ....... .. ..",
-". ........... .... ...... .... ....... ......... ........ ...... .... .",
-". ....... .... ...... .... ....... ......... ........ ...... .",
-".. ...... .... ...... .... ....... ......... ........ ...... .......",
-"...... ...... .... ...... .... ....... ......... ........ ...... .......",
-". .... ...... .... ...... ... ....... ......... ........ ....... .... .",
-".. ....... .... ....... . ....... ......... ........ ........ ..",
-"................................................................................."
+static const char *ppsz_shuffle_button[] =
+{
+"ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"oooooooooooooo oooooooooooooooooooooooooooo oooooooo oooooo ooooooooooooooo",
+"oooooooooooooo ooooooooooooooooooooooooooo ooooooooo oooooooo ooooooooooooooo",
+"oooooooooooooo ooooooooooooooooooooooooooo ooooooooo oooooooo ooooooooooooooo",
+"oo ooooooo o ooooooo oooo oooooo oooooo oooooo oooooooo ooo",
+"o oooo oooooo ooo oooooo oooo ooooooo ooooooooo oooooooo ooooooo oo oo",
+"o ooooooooooo oooo oooooo oooo ooooooo ooooooooo oooooooo oooooo oooo o",
+"o ooooooo oooo oooooo oooo ooooooo ooooooooo oooooooo oooooo o",
+"oo oooooo oooo oooooo oooo ooooooo ooooooooo oooooooo oooooo ooooooo",
+"oooooo oooooo oooo oooooo oooo ooooooo ooooooooo oooooooo oooooo ooooooo",
+"o oooo oooooo oooo oooooo ooo ooooooo ooooooooo oooooooo ooooooo oooo o",
+"oo ooooooo oooo ooooooo o ooooooo ooooooooo oooooooo oooooooo oo",
+"ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
};
+#define ARROW_WIDTH 13
+#define ARROW_HEIGHT 13
+static const char *ppsz_rot_arrow_sign[] =
+{
+" .ooo. ",
+" .o. .oo. ",
+" .o. .o. ",
+" .o. .o.",
+" o. .o",
+".o .",
+".o . ",
+" o. .o. ",
+" .o..o. ",
+" o..o ",
+" .o. ",
+"ooooo. ",
+" .. "
+};
+
+static const char *ppsz_mir_arrow_sign[] =
+{
+" ",
+" ",
+" . . ",
+" .o. .o. ",
+" .o. .o. ",
+".o. .o.",
+"ooooooooooooo",
+".o. .o.",
+" .o. .o. ",
+" .o. .o. ",
+" . . ",
+" ",
+" "
+};
/**
* Open the filter
@@ -134,214 +384,374 @@ static int Open( vlc_object_t *p_this )
filter_sys_t *p_sys;
/* */
- if( !es_format_IsSimilar( &p_filter->fmt_in, &p_filter->fmt_out ) )
- {
+ if( !es_format_IsSimilar( &p_filter->fmt_in, &p_filter->fmt_out ) ) {
msg_Err( p_filter, "Input and output format does not match" );
return VLC_EGENERIC;
}
/* Allocate structure */
- p_filter->p_sys = p_sys = malloc( sizeof( *p_sys ) );
+ p_filter->p_sys = p_sys = calloc(1, sizeof( *p_sys ) );
if( !p_sys )
return VLC_ENOMEM;
+ p_sys->b_shuffleRqst = true;
+ p_sys->b_change_param = true;
+ p_sys->i_mouse_drag_pce = NO_PCE;
+ p_sys->i_pointed_pce = NO_PCE;
+ p_sys->i_magnet_accuracy = 3;
+
config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
p_filter->p_cfg );
- p_sys->pi_order = NULL;
+ vlc_mutex_init( &p_sys->lock );
+ vlc_mutex_init( &p_sys->pce_lock );
- atomic_init( &p_sys->change.i_rows,
- var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "rows" ) );
- atomic_init( &p_sys->change.i_cols,
- var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "cols" ) );
- atomic_init( &p_sys->change.b_blackslot,
- var_CreateGetBoolCommand( p_filter, CFG_PREFIX "black-slot" ) );
- p_sys->change.b_uptodate = ATOMIC_FLAG_INIT;
+ p_sys->s_new_param.i_rows =
+ var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "rows" );
+ p_sys->s_new_param.i_cols =
+ var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "cols" );
+ p_sys->s_new_param.b_blackslot =
+ var_CreateGetBoolCommand( p_filter, CFG_PREFIX "black-slot" );
+ p_sys->s_new_param.b_near =
+ var_CreateGetBoolCommand( p_filter, CFG_PREFIX "near" );
+ p_sys->s_new_param.i_border =
+ var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "border" );
+ p_sys->s_new_param.b_preview =
+ var_CreateGetBoolCommand( p_filter, CFG_PREFIX "preview" );
+ p_sys->s_new_param.i_preview_size =
+ var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "preview-size" );
+ p_sys->s_new_param.i_shape_size =
+ var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "shape-size" );
+ p_sys->s_new_param.b_advanced =
+ var_CreateGetBoolCommand( p_filter, CFG_PREFIX "advanced-game" );
+ p_sys->s_new_param.i_auto_shuffle_speed =
+ var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "auto-shuffle" );
+ p_sys->s_new_param.i_auto_solve_speed =
+ var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "auto-solve" );
+ p_sys->s_new_param.i_rotate =
+ var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "rotation" );
- var_AddCallback( p_filter, CFG_PREFIX "rows", PuzzleCallback, p_sys );
- var_AddCallback( p_filter, CFG_PREFIX "cols", PuzzleCallback, p_sys );
- var_AddCallback( p_filter, CFG_PREFIX "black-slot", PuzzleCallback, p_sys );
+ var_AddCallback( p_filter, CFG_PREFIX "rows", PuzzleCallback, p_sys );
+ var_AddCallback( p_filter, CFG_PREFIX "cols", PuzzleCallback, p_sys );
+ var_AddCallback( p_filter, CFG_PREFIX "black-slot", PuzzleCallback, p_sys );
+ var_AddCallback( p_filter, CFG_PREFIX "near", PuzzleCallback, p_sys );
+ var_AddCallback( p_filter, CFG_PREFIX "border", PuzzleCallback, p_sys );
+ var_AddCallback( p_filter, CFG_PREFIX "preview", PuzzleCallback, p_sys );
+ var_AddCallback( p_filter, CFG_PREFIX "preview-size", PuzzleCallback, p_sys );
+ var_AddCallback( p_filter, CFG_PREFIX "shape-size", PuzzleCallback, p_sys );
+ var_AddCallback( p_filter, CFG_PREFIX "advanced-game",PuzzleCallback, p_sys );
+ var_AddCallback( p_filter, CFG_PREFIX "auto-shuffle", PuzzleCallback, p_sys );
+ var_AddCallback( p_filter, CFG_PREFIX "auto-solve", PuzzleCallback, p_sys );
+ var_AddCallback( p_filter, CFG_PREFIX "rotation", PuzzleCallback, p_sys );
p_filter->pf_video_filter = Filter;
p_filter->pf_video_mouse = Mouse;
+ p_sys->ps_bezier_pts_H = calloc( SHAPES_QTY, sizeof( point_t *) );
+ for (int32_t i_shape = 0; i_shape<SHAPES_QTY; i_shape++)
+ p_sys->ps_bezier_pts_H[i_shape] = rand_bezier(7);
+
return VLC_SUCCESS;
}
/**
* Close the filter
*/
-static void Close( vlc_object_t *p_this )
-{
+static void Close( vlc_object_t *p_this ) {
filter_t *p_filter = (filter_t *)p_this;
filter_sys_t *p_sys = p_filter->p_sys;
- var_DelCallback( p_filter, CFG_PREFIX "rows", PuzzleCallback, p_sys );
- var_DelCallback( p_filter, CFG_PREFIX "cols", PuzzleCallback, p_sys );
- var_DelCallback( p_filter, CFG_PREFIX "black-slot", PuzzleCallback, p_sys );
+ var_DelCallback( p_filter, CFG_PREFIX "rows", PuzzleCallback, p_sys );
+ var_DelCallback( p_filter, CFG_PREFIX "cols", PuzzleCallback, p_sys );
+ var_DelCallback( p_filter, CFG_PREFIX "black-slot", PuzzleCallback, p_sys );
+ var_DelCallback( p_filter, CFG_PREFIX "near", PuzzleCallback, p_sys );
+ var_DelCallback( p_filter, CFG_PREFIX "border", PuzzleCallback, p_sys );
+ var_DelCallback( p_filter, CFG_PREFIX "preview", PuzzleCallback, p_sys );
+ var_DelCallback( p_filter, CFG_PREFIX "preview-size", PuzzleCallback, p_sys );
+ var_DelCallback( p_filter, CFG_PREFIX "shape-size", PuzzleCallback, p_sys );
+ var_DelCallback( p_filter, CFG_PREFIX "advanced-game", PuzzleCallback, p_sys );
+ var_DelCallback( p_filter, CFG_PREFIX "auto-shuffle", PuzzleCallback, p_sys );
+ var_DelCallback( p_filter, CFG_PREFIX "auto-solve", PuzzleCallback, p_sys );
+ var_DelCallback( p_filter, CFG_PREFIX "rotation", PuzzleCallback, p_sys );
+ vlc_mutex_destroy( &p_sys->lock );
+ vlc_mutex_destroy( &p_sys->pce_lock );
+
+ free_ps_puzzle_array ( p_filter );
+ free_ps_pieces_shapes ( p_filter);
+ free_ps_pieces ( p_filter );
+ free(p_sys->ps_desk_planes);
+ free(p_sys->ps_pict_planes);
free( p_sys->pi_order );
+ for (int32_t i_shape = 0; i_shape<SHAPES_QTY; i_shape++)
+ free(p_sys->ps_bezier_pts_H[i_shape]);
+ free(p_sys->ps_bezier_pts_H);
+
free( p_sys );
}
/**
* Filter a picture
*/
-static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
-{
+static picture_t *Filter( filter_t *p_filter, picture_t *p_pic ) {
+ const video_format_t *p_fmt = &p_filter->fmt_in.video;
filter_sys_t *p_sys = p_filter->p_sys;
- picture_t *p_outpic = filter_NewPicture( p_filter );
- if( !p_outpic )
- {
+ int ret = 0;
+ p_sys->b_bake_request = false;
+
+ if( !p_pic ) return NULL;
+
+ if( (p_filter->fmt_in.video.i_height == 0) ||
+ (p_filter->fmt_in.video.i_width == 0) )
+ return NULL;
+
+ if( (p_filter->fmt_out.video.i_height == 0) ||
+ (p_filter->fmt_out.video.i_width == 0) )
+ return NULL;
+
+ picture_t *p_pic_dst = filter_NewPicture( p_filter );
+ if( !p_pic_dst ) {
picture_Release( p_pic );
return NULL;
}
- /* */
- if( !atomic_flag_test_and_set( &p_sys->change.b_uptodate ) )
- {
- p_sys->i_rows = atomic_load( &p_sys->change.i_rows );
- p_sys->i_cols = atomic_load( &p_sys->change.i_cols );
- p_sys->b_blackslot = atomic_load( &p_sys->change.b_blackslot );
- Shuffle( p_sys );
+ if ((p_sys->pi_order == NULL) || (p_sys->ps_desk_planes == NULL) || (p_sys->ps_pict_planes == NULL) || (p_sys->ps_puzzle_array == NULL) || (p_sys->ps_pieces == NULL))
+ p_sys->b_init = false;
+
+ if ((p_sys->ps_pieces_shapes == NULL) && p_sys->s_current_param.b_advanced && (p_sys->s_current_param.i_shape_size != 0))
+ p_sys->b_init = false;
+
+ if ( p_sys->s_allocated.i_planes != p_pic_dst->i_planes)
+ p_sys->b_init = false;
+
+ p_sys->s_current_param.i_planes = p_pic_dst->i_planes;
+
+ if (p_sys->ps_pict_planes != NULL) {
+ for (uint8_t i_plane = 0; i_plane < p_sys->s_allocated.i_planes; i_plane++) {
+ if ( (p_sys->ps_pict_planes[i_plane].i_lines != p_pic_dst->p[i_plane].i_lines)
+ || (p_sys->ps_pict_planes[i_plane].i_pitch != p_pic_dst->p[i_plane].i_pitch)
+ || (p_sys->ps_pict_planes[i_plane].i_visible_lines != p_pic_dst->p[i_plane].i_visible_lines)
+ ||(p_sys->ps_pict_planes[i_plane].i_visible_pitch != p_pic_dst->p[i_plane].i_visible_pitch) )
+ p_sys->b_init = false;
+ }
}
- /* */
- const int i_rows = p_sys->i_rows;
- const int i_cols = p_sys->i_cols;
+ p_sys->s_current_param.i_pict_width = (int) p_fmt->i_width;
+ p_sys->s_current_param.i_pict_height = (int) p_fmt->i_height;
+ p_sys->s_current_param.i_desk_width = (int) p_pic_dst->p[0].i_visible_pitch;
+ p_sys->s_current_param.i_desk_height = (int) p_pic_dst->p[0].i_visible_lines;
- /* Draw each piece of the puzzle at the right place */
- for( int i_plane = 0; i_plane < p_outpic->i_planes; i_plane++ )
- {
- const plane_t *p_in = &p_pic->p[i_plane];
- plane_t *p_out = &p_outpic->p[i_plane];
+ vlc_mutex_lock( &p_sys->lock );
+
+ if ( p_sys->b_change_param || p_sys->b_bake_request || !p_sys->b_init ) {
+ if ( p_sys->s_allocated.i_rows != p_sys->s_new_param.i_rows
+ || p_sys->s_allocated.i_cols != p_sys->s_new_param.i_cols
+ || p_sys->s_allocated.b_advanced != p_sys->s_new_param.b_advanced
+ || p_sys->s_allocated.i_rotate != p_sys->s_new_param.i_rotate
+ || p_sys->b_bake_request || !p_sys->b_init )
+ {
+ p_sys->b_bake_request = true;
+ p_sys->b_init = false;
+ p_sys->b_shuffleRqst = true;
+ p_sys->b_shape_init = false;
+ }
- for( int i = 0; i < i_cols * i_rows; i++ )
+ if ( p_sys->s_current_param.i_border != p_sys->s_new_param.i_border
+ || p_sys->s_current_param.i_shape_size != p_sys->s_new_param.i_shape_size )
{
- int i_piece_height = p_out->i_visible_lines / i_rows;
- int i_piece_width = p_out->i_visible_pitch / i_cols;
+ p_sys->b_bake_request = true;
+ p_sys->b_shape_init = false;
+ }
- int i_col = (i % i_cols) * i_piece_width;
- int i_row = (i / i_cols) * i_piece_height;
- int i_last_row = i_row + i_piece_height;
+ if ( p_sys->s_current_param.b_blackslot != p_sys->s_new_param.b_blackslot
+ && p_sys->i_selected == NO_PCE
+ && p_sys->s_current_param.b_blackslot )
+ p_sys->i_selected = 0;
- int i_ocol = (p_sys->pi_order[i] % i_cols) * i_piece_width;
- int i_orow = (p_sys->pi_order[i] / i_cols) * i_piece_height;
+ if ( p_sys->s_current_param.i_auto_shuffle_speed != p_sys->s_new_param.i_auto_shuffle_speed )
+ p_sys->i_auto_shuffle_countdown_val = init_countdown(p_sys->s_new_param.i_auto_shuffle_speed);
- if( p_sys->b_blackslot && !p_sys->b_finished && i == p_sys->i_selected )
- {
- uint8_t color = ( i_plane == Y_PLANE ? 0x0 : 0x80 );
- for( int r = i_row; r < i_last_row; r++ )
- {
- memset( p_out->p_pixels + r * p_out->i_pitch + i_col,
- color, i_piece_width );
- }
- }
- else
- {
- for( int r = i_row, or = i_orow; r < i_last_row; r++, or++ )
- {
- memcpy( p_out->p_pixels + r * p_out->i_pitch + i_col,
- p_in->p_pixels + or * p_in->i_pitch + i_ocol,
- i_piece_width );
- }
- }
+ if ( p_sys->s_current_param.i_auto_solve_speed != p_sys->s_new_param.i_auto_solve_speed )
+ p_sys->i_auto_solve_countdown_val = init_countdown(p_sys->s_current_param.i_auto_solve_speed);
- /* Draw the borders of the selected slot */
- if( i_plane == 0 && !p_sys->b_blackslot && p_sys->i_selected == i )
- {
- memset( p_out->p_pixels + i_row * p_out->i_pitch + i_col,
- 0xff, i_piece_width );
- for( int r = i_row; r < i_last_row; r++ )
- {
- p_out->p_pixels[r * p_out->i_pitch + i_col + 0 + 0 ] = 0xff;
- p_out->p_pixels[r * p_out->i_pitch + i_col + i_piece_width - 1 ] = 0xff;
- }
- memset( p_out->p_pixels + (i_last_row - 1) * p_out->i_pitch + i_col,
- 0xff, i_piece_width );
- }
+ p_sys->s_current_param.i_rows = p_sys->s_new_param.i_rows;
+ p_sys->s_current_param.i_cols = p_sys->s_new_param.i_cols;
+ p_sys->s_current_param.i_pieces_nbr = p_sys->s_current_param.i_rows * p_sys->s_current_param.i_cols;
+ p_sys->s_current_param.b_advanced = p_sys->s_new_param.b_advanced;
+ if (!p_sys->s_new_param.b_advanced) {
+ p_sys->s_current_param.b_blackslot = p_sys->s_new_param.b_blackslot;
+ p_sys->s_current_param.b_near = p_sys->s_new_param.b_near || p_sys->s_new_param.b_blackslot;
+ p_sys->s_current_param.i_border = 0;
+ p_sys->s_current_param.b_preview = false;
+ p_sys->s_current_param.i_preview_size= 0;
+ p_sys->s_current_param.i_shape_size = 0;
+ p_sys->s_current_param.i_auto_shuffle_speed = 0;
+ p_sys->s_current_param.i_auto_solve_speed = 0;
+ p_sys->s_current_param.i_rotate = 0;
+ }
+ else
+ {
+ p_sys->s_current_param.b_blackslot = false;
+ p_sys->s_current_param.b_near = false;
+ p_sys->s_current_param.i_border = p_sys->s_new_param.i_border;
+ p_sys->s_current_param.b_preview = p_sys->s_new_param.b_preview;
+ p_sys->s_current_param.i_preview_size = p_sys->s_new_param.i_preview_size;
+ p_sys->s_current_param.i_shape_size = p_sys->s_new_param.i_shape_size;
+ p_sys->s_current_param.i_auto_shuffle_speed = p_sys->s_new_param.i_auto_shuffle_speed;
+ p_sys->s_current_param.i_auto_solve_speed = p_sys->s_new_param.i_auto_solve_speed;
+ p_sys->s_current_param.i_rotate = p_sys->s_new_param.i_rotate;
}
+ p_sys->b_change_param = false;
}
- /* Draw the 'Shuffle' button if the puzzle is finished */
- if( p_sys->b_finished )
- {
- plane_t *p_out = &p_outpic->p[Y_PLANE];
- for( int i = 0; i < SHUFFLE_HEIGHT; i++ )
- {
- for( int j = 0; j < SHUFFLE_WIDTH; j++ )
- {
- if( shuffle_button[i][j] == '.' )
- p_out->p_pixels[ i * p_out->i_pitch + j ] = 0xff;
- }
+ vlc_mutex_unlock( &p_sys->lock );
+
+ // bake initial puzzle data & shapes
+ if ( p_sys->b_bake_request ) {
+ if (!p_sys->b_shuffleRqst) {
+ save_game_t *ps_save_game;
+ ps_save_game = save(p_filter);
+ bake_puzzle( p_filter, p_pic_dst, p_pic );
+ load( p_filter, ps_save_game);
+ free(ps_save_game->ps_pieces);
+ free(ps_save_game);
+ }
+ else {
+ ret = bake_puzzle( p_filter, p_pic_dst, p_pic );
+ if ( ret !=0 )
+ return CopyInfoAndRelease( p_pic_dst, p_pic );
}
}
- return CopyInfoAndRelease( p_outpic, p_pic );
-}
+ // shuffle the desk and generate data
+ if ( p_sys->b_shuffleRqst && p_sys->b_init )
+ bake_piece ( p_filter );
-static int Mouse( filter_t *p_filter, vlc_mouse_t *p_mouse,
- const vlc_mouse_t *p_old, const vlc_mouse_t *p_new )
-{
- filter_sys_t *p_sys = p_filter->p_sys;
- const video_format_t *p_fmt = &p_filter->fmt_in.video;
+ // preset output pic:
+ if ( !p_sys->b_bake_request && !p_sys->b_shuffleRqst && p_sys->b_init && !p_sys->b_finished )
+ puzzle_preset_background(p_pic_dst, 0, 127, 127);
+ else {
+ // copy src to dst during init & bake process
+ for( uint8_t i_plane = 0; i_plane < p_pic_dst->i_planes; i_plane++ )
+ memcpy( p_pic_dst->p[i_plane].p_pixels, p_pic->p[i_plane].p_pixels,
+ p_pic->p[i_plane].i_pitch * (int32_t) p_pic->p[i_plane].i_visible_lines );
+ }
- /* Only take events inside the puzzle erea */
- if( p_new->i_x < 0 || p_new->i_x >= (int)p_fmt->i_width ||
- p_new->i_y < 0 || p_new->i_y >= (int)p_fmt->i_height )
- return VLC_EGENERIC;
+ vlc_mutex_lock( &p_sys->pce_lock );
- /* */
- const bool b_clicked = vlc_mouse_HasPressed( p_old, p_new, MOUSE_BUTTON_LEFT );
+ // manage the game, adjust locations, groups and regenerate some corrupted data if any
+ for (uint32_t i = 0; i < __MAX( 4, p_sys->s_allocated.i_pieces_nbr / 4 ) && ( !p_sys->b_bake_request && !p_sys->b_mouse_drag && p_sys->b_init && p_sys->s_current_param.b_advanced ); i++)
+ solve_pces_accuracy( p_filter );
+ for (uint32_t i = 0; i < __MAX( 4, p_sys->s_allocated.i_pieces_nbr / 4 ) && ( !p_sys->b_bake_request && !p_sys->b_mouse_drag && p_sys->b_init && p_sys->s_current_param.b_advanced ); i++)
+ solve_pces_group( p_filter );
+ if ( !p_sys->b_bake_request && !p_sys->b_mouse_drag && p_sys->b_init && p_sys->s_current_param.b_advanced )
+ count_pce_group( p_filter);
+ if ( !p_sys->b_bake_request && !p_sys->b_mouse_drag && p_sys->b_init && p_sys->s_current_param.b_advanced )
+ sort_layers( p_filter);
+ for (uint32_t i = 0; i < __MAX( 4, p_sys->s_allocated.i_pieces_nbr / 24 ) && ( !p_sys->b_bake_request && !p_sys->b_mouse_drag && p_sys->b_init && p_sys->s_current_param.b_advanced ); i++) {
+ p_sys->i_calc_corn_loop++;
+ p_sys->i_calc_corn_loop %= p_sys->s_allocated.i_pieces_nbr;
+ calculate_corners( p_filter, p_sys->i_calc_corn_loop );
+ }
- /* If the puzzle is finished, shuffle it if needed */
- if( p_sys->b_finished )
+ if ( !p_sys->b_bake_request && !p_sys->b_mouse_drag && p_sys->b_init
+ && p_sys->ps_puzzle_array != NULL && p_sys->s_current_param.b_advanced )
{
- if( b_clicked &&
- p_new->i_x < SHUFFLE_WIDTH && p_new->i_y < SHUFFLE_HEIGHT )
+ // computer moves some piece:
+ auto_shuffle( p_filter );
+ auto_solve( p_filter );
+ }
+
+ vlc_mutex_unlock( &p_sys->pce_lock );
+
+ if ( !p_sys->b_bake_request && p_sys->b_init && p_sys->ps_puzzle_array != NULL ) {
+ // generate output pic:
+ puzzle_draw_borders(p_filter, p_pic, p_pic_dst);
+
+ p_sys->i_pointed_pce = NO_PCE;
+ puzzle_draw_pieces(p_filter, p_pic, p_pic_dst);
+
+ if (p_sys->i_pointed_pce == NO_PCE)
+ p_sys->i_mouse_drag_pce = find_piece( p_filter, p_sys->i_mouse_x, p_sys->i_mouse_y, -1);
+ else
+ p_sys->i_mouse_drag_pce = p_sys->i_pointed_pce;
+
+ if (p_sys->s_current_param.b_preview )
+ puzzle_draw_preview(p_filter, p_pic, p_pic_dst);
+
+ // highlight the selected piece:
+ if ( p_sys->i_selected != NO_PCE && !p_sys->s_current_param.b_blackslot
+ && !p_sys->s_current_param.b_advanced )
{
- atomic_flag_clear( &p_sys->change.b_uptodate );
- return VLC_EGENERIC;
+ int32_t c = (p_sys->i_selected % p_sys->s_allocated.i_cols);
+ int32_t r = (p_sys->i_selected / p_sys->s_allocated.i_cols);
+
+ draw_rectangle(p_pic_dst,
+ p_sys->ps_puzzle_array[r][c][0].i_x,
+ p_sys->ps_puzzle_array[r][c][0].i_y,
+ p_sys->ps_puzzle_array[r][c][0].i_size_x,
+ p_sys->ps_puzzle_array[r][c][0].i_size_y,
+ 255, 127, 127);
}
- else
+
+ if ( p_sys->i_selected != NO_PCE && p_sys->s_current_param.b_blackslot
+ && !p_sys->s_current_param.b_advanced )
{
- /* This is the only case where we can forward the mouse */
- *p_mouse = *p_new;
- return VLC_SUCCESS;
+ int32_t c = (p_sys->i_selected % p_sys->s_allocated.i_cols);
+ int32_t r = (p_sys->i_selected / p_sys->s_allocated.i_cols);
+
+ fill_rectangle(p_pic_dst,
+ p_sys->ps_puzzle_array[r][c][0].i_x,
+ p_sys->ps_puzzle_array[r][c][0].i_y,
+ p_sys->ps_puzzle_array[r][c][0].i_size_x,
+ p_sys->ps_puzzle_array[r][c][0].i_size_y,
+ 0, 127, 127);
}
- }
- if( !b_clicked )
- return VLC_EGENERIC;
- /* */
- const int i_pos_x = p_new->i_x * p_sys->i_cols / p_fmt->i_width;
- const int i_pos_y = p_new->i_y * p_sys->i_rows / p_fmt->i_height;
- const int i_pos = i_pos_y * p_sys->i_cols + i_pos_x;
+ /* Draw the 'Shuffle' button if the puzzle is finished */
+ if ( p_sys->b_finished )
+ draw_sign(p_pic_dst, 0, 0, SHUFFLE_WIDTH, SHUFFLE_HEIGHT, ppsz_shuffle_button, false);
- if( p_sys->i_selected == -1 )
- {
- p_sys->i_selected = i_pos;
- }
- else if( p_sys->i_selected == i_pos && !p_sys->b_blackslot )
- {
- p_sys->i_selected = -1;
- }
- else if( ( p_sys->i_selected == i_pos + 1 && p_sys->i_selected%p_sys->i_cols != 0 )
- || ( p_sys->i_selected == i_pos - 1 && i_pos % p_sys->i_cols != 0 )
- || p_sys->i_selected == i_pos + p_sys->i_cols
- || p_sys->i_selected == i_pos - p_sys->i_cols )
- {
- /* Swap two pieces */
- int a = p_sys->pi_order[ p_sys->i_selected ];
- p_sys->pi_order[ p_sys->i_selected ] = p_sys->pi_order[ i_pos ];
- p_sys->pi_order[ i_pos ] = a;
+ // draw an arrow to indicate rotation
+ if ((p_sys->i_mouse_drag_pce != NO_PCE) && !p_sys->b_mouse_drag
+ && !p_sys->b_finished && p_sys->s_current_param.b_advanced )
+ {
+ vlc_mutex_lock( &p_sys->pce_lock );
+
+ int32_t i_delta_x;
- p_sys->i_selected = p_sys->b_blackslot ? i_pos : -1;
- p_sys->b_finished = IsFinished( p_sys );
+ if (p_sys->s_current_param.i_rotate != 3)
+ i_delta_x = 0;
+ else if ( (p_sys->ps_pieces[p_sys->i_mouse_drag_pce].i_actual_angle & 1) == 0)
+ i_delta_x = p_sys->ps_desk_planes[0].i_pieces_max_x / 6;
+ else
+ i_delta_x = p_sys->ps_desk_planes[0].i_pieces_max_y / 6;
+
+ if (p_sys->s_current_param.i_rotate == 0)
+ p_sys->i_mouse_action = 0;
+ else if (p_sys->s_current_param.i_rotate == 1)
+ p_sys->i_mouse_action = 2;
+ else if ( p_sys->i_mouse_x >= ( p_sys->ps_pieces[p_sys->i_mouse_drag_pce].i_center_x + i_delta_x) )
+ p_sys->i_mouse_action = -1; // rotate counterclockwise
+ else if ( p_sys->i_mouse_x <= ( p_sys->ps_pieces[p_sys->i_mouse_drag_pce].i_center_x - i_delta_x) )
+ p_sys->i_mouse_action = +1;
+ else
+ p_sys->i_mouse_action = 4; // center click: only mirror
+
+ if ( p_sys->i_mouse_action == +1 )
+ draw_sign(p_pic_dst, p_sys->i_mouse_x - ARROW_WIDTH, p_sys->i_mouse_y, ARROW_WIDTH, ARROW_HEIGHT, ppsz_rot_arrow_sign, false);
+ else if ( p_sys->i_mouse_action == -1 )
+ draw_sign(p_pic_dst, p_sys->i_mouse_x - ARROW_WIDTH, p_sys->i_mouse_y, ARROW_WIDTH, ARROW_HEIGHT, ppsz_rot_arrow_sign, true);
+ else if ( p_sys->i_mouse_action == 4 )
+ draw_sign(p_pic_dst, p_sys->i_mouse_x - ARROW_WIDTH, p_sys->i_mouse_y, ARROW_WIDTH, ARROW_HEIGHT, ppsz_mir_arrow_sign, false);
+
+ vlc_mutex_unlock( &p_sys->pce_lock );
+ }
}
- return VLC_EGENERIC;
+
+ return CopyInfoAndRelease( p_pic_dst, p_pic );
}
/*****************************************************************************
@@ -352,90 +762,2480 @@ static int PuzzleCallback( vlc_object_t *p_this, char const *psz_var,
void *p_data )
{
VLC_UNUSED(p_this); VLC_UNUSED(oldval);
- filter_sys_t *p_sys = p_data;
+ filter_sys_t *p_sys = (filter_sys_t *)p_data;
+
+ vlc_mutex_lock( &p_sys->lock );
+ if( !strcmp( psz_var, CFG_PREFIX "rows" ) ) {
+ p_sys->s_new_param.i_rows = __MAX( 1, newval.i_int );
+ }
+ else if( !strcmp( psz_var, CFG_PREFIX "cols" ) ) {
+ p_sys->s_new_param.i_cols = __MAX( 1, newval.i_int );
+ }
+ else if( !strcmp( psz_var, CFG_PREFIX "black-slot" ) ) {
+ p_sys->s_new_param.b_blackslot = newval.b_bool;
+ }
+ else if( !strcmp( psz_var, CFG_PREFIX "near" ) ) {
+ p_sys->s_new_param.b_near = newval.b_bool;
+ }
+ else if( !strcmp( psz_var, CFG_PREFIX "border" ) ) {
+ p_sys->s_new_param.i_border = __MAX( 0, newval.i_int );
+ }
+ else if( !strcmp( psz_var, CFG_PREFIX "preview" ) ) {
+ p_sys->s_new_param.b_preview = newval.b_bool;
+ }
+ else if( !strcmp( psz_var, CFG_PREFIX "preview-size" ) ) {
+ p_sys->s_new_param.i_preview_size = newval.i_int;
+ }
+ else if( !strcmp( psz_var, CFG_PREFIX "shape-size" ) ) {
+ p_sys->s_new_param.i_shape_size = newval.i_int;
+ }
+ else if( !strcmp( psz_var, CFG_PREFIX "advanced-game" ) ) {
+ p_sys->s_new_param.b_advanced = newval.b_bool;
+ }
+ else if( !strcmp( psz_var, CFG_PREFIX "auto-shuffle" ) ) {
+ p_sys->s_new_param.i_auto_shuffle_speed = newval.i_int;
+ }
+ else if( !strcmp( psz_var, CFG_PREFIX "auto-solve" ) ) {
+ p_sys->s_new_param.i_auto_solve_speed = newval.i_int;
+ }
+ else if( !strcmp( psz_var, CFG_PREFIX "rotation" ) ) {
+ p_sys->s_new_param.i_rotate = newval.i_int;
+ }
- if( !strcmp( psz_var, CFG_PREFIX "rows" ) )
- atomic_store( &p_sys->change.i_rows, __MAX( 2, newval.i_int ) );
- else if( !strcmp( psz_var, CFG_PREFIX "cols" ) )
- atomic_store( &p_sys->change.i_cols, __MAX( 2, newval.i_int ) );
- else if( !strcmp( psz_var, CFG_PREFIX "black-slot" ) )
- atomic_store( &p_sys->change.b_blackslot, newval.b_bool );
- atomic_flag_clear( &p_sys->change.b_uptodate );
+ p_sys->b_change_param = true;
+ vlc_mutex_unlock( &p_sys->lock );
return VLC_SUCCESS;
}
-static bool IsFinished( filter_sys_t *p_sys )
+static int Mouse( filter_t *p_filter, vlc_mouse_t *p_mouse,
+ const vlc_mouse_t *p_old, const vlc_mouse_t *p_new )
{
- for( int i = 0; i < p_sys->i_cols * p_sys->i_rows; i++ )
- {
- if( i != p_sys->pi_order[i] )
- return false;
- }
- return true;
-}
+ filter_sys_t *p_sys = p_filter->p_sys;
+ const video_format_t *p_fmt = &p_filter->fmt_in.video;
-static bool IsValid( filter_sys_t *p_sys )
-{
- const int i_count = p_sys->i_cols * p_sys->i_rows;
+ /* Only take events inside the puzzle erea */
+ if( p_new->i_x < 0 || p_new->i_x >= (int)p_fmt->i_width ||
+ p_new->i_y < 0 || p_new->i_y >= (int)p_fmt->i_height )
+ return VLC_EGENERIC;
- if( !p_sys->b_blackslot )
- return true;
+ if (! p_sys->b_init || p_sys->b_change_param) {
+ *p_mouse = *p_new;
+ return VLC_SUCCESS;
+ }
- int d = 0;
- for( int i = 0; i < i_count; i++ )
- {
- if( p_sys->pi_order[i] == i_count - 1 )
+ p_sys->i_mouse_x = p_new->i_x;
+ p_sys->i_mouse_y = p_new->i_y;
+
+ /* If the puzzle is finished, shuffle it if needed */
+ if( p_sys->b_finished ) {
+ p_sys->b_mouse_drag = false;
+ p_sys->b_mouse_mvt = false;
+ if( vlc_mouse_HasPressed( p_old, p_new, MOUSE_BUTTON_LEFT ) &&
+ p_new->i_x < SHUFFLE_WIDTH && p_new->i_y < SHUFFLE_HEIGHT )
{
- d += i / p_sys->i_cols + 1;
- continue;
+ p_sys->b_shuffleRqst = true;
+ return VLC_EGENERIC;
}
- for( int j = i+1; j < i_count; j++ )
+ else
{
- if( p_sys->pi_order[j] == i_count - 1 )
- continue;
- if( p_sys->pi_order[i] > p_sys->pi_order[j] )
- d++;
+ /* otherwise we can forward the mouse */
+ *p_mouse = *p_new;
+ return VLC_SUCCESS;
}
}
- return (d%2) == 0;
-}
-static void Shuffle( filter_sys_t *p_sys )
-{
- const unsigned i_count = p_sys->i_cols * p_sys->i_rows;
+ if ( !p_sys->s_current_param.b_advanced ) {
+ const bool b_clicked = vlc_mouse_HasPressed( p_old, p_new, MOUSE_BUTTON_LEFT );
- free( p_sys->pi_order );
+ if( b_clicked )
+ {
+ /* */
+ const int32_t i_border_size_x = p_fmt->i_width * p_sys->s_current_param.i_border / 100 / 2;
+ const int32_t i_border_size_y = p_fmt->i_height * p_sys->s_current_param.i_border / 100 / 2;
+ const int32_t i_pos_x = (p_new->i_x - i_border_size_x) * p_sys->s_allocated.i_cols / (p_fmt->i_width - 2*i_border_size_x);
+ const int32_t i_pos_y = (p_new->i_y - i_border_size_y) * p_sys->s_allocated.i_rows / (p_fmt->i_height - 2*i_border_size_y);
- p_sys->pi_order = calloc( i_count, sizeof(*p_sys->pi_order) );
- do
+ const int32_t i_pos = i_pos_y * p_sys->s_allocated.i_cols + i_pos_x;
+ p_sys->i_mouse_drag_pce = i_pos;
+
+ // do not take into account if border clicked
+ if ((p_new->i_x <= i_border_size_x) || (p_new->i_y <= i_border_size_y) || (p_new->i_x >= (int) p_fmt->i_width - i_border_size_x) || (p_new->i_y >= (int) p_fmt->i_height - i_border_size_y ) )
+ {
+ //RAS (border clicked)
+ }
+ else if( p_sys->i_selected == NO_PCE )
+ p_sys->i_selected = i_pos;
+ else if( p_sys->i_selected == i_pos && !p_sys->s_current_param.b_blackslot )
+ p_sys->i_selected = -1;
+ else if( ( p_sys->i_selected == i_pos + 1 && p_sys->i_selected%p_sys->s_allocated.i_cols != 0 )
+ || ( p_sys->i_selected == i_pos - 1 && i_pos % p_sys->s_allocated.i_cols != 0 )
+ || p_sys->i_selected == i_pos + p_sys->s_allocated.i_cols
+ || p_sys->i_selected == i_pos - p_sys->s_allocated.i_cols
+ || !p_sys->s_current_param.b_near )
+
+ {
+ /* Swap two pieces */
+ int32_t a = p_sys->pi_order[ p_sys->i_selected ];
+ p_sys->pi_order[ p_sys->i_selected ] = p_sys->pi_order[ i_pos ];
+ p_sys->pi_order[ i_pos ] = a;
+
+ // regen piece location from updated pi_order
+ if ( p_sys->ps_pieces != NULL && p_sys->pi_order != NULL )
+ {
+ int32_t i = 0;
+ for (int32_t row = 0; row < p_sys->s_allocated.i_rows; row++) {
+ for (int32_t col = 0; col < p_sys->s_allocated.i_cols; col++) {
+ int32_t orow = p_sys->pi_order[i] / (p_sys->s_allocated.i_cols);
+ int32_t ocol = p_sys->pi_order[i] % (p_sys->s_allocated.i_cols);
+
+ p_sys->ps_pieces[i].i_original_row = orow;
+ p_sys->ps_pieces[i].i_original_col = ocol;
+ p_sys->ps_pieces[i].i_top_shape = 0;
+ p_sys->ps_pieces[i].i_btm_shape = 0;
+ p_sys->ps_pieces[i].i_right_shape = 0;
+ p_sys->ps_pieces[i].i_left_shape = 0;
+ p_sys->ps_pieces[i].i_actual_angle = 0;
+ p_sys->ps_pieces[i].i_actual_mirror = +1;
+ p_sys->ps_pieces[i].b_overlap = false;
+ p_sys->ps_pieces[i].b_finished = false;
+ p_sys->ps_pieces[i].i_group_ID = i;
+
+ for (uint8_t i_plane = 0; i_plane < p_sys->s_allocated.i_planes; i_plane++) {
+ p_sys->ps_pieces[i].ps_piece_in_plane[i_plane].i_size_x = p_sys->ps_puzzle_array[row][col][i_plane].i_size_x;
+ p_sys->ps_pieces[i].ps_piece_in_plane[i_plane].i_size_y = p_sys->ps_puzzle_array[row][col][i_plane].i_size_y;
+ p_sys->ps_pieces[i].ps_piece_in_plane[i_plane].i_original_x = p_sys->ps_puzzle_array[orow][ocol][i_plane].i_x;
+ p_sys->ps_pieces[i].ps_piece_in_plane[i_plane].i_original_y = p_sys->ps_puzzle_array[orow][ocol][i_plane].i_y;
+ p_sys->ps_pieces[i].ps_piece_in_plane[i_plane].i_actual_x = p_sys->ps_puzzle_array[row][col][i_plane].i_x;
+ p_sys->ps_pieces[i].ps_piece_in_plane[i_plane].i_actual_y = p_sys->ps_puzzle_array[row][col][i_plane].i_y;
+ }
+ i++;
+ }
+ }
+ }
+
+ p_sys->i_selected = p_sys->s_current_param.b_blackslot ? i_pos : NO_PCE;
+ p_sys->b_finished = IsFinished( p_sys, p_sys->pi_order );
+ }
+ }
+ }
+ else //if (p_sys->s_current_param.b_advanced)
{
- for( unsigned i = 0; i < i_count; i++ )
- p_sys->pi_order[i] = -1;
+ if ((p_sys->ps_desk_planes == NULL) || (p_sys->ps_pict_planes == NULL) || (p_sys->ps_puzzle_array == NULL) || (p_sys->ps_pieces == NULL)) {
+ *p_mouse = *p_new;
+ return VLC_SUCCESS;
+ }
- for( unsigned c = 0; c < i_count; )
+ if( vlc_mouse_HasPressed( p_old, p_new, MOUSE_BUTTON_LEFT ) )
{
- unsigned i = ((unsigned)vlc_mrand48()) % i_count;
- if( p_sys->pi_order[i] == -1 )
- p_sys->pi_order[i] = c++;
+
+ vlc_mutex_lock( &p_sys->pce_lock );
+
+ if (p_sys->i_mouse_drag_pce != NO_PCE) {
+ piece_foreground( p_filter, p_sys->i_mouse_drag_pce);
+ p_sys->i_mouse_drag_pce = 0;
+
+ uint32_t i_group_ID = p_sys->ps_pieces[0].i_group_ID;
+ for (uint32_t i = 0; i < p_sys->s_allocated.i_pieces_nbr; i++) {
+ if ( i_group_ID == p_sys->ps_pieces[i].i_group_ID ) {
+ p_sys->ps_pieces[i].b_finished = false;
+ }
+ else {
+ break;
+ }
+ }
+
+ p_sys->b_mouse_drag = true;
+ p_sys->b_mouse_mvt = false;
+ }
+ else {
+ // player click an empty area then search a piece which is overlapping another one and place it here
+ p_sys->b_mouse_drag = false;
+ for (uint32_t i = 0; i < p_sys->s_allocated.i_pieces_nbr; i++)
+ if ( p_sys->ps_pieces[i].b_overlap ) {
+ move_group( p_filter, i, p_new->i_x - p_sys->ps_pieces[i].i_center_x, p_new->i_y - p_sys->ps_pieces[i].i_center_y );
+ p_sys->ps_pieces[i].b_overlap = false;
+ break;
+ }
+ p_sys->b_mouse_drag = false;
+ }
+
+ vlc_mutex_unlock( &p_sys->pce_lock );
+
}
- p_sys->b_finished = IsFinished( p_sys );
+ else if( vlc_mouse_HasReleased( p_old, p_new, MOUSE_BUTTON_LEFT ) )
+ {
+ if ( !p_sys->b_mouse_mvt && p_sys->b_mouse_drag ) {
+ // piece clicked without any mvt => rotate it or mirror
+ if ( p_sys->s_current_param.i_rotate != 0) {
+ vlc_mutex_lock( &p_sys->pce_lock );
- } while( p_sys->b_finished || !IsValid( p_sys ) );
+ uint32_t i_group_ID = p_sys->ps_pieces[0].i_group_ID;
- if( p_sys->b_blackslot )
- {
- for( unsigned i = 0; i < i_count; i++ )
+ for (uint32_t i = 0; i < p_sys->s_allocated.i_pieces_nbr; i++)
+ if ( i_group_ID == p_sys->ps_pieces[i].i_group_ID )
+ rotate_pce( p_filter, i, p_sys->i_mouse_action, p_sys->ps_pieces[0].i_center_x, p_sys->ps_pieces[0].i_center_y, p_sys->i_mouse_action != 4 ? true : false );
+
+ vlc_mutex_unlock( &p_sys->pce_lock );
+ }
+ }
+ p_sys->b_mouse_drag = false;
+ p_sys->b_mouse_mvt = false;
+ }
+ else // no action on left button
{
- if( p_sys->pi_order[i] == (int)i_count - 1 )
+ // check if the mouse is in the preview area
+ switch ( p_sys->i_preview_pos )
{
- p_sys->i_selected = i;
+ case 0:
+ if ( p_new->i_x < (int)p_fmt->i_width / 2 && p_new->i_y < (int)p_fmt->i_height / 2 )
+ p_sys->i_preview_pos++;
+ break;
+ case 1:
+ if ( p_new->i_x > (int)p_fmt->i_width / 2 && p_new->i_y < (int)p_fmt->i_height / 2 )
+ p_sys->i_preview_pos++;
break;
+ case 2:
+ if ( p_new->i_x > (int)p_fmt->i_width / 2 && p_new->i_y > (int)p_fmt->i_height / 2 )
+ p_sys->i_preview_pos++;
+ break;
+ case 3:
+ if ( p_new->i_x < (int)p_fmt->i_width / 2 && p_new->i_y > (int)p_fmt->i_height / 2 )
+ p_sys->i_preview_pos++;
+ break;
+ }
+ p_sys->i_preview_pos %= 4;
+
+ if ( !vlc_mouse_IsLeftPressed( p_new ) )
+ p_sys->b_mouse_drag = false;
+
+ int i_dx, i_dy;
+ vlc_mouse_GetMotion( &i_dx, &i_dy, p_old, p_new );
+ if ( i_dx != 0 || i_dy != 0 )
+ p_sys->b_mouse_mvt = true;
+
+ if (p_sys->b_mouse_drag) {
+ if ( ( p_new->i_x <= 0 ) || ( p_new->i_y <= 0 ) || ( p_new->i_x >= (int) p_fmt->i_width )
+ || ( p_new->i_y >= (int) p_fmt->i_height ) )
+ {
+ // if the mouse is outside the window, stop moving the piece/group
+ p_sys->b_mouse_drag = false;
+ p_sys->b_mouse_mvt = true;
+ }
+ else if ( i_dx != 0 || i_dy != 0 )
+ {
+ vlc_mutex_lock( &p_sys->pce_lock );
+
+ move_group( p_filter, p_sys->i_mouse_drag_pce, i_dx, i_dy);
+
+ vlc_mutex_unlock( &p_sys->pce_lock );
+ }
}
}
}
- else
- {
- p_sys->i_selected = -1;
+ return VLC_EGENERIC;
+}
+
+static int bake_puzzle( filter_t *p_filter, picture_t *p_pic_dst, picture_t *p_pic_in)
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+ int ret = 0;
+
+ free_ps_puzzle_array ( p_filter );
+ free_ps_pieces_shapes ( p_filter);
+ free_ps_pieces ( p_filter );
+
+ p_sys->s_allocated.i_rows = p_sys->s_current_param.i_rows;
+ p_sys->s_allocated.i_cols = p_sys->s_current_param.i_cols;
+ p_sys->s_allocated.i_planes = p_sys->s_current_param.i_planes;
+ p_sys->s_allocated.i_piece_types = ((p_sys->s_current_param.b_advanced)?PIECE_TYPE_NBR:0);
+ p_sys->s_allocated.i_pieces_nbr = p_sys->s_allocated.i_rows * p_sys->s_allocated.i_cols;
+ p_sys->s_allocated.b_preview = p_sys->s_current_param.b_preview;
+ p_sys->s_allocated.i_preview_size = p_sys->s_current_param.i_preview_size;
+ p_sys->s_allocated.i_border = p_sys->s_current_param.i_border;
+ p_sys->s_allocated.b_blackslot = p_sys->s_current_param.b_blackslot;
+ p_sys->s_allocated.b_near = p_sys->s_current_param.b_near;
+ p_sys->s_allocated.i_shape_size = p_sys->s_current_param.i_shape_size;
+ p_sys->s_allocated.b_advanced = p_sys->s_current_param.b_advanced;
+ p_sys->s_allocated.i_auto_shuffle_speed = p_sys->s_current_param.i_auto_shuffle_speed;
+ p_sys->s_allocated.i_auto_solve_speed = p_sys->s_current_param.i_auto_solve_speed;
+ p_sys->s_allocated.i_rotate = p_sys->s_current_param.i_rotate;
+
+ ret = bake_puzzle_array ( p_filter, p_pic_dst, p_pic_in );
+ if (ret != VLC_SUCCESS)
+ return ret;
+
+ if (p_sys->s_current_param.b_advanced && p_sys->s_allocated.i_shape_size != 0) {
+ ret = bake_pieces_shapes ( p_filter );
+ if (ret != VLC_SUCCESS)
+ return ret;
+ }
+
+ ret = bake_piece ( p_filter );
+ if (ret != VLC_SUCCESS)
+ return ret;
+
+ if ((p_sys->pi_order != NULL) && (p_sys->ps_desk_planes != NULL) && (p_sys->ps_pict_planes != NULL) && (p_sys->ps_puzzle_array != NULL) && (p_sys->ps_pieces != NULL))
+ p_sys->b_init = true;
+
+ if ((p_sys->ps_pieces_shapes == NULL) && (p_sys->s_current_param.b_advanced) && (p_sys->s_current_param.i_shape_size != 0))
+ p_sys->b_init = false;
+
+ return VLC_SUCCESS;
+}
+
+static int bake_puzzle_array( filter_t *p_filter, picture_t *p_pic_dst, picture_t *p_pic_in)
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ free_ps_puzzle_array(p_filter);
+
+ p_sys->ps_puzzle_array = malloc( sizeof( puzzle_array_t** ) * (p_sys->s_allocated.i_rows + 1));
+ if( !p_sys->ps_puzzle_array )
+ return VLC_ENOMEM;
+
+ for (int32_t r=0; r < p_sys->s_allocated.i_rows + 1; r++) {
+ p_sys->ps_puzzle_array[r] = malloc( sizeof( puzzle_array_t* ) * (p_sys->s_allocated.i_cols + 1));
+ if( !p_sys->ps_puzzle_array[r] )
+ return VLC_ENOMEM;
+ for (int32_t c=0; c < p_sys->s_allocated.i_cols + 1; c++) {
+ p_sys->ps_puzzle_array[r][c] = malloc( sizeof( puzzle_array_t ) * p_sys->s_allocated.i_planes);
+ if( !p_sys->ps_puzzle_array[r][c] )
+ return VLC_ENOMEM;
+ }
+ }
+
+ p_sys->ps_desk_planes = malloc( sizeof( puzzle_plane_t ) * p_sys->s_allocated.i_planes);
+ if( !p_sys->ps_desk_planes )
+ return VLC_ENOMEM;
+ p_sys->ps_pict_planes = malloc( sizeof( puzzle_plane_t ) * p_sys->s_allocated.i_planes);
+ if( !p_sys->ps_pict_planes )
+ return VLC_ENOMEM;
+
+ for (uint8_t i_plane = 0; i_plane < p_sys->s_allocated.i_planes; i_plane++) {
+ p_sys->ps_desk_planes[i_plane].i_lines = p_pic_dst->p[i_plane].i_lines;
+ p_sys->ps_desk_planes[i_plane].i_pitch = p_pic_dst->p[i_plane].i_pitch;
+ p_sys->ps_desk_planes[i_plane].i_visible_lines = p_pic_dst->p[i_plane].i_visible_lines;
+ p_sys->ps_desk_planes[i_plane].i_visible_pitch = p_pic_dst->p[i_plane].i_visible_pitch;
+
+ p_sys->ps_desk_planes[i_plane].i_preview_size_x = p_pic_dst->p[i_plane].i_visible_pitch * p_sys->s_current_param.i_preview_size / 100;
+ p_sys->ps_desk_planes[i_plane].i_preview_size_y = p_pic_dst->p[i_plane].i_visible_lines * p_sys->s_current_param.i_preview_size / 100;
+
+ p_sys->ps_desk_planes[i_plane].i_border_size_x = p_pic_dst->p[i_plane].i_visible_pitch * p_sys->s_current_param.i_border / 2 / 100;
+ p_sys->ps_desk_planes[i_plane].i_border_size_y = p_pic_dst->p[i_plane].i_visible_pitch * p_sys->s_current_param.i_border / 2 / 100;
+
+ p_sys->ps_desk_planes[i_plane].i_pieces_max_x = (( p_pic_dst->p[i_plane].i_visible_pitch
+ - 2 * p_sys->ps_desk_planes[i_plane].i_border_size_x ) + p_sys->s_allocated.i_cols - 1 ) / p_sys->s_allocated.i_cols;
+ p_sys->ps_desk_planes[i_plane].i_pieces_max_y = (( p_pic_dst->p[i_plane].i_visible_lines
+ - 2 * p_sys->ps_desk_planes[i_plane].i_border_size_y ) + p_sys->s_allocated.i_rows - 1 ) / p_sys->s_allocated.i_rows;
+
+ p_sys->ps_pict_planes[i_plane].i_lines = p_pic_in->p[i_plane].i_lines;
+ p_sys->ps_pict_planes[i_plane].i_pitch = p_pic_in->p[i_plane].i_pitch;
+ p_sys->ps_pict_planes[i_plane].i_visible_lines = p_pic_in->p[i_plane].i_visible_lines;
+ p_sys->ps_pict_planes[i_plane].i_visible_pitch = p_pic_in->p[i_plane].i_visible_pitch;
+
+ p_sys->ps_pict_planes[i_plane].i_preview_size_x = p_pic_in->p[i_plane].i_visible_pitch * p_sys->s_current_param.i_preview_size / 100;
+ p_sys->ps_pict_planes[i_plane].i_preview_size_y = p_pic_in->p[i_plane].i_visible_lines * p_sys->s_current_param.i_preview_size / 100;
+
+ p_sys->ps_pict_planes[i_plane].i_border_size_x = p_pic_in->p[i_plane].i_visible_pitch * p_sys->s_current_param.i_border / 2 / 100;
+ p_sys->ps_pict_planes[i_plane].i_border_size_y = p_pic_in->p[i_plane].i_visible_pitch * p_sys->s_current_param.i_border / 2 / 100;
+
+ p_sys->ps_pict_planes[i_plane].i_pieces_max_x = (( p_pic_in->p[i_plane].i_visible_pitch
+ - 2 * p_sys->ps_pict_planes[i_plane].i_border_size_x ) + p_sys->s_allocated.i_cols - 1 ) / p_sys->s_allocated.i_cols;
+ p_sys->ps_pict_planes[i_plane].i_pieces_max_y = (( p_pic_in->p[i_plane].i_visible_lines
+ - 2 * p_sys->ps_pict_planes[i_plane].i_border_size_y ) + p_sys->s_allocated.i_rows - 1 ) / p_sys->s_allocated.i_rows;
+
+ for (int32_t r = 0; r < p_sys->s_allocated.i_rows; r++)
+ for (int32_t c = 0; c < p_sys->s_allocated.i_cols; c++) {
+ if ( r == 0 )
+ p_sys->ps_puzzle_array[r][c][i_plane].i_y = p_sys->ps_pict_planes[i_plane].i_border_size_y;
+ if ( c == 0 )
+ p_sys->ps_puzzle_array[r][c][i_plane].i_x = p_sys->ps_pict_planes[i_plane].i_border_size_x;
+ p_sys->ps_puzzle_array[r][c][i_plane].i_size_x =
+ (p_pic_dst->p[i_plane].i_visible_pitch - p_sys->ps_pict_planes[i_plane].i_border_size_x
+ - p_sys->ps_puzzle_array[r][c][i_plane].i_x) / ( p_sys->s_allocated.i_cols - c );
+ p_sys->ps_puzzle_array[r][c][i_plane].i_size_y =
+ (p_pic_dst->p[i_plane].i_visible_lines - p_sys->ps_pict_planes[i_plane].i_border_size_y
+ - p_sys->ps_puzzle_array[r][c][i_plane].i_y) / ( p_sys->s_allocated.i_rows - r );
+ p_sys->ps_puzzle_array[r][c + 1][i_plane].i_x =
+ p_sys->ps_puzzle_array[r][c][i_plane].i_x + p_sys->ps_puzzle_array[r][c][i_plane].i_size_x;
+ p_sys->ps_puzzle_array[r + 1][c][i_plane].i_y =
+ p_sys->ps_puzzle_array[r][c][i_plane].i_y + p_sys->ps_puzzle_array[r][c][i_plane].i_size_y;
+ }
+ }
+
+ p_sys->i_magnet_accuracy = ( p_sys->s_current_param.i_pict_width / 50) + 3;
+
+ return VLC_SUCCESS;
+}
+
+static void free_ps_puzzle_array( filter_t *p_filter)
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ if (p_sys->ps_puzzle_array != NULL) {
+ for (int32_t r=0; r < p_sys->s_allocated.i_rows + 1; r++) {
+ for (int32_t c=0; c < p_sys->s_allocated.i_cols + 1; c++)
+ free( p_sys->ps_puzzle_array[r][c] );
+ free( p_sys->ps_puzzle_array[r] );
+ }
+ free( p_sys->ps_puzzle_array );
+ }
+ p_sys->ps_puzzle_array = NULL;
+
+ free ( p_sys->ps_desk_planes );
+ p_sys->ps_desk_planes = NULL;
+
+ free ( p_sys->ps_pict_planes );
+ p_sys->ps_pict_planes = NULL;
+
+ return;
+}
+
+static int bake_piece( filter_t *p_filter)
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+ free_ps_pieces(p_filter);
+
+ p_sys->s_allocated.i_pieces_nbr = p_sys->s_allocated.i_rows * p_sys->s_allocated.i_cols;
+ p_sys->ps_pieces = malloc( sizeof( piece_t) * p_sys->s_allocated.i_pieces_nbr );
+ if( !p_sys->ps_pieces )
+ return VLC_ENOMEM;
+ for (uint32_t p = 0; p < p_sys->s_allocated.i_pieces_nbr; p++) {
+ p_sys->ps_pieces[p].ps_piece_in_plane = malloc( sizeof( piece_in_plane_t) * p_sys->s_allocated.i_planes );
+ if( !p_sys->ps_pieces[p].ps_piece_in_plane )
+ return VLC_ENOMEM;
+ }
+
+ p_sys->ps_pieces_tmp = malloc( sizeof( piece_t) * p_sys->s_allocated.i_pieces_nbr );
+ p_sys->pi_group_qty = malloc( sizeof( int32_t ) * (p_sys->s_allocated.i_pieces_nbr));
+
+ Shuffle( p_filter );
+
+ int32_t i = 0;
+ for (int32_t row = 0; row < p_sys->s_allocated.i_rows; row++) {
+ for (int32_t col = 0; col < p_sys->s_allocated.i_cols; col++) {
+ int32_t orow = row;
+ int32_t ocol = col;
+
+ if (p_sys->pi_order != NULL) {
+ orow = p_sys->pi_order[i] / (p_sys->s_allocated.i_cols);
+ ocol = p_sys->pi_order[i] % (p_sys->s_allocated.i_cols);
+ }
+
+ p_sys->ps_pieces[i].i_original_row = orow;
+ p_sys->ps_pieces[i].i_original_col = ocol;
+
+ p_sys->ps_pieces[i].i_left_shape = 0;
+ p_sys->ps_pieces[i].i_top_shape = 2;
+ p_sys->ps_pieces[i].i_btm_shape = 4;
+ p_sys->ps_pieces[i].i_right_shape = 6;
+
+ if (p_sys->s_allocated.i_shape_size > 0) {
+
+ if (orow < p_sys->s_allocated.i_rows - 1)
+ p_sys->ps_pieces[i].i_btm_shape = 4 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY ) ) + (vlc_mrand48() & 0x01);
+
+ if (ocol < p_sys->s_allocated.i_cols - 1)
+ p_sys->ps_pieces[i].i_right_shape = 6 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY ) ) + (vlc_mrand48() & 0x01);
+ }
+
+ p_sys->ps_pieces[i].i_actual_angle = 0;
+ p_sys->ps_pieces[i].b_overlap = false;
+ p_sys->ps_pieces[i].i_actual_mirror = +1;
+ p_sys->ps_pieces[i].b_finished = ((ocol == col) && (orow == row));
+ p_sys->ps_pieces[i].i_group_ID = i;
+
+ int32_t i_rand_x = 0;
+ int32_t i_rand_y = 0;
+ if (p_sys->s_current_param.b_advanced) {
+ i_rand_x = (( (unsigned) vlc_mrand48()) % ( p_sys->ps_desk_planes[0].i_pieces_max_x + 1 ) ) - (int32_t) p_sys->ps_desk_planes[0].i_pieces_max_x / 2;
+ i_rand_y = (( (unsigned) vlc_mrand48()) % ( p_sys->ps_desk_planes[0].i_pieces_max_y + 1 ) ) - (int32_t) p_sys->ps_desk_planes[0].i_pieces_max_y / 2;
+ }
+
+ if (p_sys->ps_puzzle_array != NULL) {
+ for (uint8_t i_plane = 0; i_plane < p_sys->s_allocated.i_planes; i_plane++) {
+
+ p_sys->ps_pieces[i].ps_piece_in_plane[i_plane].i_size_x = p_sys->ps_puzzle_array[row][col][i_plane].i_size_x; // here we use col instead of ocol
+ p_sys->ps_pieces[i].ps_piece_in_plane[i_plane].i_size_y = p_sys->ps_puzzle_array[row][col][i_plane].i_size_y;
+ p_sys->ps_pieces[i].ps_piece_in_plane[i_plane].i_original_x = p_sys->ps_puzzle_array[orow][ocol][i_plane].i_x;
+ p_sys->ps_pieces[i].ps_piece_in_plane[i_plane].i_original_y = p_sys->ps_puzzle_array[orow][ocol][i_plane].i_y;
+ p_sys->ps_pieces[i].ps_piece_in_plane[i_plane].i_actual_x = p_sys->ps_puzzle_array[row][col][i_plane].i_x + i_rand_x *
+ p_sys->ps_desk_planes[i_plane].i_visible_pitch / p_sys->ps_desk_planes[0].i_visible_pitch;
+ p_sys->ps_pieces[i].ps_piece_in_plane[i_plane].i_actual_y = p_sys->ps_puzzle_array[row][col][i_plane].i_y + i_rand_y *
+ p_sys->ps_desk_planes[i_plane].i_visible_lines / p_sys->ps_desk_planes[0].i_visible_lines;
+
+ if (i_plane == 0) {
+
+ p_sys->ps_pieces[i].i_OLx = p_sys->ps_pieces[i].ps_piece_in_plane[0].i_original_x;
+ p_sys->ps_pieces[i].i_OTy = p_sys->ps_pieces[i].ps_piece_in_plane[0].i_original_y;
+ p_sys->ps_pieces[i].i_ORx = p_sys->ps_pieces[i].ps_piece_in_plane[0].i_original_x + p_sys->ps_pieces[i].ps_piece_in_plane[0].i_size_x - 1;
+ p_sys->ps_pieces[i].i_OBy = p_sys->ps_pieces[i].ps_piece_in_plane[0].i_original_y + p_sys->ps_pieces[i].ps_piece_in_plane[0].i_size_y - 1;
+
+ calculate_corners( p_filter, i );
+ }
+ }
+ }
+ i++;
+ }
+ }
+
+ i = 0;
+ for (int32_t row = 0; row < p_sys->s_allocated.i_rows; row++) {
+ for (int32_t col = 0; col < p_sys->s_allocated.i_cols; col++) {
+ int32_t orow = row;
+ int32_t ocol = col;
+
+ if (p_sys->pi_order != NULL) {
+ orow = p_sys->pi_order[i] / (p_sys->s_allocated.i_cols);
+ ocol = p_sys->pi_order[i] % (p_sys->s_allocated.i_cols);
+ }
+
+ if (p_sys->s_allocated.i_shape_size > 0) {
+ if (ocol > 0)
+ for (uint16_t i_pce=0; i_pce < p_sys->s_allocated.i_pieces_nbr; i_pce++)
+ if ((p_sys->ps_pieces[i_pce].i_original_row == orow) && (p_sys->ps_pieces[i_pce].i_original_col == ocol-1)) {
+ p_sys->ps_pieces[i].i_left_shape = (p_sys->ps_pieces[i_pce].i_right_shape - 6 ) ^ 0x01;
+ break;
+ }
+
+ if (orow > 0)
+ for (uint16_t i_pce=0; i_pce < p_sys->s_allocated.i_pieces_nbr; i_pce++)
+ if ((p_sys->ps_pieces[i_pce].i_original_row == orow - 1) && (p_sys->ps_pieces[i_pce].i_original_col == ocol)) {
+ p_sys->ps_pieces[i].i_top_shape = (p_sys->ps_pieces[i_pce].i_btm_shape - 2 ) ^ 0x01;
+ break;
+ }
+ }
+ i++;
+ }
+ }
+
+ for (uint32_t i = 0; i < p_sys->s_allocated.i_pieces_nbr; i++)
+ {
+ p_sys->ps_pieces[i].i_actual_angle = 0;
+ p_sys->ps_pieces[i].i_actual_mirror = +1;
+
+ switch ( p_sys->s_current_param.i_rotate )
+ {
+ case 1:
+ rotate_pce( p_filter, i, (( (unsigned) vlc_mrand48()) % ( 2 ) ) * 2, p_sys->ps_pieces[i].i_center_x, p_sys->ps_pieces[i].i_center_y, false );
+ break;
+ case 2:
+ rotate_pce( p_filter, i, (( (unsigned) vlc_mrand48()) % ( 4 ) ), p_sys->ps_pieces[i].i_center_x, p_sys->ps_pieces[i].i_center_y, false );
+ break;
+ case 3:
+ rotate_pce( p_filter, i, (( (unsigned) vlc_mrand48()) % ( 8 ) ), p_sys->ps_pieces[i].i_center_x, p_sys->ps_pieces[i].i_center_y, false );
+ break;
+ }
+
+ }
+
+ return VLC_SUCCESS;
+}
+
+static void free_ps_pieces( filter_t *p_filter)
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ if (p_sys->ps_pieces != NULL) {
+ for (uint32_t i_pce = 0; i_pce < p_sys->s_allocated.i_pieces_nbr; i_pce++)
+ free( p_sys->ps_pieces[i_pce].ps_piece_in_plane );
+ free( p_sys->ps_pieces );
+ }
+ p_sys->ps_pieces = NULL;
+
+ free( p_sys->pi_order );
+ p_sys->pi_order = NULL;
+
+ free( p_sys->ps_pieces_tmp );
+ p_sys->ps_pieces_tmp = NULL;
+
+ free( p_sys->pi_group_qty );
+ p_sys->pi_group_qty = NULL;
+
+ return;
+}
+
+static int bake_pieces_shapes( filter_t *p_filter)
+{
+// note:
+// piece_shape_t **ps_pieces_shapes; // array [each piece type (PCE_TYPE_NBR * 4 ( * negative ): top, left,right,btm)][each plane] of piece definition
+// 0 => left border
+// 1 => left border (negative, never used)
+// 2 => top border
+// .....
+// 8 => bezier left
+// 9 => bezier left negative
+// 10 => bezier top
+// 11 => bezier top negative
+// 12 => bezier btm
+// 13 => bezier btm negative
+// 14 => bezier right
+// 15 => bezier right negative
+// .....
+
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ free_ps_pieces_shapes(p_filter);
+ p_sys->ps_pieces_shapes = malloc( sizeof( piece_shape_t *) * PIECE_TYPE_NBR );
+ if( !p_sys->ps_pieces_shapes )
+ return VLC_ENOMEM;
+
+ for (int32_t i_piece = 0; i_piece < PIECE_TYPE_NBR; i_piece++) {
+ p_sys->ps_pieces_shapes[i_piece] = malloc( sizeof( piece_shape_t) * p_sys->s_allocated.i_planes );
+ if( !p_sys->ps_pieces_shapes[i_piece] )
+ return VLC_ENOMEM;
+ for (uint8_t i_plane = 0; i_plane < p_filter->p_sys->s_allocated.i_planes; i_plane++) {
+ p_sys->ps_pieces_shapes[i_piece][i_plane].i_row_nbr = 0;
+ p_sys->ps_pieces_shapes[i_piece][i_plane].ps_piece_shape_row = NULL;
+ }
+ }
+
+ int32_t i_currect_shape = 0;
+
+ for (uint8_t i_plane = 0; i_plane < p_filter->p_sys->s_allocated.i_planes; i_plane++) {
+ generate_sectLeftB( p_filter, &p_sys->ps_pieces_shapes[i_currect_shape+0][i_plane], i_plane);
+ generate_sectLeftB( p_filter, &p_sys->ps_pieces_shapes[i_currect_shape+1][i_plane], i_plane);
+ generate_sectTopB( p_filter, &p_sys->ps_pieces_shapes[i_currect_shape+2][i_plane], i_plane);
+ generate_sectTopB( p_filter, &p_sys->ps_pieces_shapes[i_currect_shape+3][i_plane], i_plane);
+ generate_sectBtmB( p_filter, &p_sys->ps_pieces_shapes[i_currect_shape+4][i_plane], i_plane);
+ generate_sectBtmB( p_filter, &p_sys->ps_pieces_shapes[i_currect_shape+5][i_plane], i_plane);
+ generate_sectRightB( p_filter, &p_sys->ps_pieces_shapes[i_currect_shape+6][i_plane], i_plane);
+ generate_sectRightB( p_filter, &p_sys->ps_pieces_shapes[i_currect_shape+7][i_plane], i_plane);
+ }
+
+ i_currect_shape += 8;
+
+ int32_t i_size_x = p_sys->ps_desk_planes[0].i_pieces_max_x;
+ int32_t i_size_y = p_sys->ps_desk_planes[0].i_pieces_max_y;
+
+ for (int32_t i_shape = 0; i_shape<SHAPES_QTY; i_shape++) {
+
+ point_t *ps_scale_pts_H = scale_curve_H(i_size_x, i_size_y, 7, p_sys->ps_bezier_pts_H[i_shape], p_sys->s_allocated.i_shape_size);
+ point_t *ps_scale_pts_V = H_2_scale_curve_V(i_size_x, i_size_y, 7, p_sys->ps_bezier_pts_H[i_shape], p_sys->s_allocated.i_shape_size);
+ point_t *ps_neg_pts_H = curve_H_2_negative(7, ps_scale_pts_H);
+ point_t *ps_neg_pts_V = curve_V_2_negative(7, ps_scale_pts_V);
+
+ for (uint8_t i_plane = 0; i_plane < p_filter->p_sys->s_allocated.i_planes; i_plane++) {
+
+ generate_sectLeft( p_filter, &p_sys->ps_pieces_shapes[i_currect_shape][i_plane], 7, ps_scale_pts_V, i_plane);
+ generate_sectLeft( p_filter, &p_sys->ps_pieces_shapes[i_currect_shape+1][i_plane], 7, ps_neg_pts_V, i_plane);
+ generate_sectTop( p_filter, &p_sys->ps_pieces_shapes[i_currect_shape+2][i_plane], 7, ps_scale_pts_H, i_plane);
+ generate_sectTop( p_filter, &p_sys->ps_pieces_shapes[i_currect_shape+3][i_plane], 7, ps_neg_pts_H, i_plane);
+
+ 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);
+ 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);
+ 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);
+ 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);
+ }
+
+ free(ps_scale_pts_H);
+ free(ps_scale_pts_V);
+ free(ps_neg_pts_H);
+ free(ps_neg_pts_V);
+
+ i_currect_shape += 8;
+ }
+
+ p_sys->b_shape_init = true;
+
+ return VLC_SUCCESS;
+}
+
+static void free_ps_pieces_shapes( filter_t *p_filter)
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ if (p_sys->ps_pieces_shapes == NULL)
+ return;
+
+ for (int32_t p = 0; p < p_sys->s_allocated.i_piece_types; p++) {
+ for (uint8_t i_plane = 0; i_plane < p_sys->s_allocated.i_planes; i_plane++) {
+ for (int32_t r = 0; r < p_sys->ps_pieces_shapes[p][i_plane].i_row_nbr; r++)
+ free( p_sys->ps_pieces_shapes[p][i_plane].ps_piece_shape_row[r].ps_row_section );
+ free( p_sys->ps_pieces_shapes[p][i_plane].ps_piece_shape_row );
+ }
+ free( p_sys->ps_pieces_shapes[p] );
+ }
+ free( p_sys->ps_pieces_shapes );
+ p_sys->ps_pieces_shapes = NULL;
+}
+
+static bool IsValid( filter_sys_t *p_sys, int32_t *pi_pce_lst )
+{
+ const int32_t i_count = p_sys->s_allocated.i_pieces_nbr;
+
+ if( !p_sys->s_current_param.b_blackslot )
+ return true;
+
+ int32_t d = 0;
+ for( int32_t i = 0; i < i_count; i++ ) {
+ if( pi_pce_lst[i] == i_count - 1 ) {
+ d += i / p_sys->s_allocated.i_cols + 1;
+ continue;
+ }
+ for( int32_t j = i+1; j < i_count; j++ ) {
+ if( pi_pce_lst[j] == i_count - 1 )
+ continue;
+ if( pi_pce_lst[i] > pi_pce_lst[j] )
+ d++;
+ }
+ }
+ return (d%2) == 0;
+}
+
+static void Shuffle( filter_t *p_filter )
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ int32_t i_pieces_nbr = p_sys->s_allocated.i_pieces_nbr;
+
+ do
+ {
+ generate_rand_pce_list( p_filter, &p_sys->pi_order );
+ } while( IsFinished( p_sys, p_sys->pi_order ) || !IsValid( p_sys, p_sys->pi_order ) );
+
+
+ if( p_sys->s_current_param.b_blackslot ) {
+ for( int32_t i = 0; i < i_pieces_nbr; i++ )
+ if( p_sys->pi_order[i] == i_pieces_nbr - 1 ) {
+ p_sys->i_selected = i;
+ break;
+ }
+ }
+ else {
+ p_sys->i_selected = NO_PCE;
+ }
+
+ p_sys->b_shuffleRqst = false;
+ p_sys->b_finished = false;
+}
+
+static void generate_rand_pce_list( filter_t *p_filter, int32_t **pi_pce_lst )
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ int32_t i_pieces_nbr = p_sys->s_allocated.i_pieces_nbr;
+
+ if (pi_pce_lst != NULL )
+ free( *pi_pce_lst );
+ *pi_pce_lst = calloc( i_pieces_nbr, sizeof(**pi_pce_lst) );
+
+ for( int32_t i = 0; i < i_pieces_nbr; i++ )
+ (*pi_pce_lst)[i] = NO_PCE;
+
+ for( int32_t c = 0; c < i_pieces_nbr; ) {
+ int32_t i = ((unsigned)vlc_mrand48()) % i_pieces_nbr;
+ if( (*pi_pce_lst)[i] == NO_PCE )
+ (*pi_pce_lst)[i] = c++;
+ }
+}
+
+static bool IsFinished( filter_sys_t *p_sys, int32_t *pi_pce_lst )
+{
+ for( uint32_t i = 0; i < p_sys->s_allocated.i_pieces_nbr; i++ )
+ if( (int32_t)i != pi_pce_lst[i] )
+ return false;
+
+ return true;
+}
+
+static int find_piece( filter_t *p_filter, int32_t i_x, int32_t i_y, int32_t i_except) {
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ for (uint32_t i = 0; i < p_sys->s_allocated.i_pieces_nbr; i++) {
+ piece_t *ps_current_piece = &p_sys->ps_pieces[i];
+ if (( ps_current_piece->i_min_x <= i_x ) &&
+ ( ps_current_piece->i_max_x >= i_x ) &&
+ ( ps_current_piece->i_min_y <= i_y ) &&
+ ( ps_current_piece->i_max_y >= i_y ) &&
+ ( (int32_t)i != i_except ) )
+ {
+ return i;
+ }
+ }
+ return -1;
+}
+
+static void calculate_corners( filter_t *p_filter, int32_t i_piece )
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+ piece_t *ps_piece = &p_sys->ps_pieces[i_piece];
+
+ switch ( ps_piece->i_actual_angle)
+ {
+ case 0:
+ ps_piece->i_step_x_x = ps_piece->i_actual_mirror;
+ ps_piece->i_step_x_y = 0;
+ ps_piece->i_step_y_y = 1;
+ ps_piece->i_step_y_x = 0;
+ break;
+ case 1:
+ ps_piece->i_step_x_x = 0;
+ ps_piece->i_step_x_y = -ps_piece->i_actual_mirror; // x offset on original pict creates negative y offset on desk
+ ps_piece->i_step_y_y = 0;
+ ps_piece->i_step_y_x = 1;
+ break;
+ case 2:
+ ps_piece->i_step_x_x = -ps_piece->i_actual_mirror;
+ ps_piece->i_step_x_y = 0;
+ ps_piece->i_step_y_y = -1;
+ ps_piece->i_step_y_x = 0;
+ break;
+ case 3:
+ ps_piece->i_step_x_x = 0;
+ ps_piece->i_step_x_y = ps_piece->i_actual_mirror;
+ ps_piece->i_step_y_y = 0;
+ ps_piece->i_step_y_x = -1;
+ break;
+ }
+
+ //regen geometry
+ for (uint8_t i_plane = 1; i_plane < p_sys->s_allocated.i_planes; i_plane++) {
+ ps_piece->ps_piece_in_plane[i_plane].i_actual_x =
+ ps_piece->ps_piece_in_plane[0].i_actual_x * p_sys->ps_desk_planes[i_plane].i_visible_pitch / p_sys->ps_desk_planes[0].i_visible_pitch;
+ ps_piece->ps_piece_in_plane[i_plane].i_actual_y =
+ ps_piece->ps_piece_in_plane[0].i_actual_y * p_sys->ps_desk_planes[i_plane].i_visible_lines / p_sys->ps_desk_planes[0].i_visible_lines;
+ }
+
+ // regen location of grabed piece's corners
+ int32_t i_size_x = ps_piece->ps_piece_in_plane[0].i_size_x;
+ int32_t i_size_y = ps_piece->ps_piece_in_plane[0].i_size_y;
+
+ ps_piece->i_TLx = ps_piece->ps_piece_in_plane[0].i_actual_x;
+ ps_piece->i_TLy = ps_piece->ps_piece_in_plane[0].i_actual_y;
+ ps_piece->i_TRx = ps_piece->i_TLx + ( i_size_x - 1 ) * ps_piece->i_step_x_x;
+ ps_piece->i_TRy = ps_piece->i_TLy + ( i_size_x - 1 ) * ps_piece->i_step_x_y;
+ ps_piece->i_BRx = ps_piece->i_TLx + ( i_size_x - 1 ) * ps_piece->i_step_x_x + ( i_size_y - 1 ) * ps_piece->i_step_y_x;
+ ps_piece->i_BRy = ps_piece->i_TLy + ( i_size_x - 1 ) * ps_piece->i_step_x_y + ( i_size_y - 1 ) * ps_piece->i_step_y_y;
+ ps_piece->i_BLx = ps_piece->i_TLx + ( i_size_y - 1 ) * ps_piece->i_step_y_x;
+ ps_piece->i_BLy = ps_piece->i_TLy + ( i_size_y - 1 ) * ps_piece->i_step_y_y;
+
+ ps_piece->i_max_x = __MAX( __MAX( ps_piece->i_TLx, ps_piece->i_TRx ), __MAX( ps_piece->i_BLx, ps_piece->i_BRx ) );
+ ps_piece->i_min_x = __MIN( __MIN( ps_piece->i_TLx, ps_piece->i_TRx ), __MIN( ps_piece->i_BLx, ps_piece->i_BRx ) );
+ ps_piece->i_max_y = __MAX( __MAX( ps_piece->i_TLy, ps_piece->i_TRy ), __MAX( ps_piece->i_BLy, ps_piece->i_BRy ) );
+ ps_piece->i_min_y = __MIN( __MIN( ps_piece->i_TLy, ps_piece->i_TRy ), __MIN( ps_piece->i_BLy, ps_piece->i_BRy ) );
+
+ ps_piece->i_center_x = ( ps_piece->i_max_x + ps_piece->i_min_x ) / 2;
+ ps_piece->i_center_y = ( ps_piece->i_max_y + ps_piece->i_min_y ) / 2;
+
+ int32_t pce_overlap = find_piece( p_filter, ps_piece->i_center_x, ps_piece->i_center_y, i_piece);
+
+ if ( ( pce_overlap != NO_PCE ) && ( p_sys->pi_group_qty[ps_piece->i_group_ID] == 1 ) )
+ ps_piece->b_overlap = true;
+}
+
+static void piece_foreground( filter_t *p_filter, int32_t i_piece) {
+ filter_sys_t *p_sys = p_filter->p_sys;
+ piece_t *ps_pieces_tmp; // list [piece] of pieces data. Sort as per layers
+ uint32_t i_group_ID = p_sys->ps_pieces[i_piece].i_group_ID;
+
+ ps_pieces_tmp = malloc( sizeof( piece_t) * p_sys->s_allocated.i_pieces_nbr );
+
+ int32_t j=0;
+
+ memcpy( &ps_pieces_tmp[j], &p_sys->ps_pieces[i_piece], sizeof(piece_t) );
+ j++;
+
+ for (uint32_t i = 0; i < p_sys->s_allocated.i_pieces_nbr; i++) {
+ if ( ( p_sys->ps_pieces[i].i_group_ID == i_group_ID ) && ( (int32_t)i != i_piece ) ) {
+ memcpy( &ps_pieces_tmp[j], &p_sys->ps_pieces[i], sizeof(piece_t));
+ j++;
+ }
+ }
+ for (uint32_t i = 0; i < p_sys->s_allocated.i_pieces_nbr; i++) {
+ if ( p_sys->ps_pieces[i].i_group_ID != i_group_ID ) {
+ memcpy( &ps_pieces_tmp[j], &p_sys->ps_pieces[i], sizeof(piece_t));
+ j++;
+ }
+ }
+
+ free( p_filter->p_sys->ps_pieces );
+ p_filter->p_sys->ps_pieces = ps_pieces_tmp;
+
+}
+
+static void count_pce_group( filter_t *p_filter) { // count pce in each group
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ memset ( p_sys->pi_group_qty, 0, sizeof( int32_t ) * (p_sys->s_allocated.i_pieces_nbr) );
+ for (uint32_t i_pce = 0; i_pce < p_sys->s_allocated.i_pieces_nbr; i_pce++)
+ p_sys->pi_group_qty[p_sys->ps_pieces[i_pce].i_group_ID]++;
+}
+
+static void solve_pces_group( filter_t *p_filter) {
+ filter_sys_t *p_sys = p_filter->p_sys;
+ int32_t i_dx, i_dy;
+
+ p_sys->i_solve_grp_loop++;
+ p_sys->i_solve_grp_loop %= p_sys->s_allocated.i_pieces_nbr;
+
+ int32_t i_piece_A = p_sys->i_solve_grp_loop;
+ piece_t *ps_piece_A = &p_sys->ps_pieces[i_piece_A];
+
+ for (uint32_t i_piece_B = 0; i_piece_B < p_sys->s_allocated.i_pieces_nbr; i_piece_B++) {
+ piece_t *ps_piece_B = &p_sys->ps_pieces[i_piece_B];
+ if ( ps_piece_A->i_actual_angle == ps_piece_B->i_actual_angle && ps_piece_A->i_actual_mirror == ps_piece_B->i_actual_mirror ) {
+ if ( (ps_piece_B->i_group_ID != p_sys->ps_pieces[i_piece_A].i_group_ID ) ) {
+ if ( abs(ps_piece_A->i_OTy - ps_piece_B->i_OTy )<3) {
+ if (abs( ps_piece_A->i_ORx - ps_piece_B->i_OLx + 1 )<3) {
+ if ( ( abs( ps_piece_A->i_TRx - ps_piece_B->i_TLx + 1 ) < p_sys->i_magnet_accuracy ) && ( abs( ps_piece_A->i_TRy - ps_piece_B->i_TLy ) < p_sys->i_magnet_accuracy ) &&
+ ( abs( ps_piece_A->i_BRx - ps_piece_B->i_BLx + 1 ) < p_sys->i_magnet_accuracy ) && ( abs( ps_piece_A->i_BRy - ps_piece_B->i_BLy ) < p_sys->i_magnet_accuracy ) ) {
+
+ i_dx = ps_piece_A->i_TRx - ps_piece_B->i_TLx + ps_piece_A->i_step_x_x;
+ i_dy = ps_piece_A->i_TRy - ps_piece_B->i_TLy;
+
+ if (!ps_piece_B->b_finished)
+ move_group( p_filter, i_piece_B, i_dx, i_dy);
+ else
+ move_group( p_filter, i_piece_A, -i_dx, -i_dy);
+
+ uint32_t i_group_ID = ps_piece_B->i_group_ID;
+ for (uint32_t i_for = 0; i_for < p_sys->s_allocated.i_pieces_nbr; i_for++)
+ if ( p_sys->ps_pieces[i_for].i_group_ID == i_group_ID)
+ p_sys->ps_pieces[i_for].i_group_ID = p_sys->ps_pieces[i_piece_A].i_group_ID;
+ }
+ }
+ }
+ else if ( abs(ps_piece_A->i_OLx - ps_piece_B->i_OLx )<3) {
+ if ( abs(ps_piece_A->i_OBy - ps_piece_B->i_OTy + 1 )<3) {
+ if ( ( abs( ps_piece_B->i_TLx - ps_piece_A->i_BLx ) < p_sys->i_magnet_accuracy ) && ( abs( ps_piece_B->i_TLy - 1 - ps_piece_A->i_BLy ) < p_sys->i_magnet_accuracy ) &&
+ ( abs( ps_piece_B->i_TRx - ps_piece_A->i_BRx ) < p_sys->i_magnet_accuracy ) && ( abs( ps_piece_B->i_TRy - 1 - ps_piece_A->i_BRy ) < p_sys->i_magnet_accuracy ) ) {
+
+ i_dx = ps_piece_A->i_BLx - ps_piece_B->i_TLx;
+ i_dy = ps_piece_A->i_BLy - ps_piece_B->i_TLy + ps_piece_A->i_step_y_y;
+
+ if (!ps_piece_B->b_finished)
+ move_group( p_filter, i_piece_B, i_dx, i_dy);
+ else
+ move_group( p_filter, i_piece_A, -i_dx, -i_dy);
+
+ uint32_t i_group_ID = ps_piece_B->i_group_ID;
+ for (uint32_t i_for = 0; i_for < p_sys->s_allocated.i_pieces_nbr; i_for++)
+ if ( p_sys->ps_pieces[i_for].i_group_ID == i_group_ID)
+ p_sys->ps_pieces[i_for].i_group_ID = p_sys->ps_pieces[i_piece_A].i_group_ID;
+ }
+ }
+ }
+ }
+
+ if ( abs( ps_piece_A->i_OTy - ps_piece_B->i_OTy )<3 ) {
+ if ( abs( ps_piece_A->i_ORx - ps_piece_B->i_OLx + 1 )<3 )
+ if ( ( abs( ps_piece_A->i_TRx - ps_piece_B->i_TLx + 1 ) < p_sys->i_magnet_accuracy ) && ( abs( ps_piece_A->i_TRy - ps_piece_B->i_TLy ) < p_sys->i_magnet_accuracy ) &&
+ ( abs( ps_piece_A->i_BRx - ps_piece_B->i_BLx + 1 ) < p_sys->i_magnet_accuracy ) && ( abs( ps_piece_A->i_BRy - ps_piece_B->i_BLy ) < p_sys->i_magnet_accuracy ) ) {
+
+ ps_piece_B->i_left_shape = 0;
+ ps_piece_A->i_right_shape = 6;
+ }
+ }
+ else if ( abs( ps_piece_A->i_OLx - ps_piece_B->i_OLx )<3 ) {
+ if ( abs( ps_piece_A->i_OBy - ps_piece_B->i_OTy + 1 )<3 )
+ if ( ( abs( ps_piece_B->i_TLx - ps_piece_A->i_BLx ) < p_sys->i_magnet_accuracy ) && ( abs( ps_piece_B->i_TLy - 1 - ps_piece_A->i_BLy ) < p_sys->i_magnet_accuracy ) &&
+ ( abs( ps_piece_B->i_TRx - ps_piece_A->i_BRx ) < p_sys->i_magnet_accuracy ) && ( abs( ps_piece_B->i_TRy - 1 - ps_piece_A->i_BRy ) < p_sys->i_magnet_accuracy ) ) {
+
+ ps_piece_B->i_top_shape = 2;
+ ps_piece_A->i_btm_shape = 4;
+ }
+ }
+ }
+ }
+}
+
+static void solve_pces_accuracy( filter_t *p_filter) {
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ p_sys->i_solve_acc_loop++;
+ if (p_sys->i_solve_acc_loop >= p_sys->s_allocated.i_pieces_nbr) {
+ p_sys->i_done_count = p_sys->i_tmp_done_count;
+ p_sys->i_tmp_done_count = 0;
+ p_sys->i_solve_acc_loop = 0;
+ p_sys->b_finished = (p_sys->i_done_count == p_sys->s_allocated.i_pieces_nbr);
+ }
+
+ piece_t *ps_piece = &p_sys->ps_pieces[p_sys->i_solve_acc_loop];
+
+ ps_piece->b_finished = false;
+ if ( ps_piece->i_actual_mirror == 1 )
+ if ( abs( ps_piece->i_TRx - ps_piece->i_ORx ) < p_sys->i_magnet_accuracy )
+ if ( abs( ps_piece->i_TRy - ps_piece->i_OTy ) < p_sys->i_magnet_accuracy )
+ if ( abs( ps_piece->i_TLx - ps_piece->i_OLx ) < p_sys->i_magnet_accuracy )
+ if ( abs( ps_piece->i_TLy - ps_piece->i_OTy ) < p_sys->i_magnet_accuracy ) {
+ uint32_t i_group_ID = ps_piece->i_group_ID;
+ p_sys->i_tmp_done_count++;
+
+ for ( uint32_t i = 0; i < p_sys->s_allocated.i_pieces_nbr; i++) {
+ ps_piece = &p_sys->ps_pieces[i];
+ if ( ( ps_piece->i_group_ID == i_group_ID ) && ( !ps_piece->b_finished ) ) {
+ ps_piece->ps_piece_in_plane[0].i_actual_x = ps_piece->i_OLx;
+ ps_piece->ps_piece_in_plane[0].i_actual_y = ps_piece->i_OTy;
+ ps_piece->i_actual_mirror = +1;
+ calculate_corners( p_filter, i );
+ ps_piece->b_finished = true;
+ }
+ }
+ }
+}
+
+static void sort_layers( filter_t *p_filter)
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ // sort
+ int32_t i_idx = 0;
+ for (uint32_t i_qty = 1; i_qty <= p_sys->s_current_param.i_pieces_nbr; i_qty++) {
+ // pieces at the wrong place are in foreground
+ for (uint32_t i_pce_loop = 0; i_pce_loop < p_sys->s_current_param.i_pieces_nbr; i_pce_loop++) {
+ uint32_t i_grp = p_sys->ps_pieces[i_pce_loop].i_group_ID;
+ if ( p_sys->pi_group_qty[i_grp] == (int32_t)i_qty ) {
+ bool b_check_ok = true;
+ for (int32_t i_pce_check = 0; i_pce_check < i_idx; i_pce_check++)
+ if ( p_sys->ps_pieces_tmp[i_pce_check].i_group_ID == i_grp )
+ b_check_ok = false;
+ if ( b_check_ok )
+ for (uint32_t i_pce = i_pce_loop; i_pce < p_sys->s_current_param.i_pieces_nbr; i_pce++)
+ if (( p_sys->ps_pieces[i_pce].i_group_ID == i_grp ) && !p_sys->ps_pieces[i_pce].b_finished ) {
+ memcpy( &p_sys->ps_pieces_tmp[i_idx], &p_sys->ps_pieces[i_pce], sizeof(piece_t));
+ i_idx++;
+ }
+ }
+ }
+ // pieces at the final location are in background
+ for (uint32_t i_pce_loop = 0; i_pce_loop < p_sys->s_current_param.i_pieces_nbr; i_pce_loop++) {
+ uint32_t i_grp = p_sys->ps_pieces[i_pce_loop].i_group_ID;
+ if ( p_sys->pi_group_qty[i_grp] == (int32_t)i_qty ) {
+ bool b_check_ok = true;
+ for (int32_t i_pce_check = 0; i_pce_check < i_idx; i_pce_check++)
+ if ( p_sys->ps_pieces_tmp[i_pce_check].i_group_ID == i_grp && p_sys->ps_pieces_tmp[i_pce_check].b_finished )
+ b_check_ok = false;
+ if ( b_check_ok )
+ for (uint32_t i_pce = i_pce_loop; i_pce < p_sys->s_current_param.i_pieces_nbr; i_pce++)
+ if (( p_sys->ps_pieces[i_pce].i_group_ID == i_grp ) && p_sys->ps_pieces[i_pce].b_finished ) {
+ memcpy( &p_sys->ps_pieces_tmp[i_idx], &p_sys->ps_pieces[i_pce], sizeof(piece_t));
+ i_idx++;
+ }
+ }
+ }
+ }
+
+ free( p_filter->p_sys->ps_pieces );
+ p_filter->p_sys->ps_pieces = p_sys->ps_pieces_tmp;
+ p_sys->ps_pieces_tmp = malloc( sizeof( piece_t) * p_sys->s_allocated.i_pieces_nbr );
+}
+
+static void 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 )
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+ piece_t *ps_piece = &p_sys->ps_pieces[i_piece];
+
+ if ( p_sys->s_current_param.i_rotate == 0 )
+ return;
+
+ if ( p_sys->s_current_param.i_rotate == 1 && (i_rotate_mirror != 2) )
+ return;
+
+ for ( uint8_t i=0; i < abs( i_rotate_mirror ); i++) {
+ int32_t i_tempx, i_tempy;
+
+ // piece has to be rotated by 90°:
+ if ( i_rotate_mirror > 0 ) {
+ ps_piece->i_actual_angle++;
+ ps_piece->i_actual_angle &= 0x03;
+
+ i_tempx = -( i_center_y - ps_piece->ps_piece_in_plane[0].i_actual_y ) + i_center_x;
+ i_tempy = +( i_center_x - ps_piece->ps_piece_in_plane[0].i_actual_x ) + i_center_y;
+ }
+ else {
+ ps_piece->i_actual_angle--;
+ ps_piece->i_actual_angle &= 0x03;
+
+ i_tempx = +( i_center_y - ps_piece->ps_piece_in_plane[0].i_actual_y ) + i_center_x;
+ i_tempy = -( i_center_x - ps_piece->ps_piece_in_plane[0].i_actual_x ) + i_center_y;
+ }
+
+ ps_piece->ps_piece_in_plane[0].i_actual_x = i_tempx;
+ ps_piece->ps_piece_in_plane[0].i_actual_y = i_tempy;
+
+ if ( ps_piece->i_actual_angle == 0 && p_sys->s_current_param.i_rotate == 3 && !b_avoid_mirror ) {
+ ps_piece->ps_piece_in_plane[0].i_actual_x = 2 * i_center_x - ps_piece->ps_piece_in_plane[0].i_actual_x;
+ ps_piece->i_actual_mirror *= -1;
+ }
+ calculate_corners( p_filter, i_piece );
+ }
+}
+
+static void move_group( filter_t *p_filter, int32_t i_piece, int32_t i_dx, int32_t i_dy)
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+ uint32_t i_group_ID = p_sys->ps_pieces[i_piece].i_group_ID;
+ for (uint32_t i = 0; i < p_sys->s_allocated.i_pieces_nbr; i++) {
+ piece_t *ps_piece = &p_sys->ps_pieces[i];
+ if (ps_piece->i_group_ID == i_group_ID) {
+ ps_piece->b_finished = false;
+ ps_piece->ps_piece_in_plane[0].i_actual_x += i_dx;
+ ps_piece->ps_piece_in_plane[0].i_actual_y += i_dy;
+
+ calculate_corners( p_filter, i );
+ }
+ }
+}
+
+static void auto_solve( filter_t *p_filter)
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ if ( p_sys->s_current_param.i_auto_solve_speed < 500 )
+ return;
+
+ if ( --p_sys->i_auto_solve_countdown_val > 0 )
+ return;
+
+ // delay reached, preset next delay and proceed with auto_solve
+ p_sys->i_auto_solve_countdown_val = init_countdown(p_sys->s_current_param.i_auto_solve_speed);
+
+ // random piece to be moved
+ int32_t i_start = ((unsigned)vlc_mrand48()) % p_sys->s_allocated.i_pieces_nbr;
+
+ // here the computer will help player by placing the piece at the final location:
+ for (uint32_t i_l = 0; i_l < p_sys->s_allocated.i_pieces_nbr; i_l++) {
+ int32_t i = ( i_l + i_start ) % p_sys->s_allocated.i_pieces_nbr;
+ if ( !p_sys->ps_pieces[i].b_finished ) {
+ for (uint32_t j = 0; j < p_sys->s_allocated.i_pieces_nbr; j++) {
+ if ( p_sys->ps_pieces[j].i_group_ID == p_sys->ps_pieces[i].i_group_ID ) {
+ p_sys->ps_pieces[j].i_actual_angle = 0;
+ p_sys->ps_pieces[j].i_actual_mirror = +1;
+ p_sys->ps_pieces[j].ps_piece_in_plane[0].i_actual_x = p_sys->ps_pieces[j].ps_piece_in_plane[0].i_original_x;
+ p_sys->ps_pieces[j].ps_piece_in_plane[0].i_actual_y = p_sys->ps_pieces[j].ps_piece_in_plane[0].i_original_y;
+ calculate_corners( p_filter, j );
+ }
+ }
+ break;
+ }
+ }
+}
+
+static void auto_shuffle( filter_t *p_filter)
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ if ( p_sys->s_current_param.i_auto_shuffle_speed < 500 )
+ return;
+
+ if ( --p_sys->i_auto_shuffle_countdown_val > 0 )
+ return;
+
+ // delay reached, preset next delay and proceed with auto_shuffle
+ p_sys->i_auto_shuffle_countdown_val = init_countdown(p_sys->s_current_param.i_auto_shuffle_speed);
+
+ // random piece to be moved
+ int32_t i_start = ((unsigned)vlc_mrand48()) % p_sys->s_allocated.i_pieces_nbr;
+
+ for (uint32_t i_l = 0; i_l < p_sys->s_allocated.i_pieces_nbr; i_l++){
+ int32_t i = ( i_l + i_start ) % p_sys->s_allocated.i_pieces_nbr;
+
+ // find one piece which is part of one group
+ if ( p_sys->pi_group_qty[p_sys->ps_pieces[i].i_group_ID] > 1 ) {
+ // find an empty group to be used by this dismanteled piece
+ uint32_t i_new_group;
+ for ( i_new_group = 0 ; i_new_group < p_sys->s_allocated.i_pieces_nbr ; i_new_group ++ )
+ if ( p_sys->pi_group_qty[i_new_group] == 0 )
+ break;
+ p_sys->ps_pieces[i].i_group_ID = i_new_group;
+ p_sys->ps_pieces[i].b_finished = false;
+
+ //random rotate & mirror
+ switch ( p_sys->s_current_param.i_rotate )
+ {
+ case 1:
+ rotate_pce( p_filter, i, (( (unsigned) vlc_mrand48()) % ( 2 ) ) * 2, p_sys->ps_pieces[i].i_center_x, p_sys->ps_pieces[i].i_center_y, false );
+ break;
+ case 2:
+ rotate_pce( p_filter, i, (( (unsigned) vlc_mrand48()) % ( 4 ) ), p_sys->ps_pieces[i].i_center_x, p_sys->ps_pieces[i].i_center_y, false );
+ break;
+ case 3:
+ rotate_pce( p_filter, i, (( (unsigned) vlc_mrand48()) % ( 8 ) ), p_sys->ps_pieces[i].i_center_x, p_sys->ps_pieces[i].i_center_y, false );
+ break;
+ }
+
+ // random mvt
+ p_sys->ps_pieces[i].ps_piece_in_plane[0].i_actual_x =
+ p_sys->ps_desk_planes[0].i_border_size_x
+ + ( (unsigned) vlc_mrand48()) % ( p_sys->ps_desk_planes[0].i_visible_pitch - 2*p_sys->ps_desk_planes[0].i_border_size_x - p_sys->ps_pieces[i].ps_piece_in_plane[0].i_size_x)
+ + p_sys->ps_pieces[i].ps_piece_in_plane[0].i_size_x / 2 * ( 1 - p_sys->ps_pieces[i].i_step_x_x )
+ - (p_sys->ps_pieces[i].ps_piece_in_plane[0].i_size_y / 2) * p_sys->ps_pieces[i].i_step_y_x;
+ p_sys->ps_pieces[i].ps_piece_in_plane[0].i_actual_y =
+ p_sys->ps_desk_planes[0].i_border_size_y
+ + ( (unsigned) vlc_mrand48()) % ( p_sys->ps_desk_planes[0].i_visible_lines - 2*p_sys->ps_desk_planes[0].i_border_size_y - p_sys->ps_pieces[i].ps_piece_in_plane[0].i_size_y)
+ + p_sys->ps_pieces[i].ps_piece_in_plane[0].i_size_y / 2 * ( 1 - p_sys->ps_pieces[i].i_step_y_y )
+ - (p_sys->ps_pieces[i].ps_piece_in_plane[0].i_size_x / 2) * p_sys->ps_pieces[i].i_step_x_y;
+
+ // redefine shapes
+ uint32_t i_left_pce = 0;
+ uint32_t i_right_pce = 6;
+ uint32_t i_top_pce = 2;
+ uint32_t i_btm_pce = 4;
+
+ uint32_t i_pce = 0;
+ for (int32_t i_row = 0; i_row < p_sys->s_allocated.i_rows; i_row++)
+ for (int32_t i_col = 0; i_col < p_sys->s_allocated.i_cols; i_col++) {
+ if (p_sys->ps_pieces[i].i_original_row == p_sys->ps_pieces[i_pce].i_original_row) {
+ if (p_sys->ps_pieces[i].i_original_col == p_sys->ps_pieces[i_pce].i_original_col - 1)
+ i_right_pce = i_pce;
+ else if (p_sys->ps_pieces[i].i_original_col == p_sys->ps_pieces[i_pce].i_original_col + 1)
+ i_left_pce = i_pce;
+ }
+ else if (p_sys->ps_pieces[i].i_original_col == p_sys->ps_pieces[i_pce].i_original_col) {
+ if (p_sys->ps_pieces[i].i_original_row == p_sys->ps_pieces[i_pce].i_original_row - 1)
+ i_btm_pce = i_pce;
+ else if (p_sys->ps_pieces[i].i_original_row == p_sys->ps_pieces[i_pce].i_original_row + 1)
+ i_top_pce = i_pce;
+ }
+ i_pce++;
+ }
+
+ if ((p_sys->ps_pieces[i].i_left_shape == 0) && (p_sys->ps_pieces[i].i_original_col != 0)) {
+ p_sys->ps_pieces[i_left_pce].i_right_shape = 6 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY ) ) + (vlc_mrand48() & 0x01);
+ p_sys->ps_pieces[i].i_left_shape = (p_sys->ps_pieces[i_left_pce].i_right_shape - 6 ) ^ 0x01;
+ }
+
+ if ((p_sys->ps_pieces[i].i_right_shape == 6) && (p_sys->ps_pieces[i].i_original_col != p_sys->s_allocated.i_cols-1)) {
+ p_sys->ps_pieces[i].i_right_shape = 6 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY ) ) + (vlc_mrand48() & 0x01);
+ p_sys->ps_pieces[i_right_pce].i_left_shape = (p_sys->ps_pieces[i].i_right_shape - 6 ) ^ 0x01;
+ }
+
+ if ((p_sys->ps_pieces[i].i_top_shape == 2) && (p_sys->ps_pieces[i].i_original_row != 0)) {
+ p_sys->ps_pieces[i_top_pce].i_btm_shape = 4 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY ) ) + (vlc_mrand48() & 0x01);
+ p_sys->ps_pieces[i].i_top_shape = (p_sys->ps_pieces[i_top_pce].i_btm_shape - 2 ) ^ 0x01;
+ }
+
+ if ((p_sys->ps_pieces[i].i_btm_shape == 4) && (p_sys->ps_pieces[i].i_original_row != p_sys->s_allocated.i_rows-1)) {
+ p_sys->ps_pieces[i].i_btm_shape = 4 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY ) ) + (vlc_mrand48() & 0x01);
+ p_sys->ps_pieces[i_btm_pce].i_top_shape = (p_sys->ps_pieces[i].i_btm_shape - 2 ) ^ 0x01;
+ }
+
+ calculate_corners( p_filter, i );
+ break;
+ }
+ }
+}
+
+static void puzzle_preset_background( picture_t *p_pic_dst, uint8_t Y, uint8_t U, uint8_t V)
+{
+ uint8_t i_c;
+
+ for( uint8_t i_plane = 0; i_plane < p_pic_dst->i_planes; i_plane++ ) {
+ if (i_plane == Y_PLANE)
+ i_c = Y;
+ else if (i_plane == U_PLANE)
+ i_c = U;
+ else if (i_plane == V_PLANE)
+ i_c = V;
+
+ const int32_t i_dst_pitch = p_pic_dst->p[i_plane].i_pitch;
+ const int32_t i_dst_lines = p_pic_dst->p[i_plane].i_lines;
+
+ uint8_t *p_dst = p_pic_dst->p[i_plane].p_pixels;
+
+ for (int32_t y = 0; y < i_dst_lines; y++)
+ memset(&p_dst[y * i_dst_pitch], i_c, i_dst_pitch);
+ }
+}
+
+static void puzzle_draw_borders( filter_t *p_filter, picture_t *p_pic, picture_t *p_pic_dst)
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ for( uint8_t i_plane = 0; i_plane < p_pic_dst->i_planes; i_plane++ ) {
+ const int32_t i_pitch = p_sys->ps_pict_planes[i_plane].i_pitch;
+ const int32_t i_out_pitch = p_sys->ps_desk_planes[i_plane].i_pitch;
+ const int32_t i_vis_lines = p_sys->ps_pict_planes[i_plane].i_visible_lines;
+ const int32_t i_vis_pitch = p_sys->ps_pict_planes[i_plane].i_visible_pitch;
+ const int32_t i_border_size_x = p_sys->ps_pict_planes[i_plane].i_border_size_x;
+ const int32_t i_border_size_y = p_sys->ps_pict_planes[i_plane].i_border_size_y;
+
+ uint8_t *p_src = p_pic->p[i_plane].p_pixels;
+ uint8_t *p_dst = p_pic_dst->p[i_plane].p_pixels;
+
+ for (int32_t y = 0 ; y < i_border_size_y; y++)
+ memcpy( &p_dst[y * i_out_pitch], &p_src[y * i_pitch], i_vis_pitch);
+
+ for (int32_t y = i_vis_lines - i_border_size_y ; y < i_vis_lines; y++)
+ memcpy( &p_dst[y * i_out_pitch], &p_src[y * i_pitch], i_vis_pitch);
+
+ for (int32_t y = i_border_size_y ; y < i_vis_lines - i_border_size_y; y++) {
+ memcpy( &p_dst[y * i_out_pitch], &p_src[y * i_pitch], i_border_size_x);
+ memcpy( &p_dst[y * i_out_pitch + i_vis_pitch - i_border_size_x], &p_src[y * i_pitch + i_vis_pitch - i_border_size_x], i_border_size_x);
+ }
+ }
+}
+
+static void puzzle_draw_preview( filter_t *p_filter, picture_t *p_pic, picture_t *p_pic_dst)
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+
+ for( uint8_t i_plane = 0; i_plane < p_pic_dst->i_planes; i_plane++ ) {
+ int32_t i_preview_offset = 0;
+ int32_t i_preview_size_x = p_sys->ps_desk_planes[i_plane].i_visible_pitch * p_sys->s_current_param.i_preview_size / 100;
+ int32_t i_preview_size_y = p_sys->ps_desk_planes[i_plane].i_visible_lines * p_sys->s_current_param.i_preview_size / 100;
+
+ const int32_t i_src_pitch = p_pic->p[i_plane].i_pitch;
+ const int32_t i_dst_pitch = p_sys->ps_desk_planes[i_plane].i_pitch;
+
+ switch ( p_sys->i_preview_pos ) {
+ case 0:
+ i_preview_offset = 0;
+ break;
+ case 1:
+ i_preview_offset = p_sys->ps_desk_planes[i_plane].i_visible_pitch - 1 - i_preview_size_x;
+ break;
+ case 2:
+ i_preview_offset =
+ p_sys->ps_desk_planes[i_plane].i_visible_pitch - 1 - i_preview_size_x
+ + ((int32_t) ( p_sys->ps_desk_planes[i_plane].i_visible_lines - 1 - i_preview_size_y )) * i_dst_pitch;
+ break;
+ case 3:
+ i_preview_offset = ((int32_t) ( p_sys->ps_desk_planes[i_plane].i_visible_lines - 1 - i_preview_size_y )) * i_dst_pitch;
+ break;
+ default:
+ i_preview_offset = 0;
+ break;
+ }
+
+ uint8_t *p_src = p_pic->p[i_plane].p_pixels;
+ uint8_t *p_dst = p_pic_dst->p[i_plane].p_pixels;
+
+ for ( int32_t y = 0; y < i_preview_size_y; y++ )
+ for ( int32_t x = 0; x < i_preview_size_x; x++ )
+ p_dst[ y * i_dst_pitch + x + i_preview_offset ] =
+ p_src[ ( y * 100 / p_sys->s_current_param.i_preview_size ) * i_src_pitch + ( x * 100 / p_sys->s_current_param.i_preview_size ) ];
+ }
+}
+
+static void puzzle_draw_pieces( filter_t *p_filter, picture_t *p_src_pic, picture_t *p_dst_pic)
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ if ((p_sys->ps_puzzle_array == NULL) || (p_sys->ps_pieces == NULL))
+ return;
+
+ for( uint8_t i_plane = 0; i_plane < p_dst_pic->i_planes; i_plane++ ) {
+ const int32_t i_src_pitch = p_src_pic->p[i_plane].i_pitch;
+ const int32_t i_dst_pitch = p_dst_pic->p[i_plane].i_pitch;
+ const int32_t i_src_visible_lines = p_src_pic->p[i_plane].i_visible_lines;
+ const int32_t i_dst_visible_lines = p_dst_pic->p[i_plane].i_visible_lines;
+ uint8_t *p_src = p_src_pic->p[i_plane].p_pixels;
+ uint8_t *p_dst = p_dst_pic->p[i_plane].p_pixels;
+
+ for ( int32_t i = p_sys->s_allocated.i_pieces_nbr-1; i >= 0 ; i-- ) {
+ piece_t *ps_piece = &p_sys->ps_pieces[i];
+
+ const int32_t i_desk_start_x = ps_piece->ps_piece_in_plane[i_plane].i_actual_x;
+ const int32_t i_desk_start_y = ps_piece->ps_piece_in_plane[i_plane].i_actual_y;
+ const int32_t i_pic_start_x = ps_piece->ps_piece_in_plane[i_plane].i_original_x;
+ const int32_t i_pic_start_y = ps_piece->ps_piece_in_plane[i_plane].i_original_y;
+ const int32_t i_size_x = ps_piece->ps_piece_in_plane[i_plane].i_size_x;
+ const int32_t i_size_y = ps_piece->ps_piece_in_plane[i_plane].i_size_y;
+
+ if (!p_sys->s_current_param.b_advanced
+ || (ps_piece->i_actual_mirror == 1 && ps_piece->i_actual_angle == 0
+ && p_sys->s_current_param.i_shape_size == 0))
+ {
+ // basic version rectangular & angle = 0
+ const int32_t i_ofs_x = __MAX(0, __MAX(-i_desk_start_x,-i_pic_start_x));
+ const int32_t i_count_x = i_size_x - __MAX(0, __MAX(i_desk_start_x + i_size_x - i_dst_pitch, i_pic_start_x + i_size_x - i_src_pitch ));
+ const int32_t i_ofs_y = __MAX(0, __MAX(-i_desk_start_y,-i_pic_start_y));
+ const int32_t i_count_y = i_size_y - __MAX(0, __MAX(i_desk_start_y + i_size_y - i_dst_visible_lines, i_pic_start_y + i_size_y - i_src_visible_lines ));
+
+ for (int32_t i_y = i_ofs_y; i_y < i_count_y; i_y++) {
+ memcpy( p_dst + (i_desk_start_y + i_y) * i_dst_pitch + i_desk_start_x + i_ofs_x,
+ p_src + (i_pic_start_y + i_y) * i_src_pitch + i_pic_start_x + i_ofs_x,
+ i_count_x - i_ofs_x);
+ }
+ }
+ else if ( ( p_sys->s_current_param.i_shape_size == 0) || !p_sys->b_shape_init || (p_sys->ps_pieces_shapes == NULL) || (!p_sys->b_shape_init) )
+ {
+ // here we still have rectangular shape but angle is not 0
+ for (int32_t i_y = 0; i_y < i_size_y; i_y++) {
+ int32_t i_current_src_y = i_pic_start_y + i_y;
+
+ if ( ( i_current_src_y >= 0 ) && ( i_current_src_y < i_src_visible_lines ) ) {
+ for (int32_t i_x = 0; i_x < i_size_x; i_x++) {
+ 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;
+ 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;
+ int32_t i_current_src_x = i_pic_start_x + i_x;
+
+ if ( ( i_current_dst_x >= 0 ) && ( i_current_src_x >= 0 )
+ && ( i_current_dst_x < i_dst_pitch ) && ( i_current_src_x < i_src_pitch )
+ && ( i_current_dst_y >= 0 ) && ( i_current_dst_y < i_dst_visible_lines ) )
+ {
+ p_dst[ i_current_dst_y * i_dst_pitch + i_current_dst_x ] =
+ p_src[ i_current_src_y * i_src_pitch + i_current_src_x ];
+ }
+ }
+ }
+ }
+ }
+ else {
+ // "puzzle" shape and maybe angle != 0
+ piece_shape_t *ps_top_shape = &p_sys->ps_pieces_shapes[ps_piece->i_top_shape][i_plane];
+ piece_shape_t *ps_btm_shape = &p_sys->ps_pieces_shapes[ps_piece->i_btm_shape][i_plane];
+ piece_shape_t *ps_right_shape = &p_sys->ps_pieces_shapes[ps_piece->i_right_shape][i_plane];
+ piece_shape_t *ps_left_shape = &p_sys->ps_pieces_shapes[ps_piece->i_left_shape][i_plane];
+ piece_shape_t *ps_shape;
+
+ int32_t i_min_y = ps_top_shape->i_first_row_offset;
+ int32_t i_max_y = ps_btm_shape->i_first_row_offset + ps_btm_shape->i_row_nbr - 1;
+
+ for (int32_t i_y = i_min_y; i_y <= i_max_y; i_y++) {
+ int32_t i_current_src_y = i_pic_start_y + i_y;
+
+ if ( ( i_current_src_y >= 0 ) && ( i_current_src_y < i_src_visible_lines ) ) {
+ int32_t i_sect_start_x = 0;
+
+ //process each sub shape (each quarter):
+ for (int8_t i_shape=0; i_shape < 4; i_shape++) {
+ switch ( i_shape )
+ {
+ case 0:
+ ps_shape = ps_left_shape;
+ break;
+ case 1:
+ ps_shape = ps_top_shape;
+ break;
+ case 2:
+ ps_shape = ps_btm_shape;
+ break;
+ case 3:
+ ps_shape = ps_right_shape;
+ break;
+ }
+
+ int32_t i_r = i_y - ps_shape->i_first_row_offset;
+
+ if (i_r >=0 && i_r < ps_shape->i_row_nbr) {
+ piece_shape_row_t *ps_piece_shape_row = &ps_shape->ps_piece_shape_row[i_r];
+
+ for (int32_t i_s = 0; i_s < ps_piece_shape_row->i_section_nbr; i_s++) {
+ uint8_t i_type = ps_piece_shape_row->ps_row_section[i_s].i_type;
+ int32_t i_width = ps_piece_shape_row->ps_row_section[i_s].i_width;
+ if (i_type == 0) {
+ // fill
+ for (int32_t i_x = 0; i_x < i_width; i_x++) {
+ 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;
+ 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;
+ int32_t i_current_src_x = i_pic_start_x + (i_sect_start_x + i_x);
+
+ if ( ( i_current_dst_x >= 0 ) && ( i_current_src_x >= 0 )
+ && ( i_current_dst_x < i_dst_pitch ) && ( i_current_src_x < i_src_pitch )
+ && ( i_current_dst_y >= 0 ) && ( i_current_dst_y < i_dst_visible_lines ) )
+ {
+ p_dst[ i_current_dst_y * i_dst_pitch + i_current_dst_x ] =
+ p_src[ i_current_src_y * i_src_pitch + i_current_src_x ];
+ if ((i_plane == 0) && (p_sys->i_mouse_x == i_current_dst_x )
+ && (p_sys->i_mouse_y == i_current_dst_y ))
+ p_sys->i_pointed_pce = i;
+ }
+ }
+ }
+ i_sect_start_x += i_width;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return;
+}
+
+static void draw_sign(picture_t *p_pic_dst, int32_t i_x, int32_t i_y, int32_t i_size_x, int32_t i_size_y, const char **ppsz_sign, bool b_reverse)
+{
+ plane_t *p_out = &p_pic_dst->p[Y_PLANE];
+ uint8_t i_Y;
+
+ i_Y = ( p_out->p_pixels[ i_y * p_out->i_pitch + i_x ] >= 0x7F ) ? 0x00 : 0xFF;
+
+ for( int32_t i = 0; i < i_size_y ; i++ )
+ for( int32_t j = 0; j < i_size_x; j++ ) {
+ int32_t i_dst_x = j + i_x;
+ int32_t i_dst_y = i + i_y;
+ if ( ppsz_sign[i][b_reverse?i_size_x-1-j:j] == 'o' ) {
+ 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))
+ p_out->p_pixels[ i_dst_y * p_out->i_pitch + i_dst_x ] = i_Y;
+ }
+ else if ( ppsz_sign[i][b_reverse?i_size_x-1-j:j] == '.' ) {
+ 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))
+ 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;
+ }
+ }
+}
+
+static void draw_rectangle(picture_t *p_pic_dst, 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 )
+{
+ uint8_t i_c;
+
+ for( uint8_t i_plane = 0; i_plane < p_pic_dst->i_planes; i_plane++ ) {
+ plane_t *p_oyp = &p_pic_dst->p[i_plane];
+
+ if (i_plane == Y_PLANE)
+ i_c = i_Y;
+ else if (i_plane == U_PLANE)
+ i_c = i_U;
+ else if (i_plane == V_PLANE)
+ i_c = i_V;
+
+ int32_t i_x_min = i_x * p_oyp->i_visible_pitch / p_pic_dst->p[0].i_visible_pitch;
+ int32_t i_x_max = (i_x + i_w) * p_oyp->i_visible_pitch / p_pic_dst->p[0].i_visible_pitch;
+ int32_t i_y_min = i_y * p_oyp->i_visible_lines / p_pic_dst->p[0].i_visible_lines;
+ int32_t i_y_max = (i_y + i_h) * p_oyp->i_visible_lines /p_pic_dst->p[0].i_visible_lines;
+
+ /* top line */
+ memset( &p_oyp->p_pixels[i_y_min * p_oyp->i_pitch + i_x_min], i_c, i_x_max - i_x_min);
+
+ /* left and right */
+ for( int32_t i_dy = 1; i_dy < i_y_max - i_y_min - 1; i_dy++ ) {
+ p_oyp->p_pixels[(i_y_min + i_dy) * p_oyp->i_pitch + i_x_min ] = i_c;
+ p_oyp->p_pixels[(i_y_min + i_dy) * p_oyp->i_pitch + i_x_max - 1] = i_c;
+ }
+
+ /* bottom line */
+ memset( &p_oyp->p_pixels[(i_y_max - 1) * p_oyp->i_pitch + i_x_min], i_c, i_x_max - i_x_min);
+ }
+}
+
+static void fill_rectangle(picture_t *p_pic_dst, 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 )
+{
+ uint8_t i_c;
+
+ for( uint8_t i_plane = 0; i_plane < p_pic_dst->i_planes; i_plane++ ) {
+ plane_t *p_oyp = &p_pic_dst->p[i_plane];
+
+ if (i_plane == Y_PLANE)
+ i_c = i_Y;
+ else if (i_plane == U_PLANE)
+ i_c = i_U;
+ else if (i_plane == V_PLANE)
+ i_c = i_V;
+
+ int32_t i_x_min = i_x * p_oyp->i_visible_pitch / p_pic_dst->p[0].i_visible_pitch;
+ int32_t i_x_max = (i_x + i_w) * p_oyp->i_visible_pitch / p_pic_dst->p[0].i_visible_pitch;
+ int32_t i_y_min = i_y * p_oyp->i_visible_lines / p_pic_dst->p[0].i_visible_lines;
+ int32_t i_y_max = (i_y + i_h) * p_oyp->i_visible_lines /p_pic_dst->p[0].i_visible_lines;
+
+ for( int32_t i_dy = 0; i_dy < i_y_max - i_y_min; i_dy++ )
+ 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);
+ }
+}
+
+static int32_t diagonal_limit( filter_t *p_filter, int32_t i_y, bool b_left, uint8_t i_plane )
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ if (b_left ^ (i_y >= p_sys->ps_desk_planes[i_plane].i_pieces_max_y / 2))
+ return ( i_y * p_sys->ps_desk_planes[i_plane].i_pieces_max_x) / p_sys->ps_desk_planes[i_plane].i_pieces_max_y;
+ else
+ return p_sys->ps_desk_planes[i_plane].i_pieces_max_x - ( ( i_y * p_sys->ps_desk_planes[i_plane].i_pieces_max_x) / p_sys->ps_desk_planes[i_plane].i_pieces_max_y);
+
+}
+
+#define bezier_val(ps_pt,f_sub_t,i_main_t,axis) (( 1 - (f_sub_t)) * ( 1 - (f_sub_t) ) * ( 1 - (f_sub_t) ) * ps_pt[ 3 * (i_main_t) ].f_ ## axis \
+ + 3 * (f_sub_t) * ( 1 - (f_sub_t) ) * ( 1 - (f_sub_t) ) * ps_pt[ 3 * (i_main_t) + 1 ].f_ ## axis \
+ + 3 * (f_sub_t) * (f_sub_t) * ( 1 - (f_sub_t) ) * ps_pt[ 3 * (i_main_t) + 2 ].f_ ## axis \
+ + (f_sub_t) * (f_sub_t) * (f_sub_t) * ps_pt[ 3 * (i_main_t) + 3 ].f_ ## axis )
+
+static point_t *scale_curve_H(int32_t i_size_x, int32_t i_size_y, uint8_t i_pts_nbr, point_t *ps_pt, int32_t i_shape_size)
+{
+ if (ps_pt == NULL)
+ return NULL;
+
+ float f_x_ratio = ((float) i_size_x) / (1 - (-1));
+ float f_y_ratio = (((float)i_size_y) / 2) / (1 - (0));
+ float f_x_offset = ((float)i_size_x) / (1 - (-1));
+ float f_y_offset = 0;
+ float f_bez_x, f_bez_y;
+
+ float f_current_scale = 1;
+
+ uint8_t i_last_pt = (3 * (i_pts_nbr-1) + 1);
+
+ point_t *ps_new_pt = malloc( sizeof( point_t ) * i_last_pt );
+ if (ps_new_pt == NULL)
+ return NULL;
+
+ bool b_fit = true;
+
+ //check if the curve fit with available space:
+ do {
+ b_fit = true;
+
+ for (uint8_t i_p = 0; i_p < i_last_pt; i_p++) {
+ if ( i_p == 0 || i_p == 1 )
+ ps_new_pt[i_p].f_x = ps_pt[i_p].f_x * f_x_ratio + f_x_offset;
+ else if ( i_p == i_last_pt - 2 || i_p == i_last_pt - 1 )
+ ps_new_pt[i_p].f_x = ps_pt[i_p].f_x * f_x_ratio + f_x_offset;
+ else
+ ps_new_pt[i_p].f_x = ps_pt[i_p].f_x * f_x_ratio * f_current_scale + f_x_offset;
+ ps_new_pt[i_p].f_y = ps_pt[i_p].f_y * f_y_ratio * f_current_scale + f_y_offset;
+ }
+
+ for (float f_t = 0; f_t <= i_pts_nbr - 1; f_t += 0.1 ) {
+ int8_t i_main_t = floor(f_t);
+ if ( i_main_t == i_pts_nbr - 1 )
+ i_main_t = i_pts_nbr - 2;
+ float f_sub_t = f_t - i_main_t;
+
+ f_bez_x = bezier_val(ps_new_pt,f_sub_t,i_main_t,x);
+ f_bez_y = bezier_val(ps_new_pt,f_sub_t,i_main_t,y);
+
+ if ( f_bez_x < ((float) i_size_x) / 2 ) {
+ if ( abs ( f_bez_y ) > ( f_bez_x * ( 0.9 * ((float)i_size_y) / ((float)i_size_x) ) ) )
+ b_fit = false;
+ }
+ else {
+ if ( abs ( f_bez_y ) > ( ( ((float)i_size_x) - f_bez_x ) * ( 0.9 * ((float)i_size_y) / ((float)i_size_x) ) ) )
+ b_fit = false;
+ }
+ }
+
+ if (!b_fit)
+ f_current_scale = f_current_scale * 0.9;
+ }
+ while ((!b_fit) && (f_current_scale>0.1));
+
+ if (!b_fit) {
+ free(ps_new_pt);
+ ps_new_pt = NULL;
+ }
+
+ // global scale shall be applied:
+ f_current_scale = f_current_scale * (0.5 + 0.5* (float)i_shape_size / 100);
+ for (uint8_t i_p = 0; i_p < i_last_pt; i_p++) {
+ if ( i_p == 0 || i_p == 1 )
+ ps_new_pt[i_p].f_x = ps_pt[i_p].f_x * f_x_ratio + f_x_offset;
+ else if ( i_p == i_last_pt - 2 || i_p == i_last_pt - 1 )
+ ps_new_pt[i_p].f_x = ps_pt[i_p].f_x * f_x_ratio + f_x_offset;
+ else
+ ps_new_pt[i_p].f_x = ps_pt[i_p].f_x * f_x_ratio * f_current_scale + f_x_offset;
+ ps_new_pt[i_p].f_y = ps_pt[i_p].f_y * f_y_ratio * f_current_scale + f_y_offset;
+ }
+
+
+ return ps_new_pt;
+}
+
+static point_t *H_2_scale_curve_V(int32_t i_size_x, int32_t i_size_y, uint8_t i_pts_nbr, point_t *ps_pt, int32_t i_shape_size)
+{
+ if (ps_pt == NULL)
+ return NULL;
+
+ point_t *ps_bezier_scale_H = scale_curve_H(i_size_y, i_size_x, i_pts_nbr, ps_pt, i_shape_size);
+ point_t *ps_pts_V = curve_H_2_V(i_pts_nbr, ps_bezier_scale_H);
+ free(ps_bezier_scale_H);
+
+ return ps_pts_V;
+}
+
+static point_t *curve_H_2_V(uint8_t i_pts_nbr, point_t *ps_pt)
+{
+ if (ps_pt == NULL)
+ return NULL;
+
+ point_t *ps_new_pt = malloc( sizeof( point_t ) * (3 * (i_pts_nbr-1) + 1) );
+
+ if (ps_new_pt == NULL)
+ return NULL;
+
+ for (uint8_t i=0; i < (3 * (i_pts_nbr-1) + 1); i++) {
+ ps_new_pt[i].f_x = ps_pt[i].f_y;
+ ps_new_pt[i].f_y = ps_pt[i].f_x;
+ }
+
+ return ps_new_pt;
+}
+
+static point_t *curve_H_2_negative(uint8_t i_pts_nbr, point_t *ps_pt)
+{
+ if (ps_pt == NULL)
+ return NULL;
+
+ point_t *ps_new_pt = malloc( sizeof( point_t ) * (3 * (i_pts_nbr-1) + 1) );
+ if (ps_new_pt == NULL)
+ return NULL;
+
+ for (uint8_t i=0; i < (3 * (i_pts_nbr-1) + 1); i++) {
+ ps_new_pt[i].f_x = ps_pt[i].f_x;
+ ps_new_pt[i].f_y = -ps_pt[i].f_y;
+ }
+
+ return ps_new_pt;
+}
+
+static point_t *curve_V_2_negative(uint8_t i_pts_nbr, point_t *ps_pt)
+{
+ if (ps_pt == NULL)
+ return NULL;
+
+ point_t *ps_new_pt = malloc( sizeof( point_t ) * (3 * (i_pts_nbr-1) + 1) );
+ if (ps_new_pt == NULL)
+ return NULL;
+
+ for (uint8_t i=0; i < (3 * (i_pts_nbr-1) + 1); i++) {
+ ps_new_pt[i].f_x = -ps_pt[i].f_x;
+ ps_new_pt[i].f_y = ps_pt[i].f_y;
+ }
+
+ return ps_new_pt;
+}
+
+static point_t *rand_bezier(uint8_t i_pts_nbr)
+{
+#define NB_PRIM 13
+ point_t ps_pt[NB_PRIM][19] = { {{ -1, 0}, { -0.708333333333333, 0},
+ { -0.375, -0.333333333333333}, { -0.166666666666667, 0.0833333333333333}, { -0.0833333333333334, 0.208333333333333},
+ { -0.375, 0.416666666666667}, { -0.4, 0.583333333333333}, { -0.416666666666667, 0.833333333333333},
+ { -0.25, 1}, { 0, 1}, { 0.25, 1},
+ { 0.416666666666667, 0.833333333333333}, { 0.4, 0.583333333333333}, { 0.375, 0.416666666666667},
+ { 0.0833333333333334, 0.208333333333333}, { 0.166666666666667, 0.0833333333333333}, { 0.375, -0.333333333333333},
+ { 0.708333333333333, 0}, { 1, 0}},
+
+ {{ -1, 0}, { -0.708231074018077, 0.00464090724581488},
+ { -0.323236452068492, -0.372786060362316}, { -0.116455168200171, 0.044302770499351}, { -0.0335691043909019, 0.211488362938889},
+ { -0.437927544463254, 0.38719460194857}, { -0.465325829944998, 0.551293871552922}, { -0.483454564038933, 0.65987409733561},
+ { -0.190232837055291, 0.93567381392124}, { 0.0642797691187335, 0.936855546259066}, {0.313367868665637, 0.938012091966671},
+ {0.487146524283283, 0.816195130161918}, {0.469545566313243, 0.564387421486367}, {0.446892478470506, 0.24030153060388},
+ {0.207135456718658, 0.246041323358689}, {0.287851875888374, 0.122157561245575}, {0.492785457693622, -0.19237501290106},
+ { 0.707786879710212, 0.000871347032899226}, {1, 0}},
+
+ {{ -1, 0}, { -0.704537606957651, 0.00470344095405053},
+ { -0.435930692234854, -0.352359270526667}, { -0.228149843936683, 0.0679948519756222}, { -0.146863413857337, 0.232442568245956},
+ { -0.400774053301818, 0.353459760810654}, { -0.422294600163745, 0.522585095895632}, { -0.436816721748459, 0.636711316521778},
+ { -0.139151386987432, 1.08020929564109}, { 0.110882572064929, 1.08261729027387}, {0.36153850539327, 1.08503127493587},
+ {0.34588115345217, 0.865990116291394}, {0.329903557511847, 0.612892723601664}, {0.308148644342904, 0.26827818823501},
+ {0.127493141873546, 0.13002329074962}, {0.214157995034913, 0.0010516930680228}, {0.419298604696494, -0.304231373969182},
+ { 0.710915592189813, -0.00442574861414977}, {1, 0}},
+
+ {{ -1, 0}, { -0.712310641244798, -0.00176730760415818},
+ { -0.493540738434648, -0.309260977632173}, { -0.285884861158849, 0.102814242456153}, { -0.204387117876255, 0.264539501285563},
+ { -0.420693738052021, 0.397849004532357}, { -0.441431505287778, 0.562611714939519}, { -0.461628378308195, 0.723076990818189},
+ { -0.237390284827422, 0.937205665156549}, { 0.012635296180645, 0.941029970697368}, {0.262998571390198, 0.94485944149288},
+ {0.388416614305901, 0.85661645417048}, {0.371248440058972, 0.611257540385605}, {0.345208629600827, 0.239109662732447},
+ {0.0581354739284663, 0.176880217503811}, {0.136998743377185, 0.0517079719473858}, {0.348267592311711, -0.283619188873049},
+ { 0.708090161530147, 0.000345266964160967}, {1, 0}},
+
+ {{ -1, 0}, { -0.711243094744545, -0.00459592941542872},
+ { -0.344045254972826, -0.249350550360079}, { -0.133712969208732, 0.170729185550043}, { -0.0464161071620253, 0.345080177938788},
+ { -0.422103631801675, 0.334575981154338}, { -0.450380528566562, 0.498555760394576}, { -0.467099640727027, 0.595511106801977},
+ { -0.207078052226595, 0.975846125373965}, { 0.042159574981007, 0.973462055639965}, {0.287191021206139, 0.971118219914322},
+ {0.330852515542335, 0.808592956913444}, {0.310390322812144, 0.55585802623889}, {0.283433878730578, 0.222910569628582},
+ {0.164262943948071, 0.173598366742734}, {0.251741291720702, 0.049453960261478}, {0.457341230249114, -0.24232203906962},
+ { 0.708383662881845, 0.00453591968074395}, {1, 0}},
+
+ {{ -1, 0}, { -0.709563566764519, 0.000504612933340335},
+ { -0.401784990268149, -0.401999124062464}, { -0.193592021826356, 0.0146187796927396}, { -0.111906932669809, 0.178079970851903},
+ { -0.31875772800715, 0.350308507939804}, { -0.348317101378293, 0.519642874263023}, { -0.364751907373417, 0.613791604139223},
+ { -0.261109769059908, 0.917602975781519}, { -0.0140971269841824, 0.920487199482641}, {0.239116574515885, 0.923443829366756},
+ {0.464370661288271, 0.826483978760365}, {0.447638420230199, 0.579781906213412}, {0.422345781938457, 0.206864359478527},
+ {0.125463036793575, 0.196073913812856}, {0.210079852894537, 0.0665488867084866}, {0.418467910269307, -0.25243580242811},
+ { 0.703900021885974, 0.00330911444674605}, {1, 0}},
+
+ {{ -1, 0}, { -0.705550924110721, 0.00312677407583926},
+ { -0.415041079490389, -0.256262603613135}, { -0.206251758814373, 0.165228519752475}, { -0.127460686840124, 0.324287121648782},
+ { -0.353486555975517, 0.448219649272319}, { -0.374301593332884, 0.615673871700604}, { -0.394013085772568, 0.774250221227079},
+ { -0.28341474824943, 1.03226208905838}, { -0.0332682368974526, 1.03258310507818}, {0.21500235815775, 1.03290171371209},
+ {0.359673321091526, 0.870921326239785}, {0.339932613238046, 0.624982013252291}, {0.312186121753393, 0.279302764858672},
+ {0.115889225615101, 0.23413749518865}, {0.199563649684811, 0.112671061164123}, {0.404949947429742, -0.185479078044395},
+ { 0.711077310890697, -0.00496397607736578}, {1, 0}},
+
+ {{ -1, 0}, { -0.703393023950601, 0.00477096251262726},
+ { -0.397655885794691, -0.396549402674607}, { -0.188941722741602, 0.0154382717692692}, { -0.108388702754651, 0.174444497740687},
+ { -0.373390092271521, 0.482883861046198}, { -0.40085845720332, 0.649893787354158}, { -0.415216707820891, 0.73719313638733},
+ { -0.207371750103189, 0.945376369116883}, { 0.0450859051405016, 0.945770549381538}, {0.295681992651987, 0.946161823046823},
+ {0.436428045351514, 0.895032817250379}, {0.416214840162102, 0.640148265397975}, {0.392784984133714, 0.344702377534045},
+ {0.112552686103251, 0.228040049100136}, {0.197835182813393, 0.100734153702732}, {0.405083123585628, -0.208636299638369},
+ { 0.710532321943806, 0.00118461271792703}, {1, 0}},
+
+ {{ -1, 0}, { -0.708545258498605, -0.00125649641636185},
+ { -0.337498620726249, -0.244893936731276}, { -0.124910631945282, 0.17201407250253}, { -0.0378099534640198, 0.342827911406433},
+ { -0.388593443990334, 0.484174318751186}, { -0.418161094500799, 0.649198946145559}, { -0.437373248647437, 0.756426897124284},
+ { -0.189109020838902, 0.919750563663455}, { 0.0617320119458061, 0.92141119323056}, {0.31608889374516, 0.923095098586168},
+ {0.498311890876136, 0.848907293614162}, {0.486010157001842, 0.596632149071449}, {0.461260133020122, 0.0890763897591911},
+ {0.075676233826577, 0.15314863012444}, {0.155893607369245, 0.0261168678327565}, {0.366248653274704, -0.307000149194794},
+ { 0.711164480468843, 0.00394203362859574}, {1, 0}},
+
+ {{ -1, 0}, { -0.707183721193905, 0.00108263364450203},
+ { -0.483784802307194, -0.278675576139177}, { -0.276928949597787, 0.142419327760986}, { -0.193170452053892, 0.312925871385917},
+ { -0.451215340488792, 0.477259970702323}, { -0.47460300367851, 0.643765731024187}, { -0.494031809431451, 0.782086864170215},
+ { -0.236790915210626, 0.959374429536679}, { 0.0132927154237516, 0.955639549881874}, {0.267150847268955, 0.951848299853113},
+ {0.394360682972295, 0.847565361471232}, {0.378470732344786, 0.601630247482969}, {0.354536849929646, 0.231195987620713},
+ {0.0517827835992971, 0.214030018332778}, {0.131796334571256, 0.0912722226051247}, {0.336621017220957, -0.222972380306016},
+ { 0.703679022364791, -0.00331356185794636}, {1, 0}},
+
+ {{ -1, 0}, { -0.71248840208346, -0.000315316402810925},
+ { -0.335615004340797, -0.24819255482402}, { -0.131187942697538, 0.164054053482729}, { -0.0493962500017139, 0.3289947791894},
+ { -0.419381248020232, 0.390159881019368}, { -0.441651048160997, 0.558451191050566}, { -0.455822752006908, 0.665545758156122},
+ { -0.233491027161151, 0.962685238392525}, { 0.0133445688612305, 0.95860585518251}, {0.262151404887793, 0.954493893837471},
+ {0.353774477399895, 0.909561597589476}, {0.33709535778317, 0.660905314411181}, {0.31704981166686, 0.362061544110332},
+ {0.105412252277536, 0.191206346512902}, {0.186218651070473, 0.0649153599195794}, {0.398293919310497, -0.266533575537957},
+ { 0.704071013216639, 0.00309631694609307}, {1, 0}},
+
+ {{ -1, 0}, { -0.705056079463317, 0.00448211481221729},
+ { -0.436957920272407, -0.370262236529651}, { -0.229712063674328, 0.0431705143488563}, { -0.148227797168837, 0.205722687925072},
+ { -0.393257971601542, 0.424195267916701}, { -0.413510880163265, 0.589027317989955}, { -0.431898814144998, 0.738680926783159},
+ { -0.283603628196569, 0.915912313032585}, { -0.0357952161759055, 0.912250885919817}, {0.219122757016883, 0.908484413381742},
+ {0.443769349276008, 0.835076661704473}, {0.426106787792343, 0.583529647320461}, {0.400589787646949, 0.220121134430258},
+ {0.160593774137044, 0.15625323679053}, {0.245514983733696, 0.0314675787386357}, {0.452432214072397, -0.272582526914925},
+ { 0.707859045957901, -0.00364987569003833}, {1, 0}},
+
+ { { -1, 0}, { -0.707920686483174, 0.00318900911649754},
+ { -0.434372174464315, -0.307446433658587}, { -0.22207624254243, 0.109425261995917}, { -0.137453117820789, 0.275594180895755},
+ { -0.340508174095858, 0.364631782467402}, { -0.369080584284576, 0.527714098008385}, { -0.383671882476694, 0.610996631060469},
+ { -0.233753076988816, 0.939761357928644}, { 0.0204626018463874, 0.936196353095824}, {0.268226367774715, 0.932721826949446},
+ {0.500766516589953, 0.908734435247741}, {0.488915515020803, 0.659928459184412}, {0.468202989215343, 0.225079120105809},
+ {0.106186153956061, 0.298643666003939}, {0.184680334657865, 0.170455849778656}, {0.39345790442032, -0.1704960590812},
+ { 0.713223372514099, -0.000707944210808817}, {1, 0}}
+ };
+
+ if (i_pts_nbr != 7)
+ return NULL;
+
+ //random shape
+ uint8_t i_last_pt = (3 * (i_pts_nbr-1) + 1);
+ uint8_t i_item = ((uint16_t) vlc_mrand48()) % NB_PRIM;
+
+ point_t *ps_new_pt = malloc( sizeof( point_t ) * i_last_pt );
+ if (ps_new_pt == NULL)
+ return NULL;
+
+ if ((vlc_mrand48() & 1) == 1)
+ for (uint8_t i=0; i < i_last_pt; i++) {
+ ps_new_pt[i].f_x = ps_pt[i_item][i].f_x;
+ ps_new_pt[i].f_y = ps_pt[i_item][i].f_y;
+ }
+ else
+ for (uint8_t i=0; i < i_last_pt; i++) {
+ ps_new_pt[i].f_x = ps_pt[i_item][i_last_pt-1-i].f_x;
+ ps_new_pt[i].f_y = ps_pt[i_item][i_last_pt-1-i].f_y;
+ }
+
+ //random shape size
+ float f_current_scale = 0.7 + ( (float) (vlc_mrand48() % 1001 ) / 1000 )*0.3;
+ for (uint8_t i_p = 0; i_p < i_last_pt; i_p++) {
+ if ( i_p != 0 && i_p != 1 && i_p != i_last_pt - 2 && i_p != i_last_pt - 1 )
+ ps_new_pt[i_p].f_x = ps_new_pt[i_p].f_x * f_current_scale;
+ ps_new_pt[i_p].f_y = ps_new_pt[i_p].f_y * f_current_scale;
+ }
+
+ //random shape shift
+ float f_offset = ( ( (float) (vlc_mrand48() % 1001 ) / 1000 ) - 0.5 ) * 0.2;
+ for (uint8_t i=1; i < i_pts_nbr - 1; i++) {
+ ps_new_pt[i*3-1].f_x += f_offset;
+ ps_new_pt[i*3].f_x += f_offset;
+ ps_new_pt[i*3+1].f_x += f_offset;
+ }
+
+ return ps_new_pt;
+}
+
+#define MAX_SECT 10
+
+static void generate_sectTopB( filter_t *p_filter, piece_shape_t *ps_piece_shape, uint8_t i_plane)
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ int32_t i_size_y = p_sys->ps_desk_planes[i_plane].i_pieces_max_y;
+
+ // first: get min y:
+ float f_min_curve_y = 0;
+
+ // next: process each horizontal pixel lines:
+ int32_t i_min_y =floor(f_min_curve_y);
+ int32_t i_nb_y = i_size_y /2 - i_min_y;
+
+ // allocate memory
+ ps_piece_shape->i_row_nbr = i_nb_y;
+ ps_piece_shape->i_first_row_offset = i_min_y;
+ ps_piece_shape->ps_piece_shape_row = malloc( sizeof( piece_shape_row_t ) * i_nb_y );
+
+ for (int32_t i_y = i_min_y; i_y < i_nb_y + i_min_y; i_y++) {
+ uint8_t i_sect = 0;
+ int32_t pi_sects[MAX_SECT];
+ int32_t i_row = i_y - i_min_y;
+
+ // ...fill from border to next junction
+ pi_sects[i_sect] = diagonal_limit( p_filter, i_y, false, i_plane ) - 1 - (diagonal_limit( p_filter, i_y, true, i_plane ) - 1);
+ i_sect++;
+
+ // ...allocate memory and copy final values
+ ps_piece_shape->ps_piece_shape_row[i_row].i_section_nbr = i_sect;
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section = malloc ( sizeof(row_section_t) * i_sect);
+ for (uint8_t i=0; i < i_sect; i++) {
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section[i].i_type = i % 2; // 0 = fill ; 1 = offset
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section[i].i_width = pi_sects[i];
+ }
+ }
+}
+
+static void generate_sectLeftB( filter_t *p_filter, piece_shape_t *ps_piece_shape, uint8_t i_plane)
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ int32_t i_size_y = p_sys->ps_desk_planes[i_plane].i_pieces_max_y;
+
+ // first: get min y:
+ float f_min_curve_y = 0;
+
+ // next: process each horizontal pixel lines:
+ int32_t i_min_y =floor(f_min_curve_y);
+ int32_t i_nb_y = i_size_y - i_min_y;
+
+ // allocate memory
+ ps_piece_shape->i_row_nbr = i_nb_y;
+ ps_piece_shape->i_first_row_offset = i_min_y;
+ ps_piece_shape->ps_piece_shape_row = malloc( sizeof( piece_shape_row_t ) * i_nb_y );
+
+ for (int32_t i_y = i_min_y; i_y < i_nb_y + i_min_y; i_y++) {
+ uint8_t i_sect = 0;
+ int32_t pi_sects[MAX_SECT];
+ int32_t i_row = i_y - i_min_y;
+
+ // ...fill from border to next junction
+ pi_sects[i_sect] = diagonal_limit( p_filter, i_y, true, i_plane );
+ i_sect++;
+
+ // ...allocate memory and copy final values
+ ps_piece_shape->ps_piece_shape_row[i_row].i_section_nbr = i_sect;
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section = malloc ( sizeof(row_section_t) * i_sect);
+ for (uint8_t i=0; i < i_sect; i++) {
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section[i].i_type = i % 2; // 0 = fill ; 1 = offset
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section[i].i_width = pi_sects[i];
+ }
+ }
+}
+
+static void generate_sectRightB( filter_t *p_filter, piece_shape_t *ps_piece_shape, uint8_t i_plane)
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ int32_t i_size_x = p_sys->ps_desk_planes[i_plane].i_pieces_max_x;
+ int32_t i_size_y = p_sys->ps_desk_planes[i_plane].i_pieces_max_y;
+
+ // first: get min y:
+ float f_min_curve_y = 0;
+
+ //next: process each horizontal pixel lines:
+ int32_t i_min_y =floor(f_min_curve_y);
+ int32_t i_nb_y = i_size_y - i_min_y;
+
+ // allocate memory
+ ps_piece_shape->i_row_nbr = i_nb_y;
+ ps_piece_shape->i_first_row_offset = i_min_y;
+ ps_piece_shape->ps_piece_shape_row = malloc( sizeof( piece_shape_row_t ) * i_nb_y );
+
+ for (int32_t i_y = i_min_y; i_y < i_nb_y + i_min_y; i_y++) {
+ uint8_t i_sect = 0;
+ int32_t pi_sects[MAX_SECT];
+ int32_t i_row = i_y - i_min_y;
+
+ // ...fill from border to next junction
+ pi_sects[i_sect] = i_size_x - diagonal_limit( p_filter, i_y, false, i_plane );
+ i_sect++;
+
+ // ...allocate memory and copy final values
+ ps_piece_shape->ps_piece_shape_row[i_row].i_section_nbr = i_sect;
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section = malloc ( sizeof(row_section_t) * i_sect);
+ for (uint8_t i=0; i < i_sect; i++) {
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section[i].i_type = i % 2; // 0 = fill ; 1 = offset
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section[i].i_width = pi_sects[i];
+ }
+ }
+}
+
+static void generate_sectBtmB( filter_t *p_filter, piece_shape_t *ps_piece_shape, uint8_t i_plane)
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ int32_t i_size_y = p_sys->ps_desk_planes[i_plane].i_pieces_max_y;
+
+ // first: get min y:
+ float f_min_curve_y = i_size_y / 2;
+
+ //next: process each horizontal pixel lines:
+ int32_t i_min_y =floor(f_min_curve_y);
+ int32_t i_nb_y = i_size_y - i_min_y;
+
+ // allocate memory
+ ps_piece_shape->i_row_nbr = i_nb_y;
+ ps_piece_shape->i_first_row_offset = i_min_y;
+ ps_piece_shape->ps_piece_shape_row = malloc( sizeof( piece_shape_row_t ) * i_nb_y );
+
+ for (int32_t i_y = i_min_y; i_y < i_nb_y + i_min_y; i_y++) {
+ uint8_t i_sect = 0;
+ int32_t pi_sects[MAX_SECT];
+ int32_t i_row = i_y - i_min_y;
+
+ // ...fill from border to next junction
+ pi_sects[i_sect] = diagonal_limit( p_filter, i_y, false, i_plane ) - 1 - (diagonal_limit( p_filter, i_y, true, i_plane ) - 1);
+ i_sect++;
+
+ // ...allocate memory and copy final values
+ ps_piece_shape->ps_piece_shape_row[i_row].i_section_nbr = i_sect;
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section = malloc ( sizeof(row_section_t) * i_sect);
+ for (uint8_t i=0; i < i_sect; i++) {
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section[i].i_type = i % 2; // 0 = fill ; 1 = offset
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section[i].i_width = pi_sects[i];
+ }
+ }
+}
+
+static void generate_sectTop( filter_t *p_filter, piece_shape_t *ps_piece_shape, uint8_t i_pts_nbr, point_t *ps_pt, uint8_t i_plane)
+{
+ if (ps_pt == NULL) {
+ generate_sectTopB( p_filter, ps_piece_shape, i_plane);
+ return;
+ }
+
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ int32_t i_size_x = p_sys->ps_desk_planes[i_plane].i_pieces_max_x;
+ int32_t i_size_y = p_sys->ps_desk_planes[i_plane].i_pieces_max_y;
+
+ int32_t i_size_x_0 = p_sys->ps_desk_planes[0].i_pieces_max_x;
+ int32_t i_size_y_0 = p_sys->ps_desk_planes[0].i_pieces_max_y;
+
+ float f_x_ratio = ((float) i_size_x) / ((float) i_size_x_0);
+ float f_y_ratio = ((float) i_size_y) / ((float) i_size_y_0);
+ float f_x_offset = 0;
+ float f_y_offset = 0;
+ float f_bez_x, f_bez_y;
+ float f_xo, f_yo, f_xd, f_yd;
+
+ // first: get min y:
+ float f_min_curve_y = ps_pt[0].f_y * f_y_ratio + f_y_offset;
+
+ for (float f_t = 0; f_t <= i_pts_nbr - 1; f_t += 0.1 ) {
+ int8_t i_main_t = floor(f_t);
+ if ( i_main_t == i_pts_nbr - 1 )
+ i_main_t = i_pts_nbr - 2;
+ float f_sub_t = f_t - i_main_t;
+
+ f_bez_y = bezier_val(ps_pt,f_sub_t,i_main_t,y);
+
+ f_yd = f_bez_y * f_y_ratio + f_y_offset;
+
+ if (f_yd < f_min_curve_y)
+ f_min_curve_y = f_yd;
+ }
+ f_min_curve_y = floor(f_min_curve_y);
+ if (f_min_curve_y > 0)
+ f_min_curve_y = 0;
+
+ // next: process each horizontal pixel lines:
+ int32_t i_min_y = floor(f_min_curve_y);
+ int32_t i_nb_y = i_size_y / 2 - i_min_y;
+
+ // allocate memory
+ ps_piece_shape->i_row_nbr = i_nb_y;
+ ps_piece_shape->i_first_row_offset = i_min_y;
+ ps_piece_shape->ps_piece_shape_row = malloc( sizeof( piece_shape_row_t ) * ps_piece_shape->i_row_nbr );
+
+ for (int32_t i_y = i_min_y; i_y < i_nb_y + i_min_y; i_y++) {
+ int32_t i_row = i_y - i_min_y;
+
+ uint8_t i_sect = 0;
+ int32_t pi_sects[MAX_SECT];
+
+ // ...detect curve
+ int8_t i_main_t = 0;
+ f_xo = ps_pt[0].f_x * f_x_ratio + f_x_offset;
+ f_yo = ps_pt[0].f_y * f_y_ratio + f_y_offset;
+
+ for (float f_t = 0; f_t <= i_pts_nbr - 1; f_t += 0.1 ) {
+ i_main_t = floor(f_t);
+ if ( i_main_t == i_pts_nbr - 1 )
+ i_main_t = i_pts_nbr - 2;
+ float f_sub_t = f_t - i_main_t;
+
+ f_bez_x = bezier_val(ps_pt,f_sub_t,i_main_t,x);
+ f_bez_y = bezier_val(ps_pt,f_sub_t,i_main_t,y);
+
+ f_xd = f_bez_x * f_x_ratio + f_x_offset;
+ f_yd = f_bez_y * f_y_ratio + f_y_offset;
+
+ 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)) {
+ pi_sects[i_sect] = floor(((float)i_y+0.5 - f_yo) * (f_xd - f_xo) / (f_yd - f_yo) + f_xo);
+ if (i_sect < MAX_SECT - 1)
+ i_sect++;
+ }
+
+ f_xo = f_xd;
+ f_yo = f_yd;
+ }
+ f_xd = ps_pt[i_pts_nbr - 1].f_x * f_x_ratio + f_x_offset;
+ f_yd = ps_pt[i_pts_nbr - 1].f_y * f_y_ratio + f_y_offset;
+
+ // ...fill from this junction to next junction
+ if ( i_y >= 0 ) {
+ // last diagonal intersection
+ pi_sects[i_sect] = diagonal_limit( p_filter, i_y, false, i_plane );
+ if (i_sect < MAX_SECT - 1)
+ i_sect++;
+ }
+
+ // ...reorder the list
+ int32_t i_s = 0;
+
+ while (i_s < (i_sect - 1)) {
+ if (pi_sects[i_s] > pi_sects[i_s+1]) {
+ uint32_t i_temp = pi_sects[i_s];
+ pi_sects[i_s] = pi_sects[i_s+1];
+ pi_sects[i_s+1] = i_temp;
+ i_s = 0;
+ }
+ else {
+ i_s++;
+ }
+ }
+
+ // ...we have to convert absolute values to offsets and take into account min_curve_x
+ i_s = 0;
+ int32_t i_last_x = ( i_y < 0 )?0:diagonal_limit( p_filter, i_y, true, i_plane );
+
+ for (i_s = 0; i_s<i_sect; i_s++) {
+ int32_t i_current_x = pi_sects[i_s];
+ int32_t i_delta = i_current_x - i_last_x;
+ pi_sects[i_s] = i_delta;
+
+ i_last_x = i_current_x;
+ }
+
+ // ...allocate memory and copy final values
+ // note for y > 0 we have to ignore the first offset as it is included in "Left" piece shape
+ if ( i_y >= 0 ) {
+ ps_piece_shape->ps_piece_shape_row[i_row].i_section_nbr = i_sect;
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section = malloc ( sizeof(row_section_t) * i_sect);
+ for (uint8_t i=0; i < i_sect; i++) {
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section[i].i_type = i % 2; // 0 = fill ; 1 = offset
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section[i].i_width = pi_sects[i];
+ }
+ }
+ else {
+ ps_piece_shape->ps_piece_shape_row[i_row].i_section_nbr = i_sect;
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section = malloc ( sizeof(row_section_t) * i_sect);
+ for (uint8_t i=0; i < i_sect; i++) {
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section[i].i_type = (i + 1) % 2; // 0 = fill ; 1 = offset
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section[i].i_width = pi_sects[i];
+ }
+ }
+ }
+}
+
+static void generate_sectLeft( filter_t *p_filter, piece_shape_t *ps_piece_shape, uint8_t i_pts_nbr, point_t *ps_pt, uint8_t i_plane)
+{
+
+ if (ps_pt == NULL) {
+ generate_sectLeftB( p_filter, ps_piece_shape, i_plane);
+ return;
+ }
+
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ int32_t i_size_x = p_sys->ps_desk_planes[i_plane].i_pieces_max_x;
+ int32_t i_size_y = p_sys->ps_desk_planes[i_plane].i_pieces_max_y;
+
+ int32_t i_size_x_0 = p_sys->ps_desk_planes[0].i_pieces_max_x;
+ int32_t i_size_y_0 = p_sys->ps_desk_planes[0].i_pieces_max_y;
+
+ float f_x_ratio = ((float) i_size_x) / ((float) i_size_x_0);
+ float f_y_ratio = ((float) i_size_y) / ((float) i_size_y_0);
+ float f_x_offset = 0;
+ float f_y_offset = 0;
+ float f_bez_x, f_bez_y;
+ float f_xo, f_yo, f_xd, f_yd;
+
+ // first: get min x:
+ float f_min_curve_x = ps_pt[0].f_x * f_x_ratio + f_x_offset;
+
+ for (float f_t = 0; f_t <= i_pts_nbr - 1; f_t += 0.1 ) {
+ int8_t i_main_t = floor(f_t);
+ if ( i_main_t == i_pts_nbr - 1 )
+ i_main_t = i_pts_nbr - 2;
+ float f_sub_t = f_t - i_main_t;
+
+ f_bez_x = bezier_val(ps_pt,f_sub_t,i_main_t,x);
+
+ f_xd = f_bez_x * f_x_ratio + f_x_offset;
+
+ if (f_xd < f_min_curve_x)
+ f_min_curve_x = f_xd;
+ }
+ f_min_curve_x = floor(f_min_curve_x);
+ if (f_min_curve_x > 0)
+ f_min_curve_x = 0;
+
+ // next: process each horizontal pixel lines:
+ int32_t i_min_y = 0;
+ int32_t i_nb_y = i_size_y;
+
+ // allocate memory
+ ps_piece_shape->i_row_nbr = i_nb_y;
+ ps_piece_shape->i_first_row_offset = i_min_y;
+ ps_piece_shape->ps_piece_shape_row = malloc( sizeof( piece_shape_row_t ) * ps_piece_shape->i_row_nbr );
+
+ for (int32_t i_y = i_min_y; i_y < i_nb_y + i_min_y; i_y++) {
+ int32_t i_row = i_y - i_min_y;
+
+ uint8_t i_sect = 0;
+ int32_t pi_sects[MAX_SECT];
+
+ // ...detect curve
+ int8_t i_main_t = 0;
+ f_xo = ps_pt[0].f_x * f_x_ratio + f_x_offset;
+ f_yo = ps_pt[0].f_y * f_y_ratio + f_y_offset;
+
+ for (float f_t = 0; f_t <= i_pts_nbr - 1; f_t += 0.1 ) {
+ i_main_t = floor(f_t);
+ if ( i_main_t == i_pts_nbr - 1 )
+ i_main_t = i_pts_nbr - 2;
+ float f_sub_t = f_t - i_main_t;
+
+ f_bez_x = bezier_val(ps_pt,f_sub_t,i_main_t,x);
+ f_bez_y = bezier_val(ps_pt,f_sub_t,i_main_t,y);
+
+ f_xd = f_bez_x * f_x_ratio + f_x_offset;
+ f_yd = f_bez_y * f_y_ratio + f_y_offset;
+
+ 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)) {
+ pi_sects[i_sect] = floor(((float)i_y+0.5 - f_yo) * (f_xd - f_xo) / (f_yd - f_yo) + f_xo);
+ if (i_sect < MAX_SECT - 1)
+ i_sect++;
+ }
+
+ f_xo = f_xd;
+ f_yo = f_yd;
+ }
+ f_xd = ps_pt[i_pts_nbr - 1].f_x * f_x_ratio + f_x_offset;
+ f_yd = ps_pt[i_pts_nbr - 1].f_y * f_y_ratio + f_y_offset;
+
+
+ // ...fill from this junction to next junction
+ if ( i_y >= 0 ) {
+ // last diagonal intersection
+ pi_sects[i_sect] = diagonal_limit( p_filter, i_y, true, i_plane );
+ if (i_sect < MAX_SECT - 1)
+ i_sect++;
+ }
+
+ // ...reorder the list
+ int32_t i_s = 0;
+
+ while (i_s < (i_sect - 1)) {
+ if (pi_sects[i_s] > pi_sects[i_s+1]) {
+ uint32_t i_temp = pi_sects[i_s];
+ pi_sects[i_s] = pi_sects[i_s+1];
+ pi_sects[i_s+1] = i_temp;
+ i_s = 0;
+ }
+ else
+ i_s++;
+ }
+
+ // ...we have to convert absolute values to offsets and take into account min_curve_x
+ i_s = 0;
+ int32_t i_last_x = 0;
+
+ for (i_s = 0; i_s<i_sect; i_s++) {
+ int32_t i_current_x = pi_sects[i_s];
+ int32_t i_delta = i_current_x - i_last_x;
+ pi_sects[i_s] = i_delta;
+
+ i_last_x = i_current_x;
+ }
+
+ // ...allocate memory and copy final values
+ // note for y > 0 we have to ignore the first offset as it is included in "Left" piece shape
+ ps_piece_shape->ps_piece_shape_row[i_row].i_section_nbr = i_sect;
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section = malloc ( sizeof(row_section_t) * i_sect);
+ for (uint8_t i=0; i < i_sect; i++) {
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section[i].i_type = (i+1) % 2; // 0 = fill ; 1 = offset
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section[i].i_width = pi_sects[i];
+ }
+ }
+}
+
+//generate Right from Left:
+static void generate_sectLeft2Right( filter_t *p_filter, piece_shape_t *ps_piece_shape, piece_shape_t *ps_left_piece_shape, uint8_t i_plane)
+{
+ if (ps_left_piece_shape == NULL) {
+ generate_sectRightB( p_filter, ps_piece_shape, i_plane);
+ return;
+ }
+
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ int32_t i_min_y = ps_left_piece_shape->i_first_row_offset;
+ int32_t i_nb_y = ps_left_piece_shape->i_row_nbr;
+
+ // allocate memory
+ ps_piece_shape->i_row_nbr = i_nb_y;
+ ps_piece_shape->i_first_row_offset = i_min_y;
+ ps_piece_shape->ps_piece_shape_row = malloc( sizeof( piece_shape_row_t ) * i_nb_y );
+
+ for (int32_t i_y = i_min_y; i_y < i_nb_y + i_min_y; i_y++) {
+ int32_t i_row = i_y - i_min_y;
+
+ int32_t i_size_x = p_sys->ps_desk_planes[i_plane].i_pieces_max_x;
+ int32_t i_left_width = diagonal_limit( p_filter, i_y, true, i_plane );
+ int32_t i_right_width = i_size_x - diagonal_limit( p_filter, i_y, false, i_plane );
+ int16_t i_section_nbr = ps_left_piece_shape->ps_piece_shape_row[i_row].i_section_nbr;
+
+ ps_piece_shape->ps_piece_shape_row[i_row].i_section_nbr = i_section_nbr;
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section = malloc ( sizeof(row_section_t) * i_section_nbr);
+
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section[0].i_type =
+ ps_left_piece_shape->ps_piece_shape_row[i_row].ps_row_section[0].i_type;
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section[0].i_width =
+ ps_left_piece_shape->ps_piece_shape_row[i_row].ps_row_section[0].i_width + i_right_width - i_left_width;
+
+ for (int8_t i_s=0; i_s<i_section_nbr;i_s++) {
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section[i_s].i_type =
+ ps_left_piece_shape->ps_piece_shape_row[i_row].ps_row_section[i_section_nbr - 1 - i_s].i_type;
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section[i_s].i_width =
+ ps_left_piece_shape->ps_piece_shape_row[i_row].ps_row_section[i_section_nbr - 1 - i_s].i_width
+ + (i_s == 0 ? i_right_width - i_left_width : 0);
+ }
+ }
+}
+
+//generate Btm from Top:
+static void generate_sectTop2Btm( filter_t *p_filter, piece_shape_t *ps_piece_shape, piece_shape_t *ps_top_piece_shape, uint8_t i_plane)
+{
+ if (ps_top_piece_shape == NULL) {
+ generate_sectBtmB( p_filter, ps_piece_shape, i_plane);
+ return;
+ }
+
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ int32_t i_top_min_y = ps_top_piece_shape->i_first_row_offset;
+ int32_t i_top_nb_y = ps_top_piece_shape->i_row_nbr;
+ int32_t i_size_y = p_sys->ps_desk_planes[i_plane].i_pieces_max_y;
+ int32_t i_max_y = p_sys->ps_desk_planes[i_plane].i_pieces_max_y - i_top_min_y;
+
+ int32_t i_min_y = i_size_y / 2;
+ int32_t i_nb_y = i_max_y - i_min_y;
+
+ // allocate memory
+ ps_piece_shape->i_row_nbr = i_nb_y;
+ ps_piece_shape->i_first_row_offset = i_min_y;
+ ps_piece_shape->ps_piece_shape_row = malloc( sizeof( piece_shape_row_t ) * i_nb_y );
+
+ for (int32_t i_y = i_min_y; i_y < i_nb_y + i_min_y; i_y++) {
+ int32_t i_top_y = 2 * i_min_y - i_y + (i_nb_y - i_top_nb_y);
+ int32_t i_row = i_y - i_min_y;
+ int32_t i_top_row = i_top_y - i_top_min_y;
+
+ if ( i_top_row < 0 || i_top_row >= i_top_nb_y ) { // the line does not exist in top
+ ps_piece_shape->ps_piece_shape_row[i_row].i_section_nbr = 1;
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section = malloc ( sizeof(row_section_t) * 1);
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section[0].i_type = 0;
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section[0].i_width =
+ diagonal_limit( p_filter, i_y, false, i_plane ) - 1 - (diagonal_limit( p_filter, i_y, true, i_plane ) - 1);
+ }
+ else { // copy the line from TopShape
+ int32_t i_top_width =
+ diagonal_limit( p_filter, i_top_y, false, i_plane ) - 1 - (diagonal_limit( p_filter, i_top_y, true, i_plane ) - 1);
+ int32_t i_width =
+ diagonal_limit( p_filter, i_y, false, i_plane ) - 1 - (diagonal_limit( p_filter, i_y, true, i_plane ) - 1);
+ int32_t i_left_adjust = ( i_width - i_top_width ) / 2;
+ int32_t i_right_adjust = ( i_width - i_top_width ) - i_left_adjust;
+
+ int8_t i_section_nbr = ps_top_piece_shape->ps_piece_shape_row[i_top_row].i_section_nbr;
+ ps_piece_shape->ps_piece_shape_row[i_row].i_section_nbr = i_section_nbr;
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section = malloc ( sizeof(row_section_t) * i_section_nbr);
+
+ for (int8_t i_s=0; i_s<i_section_nbr; i_s++) {
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section[i_s].i_type =
+ ps_top_piece_shape->ps_piece_shape_row[i_top_row].ps_row_section[i_s].i_type;
+ ps_piece_shape->ps_piece_shape_row[i_row].ps_row_section[i_s].i_width =
+ ps_top_piece_shape->ps_piece_shape_row[i_top_row].ps_row_section[i_s].i_width
+ + (i_s == 0 ? i_left_adjust : (i_s == i_section_nbr-1 ? i_right_adjust : 0));
+ }
+ }
+ }
+}
+
+static save_game_t* save(filter_t *p_filter)
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ save_game_t *ps_save_game = calloc(1, sizeof(*ps_save_game));
+
+ ps_save_game->i_cols = p_sys->s_allocated.i_cols;
+ ps_save_game->i_rows = p_sys->s_allocated.i_rows;
+ ps_save_game->i_rotate = p_sys->s_allocated.i_rotate;
+
+ ps_save_game->ps_pieces = calloc( ps_save_game->i_cols * ps_save_game->i_rows , sizeof(*ps_save_game->ps_pieces));
+
+ int32_t i_border_x = p_sys->ps_desk_planes[0].i_visible_pitch * (p_sys->s_current_param.i_border / 100 / 2);
+ int32_t i_border_y = p_sys->ps_desk_planes[0].i_visible_lines * (p_sys->s_current_param.i_border / 100 / 2);
+
+ for (int32_t i_pce = 0; i_pce < ps_save_game->i_cols * ps_save_game->i_rows; i_pce++) {
+ ps_save_game->ps_pieces[i_pce].i_original_row = p_sys->ps_pieces[i_pce].i_original_row;
+ ps_save_game->ps_pieces[i_pce].i_original_col = p_sys->ps_pieces[i_pce].i_original_col;
+ ps_save_game->ps_pieces[i_pce].i_top_shape = p_sys->ps_pieces[i_pce].i_top_shape;
+ ps_save_game->ps_pieces[i_pce].i_btm_shape = p_sys->ps_pieces[i_pce].i_btm_shape;
+ ps_save_game->ps_pieces[i_pce].i_right_shape = p_sys->ps_pieces[i_pce].i_right_shape;
+ ps_save_game->ps_pieces[i_pce].i_left_shape = p_sys->ps_pieces[i_pce].i_left_shape;
+ ps_save_game->ps_pieces[i_pce].f_pos_x =(p_sys->ps_pieces[i_pce].ps_piece_in_plane[0].i_actual_x - i_border_x ) / ((float)p_sys->ps_desk_planes[0].i_visible_pitch - 2*i_border_x);
+ ps_save_game->ps_pieces[i_pce].f_pos_y =(p_sys->ps_pieces[i_pce].ps_piece_in_plane[0].i_actual_y - i_border_y ) / ((float)p_sys->ps_desk_planes[0].i_visible_lines - 2*i_border_y);
+ ps_save_game->ps_pieces[i_pce].i_actual_angle = p_sys->ps_pieces[i_pce].i_actual_angle;
+ ps_save_game->ps_pieces[i_pce].i_actual_mirror = p_sys->ps_pieces[i_pce].i_actual_mirror;
+ }
+
+ return ps_save_game;
+}
+
+static void load( filter_t *p_filter, save_game_t *ps_save_game)
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ if (p_sys->s_current_param.i_cols != ps_save_game->i_cols
+ || p_sys->s_allocated.i_rows != ps_save_game->i_rows
+ || p_sys->s_allocated.i_rotate != ps_save_game->i_rotate)
+ return;
+
+ int32_t i_border_x = p_sys->ps_desk_planes[0].i_visible_pitch * (p_sys->s_current_param.i_border / 100 / 2);
+ int32_t i_border_y = p_sys->ps_desk_planes[0].i_visible_lines * (p_sys->s_current_param.i_border / 100 / 2);
+
+ for (uint32_t i_pce=0; i_pce < p_sys->s_allocated.i_pieces_nbr; i_pce++) {
+ for (uint32_t i=0; i < p_sys->s_allocated.i_pieces_nbr; i++)
+ if ( p_sys->ps_pieces[i].i_original_row == ps_save_game->ps_pieces[i_pce].i_original_row
+ && p_sys->ps_pieces[i].i_original_col == ps_save_game->ps_pieces[i_pce].i_original_col )
+ {
+ p_sys->ps_pieces[i].ps_piece_in_plane[0].i_actual_x = i_border_x
+ + ((float)p_sys->ps_desk_planes[0].i_visible_pitch - 2 * i_border_x)
+ * ps_save_game->ps_pieces[i_pce].f_pos_x;
+ p_sys->ps_pieces[i].ps_piece_in_plane[0].i_actual_y = i_border_y
+ + ((float)p_sys->ps_desk_planes[0].i_visible_lines - 2 * i_border_y)
+ * ps_save_game->ps_pieces[i_pce].f_pos_y;
+
+ p_sys->ps_pieces[i].i_top_shape = ps_save_game->ps_pieces[i_pce].i_top_shape;
+ p_sys->ps_pieces[i].i_btm_shape = ps_save_game->ps_pieces[i_pce].i_btm_shape;
+ p_sys->ps_pieces[i].i_right_shape = ps_save_game->ps_pieces[i_pce].i_right_shape;
+ p_sys->ps_pieces[i].i_left_shape = ps_save_game->ps_pieces[i_pce].i_left_shape;
+ p_sys->ps_pieces[i].i_actual_angle = ps_save_game->ps_pieces[i_pce].i_actual_angle;
+ p_sys->ps_pieces[i].i_actual_mirror = ps_save_game->ps_pieces[i_pce].i_actual_mirror;
+ p_sys->ps_pieces[i].i_group_ID = i_pce;
+ p_sys->ps_pieces[i].b_finished = false;
+
+ p_sys->ps_pieces[i].ps_piece_in_plane[0].i_actual_x = i_border_x + ((float)p_sys->ps_desk_planes[0].i_visible_pitch - 2*i_border_x) * ps_save_game->ps_pieces[i_pce].f_pos_x;
+ p_sys->ps_pieces[i].ps_piece_in_plane[0].i_actual_y = i_border_y + ((float)p_sys->ps_desk_planes[0].i_visible_lines - 2*i_border_y) * ps_save_game->ps_pieces[i_pce].f_pos_y;
+
+ calculate_corners( p_filter, i );
+
+ break;
+ }
}
}
--
1.7.9.5
More information about the vlc-devel
mailing list