[vlc-devel] [PATCH] Puzzle filter enhancement
vlcvboyer
vlcvboyer at gmail.com
Thu Jan 17 07:55:08 CET 2013
Hi,
I've modified the original puzzle filter and added some additional features:
- "puzzle style" piece shapes
- pieces rotations and mirror
- drag'n drop with mouse to manipulate pieces
- a preview can be displayed in a corner
- borders can be shown
- auto solve (to make it easier...)
- auto shuffle (...to increase difficulty)
Original puzzle filter is still available. You just have to disable
"advanced mode" parameter.
I hope you'll appreciate it and include it in the current code.
Regards
Vianney
Date: Wed, 16 Jan 2013 22:44:13 +0100
Subject: [PATCH] Puzzle filter enhancement
---
AUTHORS | 1 +
modules/gui/qt4/components/extended_panels.cpp | 10 +
modules/gui/qt4/ui/video_effects.ui | 335 ++-
modules/video_filter/puzzle.c | 3517
++++++++++++++++++++++--
4 files changed, 3575 insertions(+), 288 deletions(-)
mode change 100644 => 100755 AUTHORS
mode change 100644 => 100755 modules/gui/qt4/components/extended_panels.cpp
mode change 100644 => 100755 modules/gui/qt4/ui/video_effects.ui
mode change 100644 => 100755 modules/video_filter/puzzle.c
diff --git a/AUTHORS b/AUTHORS
old mode 100644
new mode 100755
index eac402c..6ffcd40
--- 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
old mode 100644
new mode 100755
index f6b28c9..48f64b0
--- 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/gui/qt4/ui/video_effects.ui
b/modules/gui/qt4/ui/video_effects.ui
old mode 100644
new mode 100755
index 2d21e43..1b3b42f
--- a/modules/gui/qt4/ui/video_effects.ui
+++ b/modules/gui/qt4/ui/video_effects.ui
@@ -864,80 +864,6 @@
</layout>
</widget>
</item>
- <item row="3" column="1">
- <widget class="QGroupBox" name="puzzleEnable">
- <property name="title">
- <string>Puzzle game</string>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="checked">
- <bool>false</bool>
- </property>
- <layout class="QGridLayout" name="gridLayout_3">
- <item row="0" column="0">
- <widget class="QLabel" name="label_27">
- <property name="text">
- <string>Rows</string>
- </property>
- <property name="buddy">
- <cstring>puzzleRowsSpin</cstring>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QSpinBox" name="puzzleRowsSpin">
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- <property name="minimum">
- <number>2</number>
- </property>
- <property name="maximum">
- <number>16</number>
- </property>
- <property name="value">
- <number>4</number>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_26">
- <property name="text">
- <string>Columns</string>
- </property>
- <property name="buddy">
- <cstring>puzzleColsSpin</cstring>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QSpinBox" name="puzzleColsSpin">
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- <property name="minimum">
- <number>2</number>
- </property>
- <property name="maximum">
- <number>16</number>
- </property>
- <property name="value">
- <number>4</number>
- </property>
- </widget>
- </item>
- <item row="2" column="0" colspan="2">
- <widget class="QCheckBox" name="puzzleBlackSlotCheck">
- <property name="text">
- <string>Black slot</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
</layout>
</widget>
<widget class="QWidget" name="tab_8">
@@ -1794,6 +1720,264 @@
</item>
</layout>
</widget>
+ <widget class="QWidget" name="tab_4">
+ <attribute name="title">
+ <string>Puzzle</string>
+ </attribute>
+ <widget class="QGroupBox" name="puzzleEnable">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>521</width>
+ <height>241</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Puzzle</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_21">
+ <item row="2" column="1">
+ <widget class="QLabel" name="label_44">
+ <property name="text">
+ <string>Rotate</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QSpinBox" name="puzzleColsSpin">
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ <property name="suffix">
+ <string> col</string>
+ </property>
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>20</number>
+ </property>
+ <property name="value">
+ <number>4</number>
+ </property>
+ </widget>
+ </item>
+ <item row="17" column="0">
+ <widget class="QLabel" name="label_33">
+ <property name="text">
+ <string>Auto solve</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1" colspan="4">
+ <widget class="QSlider" name="puzzlePreviewSizeSlider">
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBelow</enum>
+ </property>
+ <property name="tickInterval">
+ <number>10</number>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QCheckBox" name="puzzleAdvancedGameCheck">
+ <property name="text">
+ <string>Advanced mode</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QSpinBox" name="puzzleRowsSpin">
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ <property name="suffix">
+ <string> row</string>
+ </property>
+ <property name="prefix">
+ <string/>
+ </property>
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>20</number>
+ </property>
+ <property name="value">
+ <number>4</number>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="1" colspan="4">
+ <widget class="QSlider" name="puzzleShapeSizeSlider">
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ <property name="pageStep">
+ <number>5</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBelow</enum>
+ </property>
+ <property name="tickInterval">
+ <number>5</number>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QCheckBox" name="puzzlePreviewCheck">
+ <property name="text">
+ <string>Preview</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="label_45">
+ <property name="text">
+ <string>shape size</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_26">
+ <property name="text">
+ <string>border</string>
+ </property>
+ </widget>
+ </item>
+ <item row="18" column="0">
+ <widget class="QLabel" name="label_27">
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="text">
+ <string>Auto shuffle</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="17" column="1" colspan="4">
+ <widget class="QSlider" name="puzzleAutoSolveSlider">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximum">
+ <number>30000</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBelow</enum>
+ </property>
+ <property name="tickInterval">
+ <number>1000</number>
+ </property>
+ </widget>
+ </item>
+ <item row="18" column="1" colspan="4">
+ <widget class="QSlider" name="puzzleAutoShuffleSlider">
+ <property name="maximum">
+ <number>30000</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBelow</enum>
+ </property>
+ <property name="tickInterval">
+ <number>1000</number>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" colspan="4">
+ <widget class="QSlider" name="puzzleBorderSlider">
+ <property name="maximum">
+ <number>25</number>
+ </property>
+ <property name="pageStep">
+ <number>5</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBelow</enum>
+ </property>
+ <property name="tickInterval">
+ <number>5</number>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2" colspan="3">
+ <widget class="QComboBox" name="puzzleRotationCombo"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_46">
+ <property name="text">
+ <string>basic mode parameters:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QCheckBox" name="puzzleNearCheck">
+ <property name="text">
+ <string>Ajoining only</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QCheckBox" name="puzzleBlackSlotCheck">
+ <property name="text">
+ <string>Black slot</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <zorder>puzzleEnable</zorder>
+ <zorder>puzzleAutoShuffleSlider</zorder>
+ </widget>
</widget>
<tabstops>
<tabstop>adjustEnable</tabstop>
@@ -1816,9 +2000,6 @@
<tabstop>rotateEnable</tabstop>
<tabstop>rotateAngleDial</tabstop>
<tabstop>transformTypeCombo</tabstop>
- <tabstop>puzzleRowsSpin</tabstop>
- <tabstop>puzzleColsSpin</tabstop>
- <tabstop>puzzleBlackSlotCheck</tabstop>
<tabstop>colorthresEnable</tabstop>
<tabstop>colorthresColorText</tabstop>
<tabstop>colorthresSaturationthresSlider</tabstop>
diff --git a/modules/video_filter/puzzle.c b/modules/video_filter/puzzle.c
old mode 100644
new mode 100755
index 713d1f2..60c210c
--- 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
@@ -35,8 +36,21 @@
#include <vlc_filter.h>
#include <vlc_rand.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
#include "filter_picture.h"
+#ifndef MAX
+# define MAX(x,y) ((x>y) ? x : y)
+#endif
+#ifndef MIN
+# define MIN(x,y) ((x<y) ? x : y)
+#endif
+
+#define init_countdown(init_val) ( (MAX( 1, 30000 - init_val)/20) / 2 + (
(unsigned) vlc_mrand48() ) % ( MAX( 1, ((30000 - init_val)/20) ) ) )
+
/***************************************************************************
**
* Module descriptor
****************************************************************************
*/
@@ -46,9 +60,33 @@
#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))
+
static int Open ( vlc_object_t * );
static void Close( vlc_object_t * );
@@ -65,65 +103,271 @@ 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;
+
+ int32_t i_actual_mirror; // +1 = without mirror ; -1 = with mirror
+ int8_t i_actual_angle; // 0 = 0°, 1 = 90°... rotation center = top-left
corner
+ 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;
+
+ bool b_finished;
+ bool b_overlap;
+
+ int32_t i_group_ID;
+} piece_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;
+ uint8_t i_planes;
+ int32_t i_piece_types;
+ uint32_t i_pieces_nbr;
+ bool b_preview;
+ int32_t i_preview_size;
+ int32_t i_shape_size;
+ int32_t i_border;
+ // game settings
+ int32_t i_auto_shuffle_speed, i_auto_solve_speed;
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
+} param_t;
+
+struct filter_sys_t {
+ bool b_init;
+ bool b_bake_request;
+ bool b_shape_init;
+ param_t s_allocated;
+ param_t s_current_param;
+ param_t s_new_param;
+ bool b_change_param;
+
bool b_finished;
+ uint32_t i_done_count, i_tmp_done_count;
- /* */
- struct
- {
- atomic_flag b_uptodate;
- atomic_bool b_blackslot;
- atomic_uint i_cols;
- atomic_uint i_rows;
- } change;
+ bool b_shuffleRqst;
+ bool b_mouse_drag;
+ bool b_mouse_mvt;
+ 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 void save(filter_t *p_filter);
+static void load( filter_t *p_filter);
+
#define SHUFFLE_WIDTH 81
#define SHUFFLE_HEIGHT 13
-static const char *shuffle_button[] =
-{
-"..........................................................................
.......",
-".............. ............................ ........ ......
...............",
-".............. ........................... ......... ........
...............",
-".............. ........................... ......... ........
...............",
-".. ....... . ....... .... ...... ...... ...... ........
...",
-". .... ...... ... ...... .... ....... ......... ........ .......
.. ..",
-". ........... .... ...... .... ....... ......... ........ ......
.... .",
-". ....... .... ...... .... ....... ......... ........ ......
.",
-".. ...... .... ...... .... ....... ......... ........ ......
.......",
-"...... ...... .... ...... .... ....... ......... ........ ......
.......",
-". .... ...... .... ...... ... ....... ......... ........ .......
.... .",
-".. ....... .... ....... . ....... ......... ........ ........
..",
-"..........................................................................
......."
+static const char *ppsz_shuffle_button[] =
+{
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
ooooooo",
+"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",
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
ooooooo"
+};
+
+#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
@@ -148,23 +392,76 @@ static int Open( vlc_object_t *p_this )
config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
p_filter->p_cfg );
+ p_sys->b_init = false;
+ p_sys->b_shuffleRqst = true;
+ p_sys->b_change_param = true;
+ p_sys->b_shape_init = false;
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_shapes = NULL;
+ p_sys->ps_pieces = NULL;
+ p_sys->ps_pieces_tmp = NULL;
+ p_sys->pi_group_qty = NULL;
+ p_sys->b_mouse_drag = false;
+ p_sys->b_mouse_mvt = false;
+ p_sys->i_mouse_drag_pce = -1;
+ p_sys->i_pointed_pce = -1;
+ p_sys->i_magnet_accuracy = 3;
+ p_sys->i_mouse_x = 0;
+ p_sys->i_mouse_y = 0;
+
+ vlc_mutex_init( &p_sys->lock );
+ vlc_mutex_init( &p_sys->pce_lock );
+
+ 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" );
- 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->i_preview_pos = 0;// 0=top-left, top-right, bottom right,
bottom-left
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 = malloc( sizeof( point_t *) * SHAPES_QTY );
+ 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;
}
@@ -179,8 +476,32 @@ static void Close( vlc_object_t *p_this )
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( p_sys->pi_order );
+ free_ps_puzzle_array ( p_filter );
+ free_ps_pieces_shapes ( p_filter);
+ free_ps_pieces ( p_filter );
+ if (p_sys->ps_desk_planes != NULL)
+ free(p_sys->ps_desk_planes);
+ if (p_sys->ps_pict_planes != NULL)
+ free(p_sys->ps_pict_planes);
+ if (p_sys->pi_order != NULL )
+ 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 );
}
@@ -190,158 +511,266 @@ static void Close( vlc_object_t *p_this )
*/
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 );
- }
+ // tailles des planes, positions et tailles des pieces dans l'image
d'origine, positions aciuelles des pieces
+ 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;
- /* */
- const int i_rows = p_sys->i_rows;
- const int i_cols = p_sys->i_cols;
+ 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;
- /* 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];
+ if ( p_sys->s_allocated.i_planes != p_pic_dst->i_planes)
+ p_sys->b_init = false;
- for( int i = 0; i < i_cols * i_rows; i++ )
- {
- int i_piece_height = p_out->i_visible_lines / i_rows;
- int i_piece_width = p_out->i_visible_pitch / i_cols;
+ p_sys->s_current_param.i_planes = p_pic_dst->i_planes;
- 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->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;
+ }
+ }
- 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;
+ 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;
- 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 );
- }
- }
+ vlc_mutex_lock( &p_sys->lock );
- /* 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 );
- }
+ 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;
}
- }
- /* 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++ )
+ 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 )
{
- for( int j = 0; j < SHUFFLE_WIDTH; j++ )
- {
- if( shuffle_button[i][j] == '.' )
- p_out->p_pixels[ i * p_out->i_pitch + j ] = 0xff;
- }
+ p_sys->b_bake_request = true;
+ p_sys->b_shape_init = false;
}
- }
- return CopyInfoAndRelease( p_outpic, p_pic );
-}
+ if ( p_sys->s_current_param.b_blackslot !=
p_sys->s_new_param.b_blackslot
+ && p_sys->i_selected == -1
+ && p_sys->s_current_param.b_blackslot )
+ p_sys->i_selected = 0;
-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;
+ 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);
- /* 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->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);
- /* */
- const bool b_clicked = vlc_mouse_HasPressed( p_old, p_new,
MOUSE_BUTTON_LEFT );
+ 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;
+ }
- /* If the puzzle is finished, shuffle it if needed */
- if( p_sys->b_finished )
+ vlc_mutex_unlock( &p_sys->lock );
+
+ // 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
{
- if( b_clicked &&
- p_new->i_x < SHUFFLE_WIDTH && p_new->i_y < SHUFFLE_HEIGHT )
+ // 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 );
+ }
+
+ // bake initial puzzle data & shapes
+ if ( p_sys->b_bake_request )
+ {
+ if (!p_sys->b_shuffleRqst)
{
- atomic_flag_clear( &p_sys->change.b_uptodate );
- return VLC_EGENERIC;
+ save(p_filter);
+ bake_puzzle( p_filter, p_pic_dst, p_pic );
+ load( p_filter);
}
else
{
- /* This is the only case where we can forward the mouse */
- *p_mouse = *p_new;
- return VLC_SUCCESS;
+ ret = bake_puzzle( p_filter, p_pic_dst, p_pic );
+ if ( ret !=0 )
+ return CopyInfoAndRelease( p_pic_dst, p_pic );
}
}
- 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;
+ // shuffle the desk and generate data
+ if ( p_sys->b_shuffleRqst && p_sys->b_init )
+ bake_piece ( p_filter );
- if( p_sys->i_selected == -1 )
- {
- p_sys->i_selected = i_pos;
+ vlc_mutex_lock( &p_sys->pce_lock );
+
+ // 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 );
}
- else if( p_sys->i_selected == i_pos && !p_sys->b_blackslot )
+
+ 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 )
{
- p_sys->i_selected = -1;
+ // computer moves some piece:
+ auto_shuffle( p_filter );
+ auto_solve( p_filter );
}
- 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 )
+
+ vlc_mutex_unlock( &p_sys->pce_lock );
+
+ if ( !p_sys->b_bake_request && p_sys->b_init && p_sys->ps_puzzle_array
!= NULL )
{
- /* 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;
+ // generate output pic:
+ puzzle_draw_borders(p_filter, p_pic, p_pic_dst);
+
+ p_sys->i_pointed_pce = -1;
+ puzzle_draw_pieces(p_filter, p_pic, p_pic_dst);
+
+ if (p_sys->i_pointed_pce == -1)
+ 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 != -1 && !p_sys->s_current_param.b_blackslot
&& !p_sys->s_current_param.b_advanced )
+ {
+ 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);
+ }
+
+ if ( p_sys->i_selected != -1 && p_sys->s_current_param.b_blackslot
&& !p_sys->s_current_param.b_advanced )
+ {
+ 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);
+ }
+
+ /* 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);
+
+ // draw an arrow to indicate rotation
+ if ((p_sys->i_mouse_drag_pce != -1) && !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;
+
+ 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 );
+ }
- p_sys->i_selected = p_sys->b_blackslot ? i_pos : -1;
- p_sys->b_finished = IsFinished( p_sys );
}
- return VLC_EGENERIC;
+
+ return CopyInfoAndRelease( p_pic_dst, p_pic );
}
/***************************************************************************
**
@@ -352,90 +781,2756 @@ 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" ) )
- atomic_store( &p_sys->change.i_rows, __MAX( 2, newval.i_int ) );
+ {
+ p_sys->s_new_param.i_rows = __MAX( 1, newval.i_int );
+ }
else if( !strcmp( psz_var, CFG_PREFIX "cols" ) )
- atomic_store( &p_sys->change.i_cols, __MAX( 2, newval.i_int ) );
+ {
+ p_sys->s_new_param.i_cols = __MAX( 1, 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->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;
+ }
+
+ 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++ )
+ filter_sys_t *p_sys = p_filter->p_sys;
+ const video_format_t *p_fmt = &p_filter->fmt_in.video;
+
+ /* 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_init || p_sys->b_change_param)
{
- if( i != p_sys->pi_order[i] )
- return false;
+ *p_mouse = *p_new;
+ return VLC_SUCCESS;
}
- return true;
-}
-
-static bool IsValid( filter_sys_t *p_sys )
-{
- const int i_count = p_sys->i_cols * p_sys->i_rows;
- if( !p_sys->b_blackslot )
- return true;
+ p_sys->i_mouse_x = p_new->i_x;
+ p_sys->i_mouse_y = p_new->i_y;
- int d = 0;
- for( int i = 0; i < i_count; i++ )
+ /* If the puzzle is finished, shuffle it if needed */
+ if( p_sys->b_finished )
{
- if( p_sys->pi_order[i] == i_count - 1 )
+ 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 );
+
+ 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);
- free( p_sys->pi_order );
+ 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;
- p_sys->pi_order = calloc( i_count, sizeof(*p_sys->pi_order) );
- do
+ // 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 == -1 )
+ {
+ 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 : -1;
+ 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++;
- }
- p_sys->b_finished = IsFinished( p_sys );
- } while( p_sys->b_finished || !IsValid( p_sys ) );
+ vlc_mutex_lock( &p_sys->pce_lock );
- if( p_sys->b_blackslot )
- {
- for( unsigned i = 0; i < i_count; i++ )
+ if (p_sys->i_mouse_drag_pce != -1)
+ {
+ piece_foreground( p_filter, p_sys->i_mouse_drag_pce);
+ p_sys->i_mouse_drag_pce = 0;
+
+ int32_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 );
+
+ }
+ else if( vlc_mouse_HasReleased( p_old, p_new, MOUSE_BUTTON_LEFT ) )
{
- if( p_sys->pi_order[i] == (int)i_count - 1 )
+ if ( !p_sys->b_mouse_mvt && p_sys->b_mouse_drag )
{
- p_sys->i_selected = i;
- break;
+ // 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 );
+
+ int32_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 )
+ 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
+ {
+ // check if the mouse is in the preview area
+ switch ( p_sys->i_preview_pos )
+ {
+ 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 );
+ }
+ }
+ }
+ }
+ 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;
+ if (p_sys->s_current_param.b_advanced) {
+ p_sys->s_allocated.i_piece_types = PIECE_TYPE_NBR;
+ } else {
+ p_sys->s_allocated.i_piece_types = 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 != 0)
+ 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 != 0)
+ return ret;
+ }
+
+ ret = bake_piece ( p_filter );
+ if (ret != 0)
+ 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 0;
+}
+
+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 0;
+}
+
+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;
+
+ if (p_sys->ps_desk_planes != NULL)
+ free ( p_sys->ps_desk_planes );
+ p_sys->ps_desk_planes = NULL;
+
+ if (p_sys->ps_pict_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;
+
+ 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 0;
+}
+
+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;
+
+ if (p_sys->pi_order != NULL)
+ free( p_sys->pi_order );
+ p_sys->pi_order = NULL;
+
+ if (p_sys->ps_pieces_tmp != NULL)
+ free( p_sys->ps_pieces_tmp );
+ p_sys->ps_pieces_tmp = NULL;
+
+ if (p_sys->pi_group_qty != 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 0;
+}
+
+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)
+ {
+ 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;
+ }
+
+ return;
+}
+
+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 = -1;
}
+
+ 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] = -1;
+
+ for( int32_t c = 0; c < i_pieces_nbr; )
+ {
+ int32_t i = ((unsigned)vlc_mrand48()) % i_pieces_nbr;
+ if( (*pi_pce_lst)[i] == -1 )
+ (*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 != -1 ) && (
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
+ int32_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, (int32_t) 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);
+ }
+
+ int32_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);
+ }
+
+ int32_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 ) {
+ int32_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++)
+ {
+ int32_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++)
+ {
+ int32_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;
+ int32_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 = 0;
+ uint32_t i_top_pce = 0;
+ uint32_t i_btm_pce = 0;
+
+ 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)
+ {
+ if (p_sys->i_mouse_x ==
i_current_dst_x )
+ {
+ if
(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);
+
+}
+
+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 = ( 1 - f_sub_t ) * ( 1 - f_sub_t ) * ( 1 - f_sub_t ) *
ps_new_pt[ 3 * i_main_t ].f_x
+ + 3 * f_sub_t * ( 1 - f_sub_t ) * ( 1 - f_sub_t ) *
ps_new_pt[ 3 * i_main_t + 1 ].f_x
+ + 3 * f_sub_t * f_sub_t * ( 1 - f_sub_t ) * ps_new_pt[
3 * i_main_t + 2 ].f_x
+ + f_sub_t * f_sub_t * f_sub_t * ps_new_pt[ 3 * i_main_t
+ 3 ].f_x;
+
+ f_bez_y = ( 1 - f_sub_t ) * ( 1 - f_sub_t ) * ( 1 - f_sub_t ) *
ps_new_pt[ 3 * i_main_t ].f_y
+ + 3 * f_sub_t * ( 1 - f_sub_t ) * ( 1 - f_sub_t ) *
ps_new_pt[ 3 * i_main_t + 1 ].f_y
+ + 3 * f_sub_t * f_sub_t * ( 1 - f_sub_t ) * ps_new_pt[
3 * i_main_t + 2 ].f_y
+ + f_sub_t * f_sub_t * f_sub_t * ps_new_pt[ 3 * i_main_t
+ 3 ].f_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 = ( 1 - f_sub_t ) * ( 1 - f_sub_t ) * ( 1 - f_sub_t ) *
ps_pt[ 3 * i_main_t ].f_y
+ + 3 * f_sub_t * ( 1 - f_sub_t ) * ( 1 - f_sub_t ) * ps_pt[
3 * i_main_t + 1 ].f_y
+ + 3 * f_sub_t * f_sub_t * ( 1 - f_sub_t ) * ps_pt[ 3 *
i_main_t + 2 ].f_y
+ + f_sub_t * f_sub_t * f_sub_t * ps_pt[ 3 * i_main_t + 3
].f_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 = ( 1 - f_sub_t ) * ( 1 - f_sub_t ) * ( 1 - f_sub_t ) *
ps_pt[ 3 * i_main_t ].f_x
+ + 3 * f_sub_t * ( 1 - f_sub_t ) * ( 1 - f_sub_t ) *
ps_pt[ 3 * i_main_t + 1 ].f_x
+ + 3 * f_sub_t * f_sub_t * ( 1 - f_sub_t ) * ps_pt[ 3 *
i_main_t + 2 ].f_x
+ + f_sub_t * f_sub_t * f_sub_t * ps_pt[ 3 * i_main_t + 3
].f_x;
+
+ f_bez_y = ( 1 - f_sub_t ) * ( 1 - f_sub_t ) * ( 1 - f_sub_t ) *
ps_pt[ 3 * i_main_t ].f_y
+ + 3 * f_sub_t * ( 1 - f_sub_t ) * ( 1 - f_sub_t ) *
ps_pt[ 3 * i_main_t + 1 ].f_y
+ + 3 * f_sub_t * f_sub_t * ( 1 - f_sub_t ) * ps_pt[ 3 *
i_main_t + 2 ].f_y
+ + f_sub_t * f_sub_t * f_sub_t * ps_pt[ 3 * i_main_t + 3
].f_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;
+ if ( i_y < 0 )
+ i_last_x = 0;
+ else
+ i_last_x = diagonal_limit( p_filter, i_y, true, i_plane ); //
first diagonal intersection
+
+ 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 = ( 1 - f_sub_t ) * ( 1 - f_sub_t ) * ( 1 - f_sub_t ) *
ps_pt[ 3 * i_main_t ].f_x
+ + 3 * f_sub_t * ( 1 - f_sub_t ) * ( 1 - f_sub_t ) * ps_pt[
3 * i_main_t + 1 ].f_x
+ + 3 * f_sub_t * f_sub_t * ( 1 - f_sub_t ) * ps_pt[ 3 *
i_main_t + 2 ].f_x
+ + f_sub_t * f_sub_t * f_sub_t * ps_pt[ 3 * i_main_t + 3
].f_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 = ( 1 - f_sub_t ) * ( 1 - f_sub_t ) * ( 1 - f_sub_t ) *
ps_pt[ 3 * i_main_t ].f_x
+ + 3 * f_sub_t * ( 1 - f_sub_t ) * ( 1 - f_sub_t ) *
ps_pt[ 3 * i_main_t + 1 ].f_x
+ + 3 * f_sub_t * f_sub_t * ( 1 - f_sub_t ) * ps_pt[ 3 *
i_main_t + 2 ].f_x
+ + f_sub_t * f_sub_t * f_sub_t * ps_pt[ 3 * i_main_t + 3
].f_x;
+
+ f_bez_y = ( 1 - f_sub_t ) * ( 1 - f_sub_t ) * ( 1 - f_sub_t ) *
ps_pt[ 3 * i_main_t ].f_y
+ + 3 * f_sub_t * ( 1 - f_sub_t ) * ( 1 - f_sub_t ) *
ps_pt[ 3 * i_main_t + 1 ].f_y
+ + 3 * f_sub_t * f_sub_t * ( 1 - f_sub_t ) * ps_pt[ 3 *
i_main_t + 2 ].f_y
+ + f_sub_t * f_sub_t * f_sub_t * ps_pt[ 3 * i_main_t + 3
].f_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;
+ 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_widt
h
+ + (i_s == 0 ? i_left_adjust : (i_s ==
i_section_nbr-1 ? i_right_adjust : 0));
+ }
+ }
+ }
+}
+
+static void save(filter_t *p_filter)
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ FILE *ofp;
+ char sav_filename[] = "pzl_001.sav";
+
+ uint32_t i_orow, i_ocol;
+ int8_t i_angle, i_mirror;
+ float f_pos_x, f_pos_y;
+
+ ofp = fopen(sav_filename, "w");
+
+ if (ofp != NULL) {
+ fprintf(ofp, "%d %d %d\n", p_sys->s_allocated.i_rows,
p_sys->s_allocated.i_cols, p_sys->s_allocated.i_rotate);
+
+ uint32_t i=0;
+ for (uint32_t i_row = 0; i_row < (uint32_t)
p_sys->s_allocated.i_rows; i_row++)
+ for (uint32_t i_col = 0; i_col < (uint32_t)
p_sys->s_allocated.i_cols; i_col++)
+ {
+ int32_t i_border;
+ i_border = p_sys->ps_desk_planes[0].i_visible_pitch *
(p_sys->s_current_param.i_border / 100 / 2);
+ f_pos_x = (
p_sys->ps_pieces[i].ps_piece_in_plane[0].i_actual_x - i_border ) /
((float)p_sys->ps_desk_planes[0].i_visible_pitch - 2*i_border);
+ i_border = p_sys->ps_desk_planes[0].i_visible_lines *
(p_sys->s_current_param.i_border / 100 / 2);
+ f_pos_y = (
p_sys->ps_pieces[i].ps_piece_in_plane[0].i_actual_y - i_border ) /
((float)p_sys->ps_desk_planes[0].i_visible_lines - 2*i_border);
+ i_orow = p_sys->ps_pieces[i].i_original_row;
+ i_ocol = p_sys->ps_pieces[i].i_original_col;
+ i_angle = p_sys->ps_pieces[i].i_actual_angle;
+ i_mirror = p_sys->ps_pieces[i].i_actual_mirror;
+
+ fprintf(ofp, "%d %d %f %f %d %d\n", i_orow, i_ocol,
f_pos_x, f_pos_y, i_angle, i_mirror);
+ fprintf(ofp, "%d %d %d %d\n",
p_sys->ps_pieces[i].i_top_shape, p_sys->ps_pieces[i].i_btm_shape,
p_sys->ps_pieces[i].i_right_shape, p_sys->ps_pieces[i].i_left_shape);
+
+ i++;
+ }
+
+ fclose(ofp);
+ }
+}
+
+static void load( filter_t *p_filter)
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ FILE *ifp;
+ char sav_filename[] = "pzl_001.sav";
+
+ ifp = fopen(sav_filename, "r");
+
+ if (ifp != NULL) {
+
+ if (feof(ifp))
+ return;
+
+ int i_rows, i_cols;
+ int i_rotate;
+
+ if (feof(ifp) || (fscanf(ifp, "%d %d %d", &i_rows, &i_cols,
&i_rotate) != 3))
+ return;
+
+ if (p_sys->s_current_param.i_cols != i_cols ||
p_sys->s_allocated.i_rows != i_rows || p_sys->s_allocated.i_rotate !=
i_rotate)
+ return;
+
+ int i_orow, i_ocol;
+ int i_angle, i_mirror;
+ float f_pos_x, f_pos_y;
+ int i_top_shape, i_btm_shape, i_right_shape, i_left_shape;
+
+ for (uint32_t i_sav_pce=0; i_sav_pce <
p_sys->s_allocated.i_pieces_nbr; i_sav_pce++) {
+ if (feof(ifp) || (fscanf(ifp, "%d %d %f %f %d %d", &i_orow,
&i_ocol, &f_pos_x, &f_pos_y, &i_angle, &i_mirror) != 6))
+ return;
+ if (feof(ifp) || (fscanf(ifp, "%d %d %d %d", &i_top_shape,
&i_btm_shape, &i_right_shape, &i_left_shape) != 4))
+ return;
+
+ for (uint32_t i=0; i < p_sys->s_allocated.i_pieces_nbr; i++)
+ if (p_sys->ps_pieces[i].i_original_row == i_orow &&
p_sys->ps_pieces[i].i_original_col == i_ocol) {
+
+ int32_t i_border;
+ i_border = p_sys->ps_desk_planes[0].i_visible_pitch *
(p_sys->s_current_param.i_border / 100 / 2);
+ p_sys->ps_pieces[i].ps_piece_in_plane[0].i_actual_x =
+ i_border +
((float)p_sys->ps_desk_planes[0].i_visible_pitch - 2*i_border) * f_pos_x;
+ i_border = p_sys->ps_desk_planes[0].i_visible_lines *
(p_sys->s_current_param.i_border / 100 / 2);
+ p_sys->ps_pieces[i].ps_piece_in_plane[0].i_actual_y =
+ i_border +
((float)p_sys->ps_desk_planes[0].i_visible_lines - 2*i_border) * f_pos_y;
+
+ p_sys->ps_pieces[i].i_top_shape = i_top_shape;
+ p_sys->ps_pieces[i].i_btm_shape = i_btm_shape;
+ p_sys->ps_pieces[i].i_right_shape = i_right_shape;
+ p_sys->ps_pieces[i].i_left_shape = i_left_shape;
+ p_sys->ps_pieces[i].i_actual_angle = i_angle;
+ p_sys->ps_pieces[i].i_actual_mirror = i_mirror;
+ p_sys->ps_pieces[i].i_group_ID = i_sav_pce;
+ p_sys->ps_pieces[i].b_finished = false;
+
+ calculate_corners( p_filter, i );
+
+ break;
+ }
+ }
+
+ fclose(ifp);
+ }
}
--
1.7.9.5
More information about the vlc-devel
mailing list