diff --git a/Makefile b/Makefile index f8830ffe..fc2f66a3 100644 --- a/Makefile +++ b/Makefile @@ -287,7 +287,7 @@ endif .PHONY : all debug release clean depend zip version force install uninstall # This is the list of the objects we want to build. Dependancies are built by "make depend" automatically. -OBJ = $(OBJDIR)/main.o $(OBJDIR)/init.o $(OBJDIR)/graph.o $(OBJDIR)/sdlscreen.o $(OBJDIR)/misc.o $(OBJDIR)/special.o $(OBJDIR)/buttons.o $(OBJDIR)/palette.o $(OBJDIR)/help.o $(OBJDIR)/operatio.o $(OBJDIR)/pages.o $(OBJDIR)/loadsave.o $(OBJDIR)/readline.o $(OBJDIR)/engine.o $(OBJDIR)/filesel.o $(OBJDIR)/op_c.o $(OBJDIR)/readini.o $(OBJDIR)/saveini.o $(OBJDIR)/shade.o $(OBJDIR)/keyboard.o $(OBJDIR)/io.o $(OBJDIR)/version.o $(OBJDIR)/text.o $(OBJDIR)/SFont.o $(OBJDIR)/setup.o $(OBJDIR)/pxsimple.o $(OBJDIR)/pxtall.o $(OBJDIR)/pxwide.o $(OBJDIR)/pxdouble.o $(OBJDIR)/pxtriple.o $(OBJDIR)/pxtall2.o $(OBJDIR)/pxwide2.o $(OBJDIR)/pxquad.o $(OBJDIR)/windows.o $(OBJDIR)/brush.o $(OBJDIR)/realpath.o $(OBJDIR)/mountlist.o $(OBJDIR)/input.o $(OBJDIR)/hotkeys.o $(OBJDIR)/transform.o $(OBJDIR)/pversion.o $(OBJDIR)/factory.o $(PLATFORMOBJ) $(OBJDIR)/fileformats.o $(OBJDIR)/miscfileformats.o $(OBJDIR)/libraw2crtc.o +OBJ = $(OBJDIR)/main.o $(OBJDIR)/init.o $(OBJDIR)/graph.o $(OBJDIR)/sdlscreen.o $(OBJDIR)/misc.o $(OBJDIR)/special.o $(OBJDIR)/buttons.o $(OBJDIR)/palette.o $(OBJDIR)/help.o $(OBJDIR)/operatio.o $(OBJDIR)/pages.o $(OBJDIR)/loadsave.o $(OBJDIR)/readline.o $(OBJDIR)/engine.o $(OBJDIR)/filesel.o $(OBJDIR)/op_c.o $(OBJDIR)/readini.o $(OBJDIR)/saveini.o $(OBJDIR)/shade.o $(OBJDIR)/keyboard.o $(OBJDIR)/io.o $(OBJDIR)/version.o $(OBJDIR)/text.o $(OBJDIR)/SFont.o $(OBJDIR)/setup.o $(OBJDIR)/pxsimple.o $(OBJDIR)/pxtall.o $(OBJDIR)/pxwide.o $(OBJDIR)/pxdouble.o $(OBJDIR)/pxtriple.o $(OBJDIR)/pxtall2.o $(OBJDIR)/pxwide2.o $(OBJDIR)/pxquad.o $(OBJDIR)/windows.o $(OBJDIR)/brush.o $(OBJDIR)/realpath.o $(OBJDIR)/mountlist.o $(OBJDIR)/input.o $(OBJDIR)/hotkeys.o $(OBJDIR)/transform.o $(OBJDIR)/pversion.o $(OBJDIR)/factory.o $(PLATFORMOBJ) $(OBJDIR)/fileformats.o $(OBJDIR)/miscfileformats.o $(OBJDIR)/libraw2crtc.o $(OBJDIR)/brush_ops.o SKIN_FILES = skins/skin_classic.png skins/skin_modern.png skins/font_Classic.png skins/font_Fun.png diff --git a/brush_ops.c b/brush_ops.c new file mode 100644 index 00000000..8178a573 --- /dev/null +++ b/brush_ops.c @@ -0,0 +1,1286 @@ +/* vim:expandtab:ts=2 sw=2: +*/ +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2007 Adrien Destugues + Copyright 2009 Franck Charlet + 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 +*/ +////////////////////////////////////////////////////////////////////////////// +///@file brush_ops.c +/// Code for operations about the brush (grabbing, rotating, ...) and magnifier +////////////////////////////////////////////////////////////////////////////// + +#include + +#include "brush.h" +#include "buttons.h" +#include "engine.h" +#include "global.h" +#include "graph.h" +#include "misc.h" +#include "operatio.h" +#include "pages.h" +#include "windows.h" + + +/// Simulates clicking the "Draw" button. +void Return_to_draw_mode(void) +{ + + // Comme l'enclenchement du bouton efface le curseur, il faut l'afficher au + // préalable: + Display_cursor(); + if (Mouse_K) + Wait_end_of_click(); + // !!! Efface la croix puis affiche le viseur !!! + Select_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) + Select_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(); +} + +// ---------------------------------------------------------- OPERATION_MAGNIFY + + +void Magnifier_12_0(void) + +// Opération : 4 (item d'une Loupe) +// Click Souris: 1 ou 2 +// Taille_Pile : 0 +// +// Souris effacée: Oui + +{ + + // On passe en mode loupe + Main_magnifier_mode=1; + + // La fonction d'affichage dans la partie image est désormais un affichage + // spécial loupe. + Pixel_preview=Pixel_preview_magnifier; + + // On calcule l'origine de la loupe + Main_magnifier_offset_X=Mouse_X-(Main_magnifier_width>>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_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) + { + Set_fore_color(Colorpicker_color); + } + else + { + Set_back_color(Colorpicker_color); + } + 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_X1) 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); + + Return_to_draw_mode(); +} + + +//////////////////////////////////////////////////// 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); + + Return_to_draw_mode(); +} + +///////////////////////////////////////////////////// OPERATION_DISTORT_BRUSH + +/// Draws a 2x2 XOR square at the specified picture coordinates, on the screen. +void Draw_stretch_spot(short x_pos, short y_pos) +{ + short x,y; + + for (y=y_pos-1;y=Limit_top && y<=Limit_visible_bottom) + for (x=x_pos-1;x=Limit_left && x<=Limit_visible_right) + Pixel_preview(x,y,~Read_pixel(x-Main_offset_X,y-Main_offset_Y)); + Update_part_of_screen(x_pos-1, y_pos-1, 2, 2); +} + +void Distort_brush_0_0(void) +// +// Opération : OPERATION_DISTORT_BRUSH +// Click Souris: 0 +// Taille_Pile : 0 +// +// Souris effacée: Non +// +{ + if ( Menu_is_visible ) + { + Print_in_menu("POSITION BRUSH TO START ",0); + } +} + +void Distort_brush_1_0(void) +// +// Opération : OPERATION_DISTORT_BRUSH +// Click Souris: 1 +// Taille_Pile : 0 +// +// Souris effacée: Non +// +{ + short x_pos, y_pos; + + Init_start_operation(); + Paintbrush_hidden=1; + Hide_cursor(); + + // Top left angle + x_pos=Paintbrush_X-Brush_offset_X; + y_pos=Paintbrush_Y-Brush_offset_Y; + Draw_stretch_spot(x_pos,y_pos); + Operation_push(x_pos); + Operation_push(y_pos); + + // Top right angle + x_pos+=Brush_width; + Draw_stretch_spot(x_pos,y_pos); + Operation_push(x_pos); + Operation_push(y_pos); + + // Bottom right angle + y_pos+=Brush_height; + Draw_stretch_spot(x_pos,y_pos); + Operation_push(x_pos); + Operation_push(y_pos); + + // Bottom left angle + x_pos-=Brush_width; + Draw_stretch_spot(x_pos,y_pos); + Operation_push(x_pos); + Operation_push(y_pos); + + Distort_brush_preview( + Operation_stack[1], + Operation_stack[2], + Operation_stack[3], + Operation_stack[4], + Operation_stack[5], + Operation_stack[6], + Operation_stack[7], + Operation_stack[8]); + Display_cursor(); + Update_part_of_screen(Paintbrush_X-Brush_offset_X, Paintbrush_Y-Brush_offset_Y, Brush_width, Brush_height); + Wait_end_of_click(); + // Erase the message in status bar + if ( (Config.Coords_rel) && (Menu_is_visible) ) + { + Print_in_menu("X: Y: ",0); + } +} + +void Distort_brush_1_8(void) +// +// Opération : OPERATION_DISTORT_BRUSH +// Click Souris: 1 +// Taille_Pile : 8 +// +// Souris effacée: No +// +{ + // How far (in pixels) you can catch a handle + #define REACH_DISTANCE 100 + short i; + short x[4]; + short y[4]; + long best_distance=REACH_DISTANCE; + short best_spot=-1; + + for (i=3;i>=0;i--) + { + long distance; + Operation_pop(&y[i]); + Operation_pop(&x[i]); + distance=Distance(Paintbrush_X,Paintbrush_Y,x[i],y[i]); + if (distance-1) + { + Operation_push(best_spot); + } + if ( (Config.Coords_rel) && (Menu_is_visible) ) + { + Print_in_menu("X: Y: ",0); + Print_coordinates(); + } +} + +void Distort_brush_1_9(void) +// +// Opération : OPERATION_DISTORT_BRUSH +// Click Souris: 1 +// Taille_Pile : 9 +// +// Souris effacée: No +// +{ + short i; + short x[4]; + short y[4]; + short selected_corner; + + // Pop all arguments + Operation_pop(&selected_corner); + for (i=3;i>=0;i--) + { + Operation_pop(&y[i]); + Operation_pop(&x[i]); + } + + if (Paintbrush_X!=x[selected_corner] || Paintbrush_Y!=y[selected_corner]) + { + Hide_cursor(); + + // Easiest refresh mode: make no assumptions on how the brush was + // displayed before. + Display_all_screen(); + + x[selected_corner]=Paintbrush_X; + y[selected_corner]=Paintbrush_Y; + + for (i=0;i<4;i++) + Draw_stretch_spot(x[i],y[i]); + + Distort_brush_preview(x[0],y[0],x[1],y[1],x[2],y[2],x[3],y[3]); + + Display_cursor(); + + if ( (Config.Coords_rel) && (Menu_is_visible) ) + { + Print_in_menu("X: Y: ",0); + Print_coordinates(); + } + Update_rect(0,0,Screen_width,Menu_Y); + } + + // Push back all arguments + for (i=0;i<4;i++) + { + Operation_push(x[i]); + Operation_push(y[i]); + } + Operation_push(selected_corner); + +} +void Distort_brush_0_9(void) +// +// Opération : OPERATION_DISTORT_BRUSH +// Click Souris: 0 +// Taille_Pile : 9 +// +// Souris effacée: No +// +{ + short selected_corner; + Operation_pop(&selected_corner); + +} + +void Distort_brush_2_0(void) +// +// Opération : OPERATION_DISTORT_BRUSH +// Click Souris: 2 +// Taille_Pile : 0 +// +// Souris effacée: Oui +// +{ + Paintbrush_hidden=0; + Display_all_screen(); + // Erase the message in status bar + if ( (Config.Coords_rel) && (Menu_is_visible) ) + { + Print_in_menu("X: Y: ",0); + } + Return_to_draw_mode(); +} + +void Distort_brush_2_8(void) +// +// Opération : OPERATION_DISTORT_BRUSH +// Click Souris: 2 +// Taille_Pile : 8 +// +// Souris effacée: Oui +// +{ + short i; + short x[4]; + short y[4]; + + // Pop all arguments + for (i=3;i>=0;i--) + { + Operation_pop(&y[i]); + Operation_pop(&x[i]); + } + Distort_brush(x[0],y[0],x[1],y[1],x[2],y[2],x[3],y[3]); + + Paintbrush_hidden=0; + Display_all_screen(); + + Return_to_draw_mode(); +} + diff --git a/global.h b/global.h index 2f013869..2b0927c1 100644 --- a/global.h +++ b/global.h @@ -836,6 +836,9 @@ GFX2_GLOBAL short Colorpicker_X; /// Position of the colorpicker tool, in image coordinates. GFX2_GLOBAL short Colorpicker_Y; +GFX2_GLOBAL short * Polyfill_table_of_points; +GFX2_GLOBAL int Polyfill_number_of_points; + /// Brush container GFX2_GLOBAL T_Brush_template Brush_container[BRUSH_CONTAINER_COLUMNS*BRUSH_CONTAINER_ROWS]; diff --git a/help.c b/help.c index f498ab76..9fcf976e 100644 --- a/help.c +++ b/help.c @@ -646,11 +646,11 @@ void Button_Stats(void) // Used memory Print_in_window(10,59,"Used memory pages: ",STATS_TITLE_COLOR,MC_Black); if(Stats_pages_memory > (100LL*1024*1024*1024)) - sprintf(buffer,"%u (%u Gb)",Stats_pages_number, (unsigned int)(Stats_pages_memory/(1024*1024*1024))); + sprintf(buffer,"%ld (%lld Gb)",Stats_pages_number, Stats_pages_memory/(1024*1024*1024)); else if(Stats_pages_memory > (100*1024*1024)) - sprintf(buffer,"%u (%u Mb)",Stats_pages_number, (unsigned int)(Stats_pages_memory/(1024*1024))); + sprintf(buffer,"%ld (%lld Mb)",Stats_pages_number, Stats_pages_memory/(1024*1024)); else - sprintf(buffer,"%u (%u Kb)",Stats_pages_number, (unsigned int)(Stats_pages_memory/1024)); + sprintf(buffer,"%ld (%lld Kb)",Stats_pages_number, Stats_pages_memory/1024); Print_in_window(162,59,buffer,STATS_DATA_COLOR,MC_Black); // Affichage de l'espace disque libre diff --git a/operatio.c b/operatio.c index 728c4e08..c349af1e 100644 --- a/operatio.c +++ b/operatio.c @@ -162,35 +162,6 @@ void Display_coords_rel_or_abs(short start_x, short start_y) Print_coordinates(); } -/// Simulates clicking the "Draw" button. -void Return_to_draw_mode(void) -{ - - // Comme l'enclenchement du bouton efface le curseur, il faut l'afficher au - // préalable: - Display_cursor(); - if (Mouse_K) - Wait_end_of_click(); - // !!! Efface la croix puis affiche le viseur !!! - Select_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) - Select_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(); -} - //////////////////////////////////////////////////// OPERATION_CONTINUOUS_DRAW void Freehand_mode1_1_0(void) @@ -765,60 +736,6 @@ void K_line_12_7(void) } } - -// ---------------------------------------------------------- OPERATION_MAGNIFY - - -void Magnifier_12_0(void) - -// Opération : 4 (item d'une Loupe) -// Click Souris: 1 ou 2 -// Taille_Pile : 0 -// -// Souris effacée: Oui - -{ - - // On passe en mode loupe - Main_magnifier_mode=1; - - // La fonction d'affichage dans la partie image est désormais un affichage - // spécial loupe. - Pixel_preview=Pixel_preview_magnifier; - - // On calcule l'origine de la loupe - Main_magnifier_offset_X=Mouse_X-(Main_magnifier_width>>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) @@ -1430,141 +1347,6 @@ void Replace_2_0(void) } -/////////////////////////////////////////////////////////// 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) - { - Set_fore_color(Colorpicker_color); - } - else - { - Set_back_color(Colorpicker_color); - } - 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_X1) 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); - - Return_to_draw_mode(); -} - - -//////////////////////////////////////////////////// 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); - - Return_to_draw_mode(); -} - -///////////////////////////////////////////////////// OPERATION_DISTORT_BRUSH - -/// Draws a 2x2 XOR square at the specified picture coordinates, on the screen. -void Draw_stretch_spot(short x_pos, short y_pos) -{ - short x,y; - - for (y=y_pos-1;y=Limit_top && y<=Limit_visible_bottom) - for (x=x_pos-1;x=Limit_left && x<=Limit_visible_right) - Pixel_preview(x,y,~Read_pixel(x-Main_offset_X,y-Main_offset_Y)); - Update_part_of_screen(x_pos-1, y_pos-1, 2, 2); -} - -void Distort_brush_0_0(void) -// -// Opération : OPERATION_DISTORT_BRUSH -// Click Souris: 0 -// Taille_Pile : 0 -// -// Souris effacée: Non -// -{ - if ( Menu_is_visible ) - { - Print_in_menu("POSITION BRUSH TO START ",0); - } -} - -void Distort_brush_1_0(void) -// -// Opération : OPERATION_DISTORT_BRUSH -// Click Souris: 1 -// Taille_Pile : 0 -// -// Souris effacée: Non -// -{ - short x_pos, y_pos; - - Init_start_operation(); - Paintbrush_hidden=1; - Hide_cursor(); - - // Top left angle - x_pos=Paintbrush_X-Brush_offset_X; - y_pos=Paintbrush_Y-Brush_offset_Y; - Draw_stretch_spot(x_pos,y_pos); - Operation_push(x_pos); - Operation_push(y_pos); - - // Top right angle - x_pos+=Brush_width; - Draw_stretch_spot(x_pos,y_pos); - Operation_push(x_pos); - Operation_push(y_pos); - - // Bottom right angle - y_pos+=Brush_height; - Draw_stretch_spot(x_pos,y_pos); - Operation_push(x_pos); - Operation_push(y_pos); - - // Bottom left angle - x_pos-=Brush_width; - Draw_stretch_spot(x_pos,y_pos); - Operation_push(x_pos); - Operation_push(y_pos); - - Distort_brush_preview( - Operation_stack[1], - Operation_stack[2], - Operation_stack[3], - Operation_stack[4], - Operation_stack[5], - Operation_stack[6], - Operation_stack[7], - Operation_stack[8]); - Display_cursor(); - Update_part_of_screen(Paintbrush_X-Brush_offset_X, Paintbrush_Y-Brush_offset_Y, Brush_width, Brush_height); - Wait_end_of_click(); - // Erase the message in status bar - if ( (Config.Coords_rel) && (Menu_is_visible) ) - { - Print_in_menu("X: Y: ",0); - } -} - -void Distort_brush_1_8(void) -// -// Opération : OPERATION_DISTORT_BRUSH -// Click Souris: 1 -// Taille_Pile : 8 -// -// Souris effacée: No -// -{ - // How far (in pixels) you can catch a handle - #define REACH_DISTANCE 100 - short i; - short x[4]; - short y[4]; - long best_distance=REACH_DISTANCE; - short best_spot=-1; - - for (i=3;i>=0;i--) - { - long distance; - Operation_pop(&y[i]); - Operation_pop(&x[i]); - distance=Distance(Paintbrush_X,Paintbrush_Y,x[i],y[i]); - if (distance-1) - { - Operation_push(best_spot); - } - if ( (Config.Coords_rel) && (Menu_is_visible) ) - { - Print_in_menu("X: Y: ",0); - Print_coordinates(); - } -} - -void Distort_brush_1_9(void) -// -// Opération : OPERATION_DISTORT_BRUSH -// Click Souris: 1 -// Taille_Pile : 9 -// -// Souris effacée: No -// -{ - short i; - short x[4]; - short y[4]; - short selected_corner; - - // Pop all arguments - Operation_pop(&selected_corner); - for (i=3;i>=0;i--) - { - Operation_pop(&y[i]); - Operation_pop(&x[i]); - } - - if (Paintbrush_X!=x[selected_corner] || Paintbrush_Y!=y[selected_corner]) - { - Hide_cursor(); - - // Easiest refresh mode: make no assumptions on how the brush was - // displayed before. - Display_all_screen(); - - x[selected_corner]=Paintbrush_X; - y[selected_corner]=Paintbrush_Y; - - for (i=0;i<4;i++) - Draw_stretch_spot(x[i],y[i]); - - Distort_brush_preview(x[0],y[0],x[1],y[1],x[2],y[2],x[3],y[3]); - - Display_cursor(); - - if ( (Config.Coords_rel) && (Menu_is_visible) ) - { - Print_in_menu("X: Y: ",0); - Print_coordinates(); - } - Update_rect(0,0,Screen_width,Menu_Y); - } - - // Push back all arguments - for (i=0;i<4;i++) - { - Operation_push(x[i]); - Operation_push(y[i]); - } - Operation_push(selected_corner); - -} -void Distort_brush_0_9(void) -// -// Opération : OPERATION_DISTORT_BRUSH -// Click Souris: 0 -// Taille_Pile : 9 -// -// Souris effacée: No -// -{ - short selected_corner; - Operation_pop(&selected_corner); - -} - -void Distort_brush_2_0(void) -// -// Opération : OPERATION_DISTORT_BRUSH -// Click Souris: 2 -// Taille_Pile : 0 -// -// Souris effacée: Oui -// -{ - Paintbrush_hidden=0; - Display_all_screen(); - // Erase the message in status bar - if ( (Config.Coords_rel) && (Menu_is_visible) ) - { - Print_in_menu("X: Y: ",0); - } - Return_to_draw_mode(); -} - -void Distort_brush_2_8(void) -// -// Opération : OPERATION_DISTORT_BRUSH -// Click Souris: 2 -// Taille_Pile : 8 -// -// Souris effacée: Oui -// -{ - short i; - short x[4]; - short y[4]; - - // Pop all arguments - for (i=3;i>=0;i--) - { - Operation_pop(&y[i]); - Operation_pop(&x[i]); - } - Distort_brush(x[0],y[0],x[1],y[1],x[2],y[2],x[3],y[3]); - - Paintbrush_hidden=0; - Display_all_screen(); - - Return_to_draw_mode(); -} //////////////////////////////////////////////////////////// OPERATION_SCROLL @@ -5244,4 +3995,3 @@ void Centered_lines_0_7(void) Operation_push(Paintbrush_Y); } - diff --git a/operatio.h b/operatio.h index 97cdde15..a228c582 100644 --- a/operatio.h +++ b/operatio.h @@ -21,15 +21,21 @@ ////////////////////////////////////////////////////////////////////////////// ///@file operatio.h -/// Code for the operations, ie all drawing tools. +/// Code for the drawing tools operations. ////////////////////////////////////////////////////////////////////////////// +#include "struct.h" + +// General operation handling functions. These may be moved to ops_handler.h when operatio.c grows over 5000 lines again... + /// Do some housekeeping before starting work on a operation. void Start_operation_stack(word new_operation); /// Put a value on ::Operation_stack void Operation_push(short value); /// Take a value off ::Operation_stack void Operation_pop(short * value); +void Init_start_operation(void); +short Distance(short x1, short y1, short x2, short y2); //////////////////////////////////////////////////// OPERATION_CONTINUOUS_DRAW void Freehand_mode1_1_0(void);