/* Grafx2 - The Ultimate 256-color bitmap paint program Copyright 2007 Adrien Destugues Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) Grafx2 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. Grafx2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Grafx2; if not, see or write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "const.h" #include "struct.h" #include "global.h" #include "divers.h" #include "moteur.h" #include "graph.h" #include "operatio.h" #include "boutons.h" #include "pages.h" #include "erreurs.h" #include "sdlscreen.h" #include "brush.h" #include "windows.h" #if defined(__GP2X__) #define M_PI 3.14159265358979323846 #endif void Start_operation_stack(word new_operation) { Brush_rotation_center_is_defined=0; // On mémorise l'opération précédente si on démarre une interruption switch(new_operation) { case OPERATION_MAGNIFY : case OPERATION_COLORPICK : case OPERATION_GRAB_BRUSH : case OPERATION_POLYBRUSH : case OPERATION_STRETCH_BRUSH : case OPERATION_ROTATE_BRUSH: Operation_before_interrupt=Current_operation; // On passe à l'operation demandée Current_operation=new_operation; break; default : // On passe à l'operation demandée Current_operation=new_operation; Operation_before_interrupt=Current_operation; } // On spécifie si l'opération autorise le changement de couleur au clavier switch(new_operation) { case OPERATION_CONTINUOUS_DRAW: case OPERATION_DISCONTINUOUS_DRAW: case OPERATION_AIRBRUSH: case OPERATION_CENTERED_LINES: Allow_color_change_during_operation=1; break; default : Allow_color_change_during_operation=0; } // Et on passe au curseur qui va avec Cursor_shape=CURSOR_FOR_OPERATION[new_operation]; Operation_stack_size=0; } void Init_start_operation(void) { Operation_in_magnifier=(Mouse_X>=Main_X_zoom); Smear_start=1; } void Operation_push(short value) { Operation_stack[++Operation_stack_size]=value; } void Operation_pop(short * value) { *value=Operation_stack[Operation_stack_size--]; } byte Paintbrush_shape_before_operation; byte Paintbrush_hidden_before_scroll; short Distance(short x1, short y1, short x2, short y2) { short x2_moins_x1=x2-x1; short y2_minus_y1=y2-y1; return Round( sqrt( (x2_moins_x1*x2_moins_x1) + (y2_minus_y1*y2_minus_y1) ) ); } void Display_coords_rel_or_abs(short start_x, short start_y) { char str[6]; if (Config.Coords_rel) { if (Menu_is_visible) { if (Paintbrush_X>start_x) { Num2str(Paintbrush_X-start_x,str,5); str[0]='+'; } else if (Paintbrush_Xstart_y) { Num2str(Paintbrush_Y-start_y,str,5); str[0]='+'; } else if (Paintbrush_Y>1); Main_magnifier_offset_Y=Mouse_Y-(Main_magnifier_height>>1); // Calcul du coin haut_gauche de la fenêtre devant être zoomée DANS L'ECRAN if (Main_magnifier_offset_X+Main_magnifier_width>=Limit_right-Main_offset_X) Main_magnifier_offset_X=Limit_right-Main_magnifier_width-Main_offset_X+1; if (Main_magnifier_offset_Y+Main_magnifier_height>=Limit_bottom-Main_offset_Y) Main_magnifier_offset_Y=Limit_bottom-Main_magnifier_height-Main_offset_Y+1; // Calcul des coordonnées absolues de ce coin DANS L'IMAGE Main_magnifier_offset_X+=Main_offset_X; Main_magnifier_offset_Y+=Main_offset_Y; if (Main_magnifier_offset_X<0) Main_magnifier_offset_X=0; if (Main_magnifier_offset_Y<0) Main_magnifier_offset_Y=0; // On calcule les bornes visibles dans l'écran Position_screen_according_to_zoom(); Compute_limits(); Display_all_screen(); // Repositionner le curseur en fonction des coordonnées visibles Compute_paintbrush_coordinates(); // On fait de notre mieux pour restaurer l'ancienne opération: Start_operation_stack(Operation_before_interrupt); Display_cursor(); Wait_end_of_click(); } /////////////////////////////////////////////////// OPERATION_RECTANGLE_????? void Rectangle_12_0(void) // Opération : OPERATION_EMPTY_RECTANGLE / OPERATION_FILLED_RECTANGLE // Click Souris: 1 ou 2 // Taille_Pile : 0 // // Souris effacée: Oui { Init_start_operation(); if ((Config.Coords_rel) && (Menu_is_visible)) Print_in_menu("\035: 1 \022: 1",0); // On laisse une trace du curseur à l'écran Display_cursor(); if (Mouse_K==LEFT_SIDE) { Shade_table=Shade_table_left; Operation_push(Fore_color); } else { Shade_table=Shade_table_right; Operation_push(Back_color); } Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); } void Rectangle_12_5(void) // Opération : OPERATION_EMPTY_RECTANGLE / OPERATION_FILLED_RECTANGLE // Click Souris: 1 ou 2 // Taille_Pile : 5 // // Souris effacée: Non { short start_x; short start_y; short old_x; short old_y; char str[5]; Operation_pop(&old_y); Operation_pop(&old_x); if ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y)) { Operation_pop(&start_y); Operation_pop(&start_x); if ((Config.Coords_rel) && (Menu_is_visible)) { Num2str(((start_xcenter_x)?tangent_x-center_x :center_x-tangent_x; vertical_radius =(tangent_y>center_y)?tangent_y-center_y :center_y-tangent_y; Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius); horizontal_radius=(Paintbrush_X>center_x)?Paintbrush_X-center_x :center_x-Paintbrush_X; vertical_radius =(Paintbrush_Y>center_y)?Paintbrush_Y-center_y :center_y-Paintbrush_Y; Draw_empy_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius,color); Display_cursor(); } Operation_push(color); Operation_push(center_x); Operation_push(center_y); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); } void Empty_ellipse_0_5(void) // // Opération : OPERATION_EMPTY_ELLIPSE // Click Souris: 0 // Taille_Pile : 5 (color, X_Centre, Y_Centre, X_Tangente, Y_Tangente) // // Souris effacée: Oui // { short tangent_x; short tangent_y; short center_x; short center_y; short color; short horizontal_radius; short vertical_radius; Operation_pop(&tangent_y); Operation_pop(&tangent_x); Operation_pop(¢er_y); Operation_pop(¢er_x); Operation_pop(&color); horizontal_radius=(tangent_x>center_x)?tangent_x-center_x :center_x-tangent_x; vertical_radius =(tangent_y>center_y)?tangent_y-center_y :center_y-tangent_y; Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius); Paintbrush_shape=Paintbrush_shape_before_operation; Draw_empy_ellipse_permanent(center_x,center_y,horizontal_radius,vertical_radius,color); if ( (Config.Coords_rel) && (Menu_is_visible) ) { Print_in_menu("X: Y: ",0); Print_coordinates(); } } void Filled_ellipse_0_5(void) // // Opération : OPERATION_FILLED_ELLIPSE // Click Souris: 0 // Taille_Pile : 5 (color, X_Centre, Y_Centre, X_Tangente, Y_Tangente) // // Souris effacée: Oui // { short tangent_x; short tangent_y; short center_x; short center_y; short color; short horizontal_radius; short vertical_radius; Operation_pop(&tangent_y); Operation_pop(&tangent_x); Operation_pop(¢er_y); Operation_pop(¢er_x); Operation_pop(&color); horizontal_radius=(tangent_x>center_x)?tangent_x-center_x :center_x-tangent_x; vertical_radius =(tangent_y>center_y)?tangent_y-center_y :center_y-tangent_y; Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius); Paintbrush_shape=Paintbrush_shape_before_operation; Draw_filled_ellipse(center_x,center_y,horizontal_radius,vertical_radius,color); if ( (Config.Coords_rel) && (Menu_is_visible) ) { Print_in_menu("X: Y: ",0); Print_coordinates(); } } ////////////////////////////////////////////////////////////// OPERATION_FILL void Fill_1_0(void) // // Opération : OPERATION_FILL // Click Souris: 1 // Taille_Pile : 0 // // Souris effacée: Oui // { Hide_cursor(); // Pas besoin d'initialiser le début d'opération car le Smear n'affecte pas // le Fill, et on se fout de savoir si on est dans la partie gauche ou // droite de la loupe. // On ne s'occupe pas de faire un Backup: c'est "Fill_general" qui s'en charge. Shade_table=Shade_table_left; Fill_general(Fore_color); Display_cursor(); Wait_end_of_click(); } void Fill_2_0(void) // // Opération : OPERATION_FILL // Click Souris: 2 // Taille_Pile : 0 // // Souris effacée: Oui // { Hide_cursor(); // Pas besoin d'initialiser le début d'opération car le Smear n'affecte pas // le Fill, et on se fout de savoir si on est dans la partie gauche ou // droite de la loupe. // On ne s'occupe pas de faire un Backup: c'est "Fill_general" qui s'en charge. Shade_table=Shade_table_right; Fill_general(Back_color); Display_cursor(); Wait_end_of_click(); } ///////////////////////////////////////////////////////// OPERATION_REPLACE void Replace_1_0(void) // // Opération : OPERATION_REPLACE // Click Souris: 1 // Taille_Pile : 0 // // Souris effacée: Oui // { Hide_cursor(); // Pas besoin d'initialiser le début d'opération car le Smear n'affecte pas // le Replace, et on se fout de savoir si on est dans la partie gauche ou // droite de la loupe. Backup(); // Shade_table=Shade_table_left; Replace(Fore_color); Display_cursor(); Wait_end_of_click(); } void Replace_2_0(void) // // Opération : OPERATION_REPLACE // Click Souris: 2 // Taille_Pile : 0 // // Souris effacée: Oui // { Hide_cursor(); // Pas besoin d'initialiser le début d'opération car le Smear n'affecte pas // le Replace, et on se fout de savoir si on est dans la partie gauche ou // droite de la loupe. Backup(); // Shade_table=Shade_table_right; Replace(Back_color); Display_cursor(); Wait_end_of_click(); } /////////////////////////////////////////////////////////// OPERATION_COLORPICK void Colorpicker_12_0(void) // // Opération : OPERATION_COLORPICK // Click Souris: 1 ou 2 // Taille_Pile : 0 // // Souris effacée: Oui // { Init_start_operation(); if (Mouse_K==LEFT_SIDE) { Frame_menu_color(MC_Black); Fore_color=Colorpicker_color; Reposition_palette(); Display_foreback(); Frame_menu_color(MC_White); } else { Back_color=Colorpicker_color; Display_foreback(); } Operation_push(Mouse_K); } void Colorpicker_1_1(void) // // Opération : OPERATION_COLORPICK // Click Souris: 1 // Taille_Pile : 1 // // Souris effacée: Non // { char str[4]; if ( (Paintbrush_X>=0) && (Paintbrush_Y>=0) && (Paintbrush_X=0) && (Paintbrush_Y>=0) && (Paintbrush_X=Limit_left+3) start_x=0; else start_x=3-(x_pos-Limit_left); if (y_pos>=Limit_top+3) start_y=0; else start_y=3-(y_pos-Limit_top); if (x_pos<=Limit_visible_right-3) end_x=6; else end_x=3+(Limit_visible_right-x_pos); if (y_pos<=Limit_visible_bottom-3) end_y=6; else end_y=3+(Limit_visible_bottom-y_pos); if (start_x<=end_x && start_y<=end_y) { for (i=start_x; i<=end_x; i++) { temp=x_pos+i-3; Pixel_preview(temp,y_pos,~Read_pixel(temp -Main_offset_X, y_pos-Main_offset_Y)); } for (i=start_y; i<=end_y; i++) { temp=y_pos+i-3; Pixel_preview(x_pos,temp,~Read_pixel(x_pos-Main_offset_X, temp -Main_offset_Y)); } Update_part_of_screen(x_pos+start_x-3,y_pos+start_y-3,end_x-start_x+1,end_y-start_y+1); } } void Curve_34_points_1_0(void) // // Opération : OPERATION_COURBE_?_POINTS // Click Souris: 1 // Taille_Pile : 0 // // Souris effacée: Oui // { Init_start_operation(); Backup(); Shade_table=Shade_table_left; Paintbrush_hidden=1; Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,Fore_color); Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1); if ((Config.Coords_rel) && (Menu_is_visible)) Print_in_menu("X:± 0 Y:± 0",0); Operation_push(Fore_color); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); } void Curve_34_points_2_0(void) // // Opération : OPERATION_COURBE_?_POINTS // Click Souris: 2 // Taille_Pile : 0 // // Souris effacée: Oui // { Init_start_operation(); Backup(); Shade_table=Shade_table_right; Paintbrush_hidden=1; Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,Back_color); Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1); if ((Config.Coords_rel) && (Menu_is_visible)) Print_in_menu("X:± 0 Y:± 0",0); Operation_push(Back_color); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); } void Curve_34_points_1_5(void) // // Opération : OPERATION_COURBE_?_POINTS // Click Souris: 1 // Taille_Pile : 5 // // Souris effacée: Non // { short x1,x2,y1,y2; Operation_pop(&y2); Operation_pop(&x2); Operation_pop(&y1); Operation_pop(&x1); if ( (y2!=Paintbrush_Y) || (x2!=Paintbrush_X) ) { Hide_cursor(); Display_coords_rel_or_abs(x1,y1); Hide_line_preview(x1,y1,x2,y2); Pixel_figure_preview (x1,y1,Fore_color); Draw_line_preview (x1,y1,Paintbrush_X,Paintbrush_Y,Fore_color); Display_cursor(); } Operation_push(x1); Operation_push(y1); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); } void Curve_34_points_2_5(void) // // Opération : OPERATION_COURBE_?_POINTS // Click Souris: 2 // Taille_Pile : 5 // // Souris effacée: Non // { short x1,x2,y1,y2; Operation_pop(&y2); Operation_pop(&x2); Operation_pop(&y1); Operation_pop(&x1); if ( (y2!=Paintbrush_Y) || (x2!=Paintbrush_X) ) { Hide_cursor(); Display_coords_rel_or_abs(x1,y1); Hide_line_preview(x1,y1,x2,y2); Pixel_figure_preview (x1,y1,Back_color); Draw_line_preview (x1,y1,Paintbrush_X,Paintbrush_Y,Back_color); Display_cursor(); } Operation_push(x1); Operation_push(y1); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); } byte Cursor_hidden_before_curve; void Curve_4_points_0_5(void) // // Opération : OPERATION_4_POINTS_CURVE // Click Souris: 0 // Taille_Pile : 5 // // Souris effacée: Oui // { short x1,y1,x2,y2,x3,y3,x4,y4; short third_x,third_y; short color; Operation_pop(&y4); Operation_pop(&x4); Operation_pop(&y1); Operation_pop(&x1); Operation_pop(&color); third_x=Round_div(abs(x4-x1),3); third_y=Round_div(abs(y4-y1),3); if (x1B=(8/3) * C->P *x3=Round((bx+x4)/2.0); // · _/·· P3 P2=milieu de [P1,B] *y3=Round((by+y4)/2.0); // P4*-- P3=milieu de [P4,B] } void Curve_3_points_0_5(void) // // Opération : OPERATION_3_POINTS_CURVE // Click Souris: 0 // Taille_Pile : 5 // // Souris effacée: Oui // { short x1,y1,x2,y2,x3,y3,x4,y4; short color; Operation_pop(&y4); Operation_pop(&x4); Operation_pop(&y1); Operation_pop(&x1); Operation_pop(&color); Compute_3_point_curve(x1,y1,x4,y4,&x2,&y2,&x3,&y3); Hide_line_preview(x1,y1,x4,y4); Draw_curve_preview(x1,y1,x2,y2,x3,y3,x4,y4,color); if ( (Config.Coords_rel) && (Menu_is_visible) ) { Print_in_menu("X: Y: ",0); Print_coordinates(); } Operation_push(color); Operation_push(x1); Operation_push(y1); Operation_push(x2); Operation_push(y2); Operation_push(x3); Operation_push(y3); Operation_push(x4); Operation_push(y4); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); } void Curve_3_points_0_11(void) // // Opération : OPERATION_3_POINTS_CURVE // Click Souris: 0 // Taille_Pile : 11 // // Souris effacée: Non // { short x1,y1,x2,y2,x3,y3,x4,y4; short old_x,old_y; short color; Operation_pop(&old_y); Operation_pop(&old_x); if ( (Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y) ) { Operation_pop(&y4); Operation_pop(&x4); Operation_pop(&y3); Operation_pop(&x3); Operation_pop(&y2); Operation_pop(&x2); Operation_pop(&y1); Operation_pop(&x1); Operation_pop(&color); Hide_cursor(); Print_coordinates(); Hide_curve_preview(x1,y1,x2,y2,x3,y3,x4,y4,color); Compute_3_point_curve(x1,y1,x4,y4,&x2,&y2,&x3,&y3); Draw_curve_preview (x1,y1,x2,y2,x3,y3,x4,y4,color); Display_cursor(); Operation_push(color); Operation_push(x1); Operation_push(y1); Operation_push(x2); Operation_push(y2); Operation_push(x3); Operation_push(y3); Operation_push(x4); Operation_push(y4); } Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); } void Curve_3_points_12_11(void) // // Opération : OPERATION_3_POINTS_CURVE // Click Souris: 1 ou 2 // Taille_Pile : 11 // // Souris effacée: Oui // { short x1,y1,x2,y2,x3,y3,x4,y4; short old_x,old_y; short color; Operation_pop(&old_y); Operation_pop(&old_x); Operation_pop(&y4); Operation_pop(&x4); Operation_pop(&y3); Operation_pop(&x3); Operation_pop(&y2); Operation_pop(&x2); Operation_pop(&y1); Operation_pop(&x1); Operation_pop(&color); Paintbrush_hidden=0; Hide_cursor(); Hide_curve_preview (x1,y1,x2,y2,x3,y3,x4,y4,color); Compute_3_point_curve(x1,y1,x4,y4,&x2,&y2,&x3,&y3); Draw_curve_permanent(x1,y1,x2,y2,x3,y3,x4,y4,color); Display_cursor(); Wait_end_of_click(); } ///////////////////////////////////////////////////////////// OPERATION_AIRBRUSH Uint32 Airbrush_next_time; void Airbrush_1_0(void) // // Opération : OPERATION_AIRBRUSH // Click Souris: 1 // Taille_Pile : 0 // // Souris effacée: Non // { Init_start_operation(); Backup(); Shade_table=Shade_table_left; Airbrush_next_time = SDL_GetTicks()+Airbrush_delay*10; Airbrush(LEFT_SIDE); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); } void Airbrush_2_0(void) // // Opération : OPERATION_AIRBRUSH // Click Souris: 2 // Taille_Pile : 0 // // Souris effacée: Non // { Init_start_operation(); Backup(); Shade_table=Shade_table_right; Airbrush_next_time = SDL_GetTicks()+Airbrush_delay*10; Airbrush(RIGHT_SIDE); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); } void Airbrush_12_2(void) // // Opération : OPERATION_AIRBRUSH // Click Souris: 1 ou 2 // Taille_Pile : 2 // // Souris effacée: Non // { short old_x,old_y; Operation_pop(&old_y); Operation_pop(&old_x); if ( (Menu_is_visible) && ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y)) ) { Hide_cursor(); Print_coordinates(); Display_cursor(); } if (SDL_GetTicks()>Airbrush_next_time) { Airbrush_next_time+=Airbrush_delay*10; Airbrush(Mouse_K_unique); } Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); } void Airbrush_0_2(void) // // Opération : OPERATION_AIRBRUSH // Click Souris: 0 // Taille_Pile : 2 // // Souris effacée: Non // { Operation_stack_size-=2; } ////////////////////////////////////////////////////////// OPERATION_POLYGON void Polygon_12_0(void) // Opération : OPERATION_POLYGON // Click Souris: 1 ou 2 // Taille_Pile : 0 // // Souris effacée: Oui { byte color; Init_start_operation(); Backup(); Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right; Paintbrush_shape_before_operation=Paintbrush_shape; Paintbrush_shape=PAINTBRUSH_SHAPE_POINT; color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color; // On place temporairement le début de la ligne qui ne s'afficherait pas sinon Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,color); Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1); if ((Config.Coords_rel) && (Menu_is_visible)) Print_in_menu("X:± 0 Y:± 0",0); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); Operation_push(Mouse_K | 0x80); Operation_push(color); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); // Taille de pile 8 : phase d'appui, non interruptible } void Polygon_12_9(void) // Opération : OPERATION_POLYGON // Click Souris: 1 ou 2 // Taille_Pile : 9 // // Souris effacée: Oui { short start_x; short start_y; short end_x; short end_y; short color; short direction; Operation_pop(&end_y); Operation_pop(&end_x); Operation_pop(&start_y); Operation_pop(&start_x); Operation_pop(&color); Operation_pop(&direction); Operation_pop(&direction); if (direction==Mouse_K) { Operation_push(direction); Operation_push(color); Operation_push(start_x); Operation_push(start_y); Operation_push(end_x); Operation_push(end_y); // Taille de pile 8 : phase d'appui, non interruptible } else { // La série de ligne est terminée, il faut donc effacer la dernière // preview de ligne et relier le dernier point avec le premier Pixel_figure_preview_auto (start_x,start_y); Hide_line_preview (start_x,start_y,end_x,end_y); Operation_pop(&end_y); Operation_pop(&end_x); Paintbrush_shape=Paintbrush_shape_before_operation; // Le pied aurait été de ne pas repasser sur le 1er point de la 1ère ligne // mais c'est pas possible :( Draw_line_permanet(start_x,start_y,end_x,end_y,color); Paintbrush_shape=PAINTBRUSH_SHAPE_POINT; Display_cursor(); Wait_end_of_click(); Hide_cursor(); if ( (Config.Coords_rel) && (Menu_is_visible) ) { Print_in_menu("X: Y: ",0); Print_coordinates(); } Paintbrush_shape=Paintbrush_shape_before_operation; } } ////////////////////////////////////////////////////////// OPERATION_POLYFILL short * Polyfill_table_of_points; int Polyfill_number_of_points; void Polyfill_12_0(void) // Opération : OPERATION_POLYFILL // Click Souris: 1 ou 2 // Taille_Pile : 0 // // Souris effacée: Oui { byte color; Init_start_operation(); Backup(); Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right; Paintbrush_hidden=1; color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color; Polyfill_table_of_points=(short *) malloc((Config.Nb_max_vertices_per_polygon<<1)*sizeof(short)); Polyfill_table_of_points[0]=Paintbrush_X; Polyfill_table_of_points[1]=Paintbrush_Y; Polyfill_number_of_points=1; // On place temporairement le début de la ligne qui ne s'afficherait pas sinon Pixel_figure_preview_xor(Paintbrush_X,Paintbrush_Y,0); Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1); if ((Config.Coords_rel) && (Menu_is_visible)) Print_in_menu("X:± 0 Y:± 0",0); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); Operation_push(Mouse_K | 0x80); Operation_push(color); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); // Taille de pile 8 : phase d'appui, non interruptible } void Polyfill_0_8(void) // Opération : OPERATION_POLYFILL // Click Souris: 0 // Taille_Pile : 8 // // Souris effacée: Oui { short start_x; short start_y; short end_x; short end_y; short color; short direction; Operation_pop(&end_y); Operation_pop(&end_x); Operation_pop(&start_y); Operation_pop(&start_x); Operation_pop(&color); Operation_pop(&direction); if ((Config.Coords_rel) && (Menu_is_visible)) Print_in_menu("X:± 0 Y:± 0",0); Draw_line_preview_xor(start_x,start_y,end_x,end_y,0); if (direction & 0x80) direction=(direction & 0x7F); Operation_push(direction); // Valeur bidon servant de nouvel état de pile Operation_push(direction); Operation_push(color); Draw_line_preview_xor(start_x,start_y,Paintbrush_X,Paintbrush_Y,0); if (Polyfill_number_of_points1) width--; if (height>1) height--; } Num2str(width,str,4); Print_in_menu(str,2); Num2str(height,str,4); Print_in_menu(str,11); } else Print_coordinates(); } Display_all_screen(); x=Paintbrush_X; y=Paintbrush_Y; if (Snap_mode && Config.Adjust_brush_pick) { dx=Paintbrush_X-start_x; dy=Paintbrush_Y-start_y; if (dx<0) x++; else {if (dx>0) x--;} if (dy<0) y++; else {if (dy>0) y--;} Stretch_brush_preview(start_x,start_y,x,y); } else Stretch_brush_preview(start_x,start_y,Paintbrush_X,Paintbrush_Y); old_x=Paintbrush_X; old_y=Paintbrush_Y; Paintbrush_X=start_x; Paintbrush_Y=start_y; Display_cursor(); Paintbrush_X=old_x; Paintbrush_Y=old_y; Display_cursor(); Operation_stack_size-=2; Operation_push(x); Operation_push(y); Operation_push(start_x); Operation_push(start_y); } Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); Operation_push(2); } void Stretch_brush_0_7(void) // // Opération : OPERATION_STRETCH_BRUSH // Click Souris: 0 // Taille_Pile : 7 // // Souris effacée: Non // { char str[5]; short start_x; short start_y; short old_x; short old_y; short width=0; short height=0; byte size_change; short prev_state; Operation_pop(&prev_state); Operation_pop(&old_y); Operation_pop(&old_x); Operation_pop(&start_y); Operation_pop(&start_x); if ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y) || (prev_state!=3)) { if (Menu_is_visible) { if (Config.Coords_rel) { width=((start_x1)?start_x+(Brush_width>>1)-1:1; height=(Brush_height>1)?start_y+(Brush_height>>1)-1:1; break; case 'X': // Moitié X width=(Brush_width>1)?start_x+(Brush_width>>1)-1:1; height=start_y+Brush_height-1; break; case 'Y': // Moitié Y width=start_x+Brush_width-1; height=(Brush_height>1)?start_y+(Brush_height>>1)-1:1; break; case 'n': // Normal width=start_x+Brush_width-1; height=start_y+Brush_height-1; break; default : size_change=0; } Key_ANSI=0; } else size_change=0; if (size_change) { // On efface la preview de la brosse (et la croix) Display_all_screen(); old_x=Paintbrush_X; old_y=Paintbrush_Y; Paintbrush_X=start_x; Paintbrush_Y=start_y; Display_cursor(); Paintbrush_X=old_x; Paintbrush_Y=old_y; Stretch_brush_preview(start_x,start_y,width,height); Display_cursor(); Operation_stack_size-=2; Operation_push(width); Operation_push(height); } Operation_push(start_x); Operation_push(start_y); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); Operation_push(3); } void Stretch_brush_2_7(void) // // Opération : OPERATION_STRETCH_BRUSH // Click Souris: 2 // Taille_Pile : 7 // // Souris effacée: Oui // { short computed_x; short computed_y; short start_x; short start_y; Operation_stack_size-=3; Operation_pop(&start_y); Operation_pop(&start_x); Operation_pop(&computed_y); Operation_pop(&computed_x); // On efface la preview de la brosse (et la croix) Display_all_screen(); // Et enfin on stocke pour de bon la nouvelle brosse étirée Stretch_brush(start_x,start_y,computed_x,computed_y); // Simuler l'appui du bouton "Dessin" // Comme l'enclenchement du bouton efface le curseur, il faut l'afficher au // préalable: Display_cursor(); // !!! Efface la croix puis affiche le viseur !!! Unselect_button(BUTTON_DRAW,LEFT_SIDE); // Désenclenche au passage le bouton brosse if (Config.Auto_discontinuous) { // On se place en mode Dessin discontinu à la main while (Current_operation!=OPERATION_DISCONTINUOUS_DRAW) Unselect_button(BUTTON_DRAW,RIGHT_SIDE); } // Maintenant, il faut réeffacer le curseur parce qu'il sera raffiché en fin // d'appel à cette action: Hide_cursor(); // On passe en brosse couleur: Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH); if ((Config.Coords_rel) && (Menu_is_visible)) Print_in_menu("X: Y:",0); Print_coordinates(); // Inutile de de faire un Wait_end_of_click car c'est fait dans Unselect_button } //////////////////////////////////////////////////// OPERATION_ROTATE_BRUSH void Rotate_brush_12_0(void) // // Opération : OPERATION_ROTATE_BRUSH // Click Souris: 1 ou 2 // Taille_Pile : 0 // // Souris effacée: Oui // { Init_start_operation(); if (Mouse_K==LEFT_SIDE) { Brush_rotation_center_X=Paintbrush_X+(Brush_width>>1)-Brush_width; Brush_rotation_center_Y=Paintbrush_Y; Brush_rotation_center_is_defined=1; Operation_push(Paintbrush_X); // Dernière position calculée X Operation_push(Paintbrush_Y); // Dernière position calculée Y Operation_push(Paintbrush_X); // Dernière position X Operation_push(Paintbrush_Y); // Dernière position Y Operation_push(1); // State précédent if ((Config.Coords_rel) && (Menu_is_visible)) Print_in_menu("Angle: 0° ",0); } else { Start_operation_stack(Operation_before_interrupt); Wait_end_of_click(); // FIXME: celui-la il donne un résultat pas très chouette en visuel } } void Rotate_brush_1_5(void) // // Opération : OPERATION_ROTATE_BRUSH // Click Souris: 1 // Taille_Pile : 5 // // Souris effacée: Non // { char str[4]; short old_x; short old_y; short prev_state; float angle; int dx,dy; Operation_pop(&prev_state); Operation_pop(&old_y); Operation_pop(&old_x); if ( (Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y) || (prev_state!=2) ) { if ( (Brush_rotation_center_X==Paintbrush_X) && (Brush_rotation_center_Y==Paintbrush_Y) ) angle=0.0; else { dx=Paintbrush_X-Brush_rotation_center_X; dy=Paintbrush_Y-Brush_rotation_center_Y; angle=acos(((float)dx)/sqrt((dx*dx)+(dy*dy))); if (dy>0) angle=M_2PI-angle; } if (Menu_is_visible) { if (Config.Coords_rel) { Num2str((int)(angle*180.0/M_PI),str,3); Print_in_menu(str,7); } else Print_coordinates(); } Display_all_screen(); Rotate_brush_preview(angle); Display_cursor(); Operation_stack_size-=2; Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); } Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); Operation_push(2); } void Rotate_brush_0_5(void) // // Opération : OPERATION_ROTATE_BRUSH // Click Souris: 0 // Taille_Pile : 5 // // Souris effacée: Non // { char str[4]; short old_x; short old_y; short computed_x=0; short computed_y=0; byte angle_change; short prev_state; float angle=0.0; int dx,dy; Operation_pop(&prev_state); Operation_pop(&old_y); Operation_pop(&old_x); if ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y) || (prev_state!=3)) { if ( (Brush_rotation_center_X==Paintbrush_X) && (Brush_rotation_center_Y==Paintbrush_Y) ) angle=0.0; else { dx=Paintbrush_X-Brush_rotation_center_X; dy=Paintbrush_Y-Brush_rotation_center_Y; angle=acos(((float)dx)/sqrt((dx*dx)+(dy*dy))); if (dy>0) angle=M_2PI-angle; } if (Menu_is_visible) { if (Config.Coords_rel) { Num2str(Round(angle*180.0/M_PI),str,3); Print_in_menu(str,7); } else Print_coordinates(); } } // Utilise Key_ANSI au lieu de Key, car Get_input() met ce dernier // à zero si une operation est en cours (Operation_stack_size!=0) if (Key_ANSI) { angle_change=1; computed_x=Brush_rotation_center_X; computed_y=Brush_rotation_center_Y; switch (Key_ANSI) { case '6': angle= 0.0 ; computed_x++; break; case '9': angle=M_PI*0.25; computed_x++; computed_y--; break; case '8': angle=M_PI*0.5 ; computed_y--; break; case '7': angle=M_PI*0.75; computed_x--; computed_y--; break; case '4': angle=M_PI ; computed_x--; break; case '1': angle=M_PI*1.25; computed_x--; computed_y++; break; case '2': angle=M_PI*1.5 ; computed_y++; break; case '3': angle=M_PI*1.75; computed_x++; computed_y++; break; default : angle_change=0; } Key_ANSI=0; } else angle_change=0; if (angle_change) { // On efface la preview de la brosse Display_all_screen(); Rotate_brush_preview(angle); Display_cursor(); Operation_stack_size-=2; Operation_push(computed_x); Operation_push(computed_y); } Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); Operation_push(3); } void Rotate_brush_2_5(void) // // Opération : OPERATION_ROTATE_BRUSH // Click Souris: 2 // Taille_Pile : 5 // // Souris effacée: Oui // { short computed_x; short computed_y; int dx,dy; float angle; // On efface la preview de la brosse Display_all_screen(); Operation_stack_size-=3; Operation_pop(&computed_y); Operation_pop(&computed_x); // Calcul de l'angle par rapport à la dernière position calculée if ( (Brush_rotation_center_X==computed_x) && (Brush_rotation_center_Y==computed_y) ) angle=0.0; else { dx=computed_x-Brush_rotation_center_X; dy=computed_y-Brush_rotation_center_Y; angle=acos(((float)dx)/sqrt((dx*dx)+(dy*dy))); if (dy>0) angle=M_2PI-angle; } // Et enfin on stocke pour de bon la nouvelle brosse étirée Rotate_brush(angle); // Simuler l'appui du bouton "Dessin" // Comme l'enclenchement du bouton efface le curseur, il faut l'afficher au // préalable: Display_cursor(); // !!! Efface le curseur de l'opération puis affiche le viseur !!! Unselect_button(BUTTON_DRAW,LEFT_SIDE); // Désenclenche au passage le bouton brosse if (Config.Auto_discontinuous) { // On se place en mode Dessin discontinu à la main while (Current_operation!=OPERATION_DISCONTINUOUS_DRAW) Unselect_button(BUTTON_DRAW,RIGHT_SIDE); } // Maintenant, il faut réeffacer le curseur parce qu'il sera raffiché en fin // d'appel à cette action: Hide_cursor(); // On passe en brosse couleur: Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH); if ((Config.Coords_rel) && (Menu_is_visible)) Print_in_menu("X: Y:",0); Print_coordinates(); // Inutile de de faire un Wait_end_of_click car c'est fait dans Unselect_button } //////////////////////////////////////////////////////////// OPERATION_SCROLL byte Cursor_hidden_before_scroll; void Scroll_12_0(void) // // Opération : OPERATION_SCROLL // Click Souris: 1 ou 2 // Taille_Pile : 0 // // Souris effacée: Oui // { Init_start_operation(); Backup(); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); Cursor_hidden_before_scroll=Cursor_hidden; Cursor_hidden=1; if ((Config.Coords_rel) && (Menu_is_visible)) Print_in_menu("X:± 0 Y:± 0",0); } void Scroll_12_4(void) // // Opération : OPERATION_SCROLL // Click Souris: 1 ou 2 // Taille_Pile : 4 // // Souris effacée: Non // { short center_x; short center_y; short x_pos; short y_pos; short x_offset; short y_offset; //char str[5]; Operation_pop(&y_pos); Operation_pop(&x_pos); Operation_pop(¢er_y); Operation_pop(¢er_x); if ( (Paintbrush_X!=x_pos) || (Paintbrush_Y!=y_pos) ) { // L'utilisateur a bougé, il faut scroller l'image if (Paintbrush_X>=center_x) x_offset=(Paintbrush_X-center_x)%Main_image_width; else x_offset=Main_image_width-((center_x-Paintbrush_X)%Main_image_width); if (Paintbrush_Y>=center_y) y_offset=(Paintbrush_Y-center_y)%Main_image_height; else y_offset=Main_image_height-((center_y-Paintbrush_Y)%Main_image_height); Display_coords_rel_or_abs(center_x,center_y); Scroll_picture(x_offset,y_offset); Display_all_screen(); } Operation_push(center_x); Operation_push(center_y); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); } void Scroll_0_4(void) // // Opération : OPERATION_SCROLL // Click Souris: 0 // Taille_Pile : 4 // // Souris effacée: Oui // { Operation_stack_size-=4; Cursor_hidden=Cursor_hidden_before_scroll; if ((Config.Coords_rel) && (Menu_is_visible)) { Print_in_menu("X: Y: ",0); Print_coordinates(); } } //////////////////////////////////////////////////// OPERATION_GRAD_CIRCLE void Grad_circle_12_0(void) // // Opération : OPERATION_GRAD_CIRCLE // Click Souris: 1 ou 2 // Taille_Pile : 0 // // Souris effacée: Oui { byte color; Init_start_operation(); Backup(); Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right; color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color; Paintbrush_hidden_before_scroll=Paintbrush_hidden; Paintbrush_hidden=1; Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,color); Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1); if ((Config.Coords_rel) && (Menu_is_visible)) Print_in_menu("Radius: 0 ",0); Operation_push(Mouse_K); Operation_push(color); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); } void Grad_circle_12_6(void) // // Opération : OPERATION_GRAD_CIRCLE // Click Souris: 1 ou 2 // Taille_Pile : 6 (Mouse_K, color, X_Centre, Y_Centre, X_Tangente, Y_Tangente) // // Souris effacée: Non // { short tangent_x; short tangent_y; short center_x; short center_y; short color; short radius; char str[5]; Operation_pop(&tangent_y); Operation_pop(&tangent_x); Operation_pop(¢er_y); Operation_pop(¢er_x); Operation_pop(&color); if ( (tangent_x!=Paintbrush_X) || (tangent_y!=Paintbrush_Y) ) { Hide_cursor(); if ((Config.Coords_rel) && (Menu_is_visible)) { Num2str(Distance(center_x,center_y,Paintbrush_X,Paintbrush_Y),str,4); Print_in_menu(str,7); } else Print_coordinates(); Circle_limit=((tangent_x-center_x)*(tangent_x-center_x))+ ((tangent_y-center_y)*(tangent_y-center_y)); radius=sqrt(Circle_limit); Hide_empty_circle_preview(center_x,center_y,radius); Circle_limit=((Paintbrush_X-center_x)*(Paintbrush_X-center_x))+ ((Paintbrush_Y-center_y)*(Paintbrush_Y-center_y)); radius=sqrt(Circle_limit); Draw_empy_circle_preview(center_x,center_y,radius,color); Display_cursor(); } Operation_push(color); Operation_push(center_x); Operation_push(center_y); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); } void Grad_circle_0_6(void) // // Opération : OPERATION_GRAD_CIRCLE // Click Souris: 0 // Taille_Pile : 6 (Mouse_K, color, X_Centre, Y_Centre, X_Tangente, Y_Tangente) // // Souris effacée: Oui // { short tangent_x; short tangent_y; short center_x; short center_y; short color; short click; short radius; Operation_pop(&tangent_y); Operation_pop(&tangent_x); Operation_pop(¢er_y); Operation_pop(¢er_x); Operation_pop(&color); Operation_pop(&click); if (click==LEFT_SIDE) { Operation_push(click); Operation_push(color); Operation_push(center_x); Operation_push(center_y); Operation_push(tangent_x); Operation_push(tangent_y); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); // On change la forme du curseur Cursor_shape=CURSOR_SHAPE_XOR_TARGET; // On affiche une croix XOR au centre du cercle Draw_curve_cross(center_x,center_y); if (Menu_is_visible) { if (Config.Coords_rel) Print_in_menu("X: Y:",0); else Print_in_menu("X: Y: ",0); Display_coords_rel_or_abs(center_x,center_y); } } else { Circle_limit=((tangent_x-center_x)*(tangent_x-center_x))+ ((tangent_y-center_y)*(tangent_y-center_y)); radius=sqrt(Circle_limit); Hide_empty_circle_preview(center_x,center_y,radius); Paintbrush_hidden=Paintbrush_hidden_before_scroll; Cursor_shape=CURSOR_SHAPE_TARGET; Draw_filled_circle(center_x,center_y,radius,Back_color); if ((Config.Coords_rel) && (Menu_is_visible)) { Print_in_menu("X: Y: ",0); Print_coordinates(); } } } void Grad_circle_12_8(void) // // Opération : OPERATION_GRAD_CIRCLE // Click Souris: 0 // Taille_Pile : 8 (Mouse_K, color, X_Centre, Y_Centre, X_Tangente, Y_Tangente, old_x, old_y) // // Souris effacée: Oui // { short tangent_x; short tangent_y; short center_x; short center_y; short color; short old_mouse_k; short radius; Operation_stack_size-=2; // On fait sauter les 2 derniers élts de la pile Operation_pop(&tangent_y); Operation_pop(&tangent_x); Operation_pop(¢er_y); Operation_pop(¢er_x); Operation_pop(&color); Operation_pop(&old_mouse_k); Hide_cursor(); // On efface la croix XOR au centre du cercle Draw_curve_cross(center_x,center_y); Circle_limit=((tangent_x-center_x)*(tangent_x-center_x))+ ((tangent_y-center_y)*(tangent_y-center_y)); radius=sqrt(Circle_limit); Hide_empty_circle_preview(center_x,center_y,radius); Paintbrush_hidden=Paintbrush_hidden_before_scroll; Cursor_shape=CURSOR_SHAPE_TARGET; if (Mouse_K==old_mouse_k) Draw_grad_circle(center_x,center_y,radius,Paintbrush_X,Paintbrush_Y); Display_cursor(); Wait_end_of_click(); if ((Config.Coords_rel) && (Menu_is_visible)) { Print_in_menu("X: Y: ",0); Print_coordinates(); } } void Grad_circle_or_ellipse_0_8(void) // // Opération : OPERATION_{CERCLE|ELLIPSE}_DEGRADE // Click Souris: 0 // Taille_Pile : 8 // // Souris effacée: Non // { short start_x; short start_y; short tangent_x; short tangent_y; short old_x; short old_y; Operation_pop(&old_y); Operation_pop(&old_x); if ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y)) { Operation_pop(&tangent_y); Operation_pop(&tangent_x); Operation_pop(&start_y); Operation_pop(&start_x); Display_coords_rel_or_abs(start_x,start_y); Operation_push(start_x); Operation_push(start_y); Operation_push(tangent_x); Operation_push(tangent_y); } Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); } ////////////////////////////////////////////////// OPERATION_GRAD_ELLIPSE void Grad_ellipse_12_0(void) // // Opération : OPERATION_GRAD_ELLIPSE // Click Souris: 1 ou 2 // Taille_Pile : 0 // // Souris effacée: Oui { byte color; Init_start_operation(); Backup(); Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right; color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color; Paintbrush_hidden_before_scroll=Paintbrush_hidden; Paintbrush_hidden=1; Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,color); Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1); if ((Config.Coords_rel) && (Menu_is_visible)) Print_in_menu("X:± 0 Y:± 0",0); Operation_push(Mouse_K); Operation_push(color); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); } void Grad_ellipse_12_6(void) // // Opération : OPERATION_GRAD_ELLIPSE // Click Souris: 1 ou 2 // Taille_Pile : 6 (Mouse_K, color, X_Centre, Y_Centre, X_Tangente, Y_Tangente) // // Souris effacée: Non // { short tangent_x; short tangent_y; short center_x; short center_y; short color; short horizontal_radius; short vertical_radius; Operation_pop(&tangent_y); Operation_pop(&tangent_x); Operation_pop(¢er_y); Operation_pop(¢er_x); Operation_pop(&color); if ( (tangent_x!=Paintbrush_X) || (tangent_y!=Paintbrush_Y) ) { Hide_cursor(); Display_coords_rel_or_abs(center_x,center_y); horizontal_radius=(tangent_x>center_x)?tangent_x-center_x :center_x-tangent_x; vertical_radius =(tangent_y>center_y)?tangent_y-center_y :center_y-tangent_y; Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius); horizontal_radius=(Paintbrush_X>center_x)?Paintbrush_X-center_x :center_x-Paintbrush_X; vertical_radius =(Paintbrush_Y>center_y)?Paintbrush_Y-center_y :center_y-Paintbrush_Y; Draw_empy_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius,color); Display_cursor(); } Operation_push(color); Operation_push(center_x); Operation_push(center_y); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); } void Grad_ellipse_0_6(void) // // Opération : OPERATION_GRAD_ELLIPSE // Click Souris: 0 // Taille_Pile : 6 (Mouse_K, color, X_Centre, Y_Centre, X_Tangente, Y_Tangente) // // Souris effacée: Oui // { short tangent_x; short tangent_y; short center_x; short center_y; short color; short click; //short radius; short horizontal_radius; short vertical_radius; Operation_pop(&tangent_y); Operation_pop(&tangent_x); Operation_pop(¢er_y); Operation_pop(¢er_x); Operation_pop(&color); Operation_pop(&click); if (click==LEFT_SIDE) { Operation_push(click); Operation_push(color); Operation_push(center_x); Operation_push(center_y); Operation_push(tangent_x); Operation_push(tangent_y); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); // On change la forme du curseur Cursor_shape=CURSOR_SHAPE_XOR_TARGET; // On affiche une croix XOR au centre du cercle Draw_curve_cross(center_x,center_y); if (Menu_is_visible) { if (Config.Coords_rel) Print_in_menu("X: Y:",0); else Print_in_menu("X: Y: ",0); Display_coords_rel_or_abs(center_x,center_y); } } else { horizontal_radius=(tangent_x>center_x)?tangent_x-center_x :center_x-tangent_x; vertical_radius =(tangent_y>center_y)?tangent_y-center_y :center_y-tangent_y; Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius); Paintbrush_hidden=Paintbrush_hidden_before_scroll; Cursor_shape=CURSOR_SHAPE_TARGET; Draw_filled_ellipse(center_x,center_y,horizontal_radius,vertical_radius,Back_color); if ((Config.Coords_rel) && (Menu_is_visible)) { Print_in_menu("X: Y: ",0); Print_coordinates(); } } } void Grad_ellipse_12_8(void) // // Opération : OPERATION_GRAD_ELLIPSE // Click Souris: 0 // Taille_Pile : 8 (Mouse_K, color, X_Centre, Y_Centre, X_Tangente, Y_Tangente, old_x, old_y) // // Souris effacée: Oui // { short tangent_x; short tangent_y; short center_x; short center_y; short color; short horizontal_radius; short vertical_radius; short old_mouse_k; Operation_stack_size-=2; // On fait sauter les 2 derniers élts de la pile Operation_pop(&tangent_y); Operation_pop(&tangent_x); Operation_pop(¢er_y); Operation_pop(¢er_x); Operation_pop(&color); Operation_pop(&old_mouse_k); // On efface la croix XOR au centre de l'ellipse Draw_curve_cross(center_x,center_y); horizontal_radius=(tangent_x>center_x)?tangent_x-center_x :center_x-tangent_x; vertical_radius =(tangent_y>center_y)?tangent_y-center_y :center_y-tangent_y; Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius); Paintbrush_hidden=Paintbrush_hidden_before_scroll; Cursor_shape=CURSOR_SHAPE_TARGET; if (Mouse_K==old_mouse_k) Draw_grad_ellipse(center_x,center_y,horizontal_radius,vertical_radius,Paintbrush_X,Paintbrush_Y); Wait_end_of_click(); if ((Config.Coords_rel) && (Menu_is_visible)) { Print_in_menu("X: Y: ",0); Print_coordinates(); } } /****************************** * Operation_Rectangle_Degrade * ******************************/ // 1) tracé d'un rectangle classique avec les lignes XOR // 2) tracé d'une ligne vecteur de dégradé, comme une ligne normale // 3) dessin du dégradé void Grad_rectangle_12_0(void) // Opération : OPERATION_GRAD_RECTANGLE // Click Souris: 1 ou 2 // Taille_Pile : 0 // // Souris effacée: Oui // Initialisation de l'étape 1, on commence à dessiner le rectangle { Init_start_operation(); Backup(); if ((Config.Coords_rel) && (Menu_is_visible)) Print_in_menu("\035: 1 \022: 1",0); // On laisse une trace du curseur à l'écran Display_cursor(); if (Mouse_K==LEFT_SIDE) { Shade_table=Shade_table_left; Operation_push(Mouse_K); } else { Shade_table=Shade_table_right; Operation_push(Mouse_K); } Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); } void Grad_rectangle_12_5(void) // Opération : OPERATION_GRAD_RECTANGLE // Click Souris: 1 ou 2 // Taille_Pile : 5 // // Souris effacée: Non // Modification de la taille du rectangle { short start_x; short start_y; short old_x; short old_y; char str[5]; Operation_pop(&old_y); Operation_pop(&old_x); if ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y)) { Operation_pop(&start_y); Operation_pop(&start_x); if ((Config.Coords_rel) && (Menu_is_visible)) { Num2str(((start_x Min(Main_image_width,Main_magnifier_mode?Main_separator_position:Screen_width)) // Tous les clippings à gérer sont là offset_width = Max(rax,rbx) - Min(Main_image_width,Main_magnifier_mode?Main_separator_position:Screen_width); if (Max(ray,rby)-Main_offset_Y > Min(Main_image_height,Menu_Y)) offset_height = Max(ray,rby) - Min(Main_image_height,Menu_Y); // Dessin dans la zone de dessin normale Horizontal_XOR_line(Min(rax,rbx)-Main_offset_X,Min(ray,rby)-Main_offset_Y,width - offset_width); if(offset_height == 0) Horizontal_XOR_line(Min(rax,rbx)-Main_offset_X,Max(ray,rby)-1-Main_offset_Y,width - offset_width); Vertical_XOR_line(Min(rax,rbx)-Main_offset_X,Min(ray,rby)-Main_offset_Y,height-offset_height); if (offset_width == 0) // Sinon cette ligne est en dehors de la zone image, inutile de la dessiner Vertical_XOR_line(Max(rax,rbx)-1-Main_offset_X,Min(ray,rby)-Main_offset_Y,height-offset_height); Update_rect(Min(rax,rbx)-Main_offset_X,Min(ray,rby)-Main_offset_Y,width+1-offset_width,height+1-offset_height); // Dessin dans la zone zoomée if(Main_magnifier_mode && Min(rax,rbx)Limit_left_zoom && Min(ray,rby)Limit_top_zoom ) { offset_width = 0; offset_height=0; if(Min(rax,rbx)Limit_visible_right_zoom) // On dépasse du zoom à droite offset_width += Max(rax,rbx) - Limit_visible_right_zoom; if(Min(ray,rby)Limit_visible_bottom_zoom) // On dépasse du zoom en bas offset_height += Max(ray,rby) - Limit_visible_bottom_zoom; if(width > offset_width) { if(offset_top==0) // La ligne du haut est visible Horizontal_XOR_line_zoom(offset_left>0?offset_left:Min(rax,rbx),Min(ray,rby),width-offset_width); if(Max(ray,rby)0?offset_left:Min(rax,rbx),Max(ray,rby),width-offset_width); } if(height>offset_height) { if(offset_left==0) // La ligne de gauche est visible Vertical_XOR_line_zoom(Min(rax,rbx),offset_top>0?offset_top:Min(ray,rby),height-offset_height); if(Max(rax,rbx)0?offset_top:Min(ray,rby),height-offset_height); } } Operation_push(rax); Operation_push(ray); Operation_push(rbx); Operation_push(rby); // On ajoute des trucs dans la pile pour forcer le passage à l'étape suivante Operation_push(rbx); Operation_push(rby); } void Grad_rectangle_0_7(void) // OPERATION_GRAD_RECTANGLE // click souris 0 // Taile pile : 5 // // Souris effacée : non // On continue à attendre que l'utilisateur clique en gardant les coords à jour { Operation_stack_size -= 2; Print_coordinates(); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); } void Grad_rectangle_12_7(void) // Opération : OPERATION_GRAD_RECTANGLE // Click Souris: 1 ou 2 // Taille_Pile : 7 // // Souris effacée: Oui // Début du tracé du vecteur (premier clic) // On garde les anciennes coordonnées dans la pile, et on ajoute les nouvelles par dessus // Si l'utilisateur utilise le mauvais bouton, on annule le tracé. Mais ça nous oblige à vider toute la pile pour vérifier :( { short rax,rbx,ray,rby,vax,vay,click; Operation_pop(&vay); Operation_pop(&vax); Operation_pop(&ray); Operation_pop(&rax); Operation_pop(&rby); Operation_pop(&rbx); Operation_pop(&click); if(click==Mouse_K) { Operation_push(click); Operation_push(rbx); Operation_push(rby); Operation_push(rax); Operation_push(ray); Operation_push(vax); Operation_push(vay); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); } else { // Mauvais bouton > anulation de l'opération. // On a déjà vidé la pile, il reste à effacer le rectangle XOR short width, height; short offset_width = 0; short offset_height = 0; short offset_left = 0; short offset_top = 0; width = abs(rbx-rax); height = abs(rby-ray); if (Max(rax,rbx)-Main_offset_X > Min(Main_image_width,Main_magnifier_mode?Main_separator_position:Screen_width)) // Tous les clippings à gérer sont là offset_width = Max(rax,rbx) - Min(Main_image_width,Main_magnifier_mode?Main_separator_position:Screen_width); if (Max(ray,rby)-Main_offset_Y > Min(Main_image_height,Menu_Y)) offset_height = Max(ray,rby) - Min(Main_image_height,Menu_Y); // Dessin dans la zone de dessin normale Horizontal_XOR_line(Min(rax,rbx)-Main_offset_X,Min(ray,rby)-Main_offset_Y,width - offset_width); if(offset_height == 0) Horizontal_XOR_line(Min(rax,rbx)-Main_offset_X,Max(ray,rby)-1-Main_offset_Y,width - offset_width); Vertical_XOR_line(Min(rax,rbx)-Main_offset_X,Min(ray,rby)-Main_offset_Y,height-offset_height); if (offset_width == 0) // Sinon cette ligne est en dehors de la zone image, inutile de la dessiner Vertical_XOR_line(Max(rax,rbx)-1-Main_offset_X,Min(ray,rby)-Main_offset_Y,height-offset_height); Update_rect(Min(rax,rbx)-Main_offset_X,Min(ray,rby)-Main_offset_Y,width+1-offset_width,height+1-offset_height); // Dessin dans la zone zoomée if(Main_magnifier_mode && Min(rax,rbx)Limit_left_zoom && Min(ray,rby)Limit_top_zoom ) { offset_width = 0; offset_height=0; if(Min(rax,rbx)Limit_visible_right_zoom) // On dépasse du zoom à droite offset_width += Max(rax,rbx) - Limit_visible_right_zoom; if(Min(ray,rby)Limit_visible_bottom_zoom) // On dépasse du zoom en bas offset_height += Max(ray,rby) - Limit_visible_bottom_zoom; if(width > offset_width) { if(offset_top==0) // La ligne du haut est visible Horizontal_XOR_line_zoom(offset_left>0?offset_left:Min(rax,rbx),Min(ray,rby),width-offset_width); if(Max(ray,rby)0?offset_left:Min(rax,rbx),Max(ray,rby),width-offset_width); } if(height>offset_height) { if(offset_left==0) // La ligne de gauche est visible Vertical_XOR_line_zoom(Min(rax,rbx),offset_top>0?offset_top:Min(ray,rby),height-offset_height); if(Max(rax,rbx)0?offset_top:Min(ray,rby),height-offset_height); } } } } void Grad_rectangle_12_9(void) // Opération : OPERATION_GRAD_RECTANGLE // Click Souris: 1 // Taille_Pile : 5 // // Souris effacée: Oui // Poursuite du tracé du vecteur (déplacement de la souris en gardant le curseur appuyé) { short start_x; short start_y; short end_x; short end_y; Operation_pop(&end_y); Operation_pop(&end_x); Operation_pop(&start_y); Operation_pop(&start_x); if ((Paintbrush_X!=end_x) || (Paintbrush_Y!=end_y)) { // On corrige les coordonnées de la ligne si la touche shift est appuyée... if(SDL_GetModState() & KMOD_SHIFT) Clamp_coordinates_45_degrees(start_x,start_y,&Paintbrush_X,&Paintbrush_Y); Display_coords_rel_or_abs(start_x,start_y); Draw_line_preview_xor(start_x,start_y,end_x,end_y,0); Draw_line_preview_xor(start_x,start_y,Paintbrush_X,Paintbrush_Y,0); } Operation_push(start_x); Operation_push(start_y); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); } void Grad_rectangle_0_9(void) // Opération : OPERATION_GRAD_RECTANGLE // Click Souris: 0 // Taille_Pile : 9 // // Souris effacée: Oui // Ouf, fini ! on dessine enfin le rectangle avec son dégradé { short rect_start_x; short rect_start_y; short rect_end_x; short rect_end_y; short vector_start_x; short vector_start_y; short vector_end_x; short vector_end_y; Operation_pop(&vector_end_y); Operation_pop(&vector_end_x); Operation_pop(&vector_start_y); Operation_pop(&vector_start_x); Operation_pop(&rect_end_y); Operation_pop(&rect_end_x); Operation_pop(&rect_start_y); Operation_pop(&rect_start_x); Operation_stack_size--; Hide_cursor(); // Maintenant on efface tout le bazar temporaire : rectangle et ligne XOR Hide_line_preview(vector_start_x,vector_start_y,vector_end_x,vector_end_y); // Et enfin on trace le rectangle avec le dégradé dedans ! if (vector_end_x==vector_start_x && vector_end_y==vector_start_y) { // Vecteur nul > pas de rectangle tracé // Du coup on doit effacer la preview xor ... short width, height; short offset_width = 0; short offset_height = 0; short offset_left = 0; short offset_top = 0; width = abs(rect_end_x-rect_start_x); height = abs(rect_end_y-rect_start_y); if (Max(rect_start_x,rect_end_x)-Main_offset_X > Min(Main_image_width,Main_magnifier_mode?Main_separator_position:Screen_width)) // Tous les clippings à gérer sont là offset_width = Max(rect_start_x,rect_end_x) - Min(Main_image_width,Main_magnifier_mode?Main_separator_position:Screen_width); if (Max(rect_start_y,rect_end_y)-Main_offset_Y > Min(Main_image_height,Menu_Y)) offset_height = Max(rect_start_y,rect_end_y) - Min(Main_image_height,Menu_Y); // Dessin dans la zone de dessin normale Horizontal_XOR_line(Min(rect_start_x,rect_end_x)-Main_offset_X,Min(rect_start_y,rect_end_y)-Main_offset_Y,width - offset_width); if(offset_height == 0) Horizontal_XOR_line(Min(rect_start_x,rect_end_x)-Main_offset_X,Max(rect_start_y,rect_end_y)-1-Main_offset_Y,width - offset_width); Vertical_XOR_line(Min(rect_start_x,rect_end_x)-Main_offset_X,Min(rect_start_y,rect_end_y)-Main_offset_Y,height-offset_height); if (offset_width == 0) // Sinon cette ligne est en dehors de la zone image, inutile de la dessiner Vertical_XOR_line(Max(rect_start_x,rect_end_x)-1-Main_offset_X,Min(rect_start_y,rect_end_y)-Main_offset_Y,height-offset_height); Update_rect(Min(rect_start_x,rect_end_x)-Main_offset_X,Min(rect_start_y,rect_end_y)-Main_offset_Y,width+1-offset_width,height+1-offset_height); // Dessin dans la zone zoomée if(Main_magnifier_mode && Min(rect_start_x,rect_end_x)Limit_left_zoom && Min(rect_start_y,rect_end_y)Limit_top_zoom ) { offset_width = 0; offset_height=0; if(Min(rect_start_x,rect_end_x)Limit_visible_right_zoom) // On dépasse du zoom à droite offset_width += Max(rect_start_x,rect_end_x) - Limit_visible_right_zoom; if(Min(rect_start_y,rect_end_y)Limit_visible_bottom_zoom) // On dépasse du zoom en bas offset_height += Max(rect_start_y,rect_end_y) - Limit_visible_bottom_zoom; if(width > offset_width) { if(offset_top==0) // La ligne du haut est visible Horizontal_XOR_line_zoom(offset_left>0?offset_left:Min(rect_start_x,rect_end_x),Min(rect_start_y,rect_end_y),width-offset_width); if(Max(rect_start_y,rect_end_y)0?offset_left:Min(rect_start_x,rect_end_x),Max(rect_start_y,rect_end_y),width-offset_width); } if(height>offset_height) { if(offset_left==0) // La ligne de gauche est visible Vertical_XOR_line_zoom(Min(rect_start_x,rect_end_x),offset_top>0?offset_top:Min(rect_start_y,rect_end_y),height-offset_height); if(Max(rect_start_x,rect_end_x)0?offset_top:Min(rect_start_y,rect_end_y),height-offset_height); } } } else Draw_grad_rectangle(rect_start_x,rect_start_y,rect_end_x,rect_end_y,vector_start_x,vector_start_y,vector_end_x,vector_end_y); Display_cursor(); Wait_end_of_click(); if ((Config.Coords_rel) && (Menu_is_visible)) { Print_in_menu("X: Y: ",0); Print_coordinates(); } } /////////////////////////////////////////////////// OPERATION_CENTERED_LINES void Centered_lines_12_0(void) // Opération : OPERATION_CENTERED_LINES // Click Souris: 1 ou 2 // Taille_Pile : 0 // // Souris effacée: Oui { Init_start_operation(); Backup(); Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right; if ((Config.Coords_rel) && (Menu_is_visible)) Print_in_menu("X:± 0 Y:± 0",0); Operation_push(Mouse_K); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); } void Centered_lines_12_3(void) // Opération : OPERATION_CENTERED_LINES // Click Souris: 1 ou 2 // Taille_Pile : 3 // // Souris effacée: Non { short start_x; short start_y; Operation_pop(&start_y); Operation_pop(&start_x); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); } void Centered_lines_0_3(void) // Opération : OPERATION_CENTERED_LINES // Click Souris: 0 // Taille_Pile : 3 // // Souris effacée: Oui { short start_x; short start_y; short Button; short color; Operation_pop(&start_y); Operation_pop(&start_x); Operation_pop(&Button); color=(Button==LEFT_SIDE)?Fore_color:Back_color; Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,color); Paintbrush_shape_before_operation=Paintbrush_shape; Paintbrush_shape=PAINTBRUSH_SHAPE_POINT; Operation_push(Button); Operation_push(Paintbrush_X); // Nouveau début X Operation_push(Paintbrush_Y); // Nouveau début Y Operation_push(Paintbrush_X); // Nouvelle dernière fin X Operation_push(Paintbrush_Y); // Nouvelle dernière fin Y Operation_push(Paintbrush_X); // Nouvelle dernière position X Operation_push(Paintbrush_Y); // Nouvelle dernière position Y } void Centered_lines_12_7(void) // Opération : OPERATION_CENTERED_LINES // Click Souris: 1 ou 2 // Taille_Pile : 7 // // Souris effacée: Non { short Button; short start_x; short start_y; short end_x; short end_y; short last_x; short last_y; short color; Operation_pop(&last_y); Operation_pop(&last_x); Operation_pop(&end_y); Operation_pop(&end_x); Operation_pop(&start_y); Operation_pop(&start_x); Operation_pop(&Button); if (Mouse_K==Button) { if ( (end_x!=Paintbrush_X) || (end_y!=Paintbrush_Y) || (last_x!=Paintbrush_X) || (last_y!=Paintbrush_Y) ) { Hide_cursor(); color=(Button==LEFT_SIDE)?Fore_color:Back_color; Paintbrush_shape=Paintbrush_shape_before_operation; Pixel_figure_preview_auto (start_x,start_y); Hide_line_preview (start_x,start_y,last_x,last_y); Smear_start=1; Display_paintbrush (start_x,start_y,color,0); Draw_line_permanet(start_x,start_y,Paintbrush_X,Paintbrush_Y,color); Paintbrush_shape=PAINTBRUSH_SHAPE_POINT; Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,color); Draw_line_preview(start_x,start_y,Paintbrush_X,Paintbrush_Y,color); Display_cursor(); } Operation_push(Button); Operation_push(start_x); Operation_push(start_y); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); } else { Hide_cursor(); Paintbrush_shape=Paintbrush_shape_before_operation; Pixel_figure_preview_auto (start_x,start_y); Hide_line_preview (start_x,start_y,last_x,last_y); if ( (Config.Coords_rel) && (Menu_is_visible) ) { Print_in_menu("X: Y: ",0); Print_coordinates(); } Display_cursor(); Wait_end_of_click(); } } void Centered_lines_0_7(void) // Opération : OPERATION_CENTERED_LINES // Click Souris: 0 // Taille_Pile : 7 // // Souris effacée: Non { short Button; short start_x; short start_y; short end_x; short end_y; short last_x; short last_y; short color; Operation_pop(&last_y); Operation_pop(&last_x); Operation_pop(&end_y); Operation_pop(&end_x); if ((Paintbrush_X!=last_x) || (Paintbrush_Y!=last_y)) { Hide_cursor(); Operation_pop(&start_y); Operation_pop(&start_x); Operation_pop(&Button); color=(Button==LEFT_SIDE)?Fore_color:Back_color; Display_coords_rel_or_abs(start_x,start_y); Hide_line_preview(start_x,start_y,last_x,last_y); Pixel_figure_preview(start_x,start_y,color); Draw_line_preview(start_x,start_y,Paintbrush_X,Paintbrush_Y,color); Operation_push(Button); Operation_push(start_x); Operation_push(start_y); Display_cursor(); } Operation_push(end_x); Operation_push(end_y); Operation_push(Paintbrush_X); Operation_push(Paintbrush_Y); }