event_handling.c \
fractals.c \
pixel.c \
+ cleanup.c \
+ drawing.c \
+ init.c \
+ parsing.c \
+ trans_view.c \
SRCS := $(addprefix $(SRCDIR)/, $(SRCS))
/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/11 18:51:29 by ljiriste #+# #+# */
-/* Updated: 2024/04/26 10:16:03 by ljiriste ### ########.fr */
+/* Updated: 2024/04/26 11:01:18 by ljiriste ### ########.fr */
/* */
/* ************************************************************************** */
};
typedef struct s_session t_session;
-int handle_key_press(int keycode, t_session *s);
-int handle_mouse_press(int button, int x, int y, t_session *s);
-int no_event_handle(t_session *s);
-void process_pixel_group(t_session *s, int x, int y);
-void calculate_base(t_session *s);
+int handle_key_press(int keycode, t_session *s);
+int handle_mouse_press(int button, int x, int y, t_session *s);
+int no_event_handle(t_session *s);
+
+int parse_args(int argc, char **argv, t_session *s);
+
void draw_fractal(t_session *s);
void pure_draw_fractal(t_session *s);
+void erase_calced(t_mat *calced);
+
void change_zoom(t_session *s, t_vect2 invariant, double d_zoom);
+void change_shift_speed(double *speed, double mult, double thresh);
void move_view(t_session *s, float move_amount_right, float move_amount_up);
-int close_win(t_session *s);
-void erase_calced(t_mat *calced);
+int close_win(t_session *s);
+void cleanup(t_session *s);
+
+void init_session(t_session *s);
#endif
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* cleanup.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/04/26 10:51:11 by ljiriste #+# #+# */
+/* Updated: 2024/04/26 11:02:49 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "fractol.h"
+#include "libft.h"
+#include <mlx.h>
+#include <stdlib.h>
+
+int close_win(t_session *s)
+{
+ mlx_destroy_window(s->mlx, s->win);
+ s->win = NULL;
+ return (0);
+}
+
+static void free_session(t_session *s)
+{
+ mlx_destroy_display(s->mlx);
+ free(s->mlx);
+ return ;
+}
+
+void cleanup(t_session *s)
+{
+ ft_mat_free(&s->img.calced, NULL);
+ ft_mat_free(&s->img.base, NULL);
+ mlx_destroy_image(s->mlx, s->img.img);
+ free_session(s);
+ return ;
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* drawing.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/04/26 10:44:28 by ljiriste #+# #+# */
+/* Updated: 2024/04/26 11:04:24 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "pixel.h"
+#include "fractol.h"
+#include "libft.h"
+#include <mlx.h>
+#include <stdbool.h>
+#include <math.h>
+
+static void process_pixel_group(t_session *s, int x, int y)
+{
+ int i;
+ int j;
+ double param;
+
+ if (!*(bool *)ft_mat_access(&s->img.calced, y, x))
+ param = s->view.fractal(&s->set,
+ s->view.window_coord.x + s->view.pixel_size.x * x,
+ s->view.window_coord.y - s->view.pixel_size.y * y);
+ else
+ param = *(double *)ft_mat_access(&s->img.base, y, x);
+ i = 0;
+ while (i < s->img.undersample && x + i < s->img.width)
+ {
+ j = 0;
+ while (j < s->img.undersample && y + j < s->img.height)
+ {
+ if (!*(bool *)ft_mat_access(&s->img.calced, y + j, x + i))
+ *(double *)ft_mat_access(&s->img.base, y + j, x + i) = param;
+ ++j;
+ }
+ ++i;
+ }
+ *(bool *)ft_mat_access(&s->img.calced, y, x) = 1;
+ return ;
+}
+
+static void calculate_base(t_session *s)
+{
+ int x;
+ int y;
+
+ x = 0;
+ while (x < s->img.width)
+ {
+ y = 0;
+ while (y < s->img.height)
+ {
+ process_pixel_group(s, x, y);
+ y += s->img.undersample;
+ }
+ x += s->img.undersample;
+ }
+}
+
+void pure_draw_fractal(t_session *s)
+{
+ int x;
+ int y;
+ double param;
+
+ x = 0;
+ while (x < s->img.width)
+ {
+ y = 0;
+ while (y < s->img.height)
+ {
+ param = *(double *)ft_mat_access(&s->img.base, y, x);
+ if (param >= 0)
+ param = fmod(param + s->view.color_shift, 1.);
+ ft_putpx_img(&s->img, x, y, s->view.palette(param));
+ ++y;
+ }
+ ++x;
+ }
+ mlx_put_image_to_window(s->mlx, s->win, s->img.img, 0, 0);
+ return ;
+}
+
+void draw_fractal(t_session *s)
+{
+ calculate_base(s);
+ pure_draw_fractal(s);
+ return ;
+}
+
+void erase_calced(t_mat *calced)
+{
+ size_t i;
+ size_t j;
+
+ i = 0;
+ while (i < calced->rows)
+ {
+ j = 0;
+ while (j < calced->cols)
+ {
+ *(bool *)ft_mat_access(calced, i, j) = false;
+ ++j;
+ }
+ ++i;
+ }
+ return ;
+}
/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/05 19:35:01 by ljiriste #+# #+# */
-/* Updated: 2024/04/26 10:14:40 by ljiriste ### ########.fr */
+/* Updated: 2024/04/26 11:02:11 by ljiriste ### ########.fr */
/* */
/* ************************************************************************** */
#define SHIFT_MULT 1.2
#define SHIFT_THRESH 0.0001
-void redraw(t_session *s)
+static void set_for_redraw(t_session *s)
{
erase_calced(&s->img.calced);
s->img.undersample = s->img.undersample_max;
return ;
}
-void change_shift_speed(double *speed, double mult, double thresh)
-{
- if (-thresh < *speed && *speed < thresh)
- {
- if (mult > 0)
- *speed = thresh;
- else
- *speed = -thresh;
- return ;
- }
- if (*speed > 0 && mult > 0)
- *speed *= mult;
- else if (*speed > 0 && mult < 0)
- *speed /= -mult;
- else if (*speed < 0 && mult < 0)
- *speed *= -mult;
- else if (*speed < 0 && mult > 0)
- *speed /= mult;
- if (-thresh < *speed && *speed < thresh)
- *speed = 0;
- return ;
-}
-
static void additional_keys(int keycode, t_session *s)
{
if (keycode == XK_KP_Multiply)
if (s->set.detail * DETAIL_MULT > s->set.detail)
{
s->set.detail *= DETAIL_MULT;
- redraw(s);
+ set_for_redraw(s);
}
}
else if (keycode == XK_KP_Divide)
if (s->set.detail >= DETAIL_MULT)
{
s->set.detail /= DETAIL_MULT;
- redraw(s);
+ set_for_redraw(s);
}
}
else if (keycode == XK_KP_Up)
change_zoom(s, (t_vect2){.x = s->img.width / 2,
.y = s->img.height / 2}, ZOOM_OUT);
else if (keycode == XK_r)
- redraw(s);
+ set_for_redraw(s);
else
additional_keys(keycode, s);
if (keycode != XK_Escape)
/* valgrind indicates an issue when the draw_fractal is in proccess
* while and ESC is pressed thus ending the program.
*
- * Setting the condition to less than 1 basically turns this redrawing
+ * Setting the condition to less than 1 basically turns this set_for_redrawing
* off.
*/
int no_event_handle(t_session *s)
if (s->img.undersample > 1)
{
--s->img.undersample;
- calculate_base(s);
+ draw_fractal(s);
}
- pure_draw_fractal(s);
+ else
+ pure_draw_fractal(s);
s->view.color_shift
= fmod(s->view.color_shift + s->view.color_shift_speed, 1.);
if (s->view.color_shift < 0)
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* init.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/04/26 10:53:46 by ljiriste #+# #+# */
+/* Updated: 2024/04/26 11:05:51 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "fractol.h"
+#include "libft.h"
+#include <mlx.h>
+#include <stdbool.h>
+
+static void init_view(t_session *s)
+{
+ s->view.window_coord.x = -s->img.width / 2 * s->view.pixel_size.x;
+ s->view.window_coord.y = s->img.height / 2 * s->view.pixel_size.y;
+ return ;
+}
+
+void init_session(t_session *s)
+{
+ init_view(s);
+ s->mlx = mlx_init();
+ s->win = mlx_new_window(s->mlx, s->img.width, s->img.height, "Fract-ol");
+ s->img.img = mlx_new_image(s->mlx, s->img.width, s->img.height);
+ s->img.addr = mlx_get_data_addr(s->img.img,
+ &s->img.bpp, &s->img.bpl, &s->img.endian);
+ ft_mat_init(&s->img.calced, sizeof(bool));
+ ft_mat_init(&s->img.base, sizeof(double));
+ ft_mat_zeros(&s->img.calced, s->img.height, s->img.width);
+ ft_mat_zeros(&s->img.base, s->img.height, s->img.width);
+ s->img.undersample = s->img.undersample_max;
+}
/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/27 14:29:26 by ljiriste #+# #+# */
-/* Updated: 2024/04/26 10:15:44 by ljiriste ### ########.fr */
+/* Updated: 2024/04/26 11:08:47 by ljiriste ### ########.fr */
/* */
/* ************************************************************************** */
-#include "complex.h"
-#include "color.h"
-#include "vect2.h"
-#include "fractals.h"
-#include "pixel.h"
#include "fractol.h"
#include "libft.h"
#include <mlx.h>
#include <math.h>
-#include <stdbool.h>
#include <stdlib.h>
#include <X11/keysym.h>
#include <X11/X.h>
-int close_win(t_session *s)
-{
- mlx_destroy_window(s->mlx, s->win);
- s->win = NULL;
- return (0);
-}
-
-void free_session(t_session *s)
-{
- mlx_destroy_display(s->mlx);
- free(s->mlx);
- return ;
-}
-
-void process_pixel_group(t_session *s, int x, int y)
-{
- int i;
- int j;
- double param;
-
- if (!*(bool *)ft_mat_access(&s->img.calced, y, x))
- param = s->view.fractal(&s->set,
- s->view.window_coord.x + s->view.pixel_size.x * x,
- s->view.window_coord.y - s->view.pixel_size.y * y);
- else
- param = *(double *)ft_mat_access(&s->img.base, y, x);
- i = 0;
- while (i < s->img.undersample && x + i < s->img.width)
- {
- j = 0;
- while (j < s->img.undersample && y + j < s->img.height)
- {
- if (!*(bool *)ft_mat_access(&s->img.calced, y + j, x + i))
- *(double *)ft_mat_access(&s->img.base, y + j, x + i) = param;
- ++j;
- }
- ++i;
- }
- *(bool *)ft_mat_access(&s->img.calced, y, x) = 1;
- return ;
-}
-
-void calculate_base(t_session *s)
-{
- int x;
- int y;
-
- x = 0;
- while (x < s->img.width)
- {
- y = 0;
- while (y < s->img.height)
- {
- process_pixel_group(s, x, y);
- y += s->img.undersample;
- }
- x += s->img.undersample;
- }
-}
-
-void pure_draw_fractal(t_session *s)
-{
- int x;
- int y;
- double param;
-
- x = 0;
- while (x < s->img.width)
- {
- y = 0;
- while (y < s->img.height)
- {
- param = *(double *)ft_mat_access(&s->img.base, y, x);
- if (param >= 0)
- param = fmod(param + s->view.color_shift, 1.);
- ft_putpx_img(&s->img, x, y, s->view.palette(param));
- ++y;
- }
- ++x;
- }
- mlx_put_image_to_window(s->mlx, s->win, s->img.img, 0, 0);
- return ;
-}
-
-void draw_fractal(t_session *s)
-{
- calculate_base(s);
- pure_draw_fractal(s);
- return ;
-}
-
-void erase_calced(t_mat *calced)
-{
- size_t i;
- size_t j;
-
- i = 0;
- while (i < calced->rows)
- {
- j = 0;
- while (j < calced->cols)
- {
- *(bool *)ft_mat_access(calced, i, j) = false;
- ++j;
- }
- ++i;
- }
- return ;
-}
-
-void change_zoom(t_session *s, t_vect2 invariant, double d_zoom)
-{
- s->view.pixel_size.x /= d_zoom;
- s->view.pixel_size.y /= d_zoom;
- s->view.window_coord.x += s->view.pixel_size.x * invariant.x * (d_zoom - 1);
- s->view.window_coord.y -= s->view.pixel_size.y * invariant.y * (d_zoom - 1);
- erase_calced(&s->img.calced);
- s->img.undersample = s->img.undersample_max;
- return ;
-}
-
-void move_pixel(t_img *img, t_vect2 old, t_vect2 new)
-{
- *(double *)ft_mat_access(&img->base, new.y, new.x)
- = *(double *)ft_mat_access(&img->base, old.y, old.x);
- *(bool *)ft_mat_access(&img->calced, new.y, new.x)
- = *(bool *)ft_mat_access(&img->calced, old.y, old.x);
- return ;
-}
-
-void move_img(t_img *img, int delta_x, int delta_y)
-{
- int x;
- int y;
-
- x = 0;
- if (delta_x < 0)
- x = img->width - 1;
- while (0 <= x && x < img->width)
- {
- y = 0;
- if (delta_y < 0)
- y = img->height - 1;
- while (0 <= y && y < img->height)
- {
- if (0 <= x - delta_x && x - delta_x < img->width
- && 0 <= y - delta_y && y - delta_y < img->height)
- move_pixel(img, (t_vect2){.x = x, .y = y},
- (t_vect2){.x = x - delta_x, .y = y - delta_y});
- if (!(0 <= x + delta_x && x + delta_x < img->width
- && 0 <= y + delta_y && y + delta_y < img->height))
- *(bool *)ft_mat_access(&img->calced, y, x) = false;
- y += 1 - 2 * (delta_y < 0);
- }
- x += 1 - 2 * (delta_x < 0);
- }
- return ;
-}
-
-// move_amount is ratio of move distance to length one can see
-void move_view(t_session *s, float move_amount_right, float move_amount_up)
-{
- int x_pix_change;
- int y_pix_change;
-
- x_pix_change = round(move_amount_right * s->img.height);
- if (x_pix_change == 0)
- x_pix_change = (move_amount_right > 0) - (move_amount_right < 0);
- y_pix_change = -round(move_amount_up * s->img.height);
- if (y_pix_change == 0)
- y_pix_change = -((move_amount_up > 0) - (move_amount_up < 0));
- s->view.window_coord.x += x_pix_change * s->view.pixel_size.x;
- s->view.window_coord.y -= y_pix_change * s->view.pixel_size.y;
- move_img(&s->img, x_pix_change, y_pix_change);
- s->img.undersample = s->img.undersample_max;
- return ;
-}
-
-void init_session(t_session *s)
-{
- s->mlx = mlx_init();
- s->win = mlx_new_window(s->mlx, s->img.width, s->img.height, "Fract-ol");
- s->img.img = mlx_new_image(s->mlx, s->img.width, s->img.height);
- s->img.addr = mlx_get_data_addr(s->img.img,
- &s->img.bpp, &s->img.bpl, &s->img.endian);
- ft_mat_init(&s->img.calced, sizeof(bool));
- ft_mat_init(&s->img.base, sizeof(double));
- ft_mat_zeros(&s->img.calced, s->img.height, s->img.width);
- ft_mat_zeros(&s->img.base, s->img.height, s->img.width);
- s->img.undersample = s->img.undersample_max;
-}
-
-static void init_view(t_session *s)
-{
- s->view.window_coord.x = -s->img.width / 2 * s->view.pixel_size.x;
- s->view.window_coord.y = s->img.height / 2 * s->view.pixel_size.y;
- return ;
-}
-
void set_default(t_session *s)
{
s->img.width = 1920;
return ;
}
-t_fractal to_fractal(const char *name)
-{
- if (!ft_strcmp(name, "man") || !ft_strcmp(name, "mandelbrot"))
- return (mandelbrot);
- else if (!ft_strcmp(name, "tri") || !ft_strcmp(name, "tricorn"))
- return (tricorn);
- else if (!ft_strcmp(name, "ju") || !ft_strcmp(name, "julia"))
- return (julia);
- else
- return (NULL);
-}
-
-// The input has to be a single string of the form i1,i2,... without whitespace
-// There has to be correct number of inputs for the chosen fractal
-// The input has to be composed of integers
-int is_correct_input(const char *str, t_fractal fractal)
-{
- int count;
-
- count = 0;
- while (*str)
- {
- ++count;
- while (ft_isdigit(*str) || *str == '-')
- ++str;
- if (*str == ',')
- ++str;
- else if (*str != '\0')
- return (0);
- }
- if (fractal == julia && count != 2)
- return (0);
- return (1);
-}
-
-t_input parse_input(const char *str, t_fractal fractal)
-{
- t_input res;
-
- if (fractal == julia)
- {
- res.cpx.r = ft_atoi(str) / 1000.;
- while (ft_isdigit(*str) || *str == '-')
- ++str;
- ++str;
- res.cpx.i = ft_atoi(str) / 1000.;
- }
- return (res);
-}
-
-int parse_arg(char **argv, t_session *s, int *i)
-{
- if (!ft_strcmp(argv[*i], "-w")
- && ft_isint(argv[*i + 1]) && ft_atoi(argv[*i + 1]) > 0)
- s->img.width = ft_atoi(argv[++*i]);
- else if (!ft_strcmp(argv[*i], "-h")
- && ft_isint(argv[*i + 1]) && ft_atoi(argv[*i + 1]) > 0)
- s->img.height = ft_atoi(argv[++*i]);
- else if (!ft_strcmp(argv[*i], "-u")
- && ft_isint(argv[*i + 1]) && ft_atoi(argv[*i + 1]) >= 0)
- s->img.undersample_max = ft_atoi(argv[++*i]);
- else if (!ft_strcmp(argv[*i], "-d") && ft_isint(argv[*i + 1]))
- s->set.detail = ft_atoi(argv[++*i]);
- else if (!ft_strcmp(argv[*i], "-f") && to_fractal(argv[*i + 1]) != NULL)
- s->view.fractal = to_fractal(argv[++*i]);
- else if (!ft_strcmp(argv[*i], "-s") && ft_isint(argv[*i + 1]))
- s->view.color_shift_speed = ft_atoi(argv[++*i]) / 1000.;
- else if (!ft_strcmp(argv[*i], "-c") && ft_isint(argv[*i + 1]))
- s->set.color_stability = 10000 / ft_atoi(argv[++*i]);
- else if (!ft_strcmp(argv[*i], "-i")
- && is_correct_input(argv[*i + 1], s->view.fractal))
- s->set.input = parse_input(argv[++*i], s->view.fractal);
- else
- return (1);
- return (0);
-}
-
-int parse_args(int argc, char **argv, t_session *s)
-{
- int i;
-
- if (argc % 2 == 0)
- return (1);
- set_default(s);
- i = 1;
- while (i + 1 < argc)
- {
- if (parse_arg(argv, s, &i))
- return (1);
- ++i;
- }
- if (!s->view.fractal)
- return (1);
- init_view(s);
- return (0);
-}
-
void print_help(void)
{
ft_printf("This is the help for fractol by Lukáš Jiřiště\n"
"\tThe color change can be sped up and down with 8 and 2 keys.\n");
}
-void cleanup(t_session *s)
-{
- ft_mat_free(&s->img.calced, NULL);
- ft_mat_free(&s->img.base, NULL);
- mlx_destroy_image(s->mlx, s->img.img);
- free_session(s);
- return ;
-}
-
int main(int argc, char **argv)
{
t_session s;
+ set_default(&s);
if (parse_args(argc, argv, &s))
{
print_help();
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* parsing.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/04/26 10:47:46 by ljiriste #+# #+# */
+/* Updated: 2024/04/26 11:06:32 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "fractals.h"
+#include "fractol.h"
+#include "libft.h"
+
+static t_fractal to_fractal(const char *name)
+{
+ if (!ft_strcmp(name, "man") || !ft_strcmp(name, "mandelbrot"))
+ return (mandelbrot);
+ else if (!ft_strcmp(name, "tri") || !ft_strcmp(name, "tricorn"))
+ return (tricorn);
+ else if (!ft_strcmp(name, "ju") || !ft_strcmp(name, "julia"))
+ return (julia);
+ else
+ return (NULL);
+}
+
+// The input has to be a single string of the form i1,i2,... without whitespace
+// There has to be correct number of inputs for the chosen fractal
+// The input has to be composed of integers
+static int is_correct_input(const char *str, t_fractal fractal)
+{
+ int count;
+
+ count = 0;
+ while (*str)
+ {
+ ++count;
+ while (ft_isdigit(*str) || *str == '-')
+ ++str;
+ if (*str == ',')
+ ++str;
+ else if (*str != '\0')
+ return (0);
+ }
+ if (fractal == julia && count != 2)
+ return (0);
+ return (1);
+}
+
+static t_input parse_input(const char *str, t_fractal fractal)
+{
+ t_input res;
+
+ if (fractal == julia)
+ {
+ res.cpx.r = ft_atoi(str) / 1000.;
+ while (ft_isdigit(*str) || *str == '-')
+ ++str;
+ ++str;
+ res.cpx.i = ft_atoi(str) / 1000.;
+ }
+ return (res);
+}
+
+static int parse_arg(char **argv, t_session *s, int *i)
+{
+ if (!ft_strcmp(argv[*i], "-w")
+ && ft_isint(argv[*i + 1]) && ft_atoi(argv[*i + 1]) > 0)
+ s->img.width = ft_atoi(argv[++*i]);
+ else if (!ft_strcmp(argv[*i], "-h")
+ && ft_isint(argv[*i + 1]) && ft_atoi(argv[*i + 1]) > 0)
+ s->img.height = ft_atoi(argv[++*i]);
+ else if (!ft_strcmp(argv[*i], "-u")
+ && ft_isint(argv[*i + 1]) && ft_atoi(argv[*i + 1]) >= 0)
+ s->img.undersample_max = ft_atoi(argv[++*i]);
+ else if (!ft_strcmp(argv[*i], "-d") && ft_isint(argv[*i + 1]))
+ s->set.detail = ft_atoi(argv[++*i]);
+ else if (!ft_strcmp(argv[*i], "-f") && to_fractal(argv[*i + 1]) != NULL)
+ s->view.fractal = to_fractal(argv[++*i]);
+ else if (!ft_strcmp(argv[*i], "-s") && ft_isint(argv[*i + 1]))
+ s->view.color_shift_speed = ft_atoi(argv[++*i]) / 1000.;
+ else if (!ft_strcmp(argv[*i], "-c") && ft_isint(argv[*i + 1]))
+ s->set.color_stability = 10000 / ft_atoi(argv[++*i]);
+ else if (!ft_strcmp(argv[*i], "-i")
+ && is_correct_input(argv[*i + 1], s->view.fractal))
+ s->set.input = parse_input(argv[++*i], s->view.fractal);
+ else
+ return (1);
+ return (0);
+}
+
+int parse_args(int argc, char **argv, t_session *s)
+{
+ int i;
+
+ if (argc % 2 == 0)
+ return (1);
+ i = 1;
+ while (i + 1 < argc)
+ {
+ if (parse_arg(argv, s, &i))
+ return (1);
+ ++i;
+ }
+ if (!s->view.fractal)
+ return (1);
+ return (0);
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* trans_view.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/04/26 10:40:31 by ljiriste #+# #+# */
+/* Updated: 2024/04/26 11:06:57 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "fractol.h"
+#include "libft.h"
+#include <math.h>
+#include <stdbool.h>
+
+void change_zoom(t_session *s, t_vect2 invariant, double d_zoom)
+{
+ s->view.pixel_size.x /= d_zoom;
+ s->view.pixel_size.y /= d_zoom;
+ s->view.window_coord.x += s->view.pixel_size.x * invariant.x * (d_zoom - 1);
+ s->view.window_coord.y -= s->view.pixel_size.y * invariant.y * (d_zoom - 1);
+ erase_calced(&s->img.calced);
+ s->img.undersample = s->img.undersample_max;
+ return ;
+}
+
+static void move_pixel(t_img *img, t_vect2 old, t_vect2 new)
+{
+ *(double *)ft_mat_access(&img->base, new.y, new.x)
+ = *(double *)ft_mat_access(&img->base, old.y, old.x);
+ *(bool *)ft_mat_access(&img->calced, new.y, new.x)
+ = *(bool *)ft_mat_access(&img->calced, old.y, old.x);
+ return ;
+}
+
+static void move_img(t_img *img, int delta_x, int delta_y)
+{
+ int x;
+ int y;
+
+ x = 0;
+ if (delta_x < 0)
+ x = img->width - 1;
+ while (0 <= x && x < img->width)
+ {
+ y = 0;
+ if (delta_y < 0)
+ y = img->height - 1;
+ while (0 <= y && y < img->height)
+ {
+ if (0 <= x - delta_x && x - delta_x < img->width
+ && 0 <= y - delta_y && y - delta_y < img->height)
+ move_pixel(img, (t_vect2){.x = x, .y = y},
+ (t_vect2){.x = x - delta_x, .y = y - delta_y});
+ if (!(0 <= x + delta_x && x + delta_x < img->width
+ && 0 <= y + delta_y && y + delta_y < img->height))
+ *(bool *)ft_mat_access(&img->calced, y, x) = false;
+ y += 1 - 2 * (delta_y < 0);
+ }
+ x += 1 - 2 * (delta_x < 0);
+ }
+ return ;
+}
+
+// move_amount is ratio of move distance to length one can see
+void move_view(t_session *s, float move_amount_right, float move_amount_up)
+{
+ int x_pix_change;
+ int y_pix_change;
+
+ x_pix_change = round(move_amount_right * s->img.height);
+ if (x_pix_change == 0)
+ x_pix_change = (move_amount_right > 0) - (move_amount_right < 0);
+ y_pix_change = -round(move_amount_up * s->img.height);
+ if (y_pix_change == 0)
+ y_pix_change = -((move_amount_up > 0) - (move_amount_up < 0));
+ s->view.window_coord.x += x_pix_change * s->view.pixel_size.x;
+ s->view.window_coord.y -= y_pix_change * s->view.pixel_size.y;
+ move_img(&s->img, x_pix_change, y_pix_change);
+ s->img.undersample = s->img.undersample_max;
+ return ;
+}
+
+void change_shift_speed(double *speed, double mult, double thresh)
+{
+ if (-thresh < *speed && *speed < thresh)
+ {
+ if (mult > 0)
+ *speed = thresh;
+ else
+ *speed = -thresh;
+ return ;
+ }
+ if (*speed > 0 && mult > 0)
+ *speed *= mult;
+ else if (*speed > 0 && mult < 0)
+ *speed /= -mult;
+ else if (*speed < 0 && mult < 0)
+ *speed *= -mult;
+ else if (*speed < 0 && mult > 0)
+ *speed /= mult;
+ if (-thresh < *speed && *speed < thresh)
+ *speed = 0;
+ return ;
+}